The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1183 lines
55KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For this technical preview, this file is not subject to commercial licensing.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. #pragma once
  14. #include "jucer_ProjectExport_CodeBlocks.h"
  15. #include "jucer_ProjectExport_Make.h"
  16. #include "jucer_ProjectExport_Xcode.h"
  17. //==============================================================================
  18. class CLionProjectExporter : public ProjectExporter
  19. {
  20. protected:
  21. //==============================================================================
  22. class CLionBuildConfiguration : public BuildConfiguration
  23. {
  24. public:
  25. CLionBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e)
  26. : BuildConfiguration (p, settings, e)
  27. {
  28. }
  29. void createConfigProperties (PropertyListBuilder&) override {}
  30. String getModuleLibraryArchName() const override { return {}; }
  31. };
  32. BuildConfiguration::Ptr createBuildConfig (const ValueTree& tree) const override
  33. {
  34. return *new CLionBuildConfiguration (project, tree, *this);
  35. }
  36. public:
  37. //==============================================================================
  38. static String getDisplayName() { return "CLion (beta)"; }
  39. static String getValueTreeTypeName() { return "CLION"; }
  40. static String getTargetFolderName() { return "CLion"; }
  41. static CLionProjectExporter* createForSettings (Project& projectToUse, const ValueTree& settingsToUse)
  42. {
  43. if (settingsToUse.hasType (getValueTreeTypeName()))
  44. return new CLionProjectExporter (projectToUse, settingsToUse);
  45. return nullptr;
  46. }
  47. static bool isExporterSupported (const ProjectExporter& exporter)
  48. {
  49. return exporter.isMakefile()
  50. || (exporter.isXcode() && ! exporter.isiOS())
  51. || (exporter.isCodeBlocks() && exporter.isWindows());
  52. }
  53. //==============================================================================
  54. CLionProjectExporter (Project& p, const ValueTree& t) : ProjectExporter (p, t)
  55. {
  56. name = getDisplayName();
  57. targetLocationValue.setDefault (getDefaultBuildsRootFolder() + getTargetFolderName());
  58. }
  59. //==============================================================================
  60. bool usesMMFiles() const override { return false; }
  61. bool canCopeWithDuplicateFiles() override { return false; }
  62. bool supportsUserDefinedConfigurations() const override { return false; }
  63. bool isXcode() const override { return false; }
  64. bool isVisualStudio() const override { return false; }
  65. bool isCodeBlocks() const override { return false; }
  66. bool isMakefile() const override { return false; }
  67. bool isAndroidStudio() const override { return false; }
  68. bool isCLion() const override { return true; }
  69. bool isAndroid() const override { return false; }
  70. bool isWindows() const override { return false; }
  71. bool isLinux() const override { return false; }
  72. bool isOSX() const override { return false; }
  73. bool isiOS() const override { return false; }
  74. bool supportsTargetType (build_tools::ProjectType::Target::Type) const override { return true; }
  75. void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override {}
  76. //==============================================================================
  77. bool canLaunchProject() override
  78. {
  79. #if JUCE_MAC
  80. static Identifier exporterName (XcodeProjectExporter::getValueTreeTypeNameMac());
  81. #elif JUCE_WINDOWS
  82. static Identifier exporterName (CodeBlocksProjectExporter::getValueTreeTypeNameWindows());
  83. #elif JUCE_LINUX
  84. static Identifier exporterName (MakefileProjectExporter::getValueTreeTypeName());
  85. #else
  86. static Identifier exporterName;
  87. #endif
  88. if (getProject().getExporters().getChildWithName (exporterName).isValid())
  89. return getCLionExecutableOrApp().exists();
  90. return false;
  91. }
  92. bool launchProject() override
  93. {
  94. return getCLionExecutableOrApp().startAsProcess (getTargetFolder().getFullPathName().quoted());
  95. }
  96. String getDescription() override
  97. {
  98. String description;
  99. description << "The " << getDisplayName() << " exporter produces a single CMakeLists.txt file with "
  100. << "multiple platform dependent sections, where the configuration for each section "
  101. << "is inherited from other exporters added to this project." << newLine
  102. << newLine
  103. << "The exporters which provide the CLion configuration for the corresponding platform are:" << newLine
  104. << newLine;
  105. for (auto& exporterInfo : getExporterTypeInfos())
  106. {
  107. std::unique_ptr<ProjectExporter> exporter (createNewExporter (getProject(), exporterInfo.identifier));
  108. if (isExporterSupported (*exporter))
  109. description << exporterInfo.displayName << newLine;
  110. }
  111. description << newLine
  112. << "Add these exporters to the project to enable CLion builds." << newLine
  113. << newLine
  114. << "Not all features of all the exporters are currently supported. Notable omissions are AUv3 "
  115. << "plug-ins, embedding resources and fat binaries on MacOS. On Windows the CLion exporter "
  116. << "requires a GCC-based compiler like MinGW.";
  117. return description;
  118. }
  119. void createExporterProperties (PropertyListBuilder& properties) override
  120. {
  121. for (Project::ExporterIterator exporter (getProject()); exporter.next();)
  122. if (isExporterSupported (*exporter))
  123. properties.add (new BooleanPropertyComponent (getExporterEnabledValue (*exporter), "Import settings from exporter", exporter->getUniqueName()),
  124. "If this is enabled then settings from the corresponding exporter will "
  125. "be used in the generated CMakeLists.txt");
  126. }
  127. void createDefaultConfigs() override {}
  128. void create (const OwnedArray<LibraryModule>&) const override
  129. {
  130. // We'll append to this later.
  131. build_tools::writeStreamToFile (getTargetFolder().getChildFile ("CMakeLists.txt"), [] (MemoryOutputStream& mo)
  132. {
  133. mo.setNewLineString ("\n");
  134. mo << "# Automatically generated CMakeLists, created by the Projucer" << newLine
  135. << "# Do not edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine
  136. << newLine;
  137. mo << "cmake_minimum_required (VERSION 3.4.1)" << newLine
  138. << newLine;
  139. mo << "if (NOT CMAKE_BUILD_TYPE)" << newLine
  140. << " set (CMAKE_BUILD_TYPE \"Debug\" CACHE STRING \"Choose the type of build.\" FORCE)" << newLine
  141. << "endif (NOT CMAKE_BUILD_TYPE)" << newLine
  142. << newLine;
  143. });
  144. // CMake has stopped adding PkgInfo files to bundles, so we need to do it manually
  145. build_tools::writeStreamToFile (getTargetFolder().getChildFile ("PkgInfo"),
  146. [] (MemoryOutputStream& mo) { mo << "BNDL????"; });
  147. }
  148. void writeCMakeListsExporterSection (ProjectExporter* exporter) const
  149. {
  150. if (! (isExporterSupported (*exporter) && isExporterEnabled (*exporter)))
  151. return;
  152. MemoryBlock existingContent;
  153. getTargetFolder().getChildFile ("CMakeLists.txt").loadFileAsData (existingContent);
  154. MemoryOutputStream out (existingContent, true);
  155. out.setNewLineString ("\n");
  156. out << "###############################################################################" << newLine
  157. << "# " << exporter->getUniqueName() << newLine
  158. << "###############################################################################" << newLine
  159. << newLine;
  160. if (auto* makefileExporter = dynamic_cast<MakefileProjectExporter*> (exporter))
  161. {
  162. out << "if (UNIX AND NOT APPLE)" << newLine << newLine;
  163. writeCMakeListsMakefileSection (out, *makefileExporter);
  164. }
  165. else if (auto* xcodeExporter = dynamic_cast<XcodeProjectExporter*> (exporter))
  166. {
  167. out << "if (APPLE)" << newLine << newLine;
  168. writeCMakeListsXcodeSection (out, *xcodeExporter);
  169. }
  170. else if (auto* codeBlocksExporter = dynamic_cast<CodeBlocksProjectExporter*> (exporter))
  171. {
  172. out << "if (WIN32)" << newLine << newLine;
  173. writeCMakeListsCodeBlocksSection (out, *codeBlocksExporter);
  174. }
  175. out << "endif()" << newLine << newLine;
  176. build_tools::overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("CMakeLists.txt"), out);
  177. }
  178. private:
  179. //==============================================================================
  180. static File getCLionExecutableOrApp()
  181. {
  182. File clionExeOrApp (getAppSettings()
  183. .getStoredPath (Ids::clionExePath, TargetOS::getThisOS()).get()
  184. .toString()
  185. .replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName()));
  186. #if JUCE_MAC
  187. if (clionExeOrApp.getFullPathName().endsWith ("/Contents/MacOS/clion"))
  188. clionExeOrApp = clionExeOrApp.getParentDirectory()
  189. .getParentDirectory()
  190. .getParentDirectory();
  191. #endif
  192. return clionExeOrApp;
  193. }
  194. //==============================================================================
  195. Identifier getExporterEnabledId (const ProjectExporter& exporter) const
  196. {
  197. jassert (isExporterSupported (exporter));
  198. if (exporter.isMakefile()) return Ids::clionMakefileEnabled;
  199. else if (exporter.isXcode()) return Ids::clionXcodeEnabled;
  200. else if (exporter.isCodeBlocks()) return Ids::clionCodeBlocksEnabled;
  201. jassertfalse;
  202. return {};
  203. }
  204. bool isExporterEnabled (const ProjectExporter& exporter) const
  205. {
  206. auto setting = settings[getExporterEnabledId (exporter)];
  207. return setting.isVoid() || setting;
  208. }
  209. Value getExporterEnabledValue (const ProjectExporter& exporter)
  210. {
  211. auto enabledID = getExporterEnabledId (exporter);
  212. getSetting (enabledID) = isExporterEnabled (exporter);
  213. return getSetting (enabledID);
  214. }
  215. //==============================================================================
  216. static bool isWindowsAbsolutePath (const String& path)
  217. {
  218. return path.length() > 1 && path[1] == ':';
  219. }
  220. static bool isUnixAbsolutePath (const String& path)
  221. {
  222. return path.isNotEmpty() && (path[0] == '/' || path[0] == '~' || path.startsWith ("$ENV{HOME}"));
  223. }
  224. //==============================================================================
  225. static String setCMakeVariable (const String& variableName, const String& value)
  226. {
  227. return "set (" + variableName + " \"" + value + "\")";
  228. }
  229. static String addToCMakeVariable (const String& variableName, const String& value)
  230. {
  231. return setCMakeVariable (variableName, "${" + variableName + "} " + value);
  232. }
  233. static String getTargetVarName (build_tools::ProjectType::Target& target)
  234. {
  235. return String (target.getName()).toUpperCase().replaceCharacter (L' ', L'_');
  236. }
  237. template <class Target, class Exporter>
  238. void getFileInfoList (Target& target, Exporter& exporter, const Project::Item& projectItem, std::vector<std::tuple<String, bool, String>>& fileInfoList) const
  239. {
  240. auto targetType = (getProject().isAudioPluginProject() ? target.type : Target::Type::SharedCodeTarget);
  241. if (projectItem.isGroup())
  242. {
  243. for (int i = 0; i < projectItem.getNumChildren(); ++i)
  244. getFileInfoList (target, exporter, projectItem.getChild(i), fileInfoList);
  245. }
  246. else if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (*this)
  247. && getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType )
  248. {
  249. auto path = build_tools::RelativePath (projectItem.getFile(), exporter.getTargetFolder(), build_tools::RelativePath::buildTargetFolder).toUnixStyle();
  250. fileInfoList.push_back (std::make_tuple (path, projectItem.shouldBeCompiled(),
  251. exporter.compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString()));
  252. }
  253. }
  254. template <class Exporter>
  255. void writeCMakeTargets (OutputStream& out, Exporter& exporter) const
  256. {
  257. for (auto* target : exporter.targets)
  258. {
  259. if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget
  260. || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn)
  261. continue;
  262. String functionName;
  263. StringArray properties;
  264. switch (target->getTargetFileType())
  265. {
  266. case build_tools::ProjectType::Target::TargetFileType::executable:
  267. functionName = "add_executable";
  268. if (exporter.isCodeBlocks() && exporter.isWindows()
  269. && target->type !=
  270. build_tools::ProjectType::Target::Type::ConsoleApp)
  271. properties.add ("WIN32");
  272. break;
  273. case build_tools::ProjectType::Target::TargetFileType::staticLibrary:
  274. case build_tools::ProjectType::Target::TargetFileType::sharedLibraryOrDLL:
  275. case build_tools::ProjectType::Target::TargetFileType::pluginBundle:
  276. functionName = "add_library";
  277. if (target->getTargetFileType() ==
  278. build_tools::ProjectType::Target::TargetFileType::staticLibrary)
  279. properties.add ("STATIC");
  280. else if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::sharedLibraryOrDLL)
  281. properties.add ("SHARED");
  282. else
  283. properties.add ("MODULE");
  284. break;
  285. case build_tools::ProjectType::Target::TargetFileType::macOSAppex:
  286. case build_tools::ProjectType::Target::TargetFileType::unknown:
  287. default:
  288. continue;
  289. }
  290. out << functionName << " (" << getTargetVarName (*target);
  291. if (! properties.isEmpty())
  292. out << " " << properties.joinIntoString (" ");
  293. out << newLine;
  294. std::vector<std::tuple<String, bool, String>> fileInfoList;
  295. for (auto& group : exporter.getAllGroups())
  296. getFileInfoList (*target, exporter, group, fileInfoList);
  297. for (auto& fileInfo : fileInfoList)
  298. out << " " << std::get<0> (fileInfo).quoted() << newLine;
  299. auto isCMakeBundle = exporter.isXcode()
  300. && target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle;
  301. auto pkgInfoPath = String ("PkgInfo").quoted();
  302. if (isCMakeBundle)
  303. out << " " << pkgInfoPath << newLine;
  304. auto xcodeIcnsFilePath = [&] () -> String
  305. {
  306. if (exporter.isXcode()
  307. && target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable)
  308. {
  309. StringArray pathComponents = { "..", "MacOSX", "Icon.icns" };
  310. auto xcodeIcnsFile = getTargetFolder();
  311. for (auto& comp : pathComponents)
  312. xcodeIcnsFile = xcodeIcnsFile.getChildFile (comp);
  313. if (xcodeIcnsFile.existsAsFile())
  314. return pathComponents.joinIntoString ("/").quoted();
  315. }
  316. return {};
  317. }();
  318. if (xcodeIcnsFilePath.isNotEmpty())
  319. out << " " << xcodeIcnsFilePath << newLine;
  320. if (exporter.isCodeBlocks()
  321. && target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable)
  322. {
  323. StringArray pathComponents = { "..", "CodeBlocksWindows", "resources.rc" };
  324. auto windowsRcFile = getTargetFolder();
  325. for (auto& comp : pathComponents)
  326. windowsRcFile = windowsRcFile.getChildFile (comp);
  327. if (windowsRcFile.existsAsFile())
  328. out << " " << pathComponents.joinIntoString ("/").quoted() << newLine;
  329. }
  330. out << ")" << newLine << newLine;
  331. if (isCMakeBundle)
  332. out << "set_source_files_properties (" << pkgInfoPath << " PROPERTIES MACOSX_PACKAGE_LOCATION .)" << newLine;
  333. if (xcodeIcnsFilePath.isNotEmpty())
  334. out << "set_source_files_properties (" << xcodeIcnsFilePath << " PROPERTIES MACOSX_PACKAGE_LOCATION \"Resources\")" << newLine;
  335. for (auto& fileInfo : fileInfoList)
  336. {
  337. if (std::get<1> (fileInfo))
  338. {
  339. auto extraCompilerFlags = std::get<2> (fileInfo);
  340. if (extraCompilerFlags.isNotEmpty())
  341. out << "set_source_files_properties(" << std::get<0> (fileInfo).quoted() << " PROPERTIES COMPILE_FLAGS " << extraCompilerFlags << " )" << newLine;
  342. }
  343. else
  344. {
  345. out << "set_source_files_properties (" << std::get<0> (fileInfo).quoted() << " PROPERTIES HEADER_FILE_ONLY TRUE)" << newLine;
  346. }
  347. }
  348. out << newLine;
  349. }
  350. }
  351. //==============================================================================
  352. void writeCMakeListsMakefileSection (OutputStream& out, MakefileProjectExporter& exporter) const
  353. {
  354. out << "project (" << getProject().getProjectNameString().quoted() << " C CXX)" << newLine
  355. << newLine;
  356. out << "find_package (PkgConfig REQUIRED)" << newLine;
  357. StringArray cmakePkgconfigPackages;
  358. for (auto& package : exporter.getPackages())
  359. {
  360. cmakePkgconfigPackages.add (package.toUpperCase());
  361. out << "pkg_search_module (" << cmakePkgconfigPackages.strings.getLast() << " REQUIRED " << package << ")" << newLine;
  362. }
  363. out << newLine;
  364. writeCMakeTargets (out, exporter);
  365. for (auto* target : exporter.targets)
  366. {
  367. if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget)
  368. continue;
  369. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle)
  370. out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES PREFIX \"\")" << newLine;
  371. out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX \"" << target->getTargetFileSuffix() << "\")" << newLine
  372. << newLine;
  373. }
  374. for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
  375. {
  376. auto& config = dynamic_cast<const MakefileProjectExporter::MakeBuildConfiguration&> (*c);
  377. out << "#------------------------------------------------------------------------------" << newLine
  378. << "# Config: " << config.getName() << newLine
  379. << "#------------------------------------------------------------------------------" << newLine
  380. << newLine;
  381. auto buildTypeCondition = String ("CMAKE_BUILD_TYPE STREQUAL " + config.getName());
  382. out << "if (" << buildTypeCondition << ")" << newLine
  383. << newLine;
  384. out << "execute_process (COMMAND uname -m OUTPUT_VARIABLE JUCE_ARCH_LABEL OUTPUT_STRIP_TRAILING_WHITESPACE)" << newLine
  385. << newLine;
  386. out << "include_directories (" << newLine;
  387. for (auto& path : exporter.getHeaderSearchPaths (config))
  388. out << " " << path.quoted() << newLine;
  389. for (auto& package : cmakePkgconfigPackages)
  390. out << " ${" << package << "_INCLUDE_DIRS}" << newLine;
  391. out << ")" << newLine << newLine;
  392. StringArray cmakeFoundLibraries;
  393. for (auto& library : exporter.getLibraryNames (config))
  394. {
  395. String cmakeLibraryID (library.toUpperCase());
  396. cmakeFoundLibraries.add (String ("${") + cmakeLibraryID + "}");
  397. out << "find_library (" << cmakeLibraryID << " " << library << newLine;
  398. for (auto& path : exporter.getLibrarySearchPaths (config))
  399. out << " " << path.quoted() << newLine;
  400. out << ")" << newLine
  401. << newLine;
  402. }
  403. for (auto* target : exporter.targets)
  404. {
  405. if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget)
  406. continue;
  407. auto targetVarName = getTargetVarName (*target);
  408. out << "set_target_properties (" << targetVarName << " PROPERTIES" << newLine
  409. << " OUTPUT_NAME " << config.getTargetBinaryNameString().quoted() << newLine;
  410. auto cxxStandard = project.getCppStandardString();
  411. if (cxxStandard == "latest")
  412. cxxStandard = "17";
  413. out << " CXX_STANDARD " << cxxStandard << newLine;
  414. if (! shouldUseGNUExtensions())
  415. out << " CXX_EXTENSIONS OFF" << newLine;
  416. out << ")" << newLine << newLine;
  417. auto defines = exporter.getDefines (config);
  418. defines.addArray (target->getDefines (config));
  419. out << "target_compile_definitions (" << targetVarName << " PRIVATE" << newLine;
  420. for (auto& key : defines.getAllKeys())
  421. out << " " << key << "=" << defines[key] << newLine;
  422. out << ")" << newLine << newLine;
  423. auto targetFlags = target->getCompilerFlags();
  424. if (! targetFlags.isEmpty())
  425. {
  426. out << "target_compile_options (" << targetVarName << " PRIVATE" << newLine;
  427. for (auto& flag : targetFlags)
  428. out << " " << flag << newLine;
  429. out << ")" << newLine << newLine;
  430. }
  431. out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine;
  432. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle
  433. || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn)
  434. out << " SHARED_CODE" << newLine;
  435. out << " " << exporter.getArchFlags (config) << newLine;
  436. for (auto& flag : target->getLinkerFlags())
  437. out << " " << flag << newLine;
  438. for (auto& flag : exporter.getLinkerFlags (config))
  439. out << " " << flag << newLine;
  440. for (auto& lib : cmakeFoundLibraries)
  441. out << " " << lib << newLine;
  442. for (auto& package : cmakePkgconfigPackages)
  443. out << " ${" << package << "_LIBRARIES}" << newLine;
  444. out << ")" << newLine << newLine;
  445. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle
  446. || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn)
  447. out << "add_dependencies (" << targetVarName << " " << "SHARED_CODE)" << newLine << newLine;
  448. }
  449. StringArray cFlags;
  450. cFlags.add (exporter.getArchFlags (config));
  451. cFlags.addArray (exporter.getCPreprocessorFlags (config));
  452. cFlags.addArray (exporter.getCFlags (config));
  453. out << addToCMakeVariable ("CMAKE_C_FLAGS", cFlags.joinIntoString (" ")) << newLine;
  454. String cxxFlags;
  455. for (auto& flag : exporter.getCXXFlags())
  456. if (! flag.startsWith ("-std="))
  457. cxxFlags += " " + flag;
  458. out << addToCMakeVariable ("CMAKE_CXX_FLAGS", "${CMAKE_C_FLAGS} " + cxxFlags) << newLine
  459. << newLine;
  460. out << "endif (" << buildTypeCondition << ")" << newLine
  461. << newLine;
  462. }
  463. }
  464. //==============================================================================
  465. void writeCMakeListsCodeBlocksSection (OutputStream& out, CodeBlocksProjectExporter& exporter) const
  466. {
  467. out << "project (" << getProject().getProjectNameString().quoted() << " C CXX)" << newLine
  468. << newLine;
  469. writeCMakeTargets (out, exporter);
  470. for (auto* target : exporter.targets)
  471. {
  472. if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget)
  473. continue;
  474. out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES PREFIX \"\")" << newLine
  475. << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX " << target->getTargetSuffix().quoted() << ")" << newLine
  476. << newLine;
  477. }
  478. for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
  479. {
  480. auto& config = dynamic_cast<const CodeBlocksProjectExporter::CodeBlocksBuildConfiguration&> (*c);
  481. out << "#------------------------------------------------------------------------------" << newLine
  482. << "# Config: " << config.getName() << newLine
  483. << "#------------------------------------------------------------------------------" << newLine
  484. << newLine;
  485. auto buildTypeCondition = String ("CMAKE_BUILD_TYPE STREQUAL " + config.getName());
  486. out << "if (" << buildTypeCondition << ")" << newLine
  487. << newLine;
  488. out << "include_directories (" << newLine;
  489. for (auto& path : exporter.getIncludePaths (config))
  490. out << " " << path.replace ("\\", "/").quoted() << newLine;
  491. out << ")" << newLine << newLine;
  492. for (auto* target : exporter.targets)
  493. {
  494. if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget)
  495. continue;
  496. auto targetVarName = getTargetVarName (*target);
  497. out << "set_target_properties (" << targetVarName << " PROPERTIES" << newLine
  498. << " OUTPUT_NAME " << config.getTargetBinaryNameString().quoted() << newLine;
  499. auto cxxStandard = project.getCppStandardString();
  500. if (cxxStandard == "latest")
  501. cxxStandard = "17";
  502. out << " CXX_STANDARD " << cxxStandard << newLine;
  503. if (! shouldUseGNUExtensions())
  504. out << " CXX_EXTENSIONS OFF" << newLine;
  505. out << ")" << newLine << newLine;
  506. out << "target_compile_definitions (" << targetVarName << " PRIVATE" << newLine;
  507. for (auto& def : exporter.getDefines (config, *target))
  508. out << " " << def << newLine;
  509. out << ")" << newLine << newLine;
  510. out << "target_compile_options (" << targetVarName << " PRIVATE" << newLine;
  511. for (auto& option : exporter.getCompilerFlags (config, *target))
  512. if (! option.startsWith ("-std="))
  513. out << " " << option.quoted() << newLine;
  514. out << ")" << newLine << newLine;
  515. out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine;
  516. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle
  517. || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn)
  518. out << " SHARED_CODE" << newLine
  519. << " -L." << newLine;
  520. for (auto& path : exporter.getLinkerSearchPaths (config, *target))
  521. {
  522. out << " \"-L\\\"";
  523. if (! isWindowsAbsolutePath (path))
  524. out << "${CMAKE_CURRENT_SOURCE_DIR}/";
  525. out << path.replace ("\\", "/").unquoted() << "\\\"\"" << newLine;
  526. }
  527. for (auto& flag : exporter.getLinkerFlags (config, *target))
  528. out << " " << flag << newLine;
  529. for (auto& flag : exporter.getProjectLinkerLibs())
  530. out << " -l" << flag << newLine;
  531. for (auto& lib : exporter.mingwLibs)
  532. out << " -l" << lib << newLine;
  533. out << ")" << newLine << newLine;
  534. }
  535. out << addToCMakeVariable ("CMAKE_CXX_FLAGS", exporter.getProjectCompilerOptions().joinIntoString (" ")) << newLine
  536. << addToCMakeVariable ("CMAKE_C_FLAGS", "${CMAKE_CXX_FLAGS}") << newLine
  537. << newLine;
  538. out << "endif (" << buildTypeCondition << ")" << newLine
  539. << newLine;
  540. }
  541. }
  542. //==============================================================================
  543. void writeCMakeListsXcodeSection (OutputStream& out, XcodeProjectExporter& exporter) const
  544. {
  545. // We need to find out the SDK root before defining the project. Unfortunately this is
  546. // set per-target in the Xcode project, but we want it per-configuration.
  547. for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
  548. {
  549. auto& config = dynamic_cast<const XcodeProjectExporter::XcodeBuildConfiguration&> (*c);
  550. for (auto* target : exporter.targets)
  551. {
  552. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::macOSAppex
  553. || target->type == build_tools::ProjectType::Target::Type::AggregateTarget
  554. || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn)
  555. continue;
  556. auto targetAttributes = target->getTargetSettings (config);
  557. auto targetAttributeKeys = targetAttributes.getAllKeys();
  558. if (targetAttributes.getAllKeys().contains ("SDKROOT"))
  559. {
  560. out << "if (CMAKE_BUILD_TYPE STREQUAL " + config.getName() << ")" << newLine
  561. << " set (CMAKE_OSX_SYSROOT " << targetAttributes["SDKROOT"] << ")" << newLine
  562. << "endif()" << newLine << newLine;
  563. break;
  564. }
  565. }
  566. }
  567. out << "project (" << getProject().getProjectNameString().quoted() << " C CXX)" << newLine << newLine;
  568. writeCMakeTargets (out, exporter);
  569. for (auto* target : exporter.targets)
  570. {
  571. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::macOSAppex
  572. || target->type == build_tools::ProjectType::Target::Type::AggregateTarget
  573. || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn)
  574. continue;
  575. if (target->type == build_tools::ProjectType::Target::Type::AudioUnitPlugIn)
  576. out << "find_program (RC_COMPILER Rez NO_DEFAULT_PATHS PATHS \"/Applications/Xcode.app/Contents/Developer/usr/bin\")" << newLine
  577. << "if (NOT RC_COMPILER)" << newLine
  578. << " message (WARNING \"failed to find Rez; older resource-based AU plug-ins may not work correctly\")" << newLine
  579. << "endif (NOT RC_COMPILER)" << newLine << newLine;
  580. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::staticLibrary
  581. || target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::sharedLibraryOrDLL)
  582. out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX \"" << target->xcodeBundleExtension << "\")" << newLine
  583. << newLine;
  584. }
  585. for (ProjectExporter::ConstConfigIterator c (exporter); c.next();)
  586. {
  587. auto& config = dynamic_cast<const XcodeProjectExporter::XcodeBuildConfiguration&> (*c);
  588. out << "#------------------------------------------------------------------------------" << newLine
  589. << "# Config: " << config.getName() << newLine
  590. << "#------------------------------------------------------------------------------" << newLine
  591. << newLine;
  592. auto buildTypeCondition = String ("CMAKE_BUILD_TYPE STREQUAL " + config.getName());
  593. out << "if (" << buildTypeCondition << ")" << newLine
  594. << newLine;
  595. out << "execute_process (COMMAND uname -m OUTPUT_VARIABLE JUCE_ARCH_LABEL OUTPUT_STRIP_TRAILING_WHITESPACE)" << newLine
  596. << newLine;
  597. auto configSettings = exporter.getProjectSettings (config);
  598. auto configSettingsKeys = configSettings.getAllKeys();
  599. auto binaryName = config.getTargetBinaryNameString();
  600. if (configSettingsKeys.contains ("PRODUCT_NAME"))
  601. binaryName = configSettings["PRODUCT_NAME"].unquoted();
  602. for (auto* target : exporter.targets)
  603. {
  604. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::macOSAppex
  605. || target->type == build_tools::ProjectType::Target::Type::AggregateTarget
  606. || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn)
  607. continue;
  608. auto targetVarName = getTargetVarName (*target);
  609. auto targetAttributes = target->getTargetSettings (config);
  610. auto targetAttributeKeys = targetAttributes.getAllKeys();
  611. StringArray headerSearchPaths;
  612. if (targetAttributeKeys.contains ("HEADER_SEARCH_PATHS"))
  613. {
  614. auto paths = targetAttributes["HEADER_SEARCH_PATHS"].trim().substring (1).dropLastCharacters (1);
  615. paths = paths.replace ("\"$(inherited)\"", {})
  616. .replace ("$(HOME)", "$ENV{HOME}")
  617. .replace ("~", "$ENV{HOME}");
  618. headerSearchPaths.addTokens (paths, ",\"\t\\", {});
  619. headerSearchPaths.removeEmptyStrings();
  620. targetAttributeKeys.removeString ("HEADER_SEARCH_PATHS");
  621. }
  622. out << "target_include_directories (" << targetVarName << " PRIVATE" << newLine;
  623. for (auto& path : headerSearchPaths)
  624. out << " " << path.quoted() << newLine;
  625. out << ")" << newLine << newLine;
  626. StringArray defines;
  627. if (targetAttributeKeys.contains ("GCC_PREPROCESSOR_DEFINITIONS"))
  628. {
  629. defines.addTokens (targetAttributes["GCC_PREPROCESSOR_DEFINITIONS"], "() ,\t", {});
  630. defines.removeEmptyStrings();
  631. targetAttributeKeys.removeString ("GCC_PREPROCESSOR_DEFINITIONS");
  632. }
  633. out << "target_compile_definitions (" << targetVarName << " PRIVATE" << newLine;
  634. for (auto& def : defines)
  635. out << " " << def << newLine;
  636. out << ")" << newLine << newLine;
  637. StringArray cppFlags;
  638. String archLabel ("${JUCE_ARCH_LABEL}");
  639. // Fat binaries are not supported.
  640. if (targetAttributeKeys.contains ("ARCHS"))
  641. {
  642. auto value = targetAttributes["ARCHS"].unquoted();
  643. if (value.contains ("NATIVE_ARCH_ACTUAL"))
  644. {
  645. cppFlags.add ("-march=native");
  646. }
  647. else if (value.contains ("ARCHS_STANDARD_32_BIT"))
  648. {
  649. archLabel = "i386";
  650. cppFlags.add ("-arch x86");
  651. }
  652. else if (value.contains ("ARCHS_STANDARD_32_64_BIT")
  653. || value.contains ("ARCHS_STANDARD_64_BIT"))
  654. {
  655. archLabel = "x86_64";
  656. cppFlags.add ("-arch x86_64");
  657. }
  658. targetAttributeKeys.removeString ("ARCHS");
  659. }
  660. if (targetAttributeKeys.contains ("MACOSX_DEPLOYMENT_TARGET"))
  661. {
  662. cppFlags.add ("-mmacosx-version-min=" + targetAttributes["MACOSX_DEPLOYMENT_TARGET"]);
  663. targetAttributeKeys.removeString ("MACOSX_DEPLOYMENT_TARGET");
  664. }
  665. if (targetAttributeKeys.contains ("OTHER_CPLUSPLUSFLAGS"))
  666. {
  667. cppFlags.add (targetAttributes["OTHER_CPLUSPLUSFLAGS"].unquoted());
  668. targetAttributeKeys.removeString ("OTHER_CPLUSPLUSFLAGS");
  669. }
  670. if (targetAttributeKeys.contains ("GCC_OPTIMIZATION_LEVEL"))
  671. {
  672. cppFlags.add ("-O" + targetAttributes["GCC_OPTIMIZATION_LEVEL"]);
  673. targetAttributeKeys.removeString ("GCC_OPTIMIZATION_LEVEL");
  674. }
  675. if (targetAttributeKeys.contains ("LLVM_LTO"))
  676. {
  677. cppFlags.add ("-flto");
  678. targetAttributeKeys.removeString ("LLVM_LTO");
  679. }
  680. if (targetAttributeKeys.contains ("GCC_FAST_MATH"))
  681. {
  682. cppFlags.add ("-ffast-math");
  683. targetAttributeKeys.removeString ("GCC_FAST_MATH");
  684. }
  685. // We'll take this setting from the project
  686. targetAttributeKeys.removeString ("CLANG_CXX_LANGUAGE_STANDARD");
  687. if (targetAttributeKeys.contains ("CLANG_CXX_LIBRARY"))
  688. {
  689. cppFlags.add ("-stdlib=" + targetAttributes["CLANG_CXX_LIBRARY"].unquoted());
  690. targetAttributeKeys.removeString ("CLANG_CXX_LIBRARY");
  691. }
  692. out << "target_compile_options (" << targetVarName << " PRIVATE" << newLine;
  693. for (auto& flag : cppFlags)
  694. out << " " << flag << newLine;
  695. out << ")" << newLine << newLine;
  696. StringArray libSearchPaths;
  697. if (targetAttributeKeys.contains ("LIBRARY_SEARCH_PATHS"))
  698. {
  699. auto paths = targetAttributes["LIBRARY_SEARCH_PATHS"].trim().substring (1).dropLastCharacters (1);
  700. paths = paths.replace ("\"$(inherited)\"", {});
  701. paths = paths.replace ("$(HOME)", "$ENV{HOME}");
  702. libSearchPaths.addTokens (paths, ",\"\t\\", {});
  703. libSearchPaths.removeEmptyStrings();
  704. for (auto& libPath : libSearchPaths)
  705. {
  706. libPath = libPath.replace ("${CURRENT_ARCH}", archLabel);
  707. if (! isUnixAbsolutePath (libPath))
  708. libPath = "${CMAKE_CURRENT_SOURCE_DIR}/" + libPath;
  709. }
  710. targetAttributeKeys.removeString ("LIBRARY_SEARCH_PATHS");
  711. }
  712. StringArray linkerFlags;
  713. if (targetAttributeKeys.contains ("OTHER_LDFLAGS"))
  714. {
  715. // CMake adds its own SHARED_CODE library linking flags
  716. auto flagsWithReplacedSpaces = targetAttributes["OTHER_LDFLAGS"].unquoted().replace ("\\\\ ", "^^%%^^");
  717. linkerFlags.addTokens (flagsWithReplacedSpaces, true);
  718. linkerFlags.removeString ("-bundle");
  719. linkerFlags.removeString ("-l" + binaryName.replace (" ", "^^%%^^"));
  720. for (auto& flag : linkerFlags)
  721. flag = flag.replace ("^^%%^^", " ");
  722. targetAttributeKeys.removeString ("OTHER_LDFLAGS");
  723. }
  724. if (target->type == build_tools::ProjectType::Target::Type::AudioUnitPlugIn)
  725. {
  726. String rezFlags;
  727. if (targetAttributeKeys.contains ("OTHER_REZFLAGS"))
  728. {
  729. rezFlags = targetAttributes["OTHER_REZFLAGS"];
  730. targetAttributeKeys.removeString ("OTHER_REZFLAGS");
  731. }
  732. for (auto& item : exporter.getAllGroups())
  733. {
  734. if (item.getName() == ProjectSaver::getJuceCodeGroupName())
  735. {
  736. auto resSourcesVar = targetVarName + "_REZ_SOURCES";
  737. auto resOutputVar = targetVarName + "_REZ_OUTPUT";
  738. auto sdkVersion = config.getOSXSDKVersionString().upToFirstOccurrenceOf (" ", false, false);
  739. auto sysroot = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX" + sdkVersion + ".sdk";
  740. build_tools::RelativePath rFile ("JuceLibraryCode/include_juce_audio_plugin_client_AU.r", build_tools::RelativePath::projectFolder);
  741. rFile = rebaseFromProjectFolderToBuildTarget (rFile);
  742. out << "if (RC_COMPILER)" << newLine
  743. << " set (" << resSourcesVar << newLine
  744. << " " << ("${CMAKE_CURRENT_SOURCE_DIR}/" + rFile.toUnixStyle()).quoted() << newLine
  745. << " )" << newLine
  746. << " set (" << resOutputVar << " " << ("${CMAKE_CURRENT_BINARY_DIR}/" + binaryName + ".rsrc").quoted() << ")" << newLine
  747. << " target_sources (" << targetVarName << " PRIVATE" << newLine
  748. << " ${" << resSourcesVar << "}" << newLine
  749. << " ${" << resOutputVar << "}" << newLine
  750. << " )" << newLine
  751. << " execute_process (COMMAND" << newLine
  752. << " ${RC_COMPILER}" << newLine
  753. << " " << rezFlags.unquoted().removeCharacters ("\\") << newLine
  754. << " -isysroot " << sysroot.quoted() << newLine;
  755. for (auto& path : headerSearchPaths)
  756. {
  757. out << " -I \"";
  758. if (! isUnixAbsolutePath (path))
  759. out << "${PROJECT_SOURCE_DIR}/";
  760. out << path << "\"" << newLine;
  761. }
  762. out << " ${" << resSourcesVar << "}" << newLine
  763. << " -o ${" << resOutputVar << "}" << newLine
  764. << " )" << newLine
  765. << " set_source_files_properties (${" << resOutputVar << "} PROPERTIES" << newLine
  766. << " GENERATED TRUE" << newLine
  767. << " MACOSX_PACKAGE_LOCATION Resources" << newLine
  768. << " )" << newLine
  769. << "endif (RC_COMPILER)" << newLine << newLine;
  770. break;
  771. }
  772. }
  773. }
  774. if (targetAttributeKeys.contains ("INFOPLIST_FILE"))
  775. {
  776. auto plistFile = exporter.getTargetFolder().getChildFile (targetAttributes["INFOPLIST_FILE"]);
  777. if (auto plist = parseXML (plistFile))
  778. {
  779. if (auto* dict = plist->getChildByName ("dict"))
  780. {
  781. if (auto* entry = dict->getChildByName ("key"))
  782. {
  783. while (entry != nullptr)
  784. {
  785. if (entry->getAllSubText() == "CFBundleExecutable")
  786. {
  787. if (auto* bundleName = entry->getNextElementWithTagName ("string"))
  788. {
  789. bundleName->deleteAllTextElements();
  790. bundleName->addTextElement (binaryName);
  791. }
  792. }
  793. entry = entry->getNextElementWithTagName ("key");
  794. }
  795. }
  796. }
  797. auto updatedPlist = getTargetFolder().getChildFile (config.getName() + "-" + plistFile.getFileName());
  798. XmlElement::TextFormat format;
  799. format.dtd = "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
  800. plist->writeTo (updatedPlist, format);
  801. targetAttributes.set ("INFOPLIST_FILE", ("${CMAKE_CURRENT_SOURCE_DIR}/" + updatedPlist.getFileName()).quoted());
  802. }
  803. else
  804. {
  805. targetAttributeKeys.removeString ("INFOPLIST_FILE");
  806. }
  807. }
  808. targetAttributeKeys.sort (false);
  809. out << "set_target_properties (" << targetVarName << " PROPERTIES" << newLine
  810. << " OUTPUT_NAME " << binaryName.quoted() << newLine;
  811. auto cxxStandard = project.getCppStandardString();
  812. if (cxxStandard == "latest")
  813. cxxStandard = "17";
  814. out << " CXX_STANDARD " << cxxStandard << newLine;
  815. if (! shouldUseGNUExtensions())
  816. out << " CXX_EXTENSIONS OFF" << newLine;
  817. for (auto& key : targetAttributeKeys)
  818. out << " XCODE_ATTRIBUTE_" << key << " " << targetAttributes[key] << newLine;
  819. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable
  820. || target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle)
  821. {
  822. out << " MACOSX_BUNDLE_INFO_PLIST " << targetAttributes.getValue ("INFOPLIST_FILE", "\"\"") << newLine
  823. << " XCODE_ATTRIBUTE_PRODUCT_NAME " << binaryName.quoted() << newLine;
  824. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable)
  825. {
  826. out << " MACOSX_BUNDLE TRUE" << newLine;
  827. }
  828. else
  829. {
  830. out << " BUNDLE TRUE" << newLine
  831. << " BUNDLE_EXTENSION " << targetAttributes.getValue ("WRAPPER_EXTENSION", "\"\"") << newLine
  832. << " XCODE_ATTRIBUTE_MACH_O_TYPE \"mh_bundle\"" << newLine;
  833. }
  834. }
  835. out << ")" << newLine << newLine;
  836. out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine;
  837. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle
  838. || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn)
  839. out << " SHARED_CODE" << newLine;
  840. for (auto& path : libSearchPaths)
  841. out << " \"-L\\\"" << path << "\\\"\"" << newLine;
  842. for (auto& flag : linkerFlags)
  843. out << " " << flag.quoted() << newLine;
  844. for (auto& framework : target->frameworkNames)
  845. out << " \"-framework " << framework << "\"" << newLine;
  846. out << ")" << newLine << newLine;
  847. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle
  848. || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn)
  849. {
  850. if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle
  851. && targetAttributeKeys.contains("INSTALL_PATH"))
  852. {
  853. auto installPath = targetAttributes["INSTALL_PATH"].unquoted().replace ("$(HOME)", "$ENV{HOME}");
  854. auto productFilename = binaryName + (targetAttributeKeys.contains ("WRAPPER_EXTENSION") ? "." + targetAttributes["WRAPPER_EXTENSION"] : String());
  855. auto productPath = (installPath + productFilename).quoted();
  856. out << "add_custom_command (TARGET " << targetVarName << " POST_BUILD" << newLine
  857. << " COMMAND ${CMAKE_COMMAND} -E remove_directory " << productPath << newLine
  858. << " COMMAND ${CMAKE_COMMAND} -E copy_directory \"${CMAKE_BINARY_DIR}/" << productFilename << "\" " << productPath << newLine
  859. << " COMMENT \"Copying \\\"" << productFilename << "\\\" to \\\"" << installPath.unquoted() << "\\\"\"" << newLine
  860. << ")" << newLine << newLine;
  861. }
  862. }
  863. }
  864. std::map<String, String> basicWarnings
  865. {
  866. { "CLANG_WARN_BOOL_CONVERSION", "bool-conversion" },
  867. { "CLANG_WARN_COMMA", "comma" },
  868. { "CLANG_WARN_CONSTANT_CONVERSION", "constant-conversion" },
  869. { "CLANG_WARN_EMPTY_BODY", "empty-body" },
  870. { "CLANG_WARN_ENUM_CONVERSION", "enum-conversion" },
  871. { "CLANG_WARN_INFINITE_RECURSION", "infinite-recursion" },
  872. { "CLANG_WARN_INT_CONVERSION", "int-conversion" },
  873. { "CLANG_WARN_RANGE_LOOP_ANALYSIS", "range-loop-analysis" },
  874. { "CLANG_WARN_STRICT_PROTOTYPES", "strict-prototypes" },
  875. { "GCC_WARN_CHECK_SWITCH_STATEMENTS", "switch" },
  876. { "GCC_WARN_UNUSED_VARIABLE", "unused-variable" },
  877. { "GCC_WARN_MISSING_PARENTHESES", "parentheses" },
  878. { "GCC_WARN_NON_VIRTUAL_DESTRUCTOR", "non-virtual-dtor" },
  879. { "GCC_WARN_64_TO_32_BIT_CONVERSION", "shorten-64-to-32" },
  880. { "GCC_WARN_UNDECLARED_SELECTOR", "undeclared-selector" },
  881. { "GCC_WARN_UNUSED_FUNCTION", "unused-function" }
  882. };
  883. StringArray compilerFlags;
  884. for (auto& key : configSettingsKeys)
  885. {
  886. auto basicWarning = basicWarnings.find (key);
  887. if (basicWarning != basicWarnings.end())
  888. {
  889. compilerFlags.add (configSettings[key] == "YES" ? "-W" + basicWarning->second : "-Wno-" + basicWarning->second);
  890. }
  891. else if (key == "CLANG_WARN_SUSPICIOUS_MOVE" && configSettings[key] == "YES") compilerFlags.add ("-Wmove");
  892. else if (key == "CLANG_WARN_UNREACHABLE_CODE" && configSettings[key] == "YES") compilerFlags.add ("-Wunreachable-code");
  893. else if (key == "CLANG_WARN__DUPLICATE_METHOD_MATCH" && configSettings[key] == "YES") compilerFlags.add ("-Wduplicate-method-match");
  894. else if (key == "GCC_INLINES_ARE_PRIVATE_EXTERN" && configSettings[key] == "YES") compilerFlags.add ("-fvisibility-inlines-hidden");
  895. else if (key == "GCC_NO_COMMON_BLOCKS" && configSettings[key] == "YES") compilerFlags.add ("-fno-common");
  896. else if (key == "GCC_WARN_ABOUT_RETURN_TYPE" && configSettings[key] != "YES") compilerFlags.add (configSettings[key] == "YES_ERROR" ? "-Werror=return-type" : "-Wno-return-type");
  897. else if (key == "GCC_WARN_TYPECHECK_CALLS_TO_PRINTF" && configSettings[key] != "YES") compilerFlags.add ("-Wno-format");
  898. else if (key == "GCC_WARN_UNINITIALIZED_AUTOS")
  899. {
  900. if (configSettings[key] == "YES") compilerFlags.add ("-Wuninitialized");
  901. else if (configSettings[key] == "YES_AGGRESSIVE") compilerFlags.add ("--Wconditional-uninitialized");
  902. else compilerFlags.add (")-Wno-uninitialized");
  903. }
  904. else if (key == "WARNING_CFLAGS") compilerFlags.add (configSettings[key].unquoted());
  905. }
  906. out << addToCMakeVariable ("CMAKE_CXX_FLAGS", compilerFlags.joinIntoString (" ")) << newLine
  907. << addToCMakeVariable ("CMAKE_C_FLAGS", "${CMAKE_CXX_FLAGS}") << newLine
  908. << newLine;
  909. out << "endif (" << buildTypeCondition << ")" << newLine
  910. << newLine;
  911. }
  912. }
  913. //==============================================================================
  914. JUCE_DECLARE_NON_COPYABLE (CLionProjectExporter)
  915. };