diff --git a/.gitignore b/.gitignore
index b187bde786..4f32aa8393 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,8 @@ profile
**/Builds/Android/app/.externalNativeBuild
**/Builds/Android/lib/build
**/Builds/Android/lib/.externalNativeBuild
+**/Builds/CLion/cmake-build-*
+**/Builds/CLion/.idea
**/doxygen/doc
**/doxygen/build
extras/Projucer/JUCECompileEngine.dylib
diff --git a/extras/Projucer/Builds/MacOSX/Info-App.plist b/extras/Projucer/Builds/MacOSX/Info-App.plist
index e5c569a0cc..8af6142baa 100644
--- a/extras/Projucer/Builds/MacOSX/Info-App.plist
+++ b/extras/Projucer/Builds/MacOSX/Info-App.plist
@@ -23,7 +23,7 @@
CFBundleIconFile
Icon.icns
CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
+ com.juce.theprojucer
CFBundleName
Projucer
CFBundleDisplayName
diff --git a/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj b/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj
index 0a37ad2b2f..ff275c207a 100644
--- a/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj
+++ b/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj
@@ -182,6 +182,7 @@
5524B5C9FC6AEAA670B92AA9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ComponentLayoutEditor.h"; path = "../../Source/ComponentEditor/UI/jucer_ComponentLayoutEditor.h"; sourceTree = "SOURCE_ROOT"; };
55DEDCEB35AA1FB54C74B375 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_MessageIDs.h"; path = "../../Source/LiveBuildEngine/jucer_MessageIDs.h"; sourceTree = "SOURCE_ROOT"; };
56177921580A4855917E0205 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_AudioPluginEditorTemplate.h"; path = "../../Source/BinaryData/Templates/jucer_AudioPluginEditorTemplate.h"; sourceTree = "SOURCE_ROOT"; };
+ 56749E4C72A8F51ACA8F2330 = {isa = PBXFileReference; lastKnownFileType = file.svg; name = "export_clion.svg"; path = "../../Source/BinaryData/Icons/export_clion.svg"; sourceTree = "SOURCE_ROOT"; };
5783563E39E48ADFC68EB84A = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ComponentTextProperty.h"; path = "../../Source/ComponentEditor/Properties/jucer_ComponentTextProperty.h"; sourceTree = "SOURCE_ROOT"; };
58139D8D454051C59E77609B = {isa = PBXFileReference; lastKnownFileType = file.nib; name = RecentFilesMenuTemplate.nib; path = ../../Source/BinaryData/RecentFilesMenuTemplate.nib; sourceTree = "SOURCE_ROOT"; };
5867DC4E39DF8539B54C0D59 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; };
@@ -332,6 +333,7 @@
D251114072E67CA86D9913D6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ClassDatabase.h"; path = "../../Source/LiveBuildEngine/jucer_ClassDatabase.h"; sourceTree = "SOURCE_ROOT"; };
D2FE76E4CF003856278343CC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_CompileEngineServer.cpp"; path = "../../Source/LiveBuildEngine/jucer_CompileEngineServer.cpp"; sourceTree = "SOURCE_ROOT"; };
D588BA6A0C62DE1F18D5C2EA = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_GlobalSearchPathsWindowComponent.h"; path = "../../Source/Application/Windows/jucer_GlobalSearchPathsWindowComponent.h"; sourceTree = "SOURCE_ROOT"; };
+ D5EF5961B1F0E3FAED32E30A = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectExport_CLion.h"; path = "../../Source/ProjectSaving/jucer_ProjectExport_CLion.h"; sourceTree = "SOURCE_ROOT"; };
D6390A40B3279E0E626C78D3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_ColouredElement.cpp"; path = "../../Source/ComponentEditor/PaintElements/jucer_ColouredElement.cpp"; sourceTree = "SOURCE_ROOT"; };
D766BB9D8C32B5560F0493F3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_cryptography.mm"; path = "../../JuceLibraryCode/include_juce_cryptography.mm"; sourceTree = "SOURCE_ROOT"; };
D859E9EA11A71BD6E85DC649 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_DependencyPathPropertyComponent.cpp"; path = "../../Source/Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -411,6 +413,7 @@
F0F189518721D46C0F94FD56 = {isa = PBXGroup; children = (
514F2FAFDBF535AC03FA2E6C,
807049CA2D5B6DE18EA078F2,
+ 56749E4C72A8F51ACA8F2330,
42F4AA3EF0883D506987CA99,
69B478C992FA0B8C885946A6,
EAC1731150A7F79D59BAA0B6,
@@ -618,6 +621,7 @@
B8385E9A644BD3CD94876448, ); name = Project; sourceTree = ""; };
4DCC5D64BBE8DE85360A3D57 = {isa = PBXGroup; children = (
CCD62DB0A19A985A4B9D7F32,
+ D5EF5961B1F0E3FAED32E30A,
FA790C59A304579F660F112F,
59520B8137E6A2E483074399,
FF68231DE2B395461009116C,
diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj
index f4325f2cdf..ce5c362a44 100644
--- a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj
@@ -1517,6 +1517,7 @@
+
@@ -1958,6 +1959,7 @@
+
diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters
index 4df93f6572..c58467490a 100644
--- a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters
@@ -2118,6 +2118,9 @@
Projucer\ProjectSaving
+
+ Projucer\ProjectSaving
+
Projucer\ProjectSaving
@@ -3437,6 +3440,9 @@
Projucer\BinaryData\Icons
+
+ Projucer\BinaryData\Icons
+
Projucer\BinaryData\Icons
diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj
index 046706d6dc..d3b626758f 100644
--- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj
@@ -1517,6 +1517,7 @@
+
@@ -1958,6 +1959,7 @@
+
diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters
index dd7f7267ec..d51f8e9bde 100644
--- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters
@@ -2118,6 +2118,9 @@
Projucer\ProjectSaving
+
+ Projucer\ProjectSaving
+
Projucer\ProjectSaving
@@ -3437,6 +3440,9 @@
Projucer\BinaryData\Icons
+
+ Projucer\BinaryData\Icons
+
Projucer\BinaryData\Icons
diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
index d43515ed8c..ac75454e4a 100644
--- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
@@ -1517,6 +1517,7 @@
+
@@ -1958,6 +1959,7 @@
+
diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
index 74cb348344..134f098b34 100644
--- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
@@ -2118,6 +2118,9 @@
Projucer\ProjectSaving
+
+ Projucer\ProjectSaving
+
Projucer\ProjectSaving
@@ -3437,6 +3440,9 @@
Projucer\BinaryData\Icons
+
+ Projucer\BinaryData\Icons
+
Projucer\BinaryData\Icons
diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.cpp b/extras/Projucer/JuceLibraryCode/BinaryData.cpp
index 7e84416e26..cab1e01e3d 100644
--- a/extras/Projucer/JuceLibraryCode/BinaryData.cpp
+++ b/extras/Projucer/JuceLibraryCode/BinaryData.cpp
@@ -1305,8 +1305,47 @@ static const unsigned char temp_binary_data_5[] =
const char* export_android_svg = (const char*) temp_binary_data_5;
-//================== export_codeBlocks.svg ==================
+//================== export_clion.svg ==================
static const unsigned char temp_binary_data_6[] =
+"\n";
+
+const char* export_clion_svg = (const char*) temp_binary_data_6;
+
+//================== export_codeBlocks.svg ==================
+static const unsigned char temp_binary_data_7[] =
"\n"
"";
-const char* export_codeBlocks_svg = (const char*) temp_binary_data_6;
+const char* export_codeBlocks_svg = (const char*) temp_binary_data_7;
//================== export_linux.svg ==================
-static const unsigned char temp_binary_data_7[] =
+static const unsigned char temp_binary_data_8[] =
"\n"
"";
-const char* export_linux_svg = (const char*) temp_binary_data_7;
+const char* export_linux_svg = (const char*) temp_binary_data_8;
//================== export_visualStudio.svg ==================
-static const unsigned char temp_binary_data_8[] =
+static const unsigned char temp_binary_data_9[] =
"\n"
"";
-const char* export_visualStudio_svg = (const char*) temp_binary_data_8;
+const char* export_visualStudio_svg = (const char*) temp_binary_data_9;
//================== export_xcode.svg ==================
-static const unsigned char temp_binary_data_9[] =
+static const unsigned char temp_binary_data_10[] =
"\n"
"";
-const char* export_xcode_svg = (const char*) temp_binary_data_9;
+const char* export_xcode_svg = (const char*) temp_binary_data_10;
//================== huckleberry_icon.svg ==================
-static const unsigned char temp_binary_data_10[] =
+static const unsigned char temp_binary_data_11[] =
"\n"
"\n"
"\n";
-const char* huckleberry_icon_svg = (const char*) temp_binary_data_10;
+const char* huckleberry_icon_svg = (const char*) temp_binary_data_11;
//================== juce-logo-with-text.svg ==================
-static const unsigned char temp_binary_data_11[] =
+static const unsigned char temp_binary_data_12[] =
"\n"
"\n"
"\n";
-const char* jucelogowithtext_svg = (const char*) temp_binary_data_11;
+const char* jucelogowithtext_svg = (const char*) temp_binary_data_12;
//================== juce_icon.png ==================
-static const unsigned char temp_binary_data_12[] =
+static const unsigned char temp_binary_data_13[] =
{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,6,0,0,0,244,120,212,250,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,100,121,113,201,101,60,0,0,3,40,105,84,88,116,88,77,76,58,
99,111,109,46,97,100,111,98,101,46,120,109,112,0,0,0,0,0,60,63,120,112,97,99,107,101,116,32,98,101,103,105,110,61,34,239,187,191,34,32,105,100,61,34,87,53,77,48,77,112,67,101,104,105,72,122,114,101,83,122,78,84,99,122,107,99,57,100,34,63,62,32,60,120,
58,120,109,112,109,101,116,97,32,120,109,108,110,115,58,120,61,34,97,100,111,98,101,58,110,115,58,109,101,116,97,47,34,32,120,58,120,109,112,116,107,61,34,65,100,111,98,101,32,88,77,80,32,67,111,114,101,32,53,46,54,45,99,48,54,55,32,55,57,46,49,53,55,
@@ -2436,10 +2475,10 @@ static const unsigned char temp_binary_data_12[] =
0,0,0,2,0,0,16,0,0,128,0,0,0,4,0,0,32,0,0,0,1,0,0,8,0,0,64,0,0,0,2,0,0,16,0,0,128,0,0,0,4,0,0,32,0,0,0,1,0,0,8,0,0,64,0,0,128,0,0,0,4,0,0,32,0,0,0,1,0,0,8,0,0,64,0,0,0,2,0,0,16,0,0,128,0,0,0,4,0,0,32,0,0,128,191,246,33,192,0,100,235,173,153,70,62,64,
37,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
-const char* juce_icon_png = (const char*) temp_binary_data_12;
+const char* juce_icon_png = (const char*) temp_binary_data_13;
//================== wizard_AnimatedApp.svg ==================
-static const unsigned char temp_binary_data_13[] =
+static const unsigned char temp_binary_data_14[] =
"\n"
"\n"
"\n"
@@ -2616,10 +2655,10 @@ static const unsigned char temp_binary_data_13[] =
" id=\"line44\"\n"
" style=\"stroke:#a45c94;stroke-opacity:0.94117647\" />";
-const char* wizard_AnimatedApp_svg = (const char*) temp_binary_data_13;
+const char* wizard_AnimatedApp_svg = (const char*) temp_binary_data_14;
//================== wizard_AudioApp.svg ==================
-static const unsigned char temp_binary_data_14[] =
+static const unsigned char temp_binary_data_15[] =
"\n"
"\n"
"\n"
@@ -3373,10 +3412,10 @@ static const unsigned char temp_binary_data_14[] =
" id=\"line131\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1\" />";
-const char* wizard_AudioApp_svg = (const char*) temp_binary_data_14;
+const char* wizard_AudioApp_svg = (const char*) temp_binary_data_15;
//================== wizard_AudioPlugin.svg ==================
-static const unsigned char temp_binary_data_15[] =
+static const unsigned char temp_binary_data_16[] =
"\n"
"\n"
"\n"
@@ -4232,10 +4271,10 @@ static const unsigned char temp_binary_data_15[] =
" id=\"circle175\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1;fill:#a45c94;fill-opacity:1\" />";
-const char* wizard_AudioPlugin_svg = (const char*) temp_binary_data_15;
+const char* wizard_AudioPlugin_svg = (const char*) temp_binary_data_16;
//================== wizard_ConsoleApp.svg ==================
-static const unsigned char temp_binary_data_16[] =
+static const unsigned char temp_binary_data_17[] =
"\n"
"\n"
"\n"
@@ -4322,10 +4361,10 @@ static const unsigned char temp_binary_data_16[] =
" id=\"path19\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1;fill:#a45c94;fill-opacity:1\" />";
-const char* wizard_ConsoleApp_svg = (const char*) temp_binary_data_16;
+const char* wizard_ConsoleApp_svg = (const char*) temp_binary_data_17;
//================== wizard_DLL.svg ==================
-static const unsigned char temp_binary_data_17[] =
+static const unsigned char temp_binary_data_18[] =
"\n"
"\n"
"\n"
@@ -4596,10 +4635,10 @@ static const unsigned char temp_binary_data_17[] =
" id=\"path54\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1\" />";
-const char* wizard_DLL_svg = (const char*) temp_binary_data_17;
+const char* wizard_DLL_svg = (const char*) temp_binary_data_18;
//================== wizard_GUI.svg ==================
-static const unsigned char temp_binary_data_18[] =
+static const unsigned char temp_binary_data_19[] =
"\n"
"\n"
"\n"
@@ -4769,10 +4808,10 @@ static const unsigned char temp_binary_data_18[] =
" id=\"path47\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1\" />";
-const char* wizard_GUI_svg = (const char*) temp_binary_data_18;
+const char* wizard_GUI_svg = (const char*) temp_binary_data_19;
//================== wizard_Highlight.svg ==================
-static const unsigned char temp_binary_data_19[] =
+static const unsigned char temp_binary_data_20[] =
"\n"
"\n"
"\n"
@@ -4822,10 +4861,10 @@ static const unsigned char temp_binary_data_19[] =
" id=\"path3\"\n"
" style=\"fill:#a45c94;fill-opacity:1\" />";
-const char* wizard_Highlight_svg = (const char*) temp_binary_data_19;
+const char* wizard_Highlight_svg = (const char*) temp_binary_data_20;
//================== wizard_Openfile.svg ==================
-static const unsigned char temp_binary_data_20[] =
+static const unsigned char temp_binary_data_21[] =
"\n"
"\n"
"\n"
@@ -4877,10 +4916,10 @@ static const unsigned char temp_binary_data_20[] =
" id=\"path3\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1\" />";
-const char* wizard_Openfile_svg = (const char*) temp_binary_data_20;
+const char* wizard_Openfile_svg = (const char*) temp_binary_data_21;
//================== wizard_OpenGL.svg ==================
-static const unsigned char temp_binary_data_21[] =
+static const unsigned char temp_binary_data_22[] =
"\n"
"\n"
"\n"
@@ -5008,10 +5047,10 @@ static const unsigned char temp_binary_data_21[] =
" id=\"path23\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1\" />";
-const char* wizard_OpenGL_svg = (const char*) temp_binary_data_21;
+const char* wizard_OpenGL_svg = (const char*) temp_binary_data_22;
//================== wizard_StaticLibrary.svg ==================
-static const unsigned char temp_binary_data_22[] =
+static const unsigned char temp_binary_data_23[] =
"\n"
"\n"
"\n"
@@ -5282,10 +5321,10 @@ static const unsigned char temp_binary_data_22[] =
" id=\"path54\"\n"
" style=\"stroke:#a45c94;stroke-opacity:1\" />";
-const char* wizard_StaticLibrary_svg = (const char*) temp_binary_data_22;
+const char* wizard_StaticLibrary_svg = (const char*) temp_binary_data_23;
//================== jucer_AnimatedComponentTemplate.cpp ==================
-static const unsigned char temp_binary_data_23[] =
+static const unsigned char temp_binary_data_24[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5351,10 +5390,10 @@ static const unsigned char temp_binary_data_23[] =
"// (This function is called by the app startup code to create our main component)\r\n"
"Component* createMainContentComponent() { return new MainContentComponent(); }\r\n";
-const char* jucer_AnimatedComponentTemplate_cpp = (const char*) temp_binary_data_23;
+const char* jucer_AnimatedComponentTemplate_cpp = (const char*) temp_binary_data_24;
//================== jucer_AudioComponentTemplate.cpp ==================
-static const unsigned char temp_binary_data_24[] =
+static const unsigned char temp_binary_data_25[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5448,10 +5487,10 @@ static const unsigned char temp_binary_data_24[] =
"// (This function is called by the app startup code to create our main component)\r\n"
"Component* createMainContentComponent() { return new MainContentComponent(); }\r\n";
-const char* jucer_AudioComponentTemplate_cpp = (const char*) temp_binary_data_24;
+const char* jucer_AudioComponentTemplate_cpp = (const char*) temp_binary_data_25;
//================== jucer_AudioPluginEditorTemplate.cpp ==================
-static const unsigned char temp_binary_data_25[] =
+static const unsigned char temp_binary_data_26[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5495,10 +5534,10 @@ static const unsigned char temp_binary_data_25[] =
" // subcomponents in your editor..\r\n"
"}\r\n";
-const char* jucer_AudioPluginEditorTemplate_cpp = (const char*) temp_binary_data_25;
+const char* jucer_AudioPluginEditorTemplate_cpp = (const char*) temp_binary_data_26;
//================== jucer_AudioPluginEditorTemplate.h ==================
-static const unsigned char temp_binary_data_26[] =
+static const unsigned char temp_binary_data_27[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5535,10 +5574,10 @@ static const unsigned char temp_binary_data_26[] =
" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EDITORCLASSNAME)\r\n"
"};\r\n";
-const char* jucer_AudioPluginEditorTemplate_h = (const char*) temp_binary_data_26;
+const char* jucer_AudioPluginEditorTemplate_h = (const char*) temp_binary_data_27;
//================== jucer_AudioPluginFilterTemplate.cpp ==================
-static const unsigned char temp_binary_data_27[] =
+static const unsigned char temp_binary_data_28[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5727,10 +5766,10 @@ static const unsigned char temp_binary_data_27[] =
" return new FILTERCLASSNAME();\r\n"
"}\r\n";
-const char* jucer_AudioPluginFilterTemplate_cpp = (const char*) temp_binary_data_27;
+const char* jucer_AudioPluginFilterTemplate_cpp = (const char*) temp_binary_data_28;
//================== jucer_AudioPluginFilterTemplate.h ==================
-static const unsigned char temp_binary_data_28[] =
+static const unsigned char temp_binary_data_29[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5794,10 +5833,10 @@ static const unsigned char temp_binary_data_28[] =
" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FILTERCLASSNAME)\r\n"
"};\r\n";
-const char* jucer_AudioPluginFilterTemplate_h = (const char*) temp_binary_data_28;
+const char* jucer_AudioPluginFilterTemplate_h = (const char*) temp_binary_data_29;
//================== jucer_ComponentTemplate.cpp ==================
-static const unsigned char temp_binary_data_29[] =
+static const unsigned char temp_binary_data_30[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5873,10 +5912,10 @@ static const unsigned char temp_binary_data_29[] =
"//[EndFile] You can add extra defines here...\r\n"
"//[/EndFile]\r\n";
-const char* jucer_ComponentTemplate_cpp = (const char*) temp_binary_data_29;
+const char* jucer_ComponentTemplate_cpp = (const char*) temp_binary_data_30;
//================== jucer_ComponentTemplate.h ==================
-static const unsigned char temp_binary_data_30[] =
+static const unsigned char temp_binary_data_31[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5939,10 +5978,10 @@ static const unsigned char temp_binary_data_30[] =
"//[EndFile] You can add extra defines here...\r\n"
"//[/EndFile]\r\n";
-const char* jucer_ComponentTemplate_h = (const char*) temp_binary_data_30;
+const char* jucer_ComponentTemplate_h = (const char*) temp_binary_data_31;
//================== jucer_ContentCompTemplate.cpp ==================
-static const unsigned char temp_binary_data_31[] =
+static const unsigned char temp_binary_data_32[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -5981,10 +6020,10 @@ static const unsigned char temp_binary_data_31[] =
" // update their positions.\r\n"
"}\r\n";
-const char* jucer_ContentCompTemplate_cpp = (const char*) temp_binary_data_31;
+const char* jucer_ContentCompTemplate_cpp = (const char*) temp_binary_data_32;
//================== jucer_ContentCompTemplate.h ==================
-static const unsigned char temp_binary_data_32[] =
+static const unsigned char temp_binary_data_33[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6018,10 +6057,10 @@ static const unsigned char temp_binary_data_32[] =
" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CONTENTCOMPCLASS)\r\n"
"};\r\n";
-const char* jucer_ContentCompTemplate_h = (const char*) temp_binary_data_32;
+const char* jucer_ContentCompTemplate_h = (const char*) temp_binary_data_33;
//================== jucer_InlineComponentTemplate.h ==================
-static const unsigned char temp_binary_data_33[] =
+static const unsigned char temp_binary_data_34[] =
"//==============================================================================\r\n"
"class COMPONENTCLASS : public Component\r\n"
"{\r\n"
@@ -6063,10 +6102,10 @@ static const unsigned char temp_binary_data_33[] =
" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (COMPONENTCLASS)\r\n"
"};\r\n";
-const char* jucer_InlineComponentTemplate_h = (const char*) temp_binary_data_33;
+const char* jucer_InlineComponentTemplate_h = (const char*) temp_binary_data_34;
//================== jucer_MainConsoleAppTemplate.cpp ==================
-static const unsigned char temp_binary_data_34[] =
+static const unsigned char temp_binary_data_35[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6090,10 +6129,10 @@ static const unsigned char temp_binary_data_34[] =
" return 0;\r\n"
"}\r\n";
-const char* jucer_MainConsoleAppTemplate_cpp = (const char*) temp_binary_data_34;
+const char* jucer_MainConsoleAppTemplate_cpp = (const char*) temp_binary_data_35;
//================== jucer_MainTemplate_NoWindow.cpp ==================
-static const unsigned char temp_binary_data_35[] =
+static const unsigned char temp_binary_data_36[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6149,10 +6188,10 @@ static const unsigned char temp_binary_data_35[] =
"// This macro generates the main() routine that launches the app.\r\n"
"START_JUCE_APPLICATION (APPCLASSNAME)\r\n";
-const char* jucer_MainTemplate_NoWindow_cpp = (const char*) temp_binary_data_35;
+const char* jucer_MainTemplate_NoWindow_cpp = (const char*) temp_binary_data_36;
//================== jucer_MainTemplate_SimpleWindow.cpp ==================
-static const unsigned char temp_binary_data_36[] =
+static const unsigned char temp_binary_data_37[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6256,10 +6295,10 @@ static const unsigned char temp_binary_data_36[] =
"// This macro generates the main() routine that launches the app.\r\n"
"START_JUCE_APPLICATION (APPCLASSNAME)\r\n";
-const char* jucer_MainTemplate_SimpleWindow_cpp = (const char*) temp_binary_data_36;
+const char* jucer_MainTemplate_SimpleWindow_cpp = (const char*) temp_binary_data_37;
//================== jucer_MainTemplate_Window.cpp ==================
-static const unsigned char temp_binary_data_37[] =
+static const unsigned char temp_binary_data_38[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6361,10 +6400,10 @@ static const unsigned char temp_binary_data_37[] =
"// This macro generates the main() routine that launches the app.\r\n"
"START_JUCE_APPLICATION (APPCLASSNAME)\r\n";
-const char* jucer_MainTemplate_Window_cpp = (const char*) temp_binary_data_37;
+const char* jucer_MainTemplate_Window_cpp = (const char*) temp_binary_data_38;
//================== jucer_NewComponentTemplate.cpp ==================
-static const unsigned char temp_binary_data_38[] =
+static const unsigned char temp_binary_data_39[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6417,10 +6456,10 @@ static const unsigned char temp_binary_data_38[] =
"\r\n"
"}\r\n";
-const char* jucer_NewComponentTemplate_cpp = (const char*) temp_binary_data_38;
+const char* jucer_NewComponentTemplate_cpp = (const char*) temp_binary_data_39;
//================== jucer_NewComponentTemplate.h ==================
-static const unsigned char temp_binary_data_39[] =
+static const unsigned char temp_binary_data_40[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6451,10 +6490,10 @@ static const unsigned char temp_binary_data_39[] =
" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (COMPONENTCLASS)\r\n"
"};\r\n";
-const char* jucer_NewComponentTemplate_h = (const char*) temp_binary_data_39;
+const char* jucer_NewComponentTemplate_h = (const char*) temp_binary_data_40;
//================== jucer_NewCppFileTemplate.cpp ==================
-static const unsigned char temp_binary_data_40[] =
+static const unsigned char temp_binary_data_41[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6467,10 +6506,10 @@ static const unsigned char temp_binary_data_40[] =
"\r\n"
"INCLUDE_CORRESPONDING_HEADER\r\n";
-const char* jucer_NewCppFileTemplate_cpp = (const char*) temp_binary_data_40;
+const char* jucer_NewCppFileTemplate_cpp = (const char*) temp_binary_data_41;
//================== jucer_NewCppFileTemplate.h ==================
-static const unsigned char temp_binary_data_41[] =
+static const unsigned char temp_binary_data_42[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6483,10 +6522,10 @@ static const unsigned char temp_binary_data_41[] =
"\r\n"
"#pragma once\r\n";
-const char* jucer_NewCppFileTemplate_h = (const char*) temp_binary_data_41;
+const char* jucer_NewCppFileTemplate_h = (const char*) temp_binary_data_42;
//================== jucer_NewInlineComponentTemplate.h ==================
-static const unsigned char temp_binary_data_42[] =
+static const unsigned char temp_binary_data_43[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6549,10 +6588,10 @@ static const unsigned char temp_binary_data_42[] =
" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (COMPONENTCLASS)\r\n"
"};\r\n";
-const char* jucer_NewInlineComponentTemplate_h = (const char*) temp_binary_data_42;
+const char* jucer_NewInlineComponentTemplate_h = (const char*) temp_binary_data_43;
//================== jucer_OpenGLComponentTemplate.cpp ==================
-static const unsigned char temp_binary_data_43[] =
+static const unsigned char temp_binary_data_44[] =
"/*\r\n"
" ==============================================================================\r\n"
"\r\n"
@@ -6624,10 +6663,10 @@ static const unsigned char temp_binary_data_43[] =
"// (This function is called by the app startup code to create our main component)\r\n"
"Component* createMainContentComponent() { return new MainContentComponent(); }\r\n";
-const char* jucer_OpenGLComponentTemplate_cpp = (const char*) temp_binary_data_43;
+const char* jucer_OpenGLComponentTemplate_cpp = (const char*) temp_binary_data_44;
//================== colourscheme_dark.xml ==================
-static const unsigned char temp_binary_data_44[] =
+static const unsigned char temp_binary_data_45[] =
"\r\n"
"\r\n"
"\r\n"
@@ -6652,10 +6691,10 @@ static const unsigned char temp_binary_data_44[] =
" \r\n"
"\r\n";
-const char* colourscheme_dark_xml = (const char*) temp_binary_data_44;
+const char* colourscheme_dark_xml = (const char*) temp_binary_data_45;
//================== colourscheme_light.xml ==================
-static const unsigned char temp_binary_data_45[] =
+static const unsigned char temp_binary_data_46[] =
"\r\n"
"\r\n"
"\r\n"
@@ -6680,10 +6719,10 @@ static const unsigned char temp_binary_data_45[] =
" \r\n"
"\r\n";
-const char* colourscheme_light_xml = (const char*) temp_binary_data_45;
+const char* colourscheme_light_xml = (const char*) temp_binary_data_46;
//================== offlinepage.html ==================
-static const unsigned char temp_binary_data_46[] =
+static const unsigned char temp_binary_data_47[] =
"\n"
" \n"
" \n"
@@ -6727,10 +6766,10 @@ static const unsigned char temp_binary_data_46[] =
" \n"
"";
-const char* offlinepage_html = (const char*) temp_binary_data_46;
+const char* offlinepage_html = (const char*) temp_binary_data_47;
//================== projucer_EULA.txt ==================
-static const unsigned char temp_binary_data_47[] =
+static const unsigned char temp_binary_data_48[] =
"\r\n"
"IMPORTANT NOTICE: PLEASE READ CAREFULLY BEFORE INSTALLING THE SOFTWARE:\r\n"
"\r\n"
@@ -6894,10 +6933,10 @@ static const unsigned char temp_binary_data_47[] =
"\r\n"
"10.6. Please note that this License, its subject matter and its formation, are governed by English law. You and we both agree to that the courts of England and Wales will have exclusive jurisdiction. \r\n";
-const char* projucer_EULA_txt = (const char*) temp_binary_data_47;
+const char* projucer_EULA_txt = (const char*) temp_binary_data_48;
//================== RecentFilesMenuTemplate.nib ==================
-static const unsigned char temp_binary_data_48[] =
+static const unsigned char temp_binary_data_49[] =
{ 98,112,108,105,115,116,48,48,212,0,1,0,2,0,3,0,4,0,5,0,6,1,53,1,54,88,36,118,101,114,115,105,111,110,88,36,111,98,106,101,99,116,115,89,36,97,114,99,104,105,118,101,114,84,36,116,111,112,18,0,1,134,160,175,16,74,0,7,0,8,0,31,0,35,0,36,0,42,0,46,0,50,
0,53,0,57,0,74,0,77,0,78,0,86,0,87,0,97,0,112,0,113,0,114,0,119,0,120,0,121,0,124,0,128,0,129,0,132,0,143,0,144,0,145,0,149,0,153,0,162,0,163,0,164,0,169,0,173,0,180,0,181,0,182,0,185,0,192,0,193,0,200,0,201,0,208,0,209,0,216,0,217,0,224,0,225,0,226,
0,229,0,230,0,232,0,249,1,11,1,29,1,30,1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,44,1,47,1,50,85,36,110,117,108,108,219,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,
@@ -6934,7 +6973,7 @@ static const unsigned char temp_binary_data_48[] =
7,157,7,159,7,161,7,163,7,165,7,167,7,169,7,171,7,173,7,175,7,177,7,179,7,181,7,190,7,192,7,225,7,227,7,229,7,231,7,233,7,235,7,237,7,239,7,241,7,243,7,245,7,247,7,249,7,251,7,253,7,255,8,2,8,5,8,8,8,11,8,14,8,17,8,20,8,23,8,26,8,29,8,32,8,35,8,38,8,
41,8,44,8,53,8,55,8,56,8,65,8,67,8,68,8,77,8,92,8,97,8,115,8,120,8,134,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,136,0,0 };
-const char* RecentFilesMenuTemplate_nib = (const char*) temp_binary_data_48;
+const char* RecentFilesMenuTemplate_nib = (const char*) temp_binary_data_49;
const char* getNamedResource (const char*, int&) throw();
@@ -6953,6 +6992,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) throw
case 0x34bc1021: numBytes = 11325; return LICENSE;
case 0x406db5c1: numBytes = 3117; return background_logo_svg;
case 0xbe17d889: numBytes = 3586; return export_android_svg;
+ case 0x84c51a59: numBytes = 2244; return export_clion_svg;
case 0x83f049e3: numBytes = 1726; return export_codeBlocks_svg;
case 0x96d2a1ce: numBytes = 28184; return export_linux_svg;
case 0x2505bd06: numBytes = 1706; return export_visualStudio_svg;
@@ -7011,6 +7051,7 @@ const char* namedResourceList[] =
"LICENSE",
"background_logo_svg",
"export_android_svg",
+ "export_clion_svg",
"export_codeBlocks_svg",
"export_linux_svg",
"export_visualStudio_svg",
diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.h b/extras/Projucer/JuceLibraryCode/BinaryData.h
index d119f6ca0b..cf51071527 100644
--- a/extras/Projucer/JuceLibraryCode/BinaryData.h
+++ b/extras/Projucer/JuceLibraryCode/BinaryData.h
@@ -26,6 +26,9 @@ namespace BinaryData
extern const char* export_android_svg;
const int export_android_svgSize = 3586;
+ extern const char* export_clion_svg;
+ const int export_clion_svgSize = 2244;
+
extern const char* export_codeBlocks_svg;
const int export_codeBlocks_svgSize = 1726;
@@ -159,7 +162,7 @@ namespace BinaryData
extern const char* namedResourceList[];
// Number of elements in the namedResourceList array.
- const int namedResourceListSize = 49;
+ const int namedResourceListSize = 50;
// If you provide the name of one of the binary resource variables above, this function will
// return the corresponding data and its size (or a null pointer if the name isn't found).
diff --git a/extras/Projucer/Projucer.jucer b/extras/Projucer/Projucer.jucer
index 386f02d77a..0615e46011 100644
--- a/extras/Projucer/Projucer.jucer
+++ b/extras/Projucer/Projucer.jucer
@@ -165,6 +165,8 @@
file="Source/BinaryData/Icons/background_logo.svg"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ icon_CLion
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extras/Projucer/Source/Project/UI/Sidebar/jucer_ExporterTreeItems.h b/extras/Projucer/Source/Project/UI/Sidebar/jucer_ExporterTreeItems.h
index 447fe26669..4ecf2abb5c 100644
--- a/extras/Projucer/Source/Project/UI/Sidebar/jucer_ExporterTreeItems.h
+++ b/extras/Projucer/Source/Project/UI/Sidebar/jucer_ExporterTreeItems.h
@@ -56,11 +56,12 @@ public:
{
if (e != nullptr)
{
- if (e->isXcode()) return Icon (getIcons().xcode, Colours::transparentBlack);
+ if (e->isXcode()) return Icon (getIcons().xcode, Colours::transparentBlack);
else if (e->isVisualStudio()) return Icon (getIcons().visualStudio, Colours::transparentBlack);
- else if (e->isAndroid()) return Icon (getIcons().android, Colours::transparentBlack);
- else if (e->isCodeBlocks()) return Icon (getIcons().codeBlocks, Colours::transparentBlack);
- else if (e->isMakefile()) return Icon (getIcons().linux, Colours::transparentBlack);
+ else if (e->isAndroid()) return Icon (getIcons().android, Colours::transparentBlack);
+ else if (e->isCodeBlocks()) return Icon (getIcons().codeBlocks, Colours::transparentBlack);
+ else if (e->isMakefile()) return Icon (getIcons().linux, Colours::transparentBlack);
+ else if (e->isCLion()) return Icon (getIcons().clion, Colours::transparentBlack);
}
return Icon();
@@ -186,7 +187,9 @@ private:
struct SettingsComp : public Component
{
SettingsComp (ProjectExporter* exp)
- : group (exp->getName(), ExporterItem::getIconForExporter (exp))
+ : group (exp->getName(),
+ ExporterItem::getIconForExporter (exp),
+ exp->getDescription())
{
addAndMakeVisible (group);
diff --git a/extras/Projucer/Source/Project/UI/Sidebar/jucer_ModuleTreeItems.h b/extras/Projucer/Source/Project/UI/Sidebar/jucer_ModuleTreeItems.h
index 70259cc74a..b6ecae433f 100644
--- a/extras/Projucer/Source/Project/UI/Sidebar/jucer_ModuleTreeItems.h
+++ b/extras/Projucer/Source/Project/UI/Sidebar/jucer_ModuleTreeItems.h
@@ -166,6 +166,9 @@ private:
for (Project::ExporterIterator exporter (project); exporter.next();)
{
+ if (exporter->isCLion())
+ continue;
+
auto key = modules.isJuceModule (moduleID) ? Ids::defaultJuceModulePath
: Ids::defaultUserModulePath;
diff --git a/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h b/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h
index b596fe0ce2..488ce30328 100644
--- a/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h
+++ b/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h
@@ -235,10 +235,16 @@ private:
class PropertyGroupComponent : public Component
{
public:
- PropertyGroupComponent (String name, Icon icon)
- : header (name, icon)
+ PropertyGroupComponent (String name, Icon icon, String desc = {})
+ : header (name, icon),
+ description (desc)
{
addAndMakeVisible (header);
+
+ description.setFont (Font (16.0f));
+ description.setColour (getLookAndFeel().findColour (defaultTextColourId));
+ description.setLineSpacing (5.0f);
+ description.setJustification (Justification::centredLeft);
}
void setProperties (const PropertyListBuilder& newProps)
@@ -264,9 +270,14 @@ public:
int updateSize (int x, int y, int width)
{
- header.setBounds (0, 0, width, 40);
+ header.setBounds (0, 0, width, headerSize);
+ auto height = header.getBottom() + 10;
+
+ descriptionLayout.createLayout (description, (float) (width - 40));
+ const auto descriptionHeight = (int) descriptionLayout.getHeight();
- auto height = header.getHeight() + 5;
+ if (descriptionHeight > 0)
+ height += (int) descriptionLayout.getHeight() + 25;
for (auto i = 0; i < properties.size(); ++i)
{
@@ -303,6 +314,12 @@ public:
{
g.setColour (findColour (secondaryBackgroundColourId));
g.fillRect (getLocalBounds());
+
+ auto textArea = getLocalBounds().toFloat()
+ .withTop ((float) headerSize)
+ .reduced (20.0f, 10.0f)
+ .withHeight (descriptionLayout.getHeight());
+ descriptionLayout.draw (g, textArea);
}
int getHeightMultiplier (PropertyComponent* pp)
@@ -330,9 +347,13 @@ public:
}
OwnedArray properties;
+
+private:
OwnedArray infoButtons;
ContentViewHeader header;
+ AttributedString description;
+ TextLayout descriptionLayout;
+ const int headerSize = 40;
-private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyGroupComponent)
};
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
index 0f39d85c49..63a854c1ad 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
@@ -37,6 +37,7 @@ public:
bool isCodeBlocks() const override { return false; }
bool isMakefile() const override { return false; }
bool isAndroidStudio() const override { return true; }
+ bool isCLion() const override { return false; }
bool isAndroid() const override { return true; }
bool isWindows() const override { return false; }
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h
new file mode 100644
index 0000000000..0e5f290271
--- /dev/null
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h
@@ -0,0 +1,974 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE library.
+ Copyright (c) 2017 - ROLI Ltd.
+
+ JUCE is an open source library subject to commercial or open-source
+ licensing.
+
+ By using JUCE, you agree to the terms of both the JUCE 5 End-User License
+ Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
+ 27th April 2017).
+
+ End User License Agreement: www.juce.com/juce-5-licence
+ Privacy Policy: www.juce.com/juce-5-privacy-policy
+
+ Or: You may also use this code under the terms of the GPL v3 (see
+ www.gnu.org/licenses).
+
+ JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
+ EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
+ DISCLAIMED.
+
+ ==============================================================================
+*/
+
+#include "jucer_ProjectExport_CodeBlocks.h"
+#include "jucer_ProjectExport_Make.h"
+#include "jucer_ProjectExport_Xcode.h"
+
+class CLionProjectExporter : public ProjectExporter
+{
+protected:
+ //==============================================================================
+ class CLionBuildConfiguration : public BuildConfiguration
+ {
+ public:
+ CLionBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e)
+ : BuildConfiguration (p, settings, e)
+ {
+ }
+
+ void createConfigProperties (PropertyListBuilder&) override {}
+ var getDefaultOptimisationLevel() const override { return {}; }
+ String getModuleLibraryArchName() const override { return {}; }
+ };
+
+ BuildConfiguration::Ptr createBuildConfig (const ValueTree& tree) const override
+ {
+ return new CLionBuildConfiguration (project, tree, *this);
+ }
+
+public:
+ //==============================================================================
+ static const char* getName() { return "CLion (beta)"; }
+ static const char* getValueTreeTypeName() { return "CLION"; }
+
+ static CLionProjectExporter* createForSettings (Project& project, const ValueTree& settings)
+ {
+ if (settings.hasType (getValueTreeTypeName()))
+ return new CLionProjectExporter (project, settings);
+
+ return nullptr;
+ }
+
+ static bool isExporterSupported (const ProjectExporter& exporter)
+ {
+ return exporter.isMakefile()
+ || (exporter.isXcode() && ! exporter.isiOS())
+ || (exporter.isCodeBlocks() && exporter.isWindows());
+ }
+
+ //==============================================================================
+ CLionProjectExporter (Project& p, const ValueTree& t) : ProjectExporter (p, t)
+ {
+ name = getName();
+
+ if (getTargetLocationString().isEmpty())
+ getTargetLocationValue() = getDefaultBuildsRootFolder() + "CLion";
+ }
+
+ //==============================================================================
+ bool canLaunchProject() override { return false; }
+ bool launchProject() override { return false; }
+ bool usesMMFiles() const override { return false; }
+ bool canCopeWithDuplicateFiles() override { return false; }
+ bool supportsUserDefinedConfigurations() const override { return false; }
+
+ bool isXcode() const override { return false; }
+ bool isVisualStudio() const override { return false; }
+ bool isCodeBlocks() const override { return false; }
+ bool isMakefile() const override { return false; }
+ bool isAndroidStudio() const override { return false; }
+ bool isCLion() const override { return true; }
+
+ bool isAndroid() const override { return false; }
+ bool isWindows() const override { return false; }
+ bool isLinux() const override { return false; }
+ bool isOSX() const override { return false; }
+ bool isiOS() const override { return false; }
+
+ bool supportsTargetType (ProjectType::Target::Type) const override { return true; }
+
+ void addPlatformSpecificSettingsForProjectType (const ProjectType&) override {}
+ void initialiseDependencyPathValues() override {}
+
+ String getDescription() override
+ {
+ String description;
+
+ description << "The " << getName() << " exporter produces a single CMakeLists.txt file with "
+ << "multiple platform dependant sections, where the configuration for each section "
+ << "is inherited from other exporters added to this project." << newLine
+ << newLine
+ << "The exporters which provide the CLion configuration for the corresponding platform are:" << newLine
+ << newLine;
+
+ for (auto& exporterName : getExporterNames())
+ {
+ ScopedPointer exporter = createNewExporter (getProject(), exporterName);
+
+ if (isExporterSupported (*exporter))
+ description << exporter->getName() << newLine;
+ }
+
+ description << newLine
+ << "Add these exporters to the project to enable CLion builds." << newLine
+ << newLine
+ << "Not all features of all the exporters are currently supported. Notable omissions are AUv3 "
+ << "plug-ins, embedding resources and fat binaries on MacOS, and adding application icons. On "
+ << "Windows CLion requires a GCC-based compiler like MinGW.";
+
+ return description;
+ }
+
+ void createExporterProperties (PropertyListBuilder& properties) override
+ {
+ for (Project::ExporterIterator exporter (getProject()); exporter.next();)
+ if (isExporterSupported (*exporter))
+ properties.add (new BooleanPropertyComponent (getExporterEnabledValue (*exporter),
+ "Import settings from exporter",
+ exporter->getName()),
+ "If this is enabled then settings from the corresponding exporter will "
+ "be used in the generated CMakeLists.txt");
+ }
+
+ void createDefaultConfigs() override {}
+
+ void create (const OwnedArray&) const override
+ {
+ MemoryOutputStream out;
+
+ out << "# Automatically generated CMakeLists, created by the Projucer" << newLine
+ << "# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine
+ << newLine;
+
+ out << "cmake_minimum_required (VERSION 3.4.1)" << newLine
+ << newLine;
+
+ out << "if (NOT CMAKE_BUILD_TYPE)" << newLine
+ << " set (CMAKE_BUILD_TYPE \"Debug\" CACHE STRING \"Choose the type of build.\" FORCE)" << newLine
+ << "endif (NOT CMAKE_BUILD_TYPE)" << newLine
+ << newLine;
+
+ // We'll append to this later.
+ overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("CMakeLists.txt"), out);
+ }
+
+ void writeCMakeListsExporterSection (ProjectExporter* exporter) const
+ {
+ if (! (isExporterSupported (*exporter) && isExporterEnabled (*exporter)))
+ return;
+
+ MemoryBlock existingContent;
+ getTargetFolder().getChildFile ("CMakeLists.txt").loadFileAsData (existingContent);
+ MemoryOutputStream out (existingContent, true);
+
+ out << "###############################################################################" << newLine
+ << "# " << exporter->getName() << newLine
+ << "###############################################################################" << newLine
+ << newLine;
+
+ if (auto* makefileExporter = dynamic_cast (exporter))
+ {
+ out << "if (UNIX AND NOT APPLE)" << newLine << newLine;
+ writeCMakeListsMakefileSection (out, *makefileExporter);
+ }
+ else if (auto* xcodeExporter = dynamic_cast (exporter))
+ {
+ out << "if (APPLE)" << newLine << newLine;
+ writeCMakeListsXcodeSection (out, *xcodeExporter);
+ }
+ else if (auto* codeBlocksExporter = dynamic_cast (exporter))
+ {
+ out << "if (WIN32)" << newLine << newLine;
+ writeCMakeListsCodeBlocksSection (out, *codeBlocksExporter);
+ }
+
+ out << "endif()" << newLine << newLine;
+
+ overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("CMakeLists.txt"), out);
+ }
+
+private:
+ //==============================================================================
+ Identifier getExporterEnabledId (const ProjectExporter& exporter) const
+ {
+ jassert (isExporterSupported (exporter));
+
+ if (exporter.isMakefile()) return Ids::clionMakefileEnabled;
+ else if (exporter.isXcode()) return Ids::clionXcodeEnabled;
+ else if (exporter.isCodeBlocks()) return Ids::clionCodeBlocksEnabled;
+
+ jassertfalse;
+ return {};
+ }
+
+ bool isExporterEnabled (const ProjectExporter& exporter) const
+ {
+ auto setting = settings[getExporterEnabledId (exporter)];
+ return setting.isVoid() || setting;
+ }
+
+ Value getExporterEnabledValue (const ProjectExporter& exporter)
+ {
+ auto enabledID = getExporterEnabledId (exporter);
+ getSetting (enabledID) = isExporterEnabled (exporter);
+ return getSetting (enabledID);
+ }
+
+ //==============================================================================
+ static String setCMakeVariable (const String& variableName, const String& value)
+ {
+ return String ("set (") + variableName + " \"" + value + "\")";
+ }
+
+ static String addToCMakeVariable (const String& variableName, const String& value)
+ {
+ return setCMakeVariable (variableName, "${" + variableName + "} " + value);
+ }
+
+ static String getTargetVarName (ProjectType::Target& target)
+ {
+ return String (target.getName()).toUpperCase().replaceCharacter (L' ', L'_');
+ }
+
+ template
+ void getFileInfoList (Target& target, Exporter& exporter, const Project::Item& projectItem, std::vector>& fileInfoList) const
+ {
+ const auto targetType = (getProject().getProjectType().isAudioPlugin() ? target.type : Target::Type::SharedCodeTarget);
+
+ if (projectItem.isGroup())
+ {
+ for (int i = 0; i < projectItem.getNumChildren(); ++i)
+ getFileInfoList (target, exporter, projectItem.getChild(i), fileInfoList);
+ }
+ else if (projectItem.shouldBeAddedToTargetProject() && getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType )
+ {
+ const auto path = RelativePath (projectItem.getFile(), exporter.getTargetFolder(), RelativePath::buildTargetFolder).toUnixStyle();
+ fileInfoList.push_back ({ path, projectItem.shouldBeCompiled() });
+ }
+ }
+
+ template
+ void writeCMakeTargets (OutputStream& out, Exporter& exporter) const
+ {
+ for (auto* target : exporter.targets)
+ {
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::macOSAppex
+ || target->type == ProjectType::Target::Type::AggregateTarget
+ || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn)
+ continue;
+
+ String functionName;
+ StringArray properties;
+
+ switch (target->getTargetFileType())
+ {
+ case ProjectType::Target::TargetFileType::executable:
+ functionName = "add_executable";
+ break;
+ case ProjectType::Target::TargetFileType::staticLibrary:
+ case ProjectType::Target::TargetFileType::sharedLibraryOrDLL:
+ case ProjectType::Target::TargetFileType::pluginBundle:
+ functionName = "add_library";
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::staticLibrary)
+ properties.add ("STATIC");
+ else if (target->getTargetFileType() == ProjectType::Target::TargetFileType::sharedLibraryOrDLL)
+ properties.add ("SHARED");
+ else
+ properties.add ("MODULE");
+
+ break;
+ default:
+ continue;
+ }
+
+ out << functionName << " (" << getTargetVarName (*target);
+
+ if (! properties.isEmpty())
+ out << " " << properties.joinIntoString (" ");
+
+ out << newLine;
+
+ std::vector> fileInfoList;
+ for (auto& group : exporter.getAllGroups())
+ getFileInfoList (*target, exporter, group, fileInfoList);
+
+ for (auto& fileInfo : fileInfoList)
+ out << " " << fileInfo.first.quoted() << newLine;
+
+ out << ")" << newLine << newLine;
+
+ for (auto& fileInfo : fileInfoList)
+ if (! fileInfo.second)
+ out << "set_source_files_properties (" << fileInfo.first.quoted() << " PROPERTIES HEADER_FILE_ONLY TRUE)" << newLine;
+
+ out << newLine;
+ }
+ }
+
+ //==============================================================================
+ void writeCMakeListsMakefileSection (OutputStream& out, MakefileProjectExporter& exporter) const
+ {
+ out << "project (" << getProject().getTitle() << " C CXX)" << newLine
+ << newLine;
+
+ out << "find_package (PkgConfig REQUIRED)" << newLine;
+
+ StringArray cmakePkgconfigPackages;
+
+ for (auto& package : exporter.getPackages())
+ {
+ cmakePkgconfigPackages.add (package.toUpperCase());
+ out << "pkg_search_module (" << cmakePkgconfigPackages.strings.getLast() << " REQUIRED " << package << ")" << newLine;
+ }
+
+ out << newLine;
+
+ writeCMakeTargets (out, exporter);
+
+ for (auto* target : exporter.targets)
+ {
+ if (target->type == ProjectType::Target::Type::AggregateTarget)
+ continue;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle)
+ out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES PREFIX \"\")" << newLine;
+
+ out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX \"" << target->getTargetFileSuffix() << "\")" << newLine
+ << newLine;
+ }
+
+ for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
+ {
+ auto& config = dynamic_cast (*c);
+
+ out << "#------------------------------------------------------------------------------" << newLine
+ << "# Config: " << config.getName() << newLine
+ << "#------------------------------------------------------------------------------" << newLine
+ << newLine;
+
+ const auto buildTypeCondition = String ("CMAKE_BUILD_TYPE STREQUAL " + config.getName());
+ out << "if (" << buildTypeCondition << ")" << newLine
+ << newLine;
+
+ out << "include_directories (" << newLine;
+
+ for (auto& path : exporter.getHeaderSearchPaths (config))
+ out << " " << path.quoted() << newLine;
+
+ for (auto& package : cmakePkgconfigPackages)
+ out << " ${" << package << "_INCLUDE_DIRS}" << newLine;
+
+ out << ")" << newLine << newLine;
+
+ StringArray cmakeFoundLibraries;
+
+ for (auto& library : exporter.getLibraryNames (config))
+ {
+ const String cmakeLibraryID (library.toUpperCase());
+ cmakeFoundLibraries.add (String ("${") + cmakeLibraryID + "}");
+ out << "find_library (" << cmakeLibraryID << " " << library << newLine;
+
+ for (auto& path : exporter.getLibrarySearchPaths (config))
+ out << " " << path.quoted() << newLine;
+
+ out << ")" << newLine
+ << newLine;
+ }
+
+ for (auto* target : exporter.targets)
+ {
+ if (target->type == ProjectType::Target::Type::AggregateTarget)
+ continue;
+
+ const auto targetVarName = getTargetVarName (*target);
+
+ out << "set_target_properties (" << targetVarName << " PROPERTIES" << newLine
+ << " OUTPUT_NAME " << config.getTargetBinaryNameString().quoted() << newLine
+ << ")" << newLine << newLine;
+
+ auto defines = exporter.getDefines (config);
+ defines.addArray (target->getDefines (config));
+
+ out << "target_compile_definitions (" << targetVarName << " PRIVATE" << newLine;
+
+ for (auto& key : defines.getAllKeys())
+ out << " " << key << "=" << defines[key] << newLine;
+
+ out << ")" << newLine << newLine;
+
+ auto targetFlags = target->getCompilerFlags();
+
+ if (! targetFlags.isEmpty())
+ {
+ out << "target_compile_options (" << targetVarName << " PRIVATE" << newLine;
+
+ for (auto& flag : targetFlags)
+ out << " " << flag << newLine;
+
+ out << ")" << newLine << newLine;
+ }
+
+ out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle
+ || target->type == ProjectType::Target::Type::StandalonePlugIn)
+ out << " SHARED_CODE" << newLine;
+
+ out << " " << exporter.getArchFlags (config) << newLine;
+
+ for (auto& flag : target->getLinkerFlags())
+ out << " " << flag << newLine;
+
+ for (auto& flag : exporter.getLinkerFlags (config))
+ out << " " << flag << newLine;
+
+ for (auto& lib : cmakeFoundLibraries)
+ out << " " << lib << newLine;
+
+ for (auto& package : cmakePkgconfigPackages)
+ out << " ${" << package << "_LIBRARIES}" << newLine;
+
+ out << ")" << newLine << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle
+ || target->type == ProjectType::Target::Type::StandalonePlugIn)
+ out << "add_dependencies (" << targetVarName << " " << "SHARED_CODE)" << newLine << newLine;
+ }
+
+ StringArray cFlags;
+ cFlags.add (exporter.getArchFlags (config));
+ cFlags.addArray (exporter.getCPreprocessorFlags (config));
+ cFlags.addArray (exporter.getCFlags (config));
+
+ out << addToCMakeVariable ("CMAKE_C_FLAGS", cFlags.joinIntoString (" ")) << newLine
+ << addToCMakeVariable ("CMAKE_CXX_FLAGS", "${CMAKE_C_FLAGS} " + exporter.getCXXFlags().joinIntoString (" ")) << newLine
+ << newLine;
+
+ out << "endif (" << buildTypeCondition << ")" << newLine
+ << newLine;
+ }
+ }
+
+ //==============================================================================
+ void writeCMakeListsCodeBlocksSection (OutputStream& out, CodeBlocksProjectExporter& exporter) const
+ {
+ out << "project (" << getProject().getTitle() << " C CXX)" << newLine
+ << newLine;
+
+ writeCMakeTargets (out, exporter);
+
+ for (auto* target : exporter.targets)
+ {
+ if (target->type == ProjectType::Target::Type::AggregateTarget)
+ continue;
+
+ out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES PREFIX \"\")" << newLine
+ << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX " << target->getTargetSuffix().quoted() << ")" << newLine
+ << newLine;
+ }
+
+ for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
+ {
+ auto& config = dynamic_cast (*c);
+
+ out << "#------------------------------------------------------------------------------" << newLine
+ << "# Config: " << config.getName() << newLine
+ << "#------------------------------------------------------------------------------" << newLine
+ << newLine;
+
+ const auto buildTypeCondition = String ("CMAKE_BUILD_TYPE STREQUAL " + config.getName());
+ out << "if (" << buildTypeCondition << ")" << newLine
+ << newLine;
+
+ out << "include_directories (" << newLine;
+
+ for (auto& path : exporter.getIncludePaths (config))
+ out << " " << path.quoted() << newLine;
+
+ out << ")" << newLine << newLine;
+
+ for (auto* target : exporter.targets)
+ {
+ if (target->type == ProjectType::Target::Type::AggregateTarget)
+ continue;
+
+ const auto targetVarName = getTargetVarName (*target);
+
+ out << "set_target_properties (" << targetVarName << " PROPERTIES" << newLine
+ << " OUTPUT_NAME " << config.getTargetBinaryNameString().quoted() << newLine
+ << ")" << newLine << newLine;
+
+ out << "target_compile_definitions (" << targetVarName << " PRIVATE" << newLine;
+
+ for (auto& def : exporter.getDefines (config, *target))
+ out << " " << def << newLine;
+
+ out << ")" << newLine << newLine;
+
+ out << "target_compile_options (" << targetVarName << " PRIVATE" << newLine;
+
+ for (auto& option : exporter.getCompilerFlags (config, *target))
+ out << " " << option.quoted() << newLine;
+
+ out << ")" << newLine << newLine;
+
+ out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle
+ || target->type == ProjectType::Target::Type::StandalonePlugIn)
+ out << " SHARED_CODE" << newLine
+ << " -L." << newLine;
+
+ for (auto& flag : exporter.getLinkerFlags (config, *target))
+ out << " " << flag << newLine;
+
+ for (auto& flag : exporter.getProjectLinkerLibs())
+ out << " -l" << flag << newLine;
+
+ for (auto& lib : exporter.mingwLibs)
+ out << " -l" << lib << newLine;
+
+ out << ")" << newLine << newLine;
+ }
+
+ out << addToCMakeVariable ("CMAKE_CXX_FLAGS", exporter.getProjectCompilerOptions().joinIntoString (" ")) << newLine
+ << addToCMakeVariable ("CMAKE_C_FLAGS", "${CMAKE_CXX_FLAGS}") << newLine
+ << newLine;
+
+ out << "endif (" << buildTypeCondition << ")" << newLine
+ << newLine;
+ }
+ }
+
+ //==============================================================================
+ void writeCMakeListsXcodeSection (OutputStream& out, XcodeProjectExporter& exporter) const
+ {
+ // We need to dind out the SDK root before defining the project. Unfortunately this is
+ // set per-target in the Xcode project, but we want it per-configuration.
+ for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
+ {
+ auto& config = dynamic_cast (*c);
+
+ for (auto* target : exporter.targets)
+ {
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::macOSAppex
+ || target->type == ProjectType::Target::Type::AggregateTarget
+ || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn)
+ continue;
+
+ const auto targetAttributes = target->getTargetSettings (config);
+ const auto targetAttributeKeys = targetAttributes.getAllKeys();
+
+ if (targetAttributes.getAllKeys().contains ("SDKROOT"))
+ {
+ out << "if (CMAKE_BUILD_TYPE STREQUAL " + config.getName() << ")" << newLine
+ << " set (CMAKE_OSX_SYSROOT " << targetAttributes["SDKROOT"] << ")" << newLine
+ << "endif()" << newLine << newLine;
+ break;
+ }
+ }
+ }
+
+ out << "project (" << getProject().getTitle() << " C CXX)" << newLine << newLine;
+
+ writeCMakeTargets (out, exporter);
+
+ for (auto* target : exporter.targets)
+ {
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::macOSAppex
+ || target->type == ProjectType::Target::Type::AggregateTarget
+ || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn)
+ continue;
+
+ if (target->type == ProjectType::Target::Type::AudioUnitPlugIn)
+ out << "find_program (RC_COMPILER Rez NO_DEFAULT_PATHS PATHS /Applications/Xcode.app/Contents/Developer/usr/bin)" << newLine
+ << "if (NOT RC_COMPILER)" << newLine
+ << " message (WARNING \"failed to find Rez; older resource-based AU plug-ins may not work correctly\")" << newLine
+ << "endif (NOT RC_COMPILER)" << newLine << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::staticLibrary
+ || target->getTargetFileType() == ProjectType::Target::TargetFileType::sharedLibraryOrDLL)
+ out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX \"" << target->xcodeBundleExtension << "\")" << newLine
+ << newLine;
+ }
+
+ for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
+ {
+ auto& config = dynamic_cast (*c);
+
+ out << "#------------------------------------------------------------------------------" << newLine
+ << "# Config: " << config.getName() << newLine
+ << "#------------------------------------------------------------------------------" << newLine
+ << newLine;
+
+ const auto buildTypeCondition = String ("CMAKE_BUILD_TYPE STREQUAL " + config.getName());
+ out << "if (" << buildTypeCondition << ")" << newLine
+ << newLine;
+
+ const auto configSettings = exporter.getProjectSettings (config);
+ auto configSettingsKeys = configSettings.getAllKeys();
+
+ auto binaryName = config.getTargetBinaryNameString();
+
+ if (configSettingsKeys.contains ("PRODUCT_NAME"))
+ binaryName = configSettings["PRODUCT_NAME"].unquoted();
+
+ for (auto* target : exporter.targets)
+ {
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::macOSAppex
+ || target->type == ProjectType::Target::Type::AggregateTarget
+ || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn)
+ continue;
+
+ const auto targetVarName = getTargetVarName (*target);
+
+ auto targetAttributes = target->getTargetSettings (config);
+ auto targetAttributeKeys = targetAttributes.getAllKeys();
+
+ StringArray libSearchPaths;
+
+ if (targetAttributeKeys.contains ("LIBRARY_SEARCH_PATHS"))
+ {
+ auto paths = targetAttributes["LIBRARY_SEARCH_PATHS"].trim().substring (1).dropLastCharacters (1);
+ paths = paths.replace ("\"$(inherited)\"", {});
+ paths = paths.replace ("$(HOME)", "$ENV{HOME}");
+ libSearchPaths.addTokens (paths, ",\"\t\\", {});
+ libSearchPaths.removeEmptyStrings();
+ targetAttributeKeys.removeString ("LIBRARY_SEARCH_PATHS");
+ }
+
+ StringArray headerSearchPaths;
+
+ if (targetAttributeKeys.contains ("HEADER_SEARCH_PATHS"))
+ {
+ auto paths = targetAttributes["HEADER_SEARCH_PATHS"].trim().substring (1).dropLastCharacters (1);
+ paths = paths.replace ("\"$(inherited)\"", {});
+ paths = paths.replace ("$(HOME)", "$ENV{HOME}");
+ headerSearchPaths.addTokens (paths, ",\"\t\\", {});
+ headerSearchPaths.removeEmptyStrings();
+ targetAttributeKeys.removeString ("HEADER_SEARCH_PATHS");
+ }
+
+ out << "target_include_directories (" << targetVarName << " PRIVATE" << newLine;
+
+ for (auto& path : headerSearchPaths)
+ out << " " << path.quoted() << newLine;
+
+ out << ")" << newLine << newLine;
+
+ StringArray defines;
+
+ if (targetAttributeKeys.contains ("GCC_PREPROCESSOR_DEFINITIONS"))
+ {
+ defines.addTokens (targetAttributes["GCC_PREPROCESSOR_DEFINITIONS"], "() ,\t", {});
+ defines.removeEmptyStrings();
+ targetAttributeKeys.removeString ("GCC_PREPROCESSOR_DEFINITIONS");
+ }
+
+ out << "target_compile_definitions (" << targetVarName << " PRIVATE" << newLine;
+
+ for (auto& def : defines)
+ out << " " << def << newLine;
+
+ out << ")" << newLine << newLine;
+
+ StringArray cppFlags;
+
+ // Fat binaries are not supported.
+ if (targetAttributeKeys.contains ("ARCHS"))
+ {
+ auto value = targetAttributes["ARCHS"].unquoted();
+
+ if (value.contains ("NATIVE_ARCH_ACTUAL"))
+ cppFlags.add ("-march=native");
+ else if (value.contains ("ARCHS_STANDARD_32_BIT"))
+ cppFlags.add ("-arch x86");
+ else if (value.contains ("ARCHS_STANDARD_32_64_BIT")
+ || value.contains ("ARCHS_STANDARD_64_BIT"))
+ cppFlags.add ("-arch x86_64");
+
+ targetAttributeKeys.removeString ("ARCHS");
+ }
+
+ if (targetAttributeKeys.contains ("MACOSX_DEPLOYMENT_TARGET"))
+ {
+ cppFlags.add ("-mmacosx-version-min=" + targetAttributes["MACOSX_DEPLOYMENT_TARGET"]);
+ targetAttributeKeys.removeString ("MACOSX_DEPLOYMENT_TARGET");
+ }
+
+ if (targetAttributeKeys.contains ("OTHER_CPLUSPLUSFLAGS"))
+ {
+ cppFlags.add (targetAttributes["OTHER_CPLUSPLUSFLAGS"].unquoted());
+ targetAttributeKeys.removeString ("OTHER_CPLUSPLUSFLAGS");
+ }
+
+ if (targetAttributeKeys.contains ("GCC_OPTIMIZATION_LEVEL"))
+ {
+ cppFlags.add ("-O" + targetAttributes["GCC_OPTIMIZATION_LEVEL"]);
+ targetAttributeKeys.removeString ("GCC_OPTIMIZATION_LEVEL");
+ }
+
+ if (targetAttributeKeys.contains ("LLVM_LTO"))
+ {
+ cppFlags.add ("-flto");
+ targetAttributeKeys.removeString ("LLVM_LTO");
+ }
+
+ if (targetAttributeKeys.contains ("GCC_FAST_MATH"))
+ {
+ cppFlags.add ("-ffast-math");
+ targetAttributeKeys.removeString ("GCC_FAST_MATH");
+ }
+
+ if (targetAttributeKeys.contains ("CLANG_CXX_LANGUAGE_STANDARD"))
+ {
+ cppFlags.add ("-std=" + targetAttributes["CLANG_CXX_LANGUAGE_STANDARD"].unquoted());
+ targetAttributeKeys.removeString ("CLANG_CXX_LANGUAGE_STANDARD");
+ }
+
+ if (targetAttributeKeys.contains ("CLANG_CXX_LIBRARY"))
+ {
+ cppFlags.add ("-stdlib=" + targetAttributes["CLANG_CXX_LIBRARY"].unquoted());
+ targetAttributeKeys.removeString ("CLANG_CXX_LIBRARY");
+ }
+
+ out << "target_compile_options (" << targetVarName << " PRIVATE" << newLine;
+
+ for (auto& flag : cppFlags)
+ out << " " << flag << newLine;
+
+ out << ")" << newLine << newLine;
+
+ String linkerFlags;
+
+ if (targetAttributeKeys.contains ("OTHER_LDFLAGS"))
+ {
+ // CMake adds its own SHARED_CODE library linking flags
+ linkerFlags = targetAttributes["OTHER_LDFLAGS"]
+ .unquoted()
+ .replace ("-bundle", {})
+ .replace ("-l" + binaryName, {})
+ .trim();
+ targetAttributeKeys.removeString ("OTHER_LDFLAGS");
+ }
+
+ if (target->type == ProjectType::Target::Type::AudioUnitPlugIn)
+ {
+ String rezFlags;
+
+ if (targetAttributeKeys.contains ("OTHER_REZFLAGS"))
+ {
+ rezFlags = targetAttributes["OTHER_REZFLAGS"];
+ targetAttributeKeys.removeString ("OTHER_REZFLAGS");
+ }
+
+ for (auto& item : exporter.getAllGroups())
+ {
+ if (item.getName() == "Juce Library Code")
+ {
+ String resSourcesVar (targetVarName + "_REZ_SOURCES");
+ String resOutputVar (targetVarName + "_REZ_OUTPUT");
+
+ out << "if (RC_COMPILER)" << newLine
+ << " set (" << resSourcesVar << newLine
+ << " \"" << item.determineGroupFolder().getFullPathName() + "/include_juce_audio_plugin_client_AU.r\"" << newLine
+ << " )" << newLine
+ << " set (" << resOutputVar << " \"${CMAKE_CURRENT_BINARY_DIR}/" << binaryName << ".rsrc\")" << newLine
+ << " target_sources (" << targetVarName << " PRIVATE" << newLine
+ << " ${" << resSourcesVar << "}" << newLine
+ << " ${" << resOutputVar << "}" << newLine
+ << " )" << newLine
+ << " execute_process (COMMAND" << newLine
+ << " ${RC_COMPILER}" << newLine
+ << " " << rezFlags.unquoted().removeCharacters ("\\") << newLine;
+
+ for (auto& path : headerSearchPaths)
+ out << " -I \"${PROJECT_SOURCE_DIR}/" << path.unquoted() << "\"" << newLine;
+
+ out << " ${" << resSourcesVar << "}" << newLine
+ << " -o ${" << resOutputVar << "}" << newLine
+ << " )" << newLine
+ << " set_source_files_properties (${" << resOutputVar << "} PROPERTIES" << newLine
+ << " GENERATED TRUE" << newLine
+ << " MACOSX_PACKAGE_LOCATION Resources" << newLine
+ << " )" << newLine
+ << "endif (RC_COMPILER)" << newLine << newLine;
+ break;
+ }
+ }
+ }
+
+ if (targetAttributeKeys.contains ("INFOPLIST_FILE"))
+ {
+ auto plistFile = exporter.getTargetFolder().getChildFile (targetAttributes["INFOPLIST_FILE"]);
+ XmlDocument infoPlistData (plistFile);
+ ScopedPointer plist = infoPlistData.getDocumentElement();
+
+ if (plist != nullptr)
+ {
+ if (auto* dict = plist->getChildByName ("dict"))
+ {
+ if (auto* entry = dict->getChildByName ("key"))
+ {
+ while (entry != nullptr)
+ {
+ if (entry->getAllSubText() == "CFBundleExecutable")
+ {
+ if (auto* bundleName = entry->getNextElementWithTagName ("string"))
+ {
+ bundleName->deleteAllTextElements();
+ bundleName->addTextElement (binaryName);
+ }
+ }
+
+ entry = entry->getNextElementWithTagName ("key");
+ }
+ }
+ }
+
+ File updatedPlist (getTargetFolder().getChildFile (config.getName() + "-" + plistFile.getFileName()));
+ plist->writeToFile (updatedPlist, "");
+ targetAttributes.set ("INFOPLIST_FILE", updatedPlist.getFullPathName().quoted());
+ }
+ else
+ {
+ targetAttributeKeys.removeString ("INFOPLIST_FILE");
+ }
+ }
+
+ targetAttributeKeys.sort (false);
+
+ out << "set_target_properties (" << targetVarName << " PROPERTIES" << newLine
+ << " OUTPUT_NAME " << binaryName.quoted() << newLine;
+
+ for (auto& key : targetAttributeKeys)
+ out << " XCODE_ATTRIBUTE_" << key << " " << targetAttributes[key] << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::executable
+ || target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle)
+ {
+ out << " MACOSX_BUNDLE_INFO_PLIST " << targetAttributes.getValue ("INFOPLIST_FILE", "\"\"") << newLine
+ << " XCODE_ATTRIBUTE_PRODUCT_NAME " << binaryName.quoted() << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::executable)
+ {
+ out << " MACOSX_BUNDLE TRUE" << newLine;
+ }
+ else
+ {
+ out << " BUNDLE TRUE" << newLine
+ << " BUNDLE_EXTENSION " << targetAttributes.getValue ("WRAPPER_EXTENSION", "\"\"") << newLine
+ << " XCODE_ATTRIBUTE_MACH_O_TYPE \"mh_bundle\"" << newLine;
+ }
+ }
+
+ out << ")" << newLine << newLine;
+
+ out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle
+ || target->type == ProjectType::Target::Type::StandalonePlugIn)
+ out << " SHARED_CODE" << newLine;
+
+ for (auto& path : libSearchPaths)
+ out << " -L" << path.quoted() << newLine;
+
+ if (linkerFlags.isNotEmpty())
+ out << " " << linkerFlags << newLine;
+
+ for (auto& framework : target->frameworkNames)
+ out << " \"-framework " << framework << "\"" << newLine;
+
+ out << ")" << newLine << newLine;
+
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle
+ || target->type == ProjectType::Target::Type::StandalonePlugIn)
+ {
+ if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle
+ && targetAttributeKeys.contains("INSTALL_PATH"))
+ {
+ const auto installPath = targetAttributes["INSTALL_PATH"].unquoted();
+ const auto productFilename = binaryName + (targetAttributeKeys.contains ("WRAPPER_EXTENSION") ? "." + targetAttributes["WRAPPER_EXTENSION"] : String());
+ auto productPath = (installPath + productFilename).quoted();
+ out << "add_custom_command (TARGET " << targetVarName << " POST_BUILD" << newLine
+ << " COMMAND cmake -E remove_directory " << productPath << newLine
+ << " COMMAND cmake -E copy_directory \"${CMAKE_BINARY_DIR}/" << productFilename << "\" " << productPath << newLine
+ << " COMMENT \"Copying \\\"" << productFilename << "\\\" to \\\"" << installPath.unquoted() << "\\\"\"" << newLine
+ << ")" << newLine << newLine;
+ }
+ }
+ }
+
+ std::map basicWarnings
+ {
+ { "CLANG_WARN_BOOL_CONVERSION", "bool-conversion" },
+ { "CLANG_WARN_COMMA", "comma" },
+ { "CLANG_WARN_CONSTANT_CONVERSION", "constant-conversion" },
+ { "CLANG_WARN_EMPTY_BODY", "empty-body" },
+ { "CLANG_WARN_ENUM_CONVERSION", "enum-conversion" },
+ { "CLANG_WARN_INFINITE_RECURSION", "infinite-recursion" },
+ { "CLANG_WARN_INT_CONVERSION", "int-conversion" },
+ { "CLANG_WARN_RANGE_LOOP_ANALYSIS", "range-loop-analysis" },
+ { "CLANG_WARN_STRICT_PROTOTYPES", "strict-prototypes" },
+ { "GCC_WARN_CHECK_SWITCH_STATEMENTS", "switch" },
+ { "GCC_WARN_UNUSED_VARIABLE", "unused-variable" },
+ { "GCC_WARN_MISSING_PARENTHESES", "parentheses" },
+ { "GCC_WARN_NON_VIRTUAL_DESTRUCTOR", "non-virtual-dtor" },
+ { "GCC_WARN_64_TO_32_BIT_CONVERSION", "shorten-64-to-32" },
+ { "GCC_WARN_UNDECLARED_SELECTOR", "undeclared-selector" },
+ { "GCC_WARN_UNUSED_FUNCTION", "unused-function" }
+ };
+
+ StringArray compilerFlags;
+
+ for (auto& key : configSettingsKeys)
+ {
+ auto basicWarning = basicWarnings.find (key);
+
+ if (basicWarning != basicWarnings.end())
+ {
+ compilerFlags.add (configSettings[key] == "YES" ? "-W" + basicWarning->second : "-Wno-" + basicWarning->second);
+ }
+ else if (key == "CLANG_WARN_SUSPICIOUS_MOVE" && configSettings[key] == "YES") compilerFlags.add ("-Wmove");
+ else if (key == "CLANG_WARN_UNREACHABLE_CODE" && configSettings[key] == "YES") compilerFlags.add ("-Wunreachable-code");
+ else if (key == "CLANG_WARN__DUPLICATE_METHOD_MATCH" && configSettings[key] == "YES") compilerFlags.add ("-Wduplicate-method-match");
+ else if (key == "GCC_INLINES_ARE_PRIVATE_EXTERN" && configSettings[key] == "YES") compilerFlags.add ("-fvisibility-inlines-hidden");
+ else if (key == "GCC_NO_COMMON_BLOCKS" && configSettings[key] == "YES") compilerFlags.add ("-fno-common");
+ else if (key == "GCC_WARN_ABOUT_RETURN_TYPE" && configSettings[key] != "YES") compilerFlags.add (configSettings[key] == "YES_ERROR" ? "-Werror=return-type" : "-Wno-return-type");
+ else if (key == "GCC_WARN_TYPECHECK_CALLS_TO_PRINTF" && configSettings[key] != "YES") compilerFlags.add ("-Wno-format");
+ else if (key == "GCC_WARN_UNINITIALIZED_AUTOS")
+ {
+ if (configSettings[key] == "YES") compilerFlags.add ("-Wuninitialized");
+ else if (configSettings[key] == "YES_AGGRESSIVE") compilerFlags.add ("--Wconditional-uninitialized");
+ else compilerFlags.add (")-Wno-uninitialized");
+ }
+ else if (key == "WARNING_CFLAGS") compilerFlags.add (configSettings[key]);
+ }
+
+ out << addToCMakeVariable ("CMAKE_CXX_FLAGS", compilerFlags.joinIntoString (" ")) << newLine
+ << addToCMakeVariable ("CMAKE_C_FLAGS", "${CMAKE_CXX_FLAGS}") << newLine
+ << newLine;
+
+ out << "endif (" << buildTypeCondition << ")" << newLine
+ << newLine;
+ }
+ }
+
+ //==============================================================================
+ JUCE_DECLARE_NON_COPYABLE (CLionProjectExporter)
+};
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h
index 7ab7e693c7..ef8b9386be 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h
@@ -109,6 +109,7 @@ public:
bool isCodeBlocks() const override { return true; }
bool isMakefile() const override { return false; }
bool isAndroidStudio() const override { return false; }
+ bool isCLion() const override { return false; }
bool isAndroid() const override { return false; }
bool isWindows() const override { return os == windowsTarget; }
@@ -183,7 +184,7 @@ public:
void initialiseDependencyPathValues() override
{
DependencyPathOS pathOS = isLinux() ? TargetOS::linux
- : TargetOS::windows;
+ : TargetOS::windows;
vst3Path.referTo (Value (new DependencyPathValueSource (getSetting (Ids::vst3Folder), Ids::vst3Path, pathOS)));
@@ -212,6 +213,7 @@ private:
: Ids::linuxCodeBlocksArchitecture;
return getValue (archID);
}
+
var getArchitectureTypeVar() const
{
const auto archID = exporter.isWindows() ? Ids::windowsCodeBlocksArchitecture
@@ -259,8 +261,9 @@ private:
class CodeBlocksTarget : public ProjectType::Target
{
public:
- CodeBlocksTarget (CodeBlocksProjectExporter&, ProjectType::Target::Type typeToUse)
- : ProjectType::Target (typeToUse)
+ CodeBlocksTarget (const CodeBlocksProjectExporter& e, ProjectType::Target::Type typeToUse)
+ : ProjectType::Target (typeToUse),
+ exporter (e)
{}
String getTargetNameForConfiguration (const BuildConfiguration& config) const
@@ -275,24 +278,39 @@ private:
{
auto fileType = getTargetFileType();
- switch (fileType)
+ if (exporter.isWindows())
{
- case executable: return {};
- case staticLibrary: return ".a";
- case sharedLibraryOrDLL: return ".so";
-
- case pluginBundle:
- switch (type)
- {
- case VST3PlugIn: return ".vst3";
- case VSTPlugIn: return ".so";
- default: break;
- }
-
- return ".so";
-
- default:
- break;
+ switch (fileType)
+ {
+ case executable: return ".exe";
+ case staticLibrary: return ".lib";
+ case sharedLibraryOrDLL:
+ case pluginBundle: return ".dll";
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (fileType)
+ {
+ case executable: return {};
+ case staticLibrary: return ".a";
+ case sharedLibraryOrDLL: return ".so";
+
+ case pluginBundle:
+ switch (type)
+ {
+ case VST3PlugIn: return ".vst3";
+ case VSTPlugIn: return ".so";
+ default: break;
+ }
+
+ return ".so";
+
+ default:
+ break;
+ }
}
return {};
@@ -303,6 +321,8 @@ private:
return (type == DynamicLibrary || type == VST3PlugIn
|| type == VSTPlugIn || type == AAXPlugIn);
}
+
+ const CodeBlocksProjectExporter& exporter;
};
//==============================================================================
@@ -402,20 +422,6 @@ private:
flags.addTokens (replacePreprocessorTokens (config, getExtraCompilerFlagsString()).trim(),
" \n", "\"'");
- {
- const StringArray defines (getDefines (config, target));
-
- for (int i = 0; i < defines.size(); ++i)
- {
- String def (defines[i]);
-
- if (! def.containsChar ('='))
- def << '=';
-
- flags.add ("-D" + def);
- }
- }
-
if (config.exporter.isLinux())
{
if (target.isDynamicLibrary() || getProject().getProjectType().isAudioPlugin())
@@ -453,9 +459,6 @@ private:
flags.addTokens (replacePreprocessorTokens (config, getExtraLinkerFlagsString()).trim(),
" \n", "\"'");
- if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget)
- flags.add ("-l" + config.getTargetBinaryNameString());
-
const auto packages = getPackages();
if (config.exporter.isLinux() && packages.size() > 0)
@@ -538,9 +541,12 @@ private:
{
const String outputPath = getOutputPathForTarget (getTargetWithType (ProjectType::Target::SharedCodeTarget), config);
RelativePath path (outputPath, RelativePath::buildTargetFolder);
+ auto filename = path.getFileName();
- const String autoPrefixedFilename = "lib" + path.getFileName();
- return path.getParentDirectory().getChildFile (autoPrefixedFilename).toUnixStyle();
+ if (isLinux())
+ filename = "lib" + filename;
+
+ return path.getParentDirectory().getChildFile (filename).toUnixStyle();
}
void createBuildTarget (XmlElement& xml, CodeBlocksTarget& target, const BuildConfiguration& config) const
@@ -552,10 +558,18 @@ private:
output->setAttribute ("output", getOutputPathForTarget (target, config));
- const bool keepPrefix = (target.type == ProjectType::Target::VSTPlugIn || target.type == ProjectType::Target::VST3PlugIn
- || target.type == ProjectType::Target::AAXPlugIn || target.type == ProjectType::Target::RTASPlugIn);
+ if (isLinux())
+ {
+ const bool keepPrefix = (target.type == ProjectType::Target::VSTPlugIn || target.type == ProjectType::Target::VST3PlugIn
+ || target.type == ProjectType::Target::AAXPlugIn || target.type == ProjectType::Target::RTASPlugIn);
+
+ output->setAttribute ("prefix_auto", keepPrefix ? 0 : 1);
+ }
+ else
+ {
+ output->setAttribute ("prefix_auto", 0);
+ }
- output->setAttribute ("prefix_auto", keepPrefix ? 0 : 1);
output->setAttribute ("extension_auto", 0);
}
@@ -572,9 +586,19 @@ private:
XmlElement* const compiler = xml.createNewChildElement ("Compiler");
{
- const StringArray compilerFlags (getCompilerFlags (config, target));
+ StringArray flags;
+
+ for (auto& def : getDefines (config, target))
+ {
+ if (! def.containsChar ('='))
+ def << '=';
+
+ flags.add ("-D" + def);
+ }
+
+ flags.addArray (getCompilerFlags (config, target));
- for (auto flag : compilerFlags)
+ for (auto flag : flags)
setAddOption (*compiler, "option", flag);
}
@@ -589,7 +613,11 @@ private:
{
XmlElement* const linker = xml.createNewChildElement ("Linker");
+ if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget)
+ setAddOption (*linker, "option", getSharedCodePath (config));
+
const StringArray linkerFlags (getLinkerFlags (config, target));
+
for (auto flag : linkerFlags)
setAddOption (*linker, "option", flag);
@@ -604,9 +632,7 @@ private:
librarySearchPaths.add (RelativePath (getSharedCodePath (config), RelativePath::buildTargetFolder).getParentDirectory().toUnixStyle());
for (auto path : librarySearchPaths)
- {
setAddOption (*linker, "directory", replacePreprocessorDefs (getAllPreprocessorDefs(), path));
- }
}
}
@@ -615,11 +641,9 @@ private:
XmlElement* const build = xml.createNewChildElement ("Build");
for (ConstConfigIterator config (*this); config.next();)
- {
for (auto target : targets)
if (target->type != ProjectType::Target::AggregateTarget)
createBuildTarget (*build->createNewChildElement ("Target"), *target, *config);
- }
}
void addVirtualTargets (XmlElement& xml) const
@@ -647,32 +671,42 @@ private:
}
}
+ StringArray getProjectCompilerOptions() const
+ {
+ return { "-Wall", "-Wno-strict-aliasing", "-Wno-strict-overflow" };
+ }
+
void addProjectCompilerOptions (XmlElement& xml) const
{
XmlElement* const compiler = xml.createNewChildElement ("Compiler");
- setAddOption (*compiler, "option", "-Wall");
- setAddOption (*compiler, "option", "-Wno-strict-aliasing");
- setAddOption (*compiler, "option", "-Wno-strict-overflow");
+
+ for (auto& option : getProjectCompilerOptions())
+ setAddOption (*compiler, "option", option);
}
- void addProjectLinkerOptions (XmlElement& xml) const
+ StringArray getProjectLinkerLibs() const
{
- XmlElement* const linker = xml.createNewChildElement ("Linker");
-
- StringArray libs;
+ StringArray result;
if (isWindows())
- {
- static const char* defaultLibs[] = { "gdi32", "user32", "kernel32", "comctl32" };
- libs = StringArray (defaultLibs, numElementsInArray (defaultLibs));
- }
+ result.addArray ({ "gdi32", "user32", "kernel32", "comctl32" });
- libs.addTokens (getExternalLibrariesString(), ";\n", "\"'");
+ result.addTokens (getExternalLibrariesString(), ";\n", "\"'");
- libs = getCleanedStringArray (libs);
+ result = getCleanedStringArray (result);
- for (int i = 0; i < libs.size(); ++i)
- setAddOption (*linker, "library", replacePreprocessorDefs (getAllPreprocessorDefs(), libs[i]));
+ for (auto& option : result)
+ option = replacePreprocessorDefs (getAllPreprocessorDefs(), option);
+
+ return result;
+ }
+
+ void addProjectLinkerOptions (XmlElement& xml) const
+ {
+ XmlElement* const linker = xml.createNewChildElement ("Linker");
+
+ for (auto& lib : getProjectLinkerLibs())
+ setAddOption (*linker, "library", lib);
}
CodeBlocksTarget& getTargetWithType (ProjectType::Target::Type type) const
@@ -776,5 +810,7 @@ private:
OwnedArray targets;
+ friend class CLionProjectExporter;
+
JUCE_DECLARE_NON_COPYABLE (CodeBlocksProjectExporter)
};
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h
index c104d6e952..b51550c976 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h
@@ -1244,6 +1244,7 @@ public:
bool isCodeBlocks() const override { return false; }
bool isMakefile() const override { return false; }
bool isAndroidStudio() const override { return false; }
+ bool isCLion() const override { return false; }
bool isAndroid() const override { return false; }
bool isWindows() const override { return true; }
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h
index a2c2d97feb..a724a2e201 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h
@@ -36,7 +36,7 @@ protected:
{
public:
MakeBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e)
- : BuildConfiguration (p, settings, e)
+ : BuildConfiguration (p, settings, e)
{
}
@@ -89,46 +89,75 @@ public:
: ProjectType::Target (targetType), owner (exporter)
{}
- StringArray getTargetSettings (const BuildConfiguration& config) const
+ StringArray getCompilerFlags() const
{
- if (type == AggregateTarget)
- // the aggregate target should not specify any settings at all!
- // it just defines dependencies on the other targets.
- return {};
+ StringArray result;
+
+ if (getTargetFileType() == sharedLibraryOrDLL || getTargetFileType() == pluginBundle)
+ {
+ result.add ("-fPIC");
+ result.add ("-fvisibility=hidden");
+ }
- StringPairArray commonOptions = owner.getAllPreprocessorDefs (config, ProjectType::Target::unspecified);
- StringPairArray targetSpecific = owner.getAllPreprocessorDefs (config, type);
+ return result;
+ }
- StringArray defs;
+ StringArray getLinkerFlags() const
+ {
+ StringArray result;
- // remove any defines that have already been added by the configuration
- const int n = targetSpecific.size();
- for (int i = 0 ; i < n; ++i)
+ if (getTargetFileType() == sharedLibraryOrDLL || getTargetFileType() == pluginBundle)
{
- const String& key = targetSpecific.getAllKeys()[i];
+ result.add ("-shared");
- if (! commonOptions.getAllKeys().contains (key))
- defs.add (String ("-D") + key + String ("=") + targetSpecific.getAllValues()[i]);
+ if (getTargetFileType() == pluginBundle)
+ result.add ("-Wl,--no-undefined");
}
+ return result;
+ }
+
+ StringPairArray getDefines (const BuildConfiguration& config) const
+ {
+ StringPairArray result;
+ auto commonOptionKeys = owner.getAllPreprocessorDefs (config, ProjectType::Target::unspecified).getAllKeys();
+ auto targetSpecific = owner.getAllPreprocessorDefs (config, type);
+
+ for (auto& key : targetSpecific.getAllKeys())
+ if (! commonOptionKeys.contains (key))
+ result.set (key, targetSpecific[key]);
+
+ return result;
+ }
+
+ StringArray getTargetSettings (const MakeBuildConfiguration& config) const
+ {
+ if (type == AggregateTarget)
+ // the aggregate target should not specify any settings at all!
+ // it just defines dependencies on the other targets.
+ return {};
+
+ StringArray defines;
+ auto defs = getDefines (config);
+
+ for (auto& key : defs.getAllKeys())
+ defines.add ("-D" + key + "=" + defs[key]);
+
StringArray s;
const String cppflagsVarName = String ("JUCE_CPPFLAGS_") + getTargetVarName();
- s.add (cppflagsVarName + String (" := ") + defs.joinIntoString (" "));
+ s.add (cppflagsVarName + String (" := ") + defines.joinIntoString (" "));
- if (getTargetFileType() == sharedLibraryOrDLL || getTargetFileType() == pluginBundle)
- {
- s.add (String ("JUCE_CFLAGS_") + getTargetVarName() + String (" := -fPIC -fvisibility=hidden"));
+ auto cflags = getCompilerFlags();
- const String ldflagsVarName = String ("JUCE_LDFLAGS_") + getTargetVarName();
- String targetLinkOptions = ldflagsVarName + String (" := -shared");
+ if (! cflags.isEmpty())
+ s.add (String ("JUCE_CFLAGS_") + getTargetVarName() + " := " + cflags.joinIntoString (" "));
- if (getTargetFileType() == pluginBundle)
- targetLinkOptions += " -Wl,--no-undefined";
+ auto ldflags = getLinkerFlags();
- s.add (targetLinkOptions);
- }
+ if (! ldflags.isEmpty())
+ s.add (String ("JUCE_LDFLAGS_") + getTargetVarName() + " := " + ldflags.joinIntoString (" "));
String targetName (owner.replacePreprocessorTokens (config, config.getTargetBinaryNameString()));
@@ -287,26 +316,6 @@ public:
return nullptr;
}
- StringArray getPackages() const
- {
- StringArray packages;
- packages.addTokens (getExtraPkgConfigString(), " ", "\"'");
- packages.removeEmptyStrings();
-
- packages.addArray (linuxPackages);
-
- if (isWebBrowserComponentEnabled())
- {
- packages.add ("webkit2gtk-4.0");
- packages.add ("gtk+-x11-3.0");
- }
-
- packages.removeDuplicates (false);
-
- return packages;
- }
-
-
//==============================================================================
MakefileProjectExporter (Project& p, const ValueTree& t) : ProjectExporter (p, t)
{
@@ -328,6 +337,7 @@ public:
bool isCodeBlocks() const override { return false; }
bool isMakefile() const override { return true; }
bool isAndroidStudio() const override { return false; }
+ bool isCLion() const override { return false; }
bool isAndroid() const override { return false; }
bool isWindows() const override { return false; }
@@ -412,106 +422,238 @@ public:
}
private:
- bool isWebBrowserComponentEnabled() const
+ StringPairArray getDefines (const BuildConfiguration& config) const
{
- static String guiExtrasModule ("juce_gui_extra");
+ StringPairArray result;
- return (project.getModules().isModuleEnabled (guiExtrasModule)
- && project.isConfigFlagEnabled ("JUCE_WEB_BROWSER", true));
- }
-
- //==============================================================================
- void writeDefineFlags (OutputStream& out, const BuildConfiguration& config) const
- {
- StringPairArray defines;
- defines.set ("LINUX", "1");
+ result.set ("LINUX", "1");
if (config.isDebug())
{
- defines.set ("DEBUG", "1");
- defines.set ("_DEBUG", "1");
+ result.set ("DEBUG", "1");
+ result.set ("_DEBUG", "1");
}
else
{
- defines.set ("NDEBUG", "1");
+ result.set ("NDEBUG", "1");
}
- out << createGCCPreprocessorFlags (mergePreprocessorDefs (defines, getAllPreprocessorDefs (config, ProjectType::Target::unspecified)));
+ result = mergePreprocessorDefs (result, getAllPreprocessorDefs (config, ProjectType::Target::unspecified));
+
+ return result;
}
- void writeHeaderPathFlags (OutputStream& out, const BuildConfiguration& config) const
+ StringArray getPackages() const
{
- StringArray searchPaths (extraSearchPaths);
- searchPaths.addArray (config.getHeaderSearchPaths());
+ StringArray packages;
+ packages.addTokens (getExtraPkgConfigString(), " ", "\"'");
+ packages.removeEmptyStrings();
- auto packages = getPackages();
- if (packages.size() > 0)
+ packages.addArray (linuxPackages);
+
+ if (isWebBrowserComponentEnabled())
{
- out << " $(shell pkg-config --cflags";
+ packages.add ("webkit2gtk-4.0");
+ packages.add ("gtk+-x11-3.0");
+ }
- for (int i = 0; i < packages.size(); ++i)
- out << " " << packages[i];
+ packages.removeDuplicates (false);
- out << ")";
- }
+ return packages;
+ }
- if (linuxLibs.contains("pthread"))
- out << " -pthread";
+ String getPreprocessorPkgConfigFlags() const
+ {
+ auto packages = getPackages();
- searchPaths = getCleanedStringArray (searchPaths);
+ if (packages.size() > 0)
+ return "$(shell pkg-config --cflags " + packages.joinIntoString (" ") + ")";
- // Replace ~ character with $(HOME) environment variable
- for (int i = 0; i < searchPaths.size(); ++i)
- out << " -I" << escapeSpaces (FileHelpers::unixStylePath (replacePreprocessorTokens (config, searchPaths[i]))).replace ("~", "$(HOME)");
+ return {};
}
- void writeCppFlags (OutputStream& out, const BuildConfiguration& config) const
+ String getLinkerPkgConfigFlags() const
{
- out << " JUCE_CPPFLAGS := $(DEPFLAGS)";
- writeDefineFlags (out, config);
- writeHeaderPathFlags (out, config);
- out << " $(CPPFLAGS)" << newLine;
+ auto packages = getPackages();
+
+ if (packages.size() > 0)
+ return "$(shell pkg-config --libs " + packages.joinIntoString (" ") + ")";
+
+ return {};
}
- void writeLinkerFlags (OutputStream& out, const BuildConfiguration& config) const
+ StringArray getCPreprocessorFlags (const BuildConfiguration&) const
{
- out << " JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR)";
+ StringArray result;
- {
- StringArray flags (makefileExtraLinkerFlags);
+ if (linuxLibs.contains("pthread"))
+ result.add ("-pthread");
- if (! config.isDebug())
- flags.add ("-fvisibility=hidden");
+ return result;
+ }
- if (flags.size() > 0)
- out << " " << getCleanedStringArray (flags).joinIntoString (" ");
- }
+ StringArray getCFlags (const BuildConfiguration& config) const
+ {
+ StringArray result;
- out << config.getGCCLibraryPathFlags();
+ if (anyTargetIsSharedLibrary())
+ result.add ("-fPIC");
- auto packages = getPackages();
- if (packages.size() > 0 )
+ if (config.isDebug())
{
- out << " $(shell pkg-config --libs";
+ result.add ("-g");
+ result.add ("-ggdb");
+ }
- for (int i = 0; i < packages.size(); ++i)
- out << " " << packages[i];
+ result.add ("-O" + config.getGCCOptimisationFlag());
- out << ")";
- }
+ if (config.isLinkTimeOptimisationEnabled())
+ result.add ("-flto");
+
+ auto extra = replacePreprocessorTokens (config, getExtraCompilerFlagsString()).trim();
- for (int i = 0; i < linuxLibs.size(); ++i)
- out << " -l" << linuxLibs[i];
+ if (extra.isNotEmpty())
+ result.add (extra);
+
+ return result;
+ }
+
+ StringArray getCXXFlags() const
+ {
+ StringArray result;
+
+ auto cppStandard = project.getCppStandardValue().toString();
+
+ if (cppStandard == "latest")
+ cppStandard = "1z";
+
+ cppStandard = "-std=" + String (shouldUseGNUExtensions() ? "gnu++" : "c++") + cppStandard;
+
+ result.add (cppStandard);
+
+ return result;
+ }
+
+ StringArray getHeaderSearchPaths (const BuildConfiguration& config) const
+ {
+ StringArray searchPaths (extraSearchPaths);
+ searchPaths.addArray (config.getHeaderSearchPaths());
+ searchPaths = getCleanedStringArray (searchPaths);
+
+ StringArray result;
+
+ for (auto& path : searchPaths)
+ result.add (FileHelpers::unixStylePath (replacePreprocessorTokens (config, path)));
+
+ return result;
+ }
+
+ StringArray getLibraryNames (const BuildConfiguration& config) const
+ {
+ StringArray result (linuxLibs);
StringArray libraries;
libraries.addTokens (getExternalLibrariesString(), ";", "\"'");
libraries.removeEmptyStrings();
if (libraries.size() != 0)
- out << " -l" << replacePreprocessorTokens (config, libraries.joinIntoString (" -l")).trim();
+ result.add (replacePreprocessorTokens (config, libraries.joinIntoString (" ")).trim());
- out << " " << replacePreprocessorTokens (config, getExtraLinkerFlagsString()).trim()
- << " $(LDFLAGS)" << newLine;
+ return result;
+ }
+
+ StringArray getLibrarySearchPaths (const BuildConfiguration& config) const
+ {
+ auto result = getSearchPathsFromString (config.getLibrarySearchPathString());
+
+ for (auto path : moduleLibSearchPaths)
+ result.add (path + "/" + config.getModuleLibraryArchName());
+
+ return result;
+ }
+
+ StringArray getLinkerFlags (const BuildConfiguration& config) const
+ {
+ StringArray result (makefileExtraLinkerFlags);
+
+ if (! config.isDebug())
+ result.add ("-fvisibility=hidden");
+
+ auto extraFlags = getExtraLinkerFlagsString().trim();
+
+ if (extraFlags.isNotEmpty())
+ result.add (replacePreprocessorTokens (config, extraFlags));
+
+ return result;
+ }
+
+ bool isWebBrowserComponentEnabled() const
+ {
+ static String guiExtrasModule ("juce_gui_extra");
+
+ return (project.getModules().isModuleEnabled (guiExtrasModule)
+ && project.isConfigFlagEnabled ("JUCE_WEB_BROWSER", true));
+ }
+
+ //==============================================================================
+ void writeDefineFlags (OutputStream& out, const MakeBuildConfiguration& config) const
+ {
+ out << createGCCPreprocessorFlags (mergePreprocessorDefs (getDefines (config), getAllPreprocessorDefs (config, ProjectType::Target::unspecified)));
+ }
+
+ void writePkgConfigFlags (OutputStream& out) const
+ {
+ auto flags = getPreprocessorPkgConfigFlags();
+
+ if (flags.isNotEmpty())
+ out << " " << flags;
+ }
+
+ void writeCPreprocessorFlags (OutputStream& out, const BuildConfiguration& config) const
+ {
+ auto flags = getCPreprocessorFlags (config);
+
+ if (! flags.isEmpty())
+ out << " " << flags.joinIntoString (" ");
+ }
+
+ void writeHeaderPathFlags (OutputStream& out, const BuildConfiguration& config) const
+ {
+ for (auto& path : getHeaderSearchPaths (config))
+ out << " -I" << escapeSpaces (path).replace ("~", "$(HOME)");
+ }
+
+ void writeCppFlags (OutputStream& out, const MakeBuildConfiguration& config) const
+ {
+ out << " JUCE_CPPFLAGS := $(DEPFLAGS)";
+ writeDefineFlags (out, config);
+ writePkgConfigFlags (out);
+ writeCPreprocessorFlags (out, config);
+ writeHeaderPathFlags (out, config);
+ out << " $(CPPFLAGS)" << newLine;
+ }
+
+ void writeLinkerFlags (OutputStream& out, const BuildConfiguration& config) const
+ {
+ out << " JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR)";
+
+ for (auto path : getLibrarySearchPaths (config))
+ out << " -L" << escapeSpaces (path).replace ("~", "$(HOME)");
+
+ auto pkgConfigFlags = getLinkerPkgConfigFlags();
+
+ if (pkgConfigFlags.isNotEmpty())
+ out << " " << getLinkerPkgConfigFlags();
+
+ auto linkerFlags = getLinkerFlags (config).joinIntoString (" ");
+
+ if (linkerFlags.isNotEmpty())
+ out << " " << linkerFlags;
+
+ for (auto& libName : getLibraryNames (config))
+ out << " -l" << libName;
+
+ out << " $(LDFLAGS)" << newLine;
}
void writeTargetLines (OutputStream& out, const bool useLinuxPackages) const
@@ -520,7 +662,7 @@ private:
for (int i = 0; i < n; ++i)
{
- if (MakefileTarget* target = targets.getUnchecked (i))
+ if (auto* target = targets.getUnchecked (i))
{
if (target->type == ProjectType::Target::AggregateTarget)
{
@@ -531,7 +673,7 @@ private:
{
if (i == j) continue;
- if (MakefileTarget* dependency = targets.getUnchecked (j))
+ if (auto* dependency = targets.getUnchecked (j))
{
if (dependency->type != ProjectType::Target::SharedCodeTarget)
{
@@ -557,7 +699,7 @@ private:
}
}
- void writeConfig (OutputStream& out, const BuildConfiguration& config) const
+ void writeConfig (OutputStream& out, const MakeBuildConfiguration& config) const
{
const String buildDirName ("build");
const String intermediatesDirName (buildDirName + "/intermediate/" + config.getName());
@@ -594,28 +736,21 @@ private:
out << " JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH)";
- if (anyTargetIsSharedLibrary())
- out << " -fPIC";
+ auto cflags = getCFlags (config).joinIntoString (" ");
- if (config.isDebug())
- out << " -g -ggdb";
+ if (cflags.isNotEmpty())
+ out << " " << cflags;
- out << " -O" << config.getGCCOptimisationFlag()
- << (config.isLinkTimeOptimisationEnabled() ? " -flto" : "")
- << (" " + replacePreprocessorTokens (config, getExtraCompilerFlagsString())).trimEnd()
- << " $(CFLAGS)" << newLine;
+ out << " $(CFLAGS)" << newLine;
- {
- auto cppStandard = config.project.getCppStandardValue().toString();
+ out << " JUCE_CXXFLAGS += $(JUCE_CFLAGS)";
- if (cppStandard == "latest")
- cppStandard = "1z";
+ auto cxxflags = getCXXFlags().joinIntoString (" ");
- cppStandard = "-std=" + String (shouldUseGNUExtensions() ? "gnu++" : "c++") + cppStandard;
+ if (cxxflags.isNotEmpty())
+ out << " " << cxxflags;
- out << " JUCE_CXXFLAGS += $(CXXFLAGS) $(JUCE_CFLAGS) "
- << cppStandard << " $(CXXFLAGS)" << newLine;
- }
+ out << " $(CXXFLAGS)" << newLine;
writeLinkerFlags (out, config);
@@ -632,7 +767,7 @@ private:
for (int i = 0; i < n; ++i)
{
- if (MakefileTarget* target = targets.getUnchecked (i))
+ if (auto* target = targets.getUnchecked (i))
{
if (target->type == ProjectType::Target::AggregateTarget)
continue;
@@ -677,7 +812,7 @@ private:
<< newLine;
for (ConstConfigIterator config (*this); config.next();)
- writeConfig (out, *config);
+ writeConfig (out, dynamic_cast (*config));
for (auto target : targets)
target->writeObjects (out);
@@ -750,6 +885,8 @@ private:
return phonyTargetLine.toString();
}
+ friend class CLionProjectExporter;
+
OwnedArray targets;
JUCE_DECLARE_NON_COPYABLE (MakefileProjectExporter)
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h
index 282f5c7386..90315e6200 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h
@@ -148,6 +148,7 @@ public:
bool isCodeBlocks() const override { return false; }
bool isMakefile() const override { return false; }
bool isAndroidStudio() const override { return false; }
+ bool isCLion() const override { return false; }
bool isAndroid() const override { return false; }
bool isWindows() const override { return false; }
@@ -350,7 +351,7 @@ public:
{
callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType)
{
- if (XcodeTarget* target = new XcodeTarget (targetType, *this))
+ if (auto* target = new XcodeTarget (targetType, *this))
{
if (targetType == ProjectType::Target::AggregateTarget)
targets.insert (0, target);
@@ -668,6 +669,7 @@ public:
case SharedCodeTarget:
xcodeFileType = "archive.ar";
+ xcodeBundleExtension = ".a";
xcodeProductType = "com.apple.product-type.library.static";
xcodeCopyToProductInstallPathAfterBuild = false;
break;
@@ -707,9 +709,45 @@ public:
Array xcodeExtraLibrariesDebug, xcodeExtraLibrariesRelease;
StringArray frameworkIDs, buildPhaseIDs, configIDs, sourceIDs, rezFileIDs;
+ StringArray frameworkNames;
String dependencyID, mainBuildProductID;
File infoPlistFile;
+ struct SourceFileInfo
+ {
+ RelativePath path;
+ bool shouldBeCompiled = false;
+ };
+
+ Array getSourceFilesInfo (const Project::Item& projectItem) const
+ {
+ Array result;
+
+ const Type targetType = (owner.getProject().getProjectType().isAudioPlugin() ? type : SharedCodeTarget);
+
+ if (projectItem.isGroup())
+ {
+ for (int i = 0; i < projectItem.getNumChildren(); ++i)
+ result.addArray (getSourceFilesInfo (projectItem.getChild (i)));
+ }
+ else if (projectItem.shouldBeAddedToTargetProject()
+ && owner.getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType)
+ {
+ SourceFileInfo info;
+
+ info.path = RelativePath (projectItem.getFile(), owner.getTargetFolder(), RelativePath::buildTargetFolder);
+
+ jassert (info.path.getRoot() == RelativePath::buildTargetFolder);
+
+ if (targetType == SharedCodeTarget || projectItem.shouldBeCompiled())
+ info.shouldBeCompiled = projectItem.shouldBeCompiled();
+
+ result.add (info);
+ }
+
+ return result;
+ }
+
//==============================================================================
void addMainBuildProduct() const
{
@@ -850,10 +888,25 @@ public:
return false;
}
+ String getBundleIdentifier() const
+ {
+ String bundleIdentifier = owner.project.getBundleIdentifier().toString();
+
+ if (xcodeBundleIDSubPath.isNotEmpty())
+ {
+ StringArray bundleIdSegments = StringArray::fromTokens (bundleIdentifier, ".", StringRef());
+
+ jassert (bundleIdSegments.size() > 0);
+ bundleIdentifier += String (".") + bundleIdSegments[bundleIdSegments.size() - 1] + xcodeBundleIDSubPath;
+ }
+
+ return bundleIdentifier;
+ }
+
//==============================================================================
- StringArray getTargetSettings (const XcodeBuildConfiguration& config) const
+ StringPairArray getTargetSettings (const XcodeBuildConfiguration& config) const
{
- StringArray s;
+ StringPairArray s;
if (type == AggregateTarget && ! owner.isiOS())
{
@@ -861,44 +914,35 @@ public:
// pre-/post-build scripts
String sdkRoot;
- s.add ("MACOSX_DEPLOYMENT_TARGET = " + getOSXDeploymentTarget (config, &sdkRoot));
+ s.set ("MACOSX_DEPLOYMENT_TARGET", getOSXDeploymentTarget (config, &sdkRoot));
if (sdkRoot.isNotEmpty())
- s.add ("SDKROOT = " + sdkRoot);
+ s.set ("SDKROOT", sdkRoot);
return s;
}
- String bundleIdentifier = owner.project.getBundleIdentifier().toString();
- if (xcodeBundleIDSubPath.isNotEmpty())
- {
- StringArray bundleIdSegments = StringArray::fromTokens (bundleIdentifier, ".", StringRef());
-
- jassert (bundleIdSegments.size() > 0);
- bundleIdentifier += String (".") + bundleIdSegments[bundleIdSegments.size() - 1] + xcodeBundleIDSubPath;
- }
-
- s.add ("PRODUCT_BUNDLE_IDENTIFIER = " + bundleIdentifier);
+ s.set ("PRODUCT_BUNDLE_IDENTIFIER", getBundleIdentifier());
const String arch ((! owner.isiOS() && type == Target::AudioUnitv3PlugIn) ? osxArch_64Bit : config.osxArchitecture.get());
- if (arch == osxArch_Native) s.add ("ARCHS = \"$(NATIVE_ARCH_ACTUAL)\"");
- else if (arch == osxArch_32BitUniversal) s.add ("ARCHS = \"$(ARCHS_STANDARD_32_BIT)\"");
- else if (arch == osxArch_64BitUniversal) s.add ("ARCHS = \"$(ARCHS_STANDARD_32_64_BIT)\"");
- else if (arch == osxArch_64Bit) s.add ("ARCHS = \"$(ARCHS_STANDARD_64_BIT)\"");
+ if (arch == osxArch_Native) s.set ("ARCHS", "\"$(NATIVE_ARCH_ACTUAL)\"");
+ else if (arch == osxArch_32BitUniversal) s.set ("ARCHS", "\"$(ARCHS_STANDARD_32_BIT)\"");
+ else if (arch == osxArch_64BitUniversal) s.set ("ARCHS", "\"$(ARCHS_STANDARD_32_64_BIT)\"");
+ else if (arch == osxArch_64Bit) s.set ("ARCHS", "\"$(ARCHS_STANDARD_64_BIT)\"");
- s.add ("HEADER_SEARCH_PATHS = " + getHeaderSearchPaths (config));
- s.add ("USE_HEADERMAP = " + String (static_cast (config.exporter.settings.getProperty ("useHeaderMap")) ? "YES" : "NO"));
+ s.set ("HEADER_SEARCH_PATHS", String ("(") + getHeaderSearchPaths (config).joinIntoString (", ") + ", \"$(inherited)\")");
+ s.set ("USE_HEADERMAP", String (static_cast (config.exporter.settings.getProperty ("useHeaderMap")) ? "YES" : "NO"));
- s.add ("GCC_OPTIMIZATION_LEVEL = " + config.getGCCOptimisationFlag());
+ s.set ("GCC_OPTIMIZATION_LEVEL", config.getGCCOptimisationFlag());
if (shouldCreatePList())
{
- s.add ("INFOPLIST_FILE = " + infoPlistFile.getFileName());
+ s.set ("INFOPLIST_FILE", infoPlistFile.getFileName());
if (owner.getPListPrefixHeaderString().isNotEmpty())
- s.add ("INFOPLIST_PREFIX_HEADER = " + owner.getPListPrefixHeaderString());
+ s.set ("INFOPLIST_PREFIX_HEADER", owner.getPListPrefixHeaderString());
- s.add ("INFOPLIST_PREPROCESS = " + (owner.isPListPreprocessEnabled() ? String ("YES") : String ("NO")));
+ s.set ("INFOPLIST_PREPROCESS", (owner.isPListPreprocessEnabled() ? String ("YES") : String ("NO")));
auto plistDefs = parsePreprocessorDefs (config.plistPreprocessorDefinitions.get());
StringArray defsList;
@@ -915,41 +959,42 @@ public:
}
if (defsList.size() > 0)
- s.add ("INFOPLIST_PREPROCESSOR_DEFINITIONS = " + indentParenthesisedList (defsList));
+ s.set ("INFOPLIST_PREPROCESSOR_DEFINITIONS", indentParenthesisedList (defsList));
}
if (config.isLinkTimeOptimisationEnabled())
- s.add ("LLVM_LTO = YES");
+ s.set ("LLVM_LTO", "YES");
if (config.fastMathEnabled.get())
- s.add ("GCC_FAST_MATH = YES");
+ s.set ("GCC_FAST_MATH", "YES");
const String extraFlags (owner.replacePreprocessorTokens (config, owner.getExtraCompilerFlagsString()).trim());
+
if (extraFlags.isNotEmpty())
- s.add ("OTHER_CPLUSPLUSFLAGS = \"" + extraFlags + "\"");
+ s.set ("OTHER_CPLUSPLUSFLAGS", extraFlags.quoted());
String installPath = getInstallPathForConfiguration (config);
if (installPath.isNotEmpty())
{
- s.add ("INSTALL_PATH = \"" + installPath + "\"");
+ s.set ("INSTALL_PATH", installPath.quoted());
if (xcodeCopyToProductInstallPathAfterBuild)
{
- s.add ("DEPLOYMENT_LOCATION = YES");
- s.add ("DSTROOT = /");
+ s.set ("DEPLOYMENT_LOCATION", "YES");
+ s.set ("DSTROOT", "/");
}
}
if (getTargetFileType() == pluginBundle)
{
- s.add ("LIBRARY_STYLE = Bundle");
- s.add ("WRAPPER_EXTENSION = " + xcodeBundleExtension.substring (1));
- s.add ("GENERATE_PKGINFO_FILE = YES");
+ s.set ("LIBRARY_STYLE", "Bundle");
+ s.set ("WRAPPER_EXTENSION", xcodeBundleExtension.substring (1));
+ s.set ("GENERATE_PKGINFO_FILE", "YES");
}
if (xcodeOtherRezFlags.isNotEmpty())
- s.add ("OTHER_REZFLAGS = \"" + xcodeOtherRezFlags + "\"");
+ s.set ("OTHER_REZFLAGS", "\"" + xcodeOtherRezFlags + "\"");
String configurationBuildDir = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
@@ -964,41 +1009,41 @@ public:
.toUnixStyle());
}
- s.add ("CONFIGURATION_BUILD_DIR = " + addQuotesIfRequired (configurationBuildDir));
+ s.set ("CONFIGURATION_BUILD_DIR", addQuotesIfRequired (configurationBuildDir));
String gccVersion ("com.apple.compilers.llvm.clang.1_0");
if (owner.iOS)
{
- s.add ("ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon");
- s.add ("ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage");
+ s.set ("ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon");
+ s.set ("ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME", "LaunchImage");
}
else
{
String sdkRoot;
- s.add ("MACOSX_DEPLOYMENT_TARGET = " + getOSXDeploymentTarget (config, &sdkRoot));
+ s.set ("MACOSX_DEPLOYMENT_TARGET", getOSXDeploymentTarget (config, &sdkRoot));
if (sdkRoot.isNotEmpty())
- s.add ("SDKROOT = " + sdkRoot);
+ s.set ("SDKROOT", sdkRoot);
- s.add ("MACOSX_DEPLOYMENT_TARGET_ppc = 10.4");
- s.add ("SDKROOT_ppc = macosx10.5");
+ s.set ("MACOSX_DEPLOYMENT_TARGET_ppc", "10.4");
+ s.set ("SDKROOT_ppc", "macosx10.5");
if (xcodeExcludedFiles64Bit.isNotEmpty())
{
- s.add ("EXCLUDED_SOURCE_FILE_NAMES = \"$(EXCLUDED_SOURCE_FILE_NAMES_$(CURRENT_ARCH))\"");
- s.add ("EXCLUDED_SOURCE_FILE_NAMES_x86_64 = " + xcodeExcludedFiles64Bit);
+ s.set ("EXCLUDED_SOURCE_FILE_NAMES", "\"$(EXCLUDED_SOURCE_FILE_NAMES_$(CURRENT_ARCH))\"");
+ s.set ("EXCLUDED_SOURCE_FILE_NAMES_x86_64", xcodeExcludedFiles64Bit);
}
}
- s.add ("GCC_VERSION = " + gccVersion);
- s.add ("CLANG_LINK_OBJC_RUNTIME = NO");
+ s.set ("GCC_VERSION", gccVersion);
+ s.set ("CLANG_LINK_OBJC_RUNTIME", "NO");
if (! config.codeSignIdentity.isUsingDefault())
- s.add ("CODE_SIGN_IDENTITY = " + config.codeSignIdentity.get().quoted());
+ s.set ("CODE_SIGN_IDENTITY", config.codeSignIdentity.get().quoted());
if (shouldAddEntitlements())
- s.add (String ("CODE_SIGN_ENTITLEMENTS = \"") + owner.getEntitlementsFileName() + String ("\""));
+ s.set ("CODE_SIGN_ENTITLEMENTS", owner.getEntitlementsFileName().quoted());
{
auto cppStandard = owner.project.getCppStandardValue().toString();
@@ -1006,33 +1051,33 @@ public:
if (cppStandard == "latest")
cppStandard = "1z";
- s.add ("CLANG_CXX_LANGUAGE_STANDARD = " + (String (owner.shouldUseGNUExtensions() ? "gnu++"
- : "c++") + cppStandard).quoted());
+ s.set ("CLANG_CXX_LANGUAGE_STANDARD", (String (owner.shouldUseGNUExtensions() ? "gnu++"
+ : "c++") + cppStandard).quoted());
}
if (config.cppStandardLibrary.get().isNotEmpty())
- s.add ("CLANG_CXX_LIBRARY = " + config.cppStandardLibrary.get().quoted());
+ s.set ("CLANG_CXX_LIBRARY", config.cppStandardLibrary.get().quoted());
- s.add ("COMBINE_HIDPI_IMAGES = YES");
+ s.set ("COMBINE_HIDPI_IMAGES", "YES");
{
StringArray linkerFlags, librarySearchPaths;
getLinkerSettings (config, linkerFlags, librarySearchPaths);
if (linkerFlags.size() > 0)
- s.add ("OTHER_LDFLAGS = \"" + linkerFlags.joinIntoString (" ") + "\"");
+ s.set ("OTHER_LDFLAGS", linkerFlags.joinIntoString (" ").quoted());
librarySearchPaths.addArray (config.getLibrarySearchPaths());
librarySearchPaths = getCleanedStringArray (librarySearchPaths);
if (librarySearchPaths.size() > 0)
{
- String libPaths ("LIBRARY_SEARCH_PATHS = (\"$(inherited)\"");
+ String libPaths ("(\"$(inherited)\"");
for (auto& p : librarySearchPaths)
libPaths += ", \"\\\"" + p + "\\\"\"";
- s.add (libPaths + ")");
+ s.set ("LIBRARY_SEARCH_PATHS", libPaths + ")");
}
}
@@ -1042,24 +1087,24 @@ public:
{
defines.set ("_DEBUG", "1");
defines.set ("DEBUG", "1");
- s.add ("COPY_PHASE_STRIP = NO");
- s.add ("GCC_DYNAMIC_NO_PIC = NO");
+ s.set ("COPY_PHASE_STRIP", "NO");
+ s.set ("GCC_DYNAMIC_NO_PIC", "NO");
}
else
{
defines.set ("_NDEBUG", "1");
defines.set ("NDEBUG", "1");
- s.add ("GCC_GENERATE_DEBUGGING_SYMBOLS = NO");
- s.add ("GCC_SYMBOLS_PRIVATE_EXTERN = YES");
- s.add ("DEAD_CODE_STRIPPING = YES");
+ s.set ("GCC_GENERATE_DEBUGGING_SYMBOLS", "NO");
+ s.set ("GCC_SYMBOLS_PRIVATE_EXTERN", "YES");
+ s.set ("DEAD_CODE_STRIPPING", "YES");
}
if (type != Target::SharedCodeTarget && type != Target::StaticLibrary && type != Target::DynamicLibrary
&& config.stripLocalSymbolsEnabled.get())
{
- s.add ("STRIPFLAGS = \"-x\"");
- s.add ("DEPLOYMENT_POSTPROCESSING = YES");
- s.add ("SEPARATE_STRIP = YES");
+ s.set ("STRIPFLAGS", "\"-x\"");
+ s.set ("DEPLOYMENT_POSTPROCESSING", "YES");
+ s.set ("SEPARATE_STRIP", "YES");
}
if (owner.isInAppPurchasesEnabled())
@@ -1079,11 +1124,19 @@ public:
defsList.add ("\"" + def + "\"");
}
- s.add ("GCC_PREPROCESSOR_DEFINITIONS = " + indentParenthesisedList (defsList));
+ s.set ("GCC_PREPROCESSOR_DEFINITIONS", indentParenthesisedList (defsList));
+
+ StringArray customFlags;
+ customFlags.addTokens (config.customXcodeFlags.get(), ",", "\"'");
+ customFlags.removeEmptyStrings();
- s.addTokens (config.customXcodeFlags.get(), ",", "\"'");
+ for (auto flag : customFlags)
+ {
+ s.set (flag.upToFirstOccurrenceOf ("=", false, false).trim(),
+ flag.fromFirstOccurrenceOf ("=", false, false).trim().quoted());
+ }
- return getCleanedStringArray (s);
+ return s;
}
String getInstallPathForConfiguration (const XcodeBuildConfiguration& config) const
@@ -1173,7 +1226,7 @@ public:
if (! owner.iOS) // (NB: on iOS this causes error ITMS-90032 during publishing)
addPlistDictionaryKey (dict, "CFBundleIconFile", owner.iconFile.exists() ? owner.iconFile.getFileName() : String());
- addPlistDictionaryKey (dict, "CFBundleIdentifier", "$(PRODUCT_BUNDLE_IDENTIFIER)");
+ addPlistDictionaryKey (dict, "CFBundleIdentifier", getBundleIdentifier());
addPlistDictionaryKey (dict, "CFBundleName", owner.projectName);
// needed by NSExtension on iOS
@@ -1327,7 +1380,7 @@ public:
}
//==============================================================================
- String getHeaderSearchPaths (const BuildConfiguration& config) const
+ StringArray getHeaderSearchPaths (const BuildConfiguration& config) const
{
StringArray paths (owner.extraSearchPaths);
paths.addArray (config.getHeaderSearchPaths());
@@ -1341,8 +1394,6 @@ public:
.toUnixStyle());
}
- paths.add ("$(inherited)");
-
paths = getCleanedStringArray (paths);
for (auto& s : paths)
@@ -1355,7 +1406,7 @@ public:
s = "\"" + s + "\"";
}
- return "(" + paths.joinIntoString (", ") + ")";
+ return paths;
}
private:
@@ -1561,6 +1612,8 @@ public:
private:
//==============================================================================
+ friend class CLionProjectExporter;
+
bool xcodeCanUseDwarf;
OwnedArray targets;
@@ -1685,11 +1738,16 @@ private:
void addBuildConfigurations() const
{
- // add build configurations
for (ConstConfigIterator config (*this); config.next();)
{
- const XcodeBuildConfiguration& xcodeConfig = dynamic_cast (*config);
- addProjectConfig (config->getName(), getProjectSettings (xcodeConfig));
+ const auto& xcodeConfig = dynamic_cast (*config);
+ StringArray settingsLines;
+ const auto configSettings = getProjectSettings (xcodeConfig);
+
+ for (auto& key : configSettings.getAllKeys())
+ settingsLines.add (key + " = " + configSettings[key]);
+
+ addProjectConfig (config->getName(), settingsLines);
}
}
@@ -1736,7 +1794,14 @@ private:
for (ConstConfigIterator config (*this); config.next();)
{
const XcodeBuildConfiguration& xcodeConfig = dynamic_cast (*config);
- target->addTargetConfig (config->getName(), target->getTargetSettings (xcodeConfig));
+
+ const auto configSettings = target->getTargetSettings (xcodeConfig);
+ StringArray settingsLines;
+
+ for (auto& key : configSettings.getAllKeys())
+ settingsLines.add (key + " = " + configSettings.getValue (key, "\"\""));
+
+ target->addTargetConfig (config->getName(), settingsLines);
}
addConfigList (*target, targetConfigs, createID (String ("__configList") + target->getName()));
@@ -2065,83 +2130,85 @@ private:
return sanitisePath (searchPath);
}
- StringArray getProjectSettings (const XcodeBuildConfiguration& config) const
- {
- StringArray s;
- s.add ("ALWAYS_SEARCH_USER_PATHS = NO");
- s.add ("ENABLE_STRICT_OBJC_MSGSEND = YES");
- s.add ("GCC_C_LANGUAGE_STANDARD = c11");
- s.add ("GCC_NO_COMMON_BLOCKS = YES");
- s.add ("GCC_MODEL_TUNING = G5");
- s.add ("GCC_WARN_ABOUT_RETURN_TYPE = YES");
- s.add ("GCC_WARN_CHECK_SWITCH_STATEMENTS = YES");
- s.add ("GCC_WARN_UNUSED_VARIABLE = YES");
- s.add ("GCC_WARN_MISSING_PARENTHESES = YES");
- s.add ("GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES");
- s.add ("GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES");
- s.add ("GCC_WARN_64_TO_32_BIT_CONVERSION = YES");
- s.add ("GCC_WARN_UNDECLARED_SELECTOR = YES");
- s.add ("GCC_WARN_UNINITIALIZED_AUTOS = YES");
- s.add ("GCC_WARN_UNUSED_FUNCTION = YES");
- s.add ("CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES");
- s.add ("CLANG_WARN_BOOL_CONVERSION = YES");
- s.add ("CLANG_WARN_COMMA = YES");
- s.add ("CLANG_WARN_CONSTANT_CONVERSION = YES");
- s.add ("CLANG_WARN_EMPTY_BODY = YES");
- s.add ("CLANG_WARN_ENUM_CONVERSION = YES");
- s.add ("CLANG_WARN_INFINITE_RECURSION = YES");
- s.add ("CLANG_WARN_INT_CONVERSION = YES");
- s.add ("CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES");
- s.add ("CLANG_WARN_OBJC_LITERAL_CONVERSION = YES");
- s.add ("CLANG_WARN_RANGE_LOOP_ANALYSIS = YES");
- s.add ("CLANG_WARN_STRICT_PROTOTYPES = YES");
- s.add ("CLANG_WARN_SUSPICIOUS_MOVE = YES");
- s.add ("CLANG_WARN_UNREACHABLE_CODE = YES");
- s.add ("CLANG_WARN__DUPLICATE_METHOD_MATCH = YES");
- s.add ("WARNING_CFLAGS = -Wreorder");
+ StringPairArray getProjectSettings (const XcodeBuildConfiguration& config) const
+ {
+ StringPairArray s;
+
+ s.set ("ALWAYS_SEARCH_USER_PATHS", "NO");
+ s.set ("ENABLE_STRICT_OBJC_MSGSEND", "YES");
+ s.set ("GCC_C_LANGUAGE_STANDARD", "c11");
+ s.set ("GCC_NO_COMMON_BLOCKS", "YES");
+ s.set ("GCC_MODEL_TUNING", "G5");
+ s.set ("GCC_WARN_ABOUT_RETURN_TYPE", "YES");
+ s.set ("GCC_WARN_CHECK_SWITCH_STATEMENTS", "YES");
+ s.set ("GCC_WARN_UNUSED_VARIABLE", "YES");
+ s.set ("GCC_WARN_MISSING_PARENTHESES", "YES");
+ s.set ("GCC_WARN_NON_VIRTUAL_DESTRUCTOR", "YES");
+ s.set ("GCC_WARN_TYPECHECK_CALLS_TO_PRINTF", "YES");
+ s.set ("GCC_WARN_64_TO_32_BIT_CONVERSION", "YES");
+ s.set ("GCC_WARN_UNDECLARED_SELECTOR", "YES");
+ s.set ("GCC_WARN_UNINITIALIZED_AUTOS", "YES");
+ s.set ("GCC_WARN_UNUSED_FUNCTION", "YES");
+ s.set ("CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING", "YES");
+ s.set ("CLANG_WARN_BOOL_CONVERSION", "YES");
+ s.set ("CLANG_WARN_COMMA", "YES");
+ s.set ("CLANG_WARN_CONSTANT_CONVERSION", "YES");
+ s.set ("CLANG_WARN_EMPTY_BODY", "YES");
+ s.set ("CLANG_WARN_ENUM_CONVERSION", "YES");
+ s.set ("CLANG_WARN_INFINITE_RECURSION", "YES");
+ s.set ("CLANG_WARN_INT_CONVERSION", "YES");
+ s.set ("CLANG_WARN_NON_LITERAL_NULL_CONVERSION", "YES");
+ s.set ("CLANG_WARN_OBJC_LITERAL_CONVERSION", "YES");
+ s.set ("CLANG_WARN_RANGE_LOOP_ANALYSIS", "YES");
+ s.set ("CLANG_WARN_STRICT_PROTOTYPES", "YES");
+ s.set ("CLANG_WARN_SUSPICIOUS_MOVE", "YES");
+ s.set ("CLANG_WARN_UNREACHABLE_CODE", "YES");
+ s.set ("CLANG_WARN__DUPLICATE_METHOD_MATCH", "YES");
+ s.set ("WARNING_CFLAGS", "-Wreorder");
if (projectType.isStaticLibrary())
{
- s.add ("GCC_INLINES_ARE_PRIVATE_EXTERN = NO");
- s.add ("GCC_SYMBOLS_PRIVATE_EXTERN = NO");
+ s.set ("GCC_INLINES_ARE_PRIVATE_EXTERN", "NO");
+ s.set ("GCC_SYMBOLS_PRIVATE_EXTERN", "NO");
}
else
{
- s.add ("GCC_INLINES_ARE_PRIVATE_EXTERN = YES");
+ s.set ("GCC_INLINES_ARE_PRIVATE_EXTERN", "YES");
}
if (config.isDebug())
{
- s.add ("ENABLE_TESTABILITY = YES");
+ s.set ("ENABLE_TESTABILITY", "YES");
if (config.osxArchitecture.get() == osxArch_Default || config.osxArchitecture.get().isEmpty())
- s.add ("ONLY_ACTIVE_ARCH = YES");
+ s.set ("ONLY_ACTIVE_ARCH", "YES");
}
if (iOS)
{
- s.add ("\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = " + config.codeSignIdentity.get().quoted());
- s.add ("SDKROOT = iphoneos");
- s.add (String ("TARGETED_DEVICE_FAMILY = \"") + getDeviceFamilyString() + String ("\""));
+ s.set ("\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"", config.codeSignIdentity.get().quoted());
+ s.set ("SDKROOT", "iphoneos");
+ s.set ("TARGETED_DEVICE_FAMILY", getDeviceFamilyString().quoted());
const String iosVersion (config.iosDeploymentTarget.get());
if (iosVersion.isNotEmpty() && iosVersion != osxVersionDefault)
- s.add ("IPHONEOS_DEPLOYMENT_TARGET = " + iosVersion);
+ s.set ("IPHONEOS_DEPLOYMENT_TARGET", iosVersion);
else
- s.add ("IPHONEOS_DEPLOYMENT_TARGET = 9.3");
+ s.set ("IPHONEOS_DEPLOYMENT_TARGET", "9.3");
}
else
{
if (! config.codeSignIdentity.isUsingDefault() || getIosDevelopmentTeamIDString().isNotEmpty())
- s.add ("\"CODE_SIGN_IDENTITY\" = " + config.codeSignIdentity.get().quoted());
+ s.set ("CODE_SIGN_IDENTITY", config.codeSignIdentity.get().quoted());
}
- s.add ("ZERO_LINK = NO");
+ s.set ("ZERO_LINK", "NO");
if (xcodeCanUseDwarf)
- s.add ("DEBUG_INFORMATION_FORMAT = \"dwarf\"");
+ s.set ("DEBUG_INFORMATION_FORMAT", "\"dwarf\"");
+
+ s.set ("PRODUCT_NAME", replacePreprocessorTokens (config, config.getTargetBinaryNameString()).quoted());
- s.add ("PRODUCT_NAME = \"" + replacePreprocessorTokens (config, config.getTargetBinaryNameString()) + "\"");
return s;
}
@@ -2173,8 +2240,13 @@ private:
// find all the targets that are referring to this object
for (auto& target : targets)
+ {
if (xcodeFrameworks.contains (framework) || target->xcodeFrameworks.contains (framework))
+ {
target->frameworkIDs.add (frameworkID);
+ target->frameworkNames.add (framework);
+ }
+ }
}
}
}
@@ -2260,8 +2332,10 @@ private:
if (addToSourceBuildPhase)
{
- if (xcodeTarget != nullptr) xcodeTarget->sourceIDs.add (fileID);
- else sourceIDs.add (fileID);
+ if (xcodeTarget != nullptr)
+ xcodeTarget->sourceIDs.add (fileID);
+ else
+ sourceIDs.add (fileID);
}
ValueTree* v = new ValueTree (fileID);
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp
index 742bb42149..ef1d0868c3 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp
@@ -34,6 +34,8 @@
#include "jucer_ProjectExport_Android.h"
#include "jucer_ProjectExport_CodeBlocks.h"
+#include "jucer_ProjectExport_CLion.h"
+
//==============================================================================
static void addType (Array& list,
const char* name, const void* iconData, int iconDataSize)
@@ -55,6 +57,7 @@ Array ProjectExporter::getExporterTypes()
addType (types, AndroidProjectExporter::getName(), BinaryData::export_android_svg, BinaryData::export_android_svgSize);
addType (types, CodeBlocksProjectExporter::getNameWindows(), BinaryData::export_codeBlocks_svg, BinaryData::export_codeBlocks_svgSize);
addType (types, CodeBlocksProjectExporter::getNameLinux(), BinaryData::export_codeBlocks_svg, BinaryData::export_codeBlocks_svgSize);
+ addType (types, CLionProjectExporter::getName(), BinaryData::export_clion_svg, BinaryData::export_clion_svgSize);
return types;
}
@@ -74,7 +77,7 @@ ProjectExporter* ProjectExporter::createNewExporter (Project& project, const int
case 6: exp = new AndroidProjectExporter (project, ValueTree (AndroidProjectExporter ::getValueTreeTypeName())); break;
case 7: exp = new CodeBlocksProjectExporter (project, ValueTree (CodeBlocksProjectExporter ::getValueTreeTypeName (CodeBlocksProjectExporter::windowsTarget)), CodeBlocksProjectExporter::windowsTarget); break;
case 8: exp = new CodeBlocksProjectExporter (project, ValueTree (CodeBlocksProjectExporter ::getValueTreeTypeName (CodeBlocksProjectExporter::linuxTarget)), CodeBlocksProjectExporter::linuxTarget); break;
- default: jassertfalse; return 0;
+ case 9: exp = new CLionProjectExporter (project, ValueTree (CLionProjectExporter ::getValueTreeTypeName())); break;
}
exp->createDefaultConfigs();
@@ -122,6 +125,9 @@ String ProjectExporter::getValueTreeNameForExporter (const String& exporterName)
if (exporterName == CodeBlocksProjectExporter::getNameWindows())
return CodeBlocksProjectExporter::getValueTreeTypeName (CodeBlocksProjectExporter::CodeBlocksOS::windowsTarget);
+ if (exporterName == CLionProjectExporter::getName())
+ return CLionProjectExporter::getValueTreeTypeName();
+
return {};
}
@@ -138,6 +144,7 @@ StringArray ProjectExporter::getAllDefaultBuildsFolders()
folders.add (getDefaultBuildsRootFolder() + "CodeBlocksWindows");
folders.add (getDefaultBuildsRootFolder() + "CodeBlocksLinux");
folders.add (getDefaultBuildsRootFolder() + "Android");
+ folders.add (getDefaultBuildsRootFolder() + "CLion");
return folders;
}
@@ -169,6 +176,7 @@ ProjectExporter* ProjectExporter::createExporter (Project& project, const ValueT
if (exp == nullptr) exp = MakefileProjectExporter ::createForSettings (project, settings);
if (exp == nullptr) exp = AndroidProjectExporter ::createForSettings (project, settings);
if (exp == nullptr) exp = CodeBlocksProjectExporter ::createForSettings (project, settings);
+ if (exp == nullptr) exp = CLionProjectExporter ::createForSettings (project, settings);
jassert (exp != nullptr);
return exp;
@@ -247,33 +255,36 @@ bool ProjectExporter::shouldFileBeCompiledByDefault (const RelativePath& file) c
//==============================================================================
void ProjectExporter::createPropertyEditors (PropertyListBuilder& props)
{
- props.add (new TextPropertyComponent (getTargetLocationValue(), "Target Project Folder", 2048, false),
- "The location of the folder in which the " + name + " project will be created. "
- "This path can be absolute, but it's much more sensible to make it relative to the jucer project directory.");
+ if (! isCLion())
+ {
+ props.add (new TextPropertyComponent (getTargetLocationValue(), "Target Project Folder", 2048, false),
+ "The location of the folder in which the " + name + " project will be created. "
+ "This path can be absolute, but it's much more sensible to make it relative to the jucer project directory.");
- createDependencyPathProperties (props);
+ createDependencyPathProperties (props);
- props.add (new TextPropertyComponent (getExporterPreprocessorDefs(), "Extra Preprocessor Definitions", 32768, true),
- "Extra preprocessor definitions. Use the form \"NAME1=value NAME2=value\", using whitespace, commas, "
- "or new-lines to separate the items - to include a space or comma in a definition, precede it with a backslash.");
+ props.add (new TextPropertyComponent (getExporterPreprocessorDefs(), "Extra Preprocessor Definitions", 32768, true),
+ "Extra preprocessor definitions. Use the form \"NAME1=value NAME2=value\", using whitespace, commas, "
+ "or new-lines to separate the items - to include a space or comma in a definition, precede it with a backslash.");
- props.add (new TextPropertyComponent (getExtraCompilerFlags(), "Extra compiler flags", 8192, true),
- "Extra command-line flags to be passed to the compiler. This string can contain references to preprocessor definitions in the "
- "form ${NAME_OF_DEFINITION}, which will be replaced with their values.");
+ props.add (new TextPropertyComponent (getExtraCompilerFlags(), "Extra compiler flags", 8192, true),
+ "Extra command-line flags to be passed to the compiler. This string can contain references to preprocessor definitions in the "
+ "form ${NAME_OF_DEFINITION}, which will be replaced with their values.");
- props.add (new TextPropertyComponent (getExtraLinkerFlags(), "Extra linker flags", 8192, true),
- "Extra command-line flags to be passed to the linker. You might want to use this for adding additional libraries. "
- "This string can contain references to preprocessor definitions in the form ${NAME_OF_VALUE}, which will be replaced with their values.");
+ props.add (new TextPropertyComponent (getExtraLinkerFlags(), "Extra linker flags", 8192, true),
+ "Extra command-line flags to be passed to the linker. You might want to use this for adding additional libraries. "
+ "This string can contain references to preprocessor definitions in the form ${NAME_OF_VALUE}, which will be replaced with their values.");
- props.add (new TextPropertyComponent (getExternalLibraries(), "External libraries to link", 8192, true),
- "Additional libraries to link (one per line). You should not add any platform specific decoration to these names. "
- "This string can contain references to preprocessor definitions in the form ${NAME_OF_VALUE}, which will be replaced with their values.");
+ props.add (new TextPropertyComponent (getExternalLibraries(), "External libraries to link", 8192, true),
+ "Additional libraries to link (one per line). You should not add any platform specific decoration to these names. "
+ "This string can contain references to preprocessor definitions in the form ${NAME_OF_VALUE}, which will be replaced with their values.");
- if (! isVisualStudio())
- props.add (new BooleanPropertyComponent (getShouldUseGNUExtensionsValue(), "GNU Compiler Extensions", "Enabled"),
- "Enabling this will use the GNU C++ language standard variant for compilation.");
+ if (! isVisualStudio())
+ props.add (new BooleanPropertyComponent (getShouldUseGNUExtensionsValue(), "GNU Compiler Extensions", "Enabled"),
+ "Enabling this will use the GNU C++ language standard variant for compilation.");
- createIconProperties (props);
+ createIconProperties (props);
+ }
createExporterProperties (props);
@@ -944,20 +955,6 @@ StringArray ProjectExporter::BuildConfiguration::getLibrarySearchPaths() const
return s;
}
-String ProjectExporter::BuildConfiguration::getGCCLibraryPathFlags() const
-{
- String s;
- const auto libraryPaths = getSearchPathsFromString (getLibrarySearchPathString());
-
- for (auto path : libraryPaths)
- s << " -L" << escapeSpaces (path).replace ("~", "$(HOME)");
-
- for (auto path : exporter.moduleLibSearchPaths)
- s << " -L" << escapeSpaces (path).replace ("~", "$(HOME)") << "/" << getModuleLibraryArchName();
-
- return s;
-}
-
String ProjectExporter::getExternalLibraryFlags (const BuildConfiguration& config) const
{
StringArray libraries;
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h
index 9d68a020f6..f219c8c7bb 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h
@@ -88,6 +88,7 @@ public:
virtual bool isCodeBlocks() const = 0;
virtual bool isMakefile() const = 0;
virtual bool isAndroidStudio() const = 0;
+ virtual bool isCLion() const = 0;
// operating system targeted by exporter
virtual bool isAndroid() const = 0;
@@ -96,6 +97,8 @@ public:
virtual bool isOSX() const = 0;
virtual bool isiOS() const = 0;
+ virtual String getDescription() { return {}; }
+
//==============================================================================
// cross-platform audio plug-ins supported by exporter
virtual bool supportsTargetType (ProjectType::Target::Type type) const = 0;
@@ -242,7 +245,6 @@ public:
virtual var getDefaultOptimisationLevel() const = 0;
virtual String getModuleLibraryArchName() const = 0;
-
//==============================================================================
Value getNameValue() { return getValue (Ids::name); }
String getName() const { return config [Ids::name]; }
@@ -341,7 +343,7 @@ public:
BuildConfiguration::Ptr getConfiguration (int index) const;
ValueTree getConfigurations() const;
- void createDefaultConfigs();
+ virtual void createDefaultConfigs();
void createDefaultModulePaths();
//==============================================================================
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp
index c0702a0557..4aee5d78f5 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp
@@ -27,6 +27,8 @@
#include "../Application/jucer_Headers.h"
#include "jucer_ProjectSaver.h"
+#include "jucer_ProjectExport_CLion.h"
+
//==============================================================================
namespace
{
@@ -147,3 +149,79 @@ void ProjectSaver::writePluginCharacteristicsFile()
setExtraAppConfigFileContent (mem.toString());
}
+
+void ProjectSaver::writeProjects (const OwnedArray& modules, const String& specifiedExporterToSave, bool isCommandLineApp)
+{
+ ThreadPool threadPool;
+
+ // keep a copy of the basic generated files group, as each exporter may modify it.
+ const ValueTree originalGeneratedGroup (generatedFilesGroup.state.createCopy());
+
+ CLionProjectExporter* clionExporter = nullptr;
+ OwnedArray exporters;
+
+ try
+ {
+ for (Project::ExporterIterator exp (project); exp.next();)
+ {
+ if (specifiedExporterToSave.isNotEmpty() && exp->getName() != specifiedExporterToSave)
+ continue;
+
+ auto* exporter = exporters.add (exp.exporter.release());
+
+ exporter->initialiseDependencyPathValues();
+
+ if (exporter->getTargetFolder().createDirectory())
+ {
+ if (exporter->isCLion())
+ {
+ clionExporter = dynamic_cast (exporter);
+ }
+ else
+ {
+ exporter->copyMainGroupFromProject();
+ exporter->settings = exporter->settings.createCopy();
+
+ exporter->addToExtraSearchPaths (RelativePath ("JuceLibraryCode", RelativePath::projectFolder));
+
+ generatedFilesGroup.state = originalGeneratedGroup.createCopy();
+ exporter->addSettingsForProjectType (project.getProjectType());
+
+ for (auto& module: modules)
+ module->addSettingsForModuleToExporter (*exporter, *this);
+
+ if (project.getProjectType().isAudioPlugin())
+ writePluginCharacteristicsFile();
+
+ generatedFilesGroup.sortAlphabetically (true, true);
+ exporter->getAllGroups().add (generatedFilesGroup);
+ }
+
+ if (isCommandLineApp)
+ saveExporter (exporter, modules);
+ else
+ threadPool.addJob (new ExporterJob (*this, exporter, modules), true);
+ }
+ else
+ {
+ addError ("Can't create folder: " + exporter->getTargetFolder().getFullPathName());
+ }
+ }
+ }
+ catch (ProjectExporter::SaveError& saveError)
+ {
+ addError (saveError.message);
+ }
+
+ if (! isCommandLineApp)
+ while (threadPool.getNumJobs() > 0)
+ Thread::sleep (10);
+
+ if (clionExporter != nullptr)
+ {
+ for (auto* exporter : exporters)
+ clionExporter->writeCMakeListsExporterSection (exporter);
+
+ std::cout << "Finished saving: " << clionExporter->getName() << std::endl;
+ }
+}
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h
index 63978b62d5..657daf76cd 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h
@@ -659,68 +659,16 @@ private:
void writePluginCharacteristicsFile();
- void writeProjects (const OwnedArray& modules, const String& specifiedExporterToSave, bool isCommandLineApp)
- {
- ThreadPool threadPool;
-
- // keep a copy of the basic generated files group, as each exporter may modify it.
- const ValueTree originalGeneratedGroup (generatedFilesGroup.state.createCopy());
-
- try
- {
- for (Project::ExporterIterator exporter (project); exporter.next();)
- {
- if (specifiedExporterToSave.isNotEmpty() && exporter->getName() != specifiedExporterToSave)
- continue;
-
- exporter->initialiseDependencyPathValues();
-
- if (exporter->getTargetFolder().createDirectory())
- {
- exporter->copyMainGroupFromProject();
- exporter->settings = exporter->settings.createCopy();
-
- exporter->addToExtraSearchPaths (RelativePath ("JuceLibraryCode", RelativePath::projectFolder));
-
- generatedFilesGroup.state = originalGeneratedGroup.createCopy();
- exporter->addSettingsForProjectType (project.getProjectType());
-
- for (auto& module: modules)
- module->addSettingsForModuleToExporter (*exporter, *this);
-
- if (project.getProjectType().isAudioPlugin())
- writePluginCharacteristicsFile();
-
- generatedFilesGroup.sortAlphabetically (true, true);
- exporter->getAllGroups().add (generatedFilesGroup);
-
- if (isCommandLineApp)
- saveExporter (exporter.exporter, modules);
- else
- threadPool.addJob (new ExporterJob (*this, exporter.exporter.release(), modules), true);
- }
- else
- {
- addError ("Can't create folder: " + exporter->getTargetFolder().getFullPathName());
- }
- }
- }
- catch (ProjectExporter::SaveError& saveError)
- {
- addError (saveError.message);
- }
-
- if (! isCommandLineApp)
- while (threadPool.getNumJobs() > 0)
- Thread::sleep (10);
- }
+ void writeProjects (const OwnedArray&, const String&, bool);
void saveExporter (ProjectExporter* exporter, const OwnedArray& modules)
{
try
{
exporter->create (modules);
- std::cout << "Finished saving: " << exporter->getName() << std::endl;
+
+ if (! exporter->isCLion())
+ std::cout << "Finished saving: " << exporter->getName() << std::endl;
}
catch (ProjectExporter::SaveError& error)
{
diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
index 4ecb384033..a4cb144410 100644
--- a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
+++ b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
@@ -212,6 +212,9 @@ namespace Ids
DECLARE_ID (gradleToolchain);
DECLARE_ID (gradleToolchainVersion);
DECLARE_ID (linuxExtraPkgConfig);
+ DECLARE_ID (clionMakefileEnabled);
+ DECLARE_ID (clionXcodeEnabled);
+ DECLARE_ID (clionCodeBlocksEnabled);
DECLARE_ID (font);
DECLARE_ID (colour);
DECLARE_ID (userNotes);
diff --git a/extras/Projucer/Source/Utility/UI/jucer_Icons.cpp b/extras/Projucer/Source/Utility/UI/jucer_Icons.cpp
index 63d2da435d..200d542f13 100644
--- a/extras/Projucer/Source/Utility/UI/jucer_Icons.cpp
+++ b/extras/Projucer/Source/Utility/UI/jucer_Icons.cpp
@@ -1541,6 +1541,14 @@ const uint8 xcode[] = { 110,109,72,225,2,66,41,92,31,64,108,72,225,2,66,40,92,31
const uint8 visualStudio[] = { 110,109,0,0,112,65,0,0,0,0,108,0,0,227,64,0,0,253,64,108,0,0,0,64,0,0,128,64,108,0,0,0,0,0,0,160,64,108,0,0,0,0,0,0,112,65,108,0,0,0,64,0,0,128,65,108,0,0,224,64,0,0,64,65,108,0,0,112,65,0,0,160,65,108,0,0,160,65,0,0,144,65,108,0,0,160,65,0,0,0,64,108,
0,0,112,65,0,0,0,0,99,109,0,0,112,65,0,0,192,64,108,0,0,112,65,0,0,96,65,108,0,176,26,65,0,0,32,65,108,0,0,112,65,0,0,192,64,99,109,0,0,0,64,0,0,224,64,108,0,0,162,64,0,0,31,65,108,0,0,0,64,0,0,80,65,108,0,0,0,64,0,0,224,64,99,101,0,0 };
+const uint8 clion[] = { 110,109,0,0,0,0,0,0,0,0,98,0,0,0,0,170,170,38,67,0,0,0,0,171,170,166,67,0,0,0,0,0,0,250,67,98,170,170,38,67,0,0,250,67,171,170,166,67,0,0,250,67,0,0,250,67,0,0,250,67,98,0,0,250,67,171,170,166,67,0,0,250,67,170,170,38,67,0,0,250,67,0,0,0,0,98,171,170,
+ 166,67,0,0,0,0,170,170,38,67,0,0,0,0,0,0,0,0,0,0,0,0,99,109,246,164,21,67,176,231,121,66,98,120,35,52,67,168,63,118,66,22,248,83,67,248,250,142,66,0,128,104,67,0,0,190,66,98,172,234,94,67,0,128,212,66,86,85,85,67,0,0,235,66,2,192,75,67,0,192,0,67,98,
+ 180,250,52,67,80,226,207,66,62,108,10,67,92,105,190,66,32,159,224,66,108,117,239,66,98,40,200,154,66,148,71,22,67,110,149,174,66,254,37,89,67,80,183,4,67,52,0,104,67,98,100,211,30,67,88,243,112,67,134,23,59,67,212,126,101,67,252,63,78,67,0,64,83,67,98,
+ 84,213,87,67,86,213,92,67,170,106,97,67,174,106,102,67,0,0,107,67,2,0,112,67,98,28,218,67,67,144,199,143,67,12,199,231,66,24,70,145,67,174,142,147,66,200,71,117,67,98,16,130,199,65,74,191,69,67,80,114,21,66,130,44,211,66,170,64,198,66,178,0,150,66,98,
+ 176,33,229,66,124,94,133,66,160,27,4,67,84,87,121,66,246,164,21,67,176,231,121,66,99,109,0,32,133,67,2,0,130,66,98,85,213,140,67,2,0,130,66,171,138,148,67,2,0,130,66,0,64,156,67,2,0,130,66,98,0,64,156,67,0,128,242,66,0,64,156,67,0,128,49,67,0,64,156,
+ 67,4,192,105,67,98,1,64,171,67,4,192,105,67,0,64,186,67,4,192,105,67,0,64,201,67,4,192,105,67,98,0,64,201,67,174,170,118,67,0,64,201,67,171,202,129,67,0,64,201,67,1,64,136,67,98,170,138,178,67,1,64,136,67,86,213,155,67,1,64,136,67,0,32,133,67,1,64,136,
+ 67,98,0,32,133,67,88,85,75,67,0,32,133,67,174,42,6,67,0,32,133,67,4,0,130,66,99,109,0,0,62,66,254,31,203,67,98,0,0,220,66,254,31,203,67,0,128,44,67,254,31,203,67,0,0,107,67,254,31,203,67,98,0,0,107,67,84,85,208,67,0,0,107,67,170,138,213,67,0,0,107,67,
+ 0,192,218,67,98,0,128,44,67,0,192,218,67,0,0,220,66,0,192,218,67,252,255,61,66,0,192,218,67,98,252,255,61,66,170,138,213,67,252,255,61,66,84,85,208,67,252,255,61,66,254,31,203,67,99,101,0,0 };
}
/*static void convertSVGPathToCppData (const String& pathString)
@@ -1612,4 +1620,5 @@ Icons::Icons()
JUCE_LOAD_PATH_DATA (linux);
JUCE_LOAD_PATH_DATA (xcode);
JUCE_LOAD_PATH_DATA (visualStudio);
+ JUCE_LOAD_PATH_DATA (clion);
}
diff --git a/extras/Projucer/Source/Utility/UI/jucer_Icons.h b/extras/Projucer/Source/Utility/UI/jucer_Icons.h
index 6e3dc6e746..d605dd7813 100644
--- a/extras/Projucer/Source/Utility/UI/jucer_Icons.h
+++ b/extras/Projucer/Source/Utility/UI/jucer_Icons.h
@@ -81,7 +81,7 @@ public:
Path user, closedFolder, exporter, fileExplorer, file,
buildTab, modules, openFolder, play, settings, singleModule,
buildNow, continuousBuildStart, continuousBuildStop, edit, plus,
- android, codeBlocks, linux, xcode, visualStudio;
+ android, codeBlocks, linux, xcode, visualStudio, clion;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Icons)