| @@ -563,16 +563,11 @@ public: | |||
| m.addItem (4, "Rename File..."); | |||
| m.addSeparator(); | |||
| if (auto* group = dynamic_cast<GroupItem*> (getParentItem())) | |||
| { | |||
| if (group->isRoot()) | |||
| { | |||
| m.addItem (5, "Binary Resource", true, item.shouldBeAddedToBinaryResources()); | |||
| m.addItem (6, "Xcode Resource", true, item.shouldBeAddedToXcodeResources()); | |||
| m.addItem (7, "Compile", true, item.shouldBeCompiled()); | |||
| m.addSeparator(); | |||
| } | |||
| } | |||
| m.addItem (5, "Binary Resource", true, item.shouldBeAddedToBinaryResources()); | |||
| m.addItem (6, "Xcode Resource", true, item.shouldBeAddedToXcodeResources()); | |||
| m.addItem (7, "Compile", item.isSourceFile(), item.shouldBeCompiled()); | |||
| m.addItem (8, "Skip PCH", item.shouldBeCompiled(), item.shouldSkipPCH()); | |||
| m.addSeparator(); | |||
| m.addItem (3, "Delete"); | |||
| @@ -589,13 +584,14 @@ public: | |||
| { | |||
| switch (resultCode) | |||
| { | |||
| case 1: getFile().startAsProcess(); break; | |||
| case 2: revealInFinder(); break; | |||
| case 3: deleteAllSelectedItems(); break; | |||
| case 4: triggerAsyncRename (item); break; | |||
| case 5: item.getShouldAddToBinaryResourcesValue().setValue (! item.shouldBeAddedToBinaryResources()); break; | |||
| case 6: item.getShouldAddToXcodeResourcesValue().setValue (! item.shouldBeAddedToXcodeResources()); break; | |||
| case 7: item.getShouldCompileValue().setValue (! item.shouldBeCompiled()); break; | |||
| case 1: getFile().startAsProcess(); break; | |||
| case 2: revealInFinder(); break; | |||
| case 3: deleteAllSelectedItems(); break; | |||
| case 4: triggerAsyncRename (item); break; | |||
| case 5: item.getShouldAddToBinaryResourcesValue().setValue (! item.shouldBeAddedToBinaryResources()); break; | |||
| case 6: item.getShouldAddToXcodeResourcesValue().setValue (! item.shouldBeAddedToXcodeResources()); break; | |||
| case 7: item.getShouldCompileValue().setValue (! item.shouldBeCompiled()); break; | |||
| case 8: item.getShouldSkipPCHValue().setValue (! item.shouldSkipPCH()); break; | |||
| default: | |||
| if (auto* parentGroup = dynamic_cast<GroupItem*> (getParentProjectItem())) | |||
| @@ -223,7 +223,7 @@ private: | |||
| g.setColour (findColour (defaultTextColourId)); | |||
| g.setFont (Font (14.0f)); | |||
| g.drawFittedText (stringToDisplay, getLocalBounds(), Justification::centred, 10, 1.0f); | |||
| g.drawFittedText (stringToDisplay, getLocalBounds(), Justification::centred, 15, 0.75f); | |||
| } | |||
| String stringToDisplay; | |||
| @@ -36,8 +36,8 @@ public: | |||
| : item (group), | |||
| header (item.getName(), { getIcons().openFolder, Colours::transparentBlack }) | |||
| { | |||
| list.setHeaderComponent (std::make_unique<ListBoxHeader> (Array<String> { "File", "Binary Resource", "Xcode Resource", "Compile", "Compiler Flag Scheme" }, | |||
| Array<float> { 0.3f, 0.15f, 0.15f, 0.15f, 0.25f })); | |||
| list.setHeaderComponent (std::make_unique<ListBoxHeader> (Array<String> { "File", "Binary Resource", "Xcode Resource", "Compile", "Skip PCH", "Compiler Flag Scheme" }, | |||
| Array<float> { 0.25f, 0.125f, 0.125f, 0.125f, 0.125f, 0.25f })); | |||
| list.setModel (this); | |||
| list.setColour (ListBox::backgroundColourId, Colours::transparentBlack); | |||
| addAndMakeVisible (list); | |||
| @@ -136,9 +136,14 @@ private: | |||
| { | |||
| if (item.isFile()) | |||
| { | |||
| addAndMakeVisible (compileButton); | |||
| compileButton.getToggleStateValue().referTo (item.getShouldCompileValue()); | |||
| compileButton.onStateChange = [this] { compilerFlagSchemeSelector.setVisible (compileButton.getToggleState()); }; | |||
| auto isSourceFile = item.isSourceFile(); | |||
| if (isSourceFile) | |||
| { | |||
| addAndMakeVisible (compileButton); | |||
| compileButton.getToggleStateValue().referTo (item.getShouldCompileValue()); | |||
| compileButton.onStateChange = [this] { compileEnablementChanged(); }; | |||
| } | |||
| addAndMakeVisible (binaryResourceButton); | |||
| binaryResourceButton.getToggleStateValue().referTo (item.getShouldAddToBinaryResourcesValue()); | |||
| @@ -146,8 +151,15 @@ private: | |||
| addAndMakeVisible (xcodeResourceButton); | |||
| xcodeResourceButton.getToggleStateValue().referTo (item.getShouldAddToXcodeResourcesValue()); | |||
| addChildComponent (compilerFlagSchemeSelector); | |||
| compilerFlagSchemeSelector.setVisible (compileButton.getToggleState()); | |||
| if (isSourceFile) | |||
| { | |||
| addChildComponent (skipPCHButton); | |||
| skipPCHButton.getToggleStateValue().referTo (item.getShouldSkipPCHValue()); | |||
| addChildComponent (compilerFlagSchemeSelector); | |||
| compileEnablementChanged(); | |||
| } | |||
| } | |||
| } | |||
| @@ -182,7 +194,8 @@ private: | |||
| binaryResourceButton.setBounds (bounds.removeFromLeft (roundToInt (header->getProportionAtIndex (1) * width))); | |||
| xcodeResourceButton.setBounds (bounds.removeFromLeft (roundToInt (header->getProportionAtIndex (2) * width))); | |||
| compileButton.setBounds (bounds.removeFromLeft (roundToInt (header->getProportionAtIndex (3) * width))); | |||
| compilerFlagSchemeSelector.setBounds (bounds.removeFromLeft (roundToInt (header->getProportionAtIndex (4) * width))); | |||
| skipPCHButton.setBounds (bounds.removeFromLeft (roundToInt (header->getProportionAtIndex (4) * width))); | |||
| compilerFlagSchemeSelector.setBounds (bounds.removeFromLeft (roundToInt (header->getProportionAtIndex (5) * width))); | |||
| } | |||
| } | |||
| @@ -331,10 +344,18 @@ private: | |||
| Label newSchemeLabel; | |||
| }; | |||
| void compileEnablementChanged() | |||
| { | |||
| auto shouldBeCompiled = compileButton.getToggleState(); | |||
| skipPCHButton.setVisible (shouldBeCompiled); | |||
| compilerFlagSchemeSelector.setVisible (shouldBeCompiled); | |||
| } | |||
| //============================================================================== | |||
| ListBoxHeader* header; | |||
| ToggleButton compileButton, binaryResourceButton, xcodeResourceButton; | |||
| ToggleButton compileButton, binaryResourceButton, xcodeResourceButton, skipPCHButton; | |||
| CompilerFlagSchemeSelector compilerFlagSchemeSelector; | |||
| }; | |||
| @@ -1510,6 +1510,11 @@ bool Project::Item::isImageFile() const | |||
| || getFile().hasFileExtension ("svg")); | |||
| } | |||
| bool Project::Item::isSourceFile() const | |||
| { | |||
| return isFile() && getFile().hasFileExtension (sourceFileExtensions); | |||
| } | |||
| Project::Item Project::Item::findItemWithID (const String& targetId) const | |||
| { | |||
| if (state [Ids::ID] == targetId) | |||
| @@ -1565,6 +1570,9 @@ bool Project::Item::shouldInhibitWarnings() const { return state [Ids: | |||
| bool Project::Item::isModuleCode() const { return belongsToModule; } | |||
| Value Project::Item::getShouldSkipPCHValue() { return state.getPropertyAsValue (Ids::skipPCH, getUndoManager()); } | |||
| bool Project::Item::shouldSkipPCH() const { return isModuleCode() || state [Ids::skipPCH]; } | |||
| Value Project::Item::getCompilerFlagSchemeValue() { return state.getPropertyAsValue (Ids::compilerFlagScheme, getUndoManager()); } | |||
| String Project::Item::getCompilerFlagSchemeString() const { return state [Ids::compilerFlagScheme]; } | |||
| @@ -214,11 +214,11 @@ public: | |||
| void addCompilerFlagScheme (const String&); | |||
| void removeCompilerFlagScheme (const String&); | |||
| String getPostExportShellCommandPosixString() const { return postExportShellCommandPosixValue.get(); } | |||
| String getPostExportShellCommandWinString() const { return postExportShellCommandWinValue.get(); } | |||
| String getPostExportShellCommandPosixString() const { return postExportShellCommandPosixValue.get(); } | |||
| String getPostExportShellCommandWinString() const { return postExportShellCommandWinValue.get(); } | |||
| bool shouldUseAppConfig() const { return useAppConfigValue.get(); } | |||
| bool shouldAddUsingNamespaceToJuceHeader() const { return addUsingNamespaceToJuceHeader.get(); } | |||
| bool shouldUseAppConfig() const { return useAppConfigValue.get(); } | |||
| bool shouldAddUsingNamespaceToJuceHeader() const { return addUsingNamespaceToJuceHeader.get(); } | |||
| //============================================================================== | |||
| String getPluginNameString() const { return pluginNameValue.get(); } | |||
| @@ -340,6 +340,7 @@ public: | |||
| bool isGroup() const; | |||
| bool isMainGroup() const; | |||
| bool isImageFile() const; | |||
| bool isSourceFile() const; | |||
| String getID() const; | |||
| void setID (const String& newID); | |||
| @@ -374,6 +375,9 @@ public: | |||
| bool isModuleCode() const; | |||
| Value getShouldSkipPCHValue(); | |||
| bool shouldSkipPCH() const; | |||
| Value getCompilerFlagSchemeValue(); | |||
| String getCompilerFlagSchemeString() const; | |||
| @@ -48,6 +48,8 @@ public: | |||
| bool canCopeWithDuplicateFiles() override { return false; } | |||
| bool supportsUserDefinedConfigurations() const override { return true; } | |||
| String getNewLineString() const override { return "\n"; } | |||
| bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override | |||
| { | |||
| return type == build_tools::ProjectType::Target::GUIApp || type == build_tools::ProjectType::Target::StaticLibrary | |||
| @@ -238,7 +240,7 @@ public: | |||
| { | |||
| build_tools::writeStreamToFile (gradleProjectFolder.getChildFile (filePath), [&] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << fileContent; | |||
| }); | |||
| } | |||
| @@ -247,7 +249,7 @@ public: | |||
| { | |||
| build_tools::writeStreamToFile (gradleProjectFolder.getChildFile (filePath), [&] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo.write (binaryData, static_cast<size_t> (binarySize)); | |||
| }); | |||
| } | |||
| @@ -340,7 +342,7 @@ private: | |||
| { | |||
| build_tools::writeStreamToFile (file, [&] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << "# Automatically generated makefile, created by the Projucer" << newLine | |||
| << "# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine | |||
| @@ -578,7 +580,7 @@ private: | |||
| String getGradleSettingsFileContent() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << "rootProject.name = " << "\'" << projectName << "\'" << newLine; | |||
| mo << (isLibrary() ? "include ':lib'" : "include ':app'"); | |||
| @@ -594,7 +596,7 @@ private: | |||
| String getProjectBuildGradleFileContent() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << "buildscript {" << newLine; | |||
| mo << " repositories {" << newLine; | |||
| @@ -621,7 +623,7 @@ private: | |||
| String getAppBuildGradleFileContent (const OwnedArray<LibraryModule>& modules) const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << "apply plugin: 'com.android." << (isLibrary() ? "library" : "application") << "'" << newLine << newLine; | |||
| @@ -653,7 +655,7 @@ private: | |||
| String getAndroidProductFlavours() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << " flavorDimensions \"default\"" << newLine; | |||
| mo << " productFlavors {" << newLine; | |||
| @@ -702,7 +704,7 @@ private: | |||
| String getAndroidSigningConfig() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| auto keyStoreFilePath = androidKeyStore.get().toString().replace ("${user.home}", "${System.properties['user.home']}") | |||
| .replace ("/", "${File.separator}"); | |||
| @@ -728,7 +730,7 @@ private: | |||
| auto targetSdkVersion = static_cast<int> (androidTargetSDK.get()); | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << " defaultConfig {" << newLine; | |||
| @@ -753,7 +755,7 @@ private: | |||
| String getAndroidBuildTypes() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << " buildTypes {" << newLine; | |||
| @@ -784,7 +786,7 @@ private: | |||
| String getAndroidVariantFilter() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << " variantFilter { variant ->" << newLine; | |||
| mo << " def names = variant.flavors*.name" << newLine; | |||
| @@ -807,7 +809,7 @@ private: | |||
| String getAndroidProjectRepositories() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| auto repositories = StringArray::fromLines (androidProjectRepositories.get().toString()); | |||
| @@ -827,7 +829,7 @@ private: | |||
| String getAndroidRepositories() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| auto repositories = StringArray::fromLines (androidRepositories.get().toString()); | |||
| @@ -844,7 +846,7 @@ private: | |||
| String getAndroidDependencies() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << " dependencies {" << newLine; | |||
| @@ -871,7 +873,7 @@ private: | |||
| String getApplyPlugins() const | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| if (areRemoteNotificationsEnabled()) | |||
| mo << "apply plugin: 'com.google.gms.google-services'" << newLine; | |||
| @@ -931,12 +933,12 @@ private: | |||
| addOptJavaFolderToSourceSetsForModule (javaSourceSets, modules, "juce_product_unlocking"); | |||
| MemoryOutputStream mo; | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << " sourceSets {" << newLine; | |||
| mo << getSourceSetStringFor ("main.java.srcDirs", javaSourceSets); | |||
| mo << getSourceSetStringFor ("main.java.srcDirs", javaSourceSets, getNewLineString()); | |||
| mo << newLine; | |||
| mo << getSourceSetStringFor ("main.res.srcDirs", resourceSets); | |||
| mo << getSourceSetStringFor ("main.res.srcDirs", resourceSets, getNewLineString()); | |||
| mo << " }" << newLine; | |||
| return mo.toString(); | |||
| @@ -967,7 +969,7 @@ private: | |||
| return sourceSets; | |||
| } | |||
| static String getSourceSetStringFor (const String& type, const StringArray& srcDirs) | |||
| static String getSourceSetStringFor (const String& type, const StringArray& srcDirs, const String& newLineString) | |||
| { | |||
| String s; | |||
| @@ -987,7 +989,7 @@ private: | |||
| s << "]" << newLine; | |||
| return replaceLineFeeds (s, "\n"); | |||
| return replaceLineFeeds (s, newLineString); | |||
| } | |||
| //============================================================================== | |||
| @@ -998,7 +1000,7 @@ private: | |||
| props << "ndk.dir=" << sanitisePath (getAppSettings().getStoredPath (Ids::androidNDKPath, TargetOS::getThisOS()).get().toString()) << newLine | |||
| << "sdk.dir=" << sanitisePath (getAppSettings().getStoredPath (Ids::androidSDKPath, TargetOS::getThisOS()).get().toString()) << newLine; | |||
| return replaceLineFeeds (props, "\n"); | |||
| return replaceLineFeeds (props, getNewLineString()); | |||
| } | |||
| String getGradleWrapperPropertiesFileContent() const | |||
| @@ -1302,7 +1304,7 @@ private: | |||
| build_tools::writeStreamToFile (file, [&] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| PNGImageFormat png; | |||
| @@ -1355,7 +1357,7 @@ private: | |||
| if (projectItem.isGroup()) | |||
| { | |||
| for (int i = 0; i < projectItem.getNumChildren(); ++i) | |||
| addCompileUnits (projectItem.getChild(i), mo, excludeFromBuild, extraCompilerFlags); | |||
| addCompileUnits (projectItem.getChild (i), mo, excludeFromBuild, extraCompilerFlags); | |||
| } | |||
| else if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (*this)) | |||
| { | |||
| @@ -97,6 +97,8 @@ public: | |||
| bool isOSX() const override { return false; } | |||
| bool isiOS() const override { return false; } | |||
| String getNewLineString() const override { return "\n"; } | |||
| bool supportsTargetType (build_tools::ProjectType::Target::Type) const override { return true; } | |||
| void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override {} | |||
| @@ -168,9 +170,9 @@ public: | |||
| void create (const OwnedArray<LibraryModule>&) const override | |||
| { | |||
| // We'll append to this later. | |||
| build_tools::writeStreamToFile (getTargetFolder().getChildFile ("CMakeLists.txt"), [] (MemoryOutputStream& mo) | |||
| build_tools::writeStreamToFile (getTargetFolder().getChildFile ("CMakeLists.txt"), [this] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << "# Automatically generated CMakeLists, created by the Projucer" << newLine | |||
| << "# Do not edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine | |||
| @@ -199,7 +201,7 @@ public: | |||
| getTargetFolder().getChildFile ("CMakeLists.txt").loadFileAsData (existingContent); | |||
| MemoryOutputStream out (existingContent, true); | |||
| out.setNewLineString ("\n"); | |||
| out.setNewLineString (getNewLineString()); | |||
| out << "###############################################################################" << newLine | |||
| << "# " << exporter->getUniqueName() << newLine | |||
| @@ -314,7 +316,8 @@ private: | |||
| { | |||
| auto path = build_tools::RelativePath (projectItem.getFile(), exporter.getTargetFolder(), build_tools::RelativePath::buildTargetFolder).toUnixStyle(); | |||
| fileInfoList.push_back (std::make_tuple (path, projectItem.shouldBeCompiled(), | |||
| fileInfoList.push_back (std::make_tuple (path, | |||
| projectItem.shouldBeCompiled(), | |||
| exporter.compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString())); | |||
| } | |||
| } | |||
| @@ -98,6 +98,8 @@ public: | |||
| bool isOSX() const override { return false; } | |||
| bool isiOS() const override { return false; } | |||
| String getNewLineString() const override { return isWindows() ? "\r\n" : "\n"; } | |||
| bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override | |||
| { | |||
| switch (type) | |||
| @@ -478,7 +478,7 @@ public: | |||
| } | |||
| { | |||
| auto* intdir = props->createNewChildElement("IntDir"); | |||
| auto* intdir = props->createNewChildElement ("IntDir"); | |||
| setConditionAttribute (*intdir, config); | |||
| auto intermediatesPath = getIntermediatesPath (config); | |||
| @@ -556,7 +556,7 @@ public: | |||
| cl->createNewChildElement ("RuntimeLibrary")->addTextElement (config.isUsingRuntimeLibDLL() ? (isDebug ? "MultiThreadedDebugDLL" : "MultiThreadedDLL") | |||
| : (isDebug ? "MultiThreadedDebug" : "MultiThreaded")); | |||
| cl->createNewChildElement ("RuntimeTypeInfo")->addTextElement ("true"); | |||
| cl->createNewChildElement ("PrecompiledHeader"); | |||
| cl->createNewChildElement ("PrecompiledHeader")->addTextElement ("NotUsing"); | |||
| cl->createNewChildElement ("AssemblerListingLocation")->addTextElement ("$(IntDir)\\"); | |||
| cl->createNewChildElement ("ObjectFileName")->addTextElement ("$(IntDir)\\"); | |||
| cl->createNewChildElement ("ProgramDataBaseFileName")->addTextElement ("$(IntDir)\\"); | |||
| @@ -698,6 +698,8 @@ public: | |||
| auto* cppFiles = projectXml.createNewChildElement ("ItemGroup"); | |||
| auto* headerFiles = projectXml.createNewChildElement ("ItemGroup"); | |||
| writePrecompiledHeaderFiles (*cppFiles); | |||
| for (int i = 0; i < getOwner().getAllGroups().size(); ++i) | |||
| { | |||
| auto& group = getOwner().getAllGroups().getReference (i); | |||
| @@ -761,6 +763,59 @@ public: | |||
| } | |||
| //============================================================================== | |||
| static void setSourceFilePCHSettings (XmlElement& element, const File& pchFile, const String& option, const BuildConfiguration& config) | |||
| { | |||
| auto setConfigConditionAttribute = [&config] (XmlElement* elementToSet) -> XmlElement* | |||
| { | |||
| setConditionAttribute (*elementToSet, config); | |||
| return elementToSet; | |||
| }; | |||
| setConfigConditionAttribute (element.createNewChildElement ("PrecompiledHeader"))->addTextElement (option); | |||
| setConfigConditionAttribute (element.createNewChildElement ("PrecompiledHeaderFile"))->addTextElement (pchFile.getFileName()); | |||
| setConfigConditionAttribute (element.createNewChildElement ("PrecompiledHeaderOutputFile"))->addTextElement ("$(Platform)\\$(Configuration)\\JucePrecompiledHeader.pch"); | |||
| setConfigConditionAttribute (element.createNewChildElement ("ForcedIncludeFiles"))->addTextElement (pchFile.getFileName()); | |||
| } | |||
| void writePrecompiledHeaderFiles (XmlElement& cpps) const | |||
| { | |||
| for (ConstConfigIterator config (owner); config.next();) | |||
| { | |||
| if (config->shouldUsePrecompiledHeaderFile()) | |||
| { | |||
| auto pchFileContent = config->getPrecompiledHeaderFileContent(); | |||
| if (pchFileContent.isNotEmpty()) | |||
| { | |||
| auto pchFile = owner.getTargetFolder().getChildFile (config->getPrecompiledHeaderFilename()).withFileExtension (".h"); | |||
| build_tools::writeStreamToFile (pchFile, [&] (MemoryOutputStream& mo) | |||
| { | |||
| mo << pchFileContent; | |||
| }); | |||
| auto pchSourceFile = pchFile.withFileExtension (".cpp"); | |||
| build_tools::writeStreamToFile (pchSourceFile, [this] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString (owner.getNewLineString()); | |||
| writeAutoGenWarningComment (mo); | |||
| mo << " This is an empty source file generated by JUCE required for Visual Studio PCH." << newLine | |||
| << newLine | |||
| << "*/" << newLine | |||
| << newLine; | |||
| }); | |||
| auto* pchSourceElement = cpps.createNewChildElement ("ClCompile"); | |||
| pchSourceElement->setAttribute ("Include", prependDot (pchSourceFile.getFileName())); | |||
| setSourceFilePCHSettings (*pchSourceElement, pchFile, "Create", *config); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void addFilesToCompile (const Project::Item& projectItem, XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles) const | |||
| { | |||
| auto targetType = (getOwner().getProject().isAudioPluginProject() ? type : SharedCodeTarget); | |||
| @@ -791,6 +846,20 @@ public: | |||
| if (extraCompilerFlags.isNotEmpty()) | |||
| e->createNewChildElement ("AdditionalOptions")->addTextElement (extraCompilerFlags + " %(AdditionalOptions)"); | |||
| if (! projectItem.shouldSkipPCH()) | |||
| { | |||
| for (ConstConfigIterator i (owner); i.next();) | |||
| { | |||
| if (i->shouldUsePrecompiledHeaderFile()) | |||
| { | |||
| auto pchFile = owner.getTargetFolder().getChildFile (i->getPrecompiledHeaderFilename()).withFileExtension (".h"); | |||
| if (pchFile.existsAsFile()) | |||
| setSourceFilePCHSettings (*e, pchFile, "Use", *i); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| @@ -808,7 +877,7 @@ public: | |||
| } | |||
| } | |||
| void setConditionAttribute (XmlElement& xml, const BuildConfiguration& config) const | |||
| static void setConditionAttribute (XmlElement& xml, const BuildConfiguration& config) | |||
| { | |||
| auto& msvcConfig = dynamic_cast<const MSVCBuildConfiguration&> (config); | |||
| xml.setAttribute ("Condition", "'$(Configuration)|$(Platform)'=='" + msvcConfig.createMSVCConfigName() + "'"); | |||
| @@ -1314,22 +1383,26 @@ public: | |||
| }; | |||
| //============================================================================== | |||
| bool usesMMFiles() const override { return false; } | |||
| bool canCopeWithDuplicateFiles() override { return false; } | |||
| bool supportsUserDefinedConfigurations() const override { return true; } | |||
| bool isXcode() const override { return false; } | |||
| bool isVisualStudio() const override { return true; } | |||
| 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; } | |||
| bool isLinux() const override { return false; } | |||
| bool isOSX() const override { return false; } | |||
| bool isiOS() const override { return false; } | |||
| bool usesMMFiles() const override { return false; } | |||
| bool canCopeWithDuplicateFiles() override { return false; } | |||
| bool supportsUserDefinedConfigurations() const override { return true; } | |||
| bool isXcode() const override { return false; } | |||
| bool isVisualStudio() const override { return true; } | |||
| 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; } | |||
| bool isLinux() const override { return false; } | |||
| bool isOSX() const override { return false; } | |||
| bool isiOS() const override { return false; } | |||
| bool supportsPrecompiledHeaders() const override { return true; } | |||
| String getNewLineString() const override { return "\r\n"; } | |||
| bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override | |||
| { | |||
| @@ -255,7 +255,8 @@ public: | |||
| out << "OBJECTS_" + getTargetVarName() + String (" := \\") << newLine; | |||
| for (auto& f : filesToCompile) | |||
| out << " $(JUCE_OBJDIR)/" << escapeSpaces (owner.getObjectFileFor ({ f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder })) << " \\" << newLine; | |||
| out << " $(JUCE_OBJDIR)/" << escapeSpaces (owner.getObjectFileFor ({ f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder })) | |||
| << " \\" << newLine; | |||
| out << newLine; | |||
| } | |||
| @@ -274,7 +275,7 @@ public: | |||
| << "\t@echo \"Compiling " << relativePath.getFileName() << "\"" << newLine | |||
| << (relativePath.hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS) " : "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) ") | |||
| << "$(" << cppflagsVarName << ") $(" << cflagsVarName << ")" | |||
| << (f.second.isNotEmpty() ? " $(" + owner.getCompilerFlagSchemeVariableName (f.second) + ")" : "") << " -o \"$@\" -c \"$<\"" << newLine | |||
| << (f.second.isNotEmpty() ? " $(" + owner.getCompilerFlagSchemeVariableName (f.second) + ")" : "") << " -o \"$@\" -c \"$<\"" << newLine | |||
| << newLine; | |||
| } | |||
| } | |||
| @@ -415,6 +416,8 @@ public: | |||
| bool isOSX() const override { return false; } | |||
| bool isiOS() const override { return false; } | |||
| String getNewLineString() const override { return "\n"; } | |||
| bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override | |||
| { | |||
| switch (type) | |||
| @@ -474,7 +477,7 @@ public: | |||
| { | |||
| build_tools::writeStreamToFile (getTargetFolder().getChildFile ("Makefile"), [&] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| writeMakefile (mo); | |||
| }); | |||
| @@ -955,7 +958,9 @@ private: | |||
| writeCompilerFlagSchemes (out, filesToCompile); | |||
| auto getFilesForTarget = [] (const Array<std::pair<File, String>>& files, MakefileTarget* target, const Project& p) -> Array<std::pair<File, String>> | |||
| auto getFilesForTarget = [] (const Array<std::pair<File, String>>& files, | |||
| MakefileTarget* target, | |||
| const Project& p) -> Array<std::pair<File, String>> | |||
| { | |||
| Array<std::pair<File, String>> targetFiles; | |||
| @@ -295,6 +295,10 @@ public: | |||
| bool isOSX() const override { return ! iOS; } | |||
| bool isiOS() const override { return iOS; } | |||
| bool supportsPrecompiledHeaders() const override { return true; } | |||
| String getNewLineString() const override { return "\n"; } | |||
| bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override | |||
| { | |||
| switch (type) | |||
| @@ -1387,6 +1391,23 @@ public: | |||
| s.set ("GCC_OPTIMIZATION_LEVEL", config.getGCCOptimisationFlag()); | |||
| if (config.shouldUsePrecompiledHeaderFile()) | |||
| { | |||
| s.set ("GCC_PRECOMPILE_PREFIX_HEADER", "YES"); | |||
| auto pchFileContent = config.getPrecompiledHeaderFileContent(); | |||
| if (pchFileContent.isNotEmpty()) | |||
| { | |||
| auto pchFilename = config.getPrecompiledHeaderFilename() + ".h"; | |||
| build_tools::writeStreamToFile (owner.getTargetFolder().getChildFile (pchFilename), | |||
| [&] (MemoryOutputStream& mo) { mo << pchFileContent; }); | |||
| s.set ("GCC_PREFIX_HEADER", pchFilename); | |||
| } | |||
| } | |||
| if (shouldCreatePList()) | |||
| { | |||
| s.set ("INFOPLIST_FILE", infoPlistFile.getFileName()); | |||
| @@ -1975,8 +1996,7 @@ private: | |||
| writeDefaultLaunchStoryboardFile(); | |||
| else if (getProject().getProjectFolder().getChildFile (customLaunchStoryboard).existsAsFile()) | |||
| addLaunchStoryboardFileReference (build_tools::RelativePath (customLaunchStoryboard, build_tools::RelativePath::projectFolder) | |||
| .rebased (getProject().getProjectFolder(), getTargetFolder(), build_tools::RelativePath::buildTargetFolder) | |||
| .toUnixStyle()); | |||
| .rebased (getProject().getProjectFolder(), getTargetFolder(), build_tools::RelativePath::buildTargetFolder)); | |||
| } | |||
| } | |||
| else | |||
| @@ -2053,7 +2073,7 @@ private: | |||
| build_tools::RelativePath menuNibPath (menuNibFile, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); | |||
| addFileReference (menuNibPath.toUnixStyle()); | |||
| resourceIDs.add (addBuildFile (menuNibPath, false, false)); | |||
| resourceIDs.add (addBuildFile (FileOptions().withRelativePath (menuNibPath))); | |||
| resourceFileRefs.add (createFileRefID (menuNibPath)); | |||
| } | |||
| @@ -2063,7 +2083,7 @@ private: | |||
| { | |||
| build_tools::RelativePath iconPath (iconFile, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); | |||
| addFileReference (iconPath.toUnixStyle()); | |||
| resourceIDs.add (addBuildFile (iconPath, false, false)); | |||
| resourceIDs.add (addBuildFile (FileOptions().withRelativePath (iconPath))); | |||
| resourceFileRefs.add (createFileRefID (iconPath)); | |||
| } | |||
| } | |||
| @@ -2216,7 +2236,8 @@ private: | |||
| auto path = scriptPath.toUnixStyle(); | |||
| auto refID = addFileReference (path); | |||
| auto fileID = addBuildFile (path, refID, false, false); | |||
| auto fileID = addBuildFile (FileOptions().withPath (path) | |||
| .withFileRefID (refID)); | |||
| resourceIDs.add (fileID); | |||
| resourceFileRefs.add (refID); | |||
| @@ -2281,9 +2302,9 @@ private: | |||
| .getChildFile ("xcshareddata") | |||
| .getChildFile ("WorkspaceSettings.xcsettings"); | |||
| build_tools::writeStreamToFile (settingsFile, [] (MemoryOutputStream& mo) | |||
| build_tools::writeStreamToFile (settingsFile, [this] (MemoryOutputStream& mo) | |||
| { | |||
| mo.setNewLineString ("\n"); | |||
| mo.setNewLineString (getNewLineString()); | |||
| mo << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << newLine | |||
| << "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" << newLine | |||
| @@ -2586,7 +2607,7 @@ private: | |||
| if (availableBuildProducts.empty()) | |||
| continue; | |||
| auto subprojectFileType = getFileType (build_tools::RelativePath (subprojectFile.getFullPathName(), build_tools::RelativePath::buildTargetFolder)); | |||
| auto subprojectFileType = getFileType (subprojectFile.getFullPathName()); | |||
| auto subprojectFileID = addFileOrFolderReference (subprojectFile.getFullPathName(), "<group>", subprojectFileType); | |||
| subprojectFileIDs.add (subprojectFileID); | |||
| @@ -2594,7 +2615,7 @@ private: | |||
| for (auto& buildProduct : availableBuildProducts) | |||
| { | |||
| auto buildProductFileType = getFileType (build_tools::RelativePath (buildProduct.second, build_tools::RelativePath::projectFolder)); | |||
| auto buildProductFileType = getFileType (buildProduct.second); | |||
| auto containerID = addContainerItemProxy (subprojectFileID, buildProduct.first); | |||
| auto proxyID = addReferenceProxy (containerID, buildProduct.second, buildProductFileType); | |||
| @@ -2602,7 +2623,9 @@ private: | |||
| if (buildProductFileType == "archive.ar" || buildProductFileType == "wrapper.framework") | |||
| { | |||
| auto buildFileID = addBuildFile (buildProduct.second, proxyID, false, true); | |||
| auto buildFileID = addBuildFile (FileOptions().withPath (buildProduct.second) | |||
| .withFileRefID (proxyID) | |||
| .withInhibitWarningsEnabled (true)); | |||
| for (auto& target : targets) | |||
| target->frameworkIDs.add (buildFileID); | |||
| @@ -2649,7 +2672,9 @@ private: | |||
| addFileOrFolderReference (folderPath, "<group>", fileType); | |||
| resourceIDs.add (addBuildFile (folderPath, fileRefID, false, false)); | |||
| resourceIDs.add (addBuildFile (FileOptions().withPath (folderPath) | |||
| .withFileRefID (fileRefID))); | |||
| resourceFileRefs.add (createFileRefID (folderPath)); | |||
| } | |||
| @@ -2694,38 +2719,6 @@ private: | |||
| output << "\t};\n\trootObject = " << createID ("__root") << ";\n}\n"; | |||
| } | |||
| String addBuildFile (const String& path, const String& fileRefID, bool addToSourceBuildPhase, bool inhibitWarnings, | |||
| XcodeTarget* xcodeTarget = nullptr, String compilerFlags = {}) const | |||
| { | |||
| auto fileID = createID (path + "buildref"); | |||
| if (addToSourceBuildPhase) | |||
| { | |||
| if (xcodeTarget != nullptr) | |||
| xcodeTarget->sourceIDs.add (fileID); | |||
| else | |||
| sourceIDs.add (fileID); | |||
| } | |||
| auto* v = new ValueTree (fileID); | |||
| v->setProperty ("isa", "PBXBuildFile", nullptr); | |||
| v->setProperty ("fileRef", fileRefID, nullptr); | |||
| if (inhibitWarnings) | |||
| compilerFlags += " -w"; | |||
| if (compilerFlags.isNotEmpty()) | |||
| v->setProperty ("settings", "{ COMPILER_FLAGS = \"" + compilerFlags.trim() + "\"; }", nullptr); | |||
| pbxBuildFiles.add (v); | |||
| return fileID; | |||
| } | |||
| String addBuildFile (const build_tools::RelativePath& path, bool addToSourceBuildPhase, bool inhibitWarnings, XcodeTarget* xcodeTarget = nullptr) const | |||
| { | |||
| return addBuildFile (path.toUnixStyle(), createFileRefID (path), addToSourceBuildPhase, inhibitWarnings, xcodeTarget); | |||
| } | |||
| String addFileReference (String pathString) const | |||
| { | |||
| String sourceTree ("SOURCE_ROOT"); | |||
| @@ -2741,9 +2734,7 @@ private: | |||
| sourceTree = "<absolute>"; | |||
| } | |||
| auto fileType = getFileType (path); | |||
| return addFileOrFolderReference (pathString, sourceTree, fileType); | |||
| return addFileOrFolderReference (pathString, sourceTree, getFileType (pathString)); | |||
| } | |||
| void checkAndAddFileReference (std::unique_ptr<ValueTree> v) const | |||
| @@ -2817,8 +2808,34 @@ public: | |||
| } | |||
| private: | |||
| static String getFileType (const build_tools::RelativePath& file) | |||
| struct FileOptions | |||
| { | |||
| FileOptions& withPath (const String& p) { path = p; return *this; } | |||
| FileOptions& withRelativePath (const build_tools::RelativePath& p) { path = p.toUnixStyle(); return *this; } | |||
| FileOptions& withFileRefID (const String& fid) { fileRefID = fid; return *this; } | |||
| FileOptions& withCompilerFlags (const String& f) { compilerFlags = f; return *this; } | |||
| FileOptions& withCompilationEnabled (bool e) { compile = e; return *this; } | |||
| FileOptions& withAddToBinaryResourcesEnabled (bool e) { addToBinaryResources = e; return *this; } | |||
| FileOptions& withAddToXcodeResourcesEnabled (bool e) { addToXcodeResources = e; return *this; } | |||
| FileOptions& withInhibitWarningsEnabled (bool e) { inhibitWarnings = e; return *this; } | |||
| FileOptions& withSkipPCHEnabled (bool e) { skipPCH = e; return *this; } | |||
| FileOptions& withXcodeTarget (XcodeTarget* t) { xcodeTarget = t; return *this; } | |||
| String path; | |||
| String fileRefID; | |||
| String compilerFlags; | |||
| bool compile = false; | |||
| bool addToBinaryResources = false; | |||
| bool addToXcodeResources = false; | |||
| bool inhibitWarnings = false; | |||
| bool skipPCH = false; | |||
| XcodeTarget* xcodeTarget = nullptr; | |||
| }; | |||
| static String getFileType (const String& filePath) | |||
| { | |||
| auto file = File::createFileWithoutCheckingPath (filePath); | |||
| if (file.hasFileExtension (cppFileExtensions)) return "sourcecode.cpp.cpp"; | |||
| if (file.hasFileExtension (".mm")) return "sourcecode.cpp.objcpp"; | |||
| if (file.hasFileExtension (".m")) return "sourcecode.c.objc"; | |||
| @@ -2842,23 +2859,17 @@ private: | |||
| return "file" + file.getFileExtension(); | |||
| } | |||
| String addFile (const build_tools::RelativePath& path, bool shouldBeCompiled, bool shouldBeAddedToBinaryResources, | |||
| bool shouldBeAddedToXcodeResources, bool inhibitWarnings, XcodeTarget* xcodeTarget, const String& compilerFlags) const | |||
| String addFile (const FileOptions& opts) const | |||
| { | |||
| auto pathAsString = path.toUnixStyle(); | |||
| auto refID = addFileReference (path.toUnixStyle()); | |||
| auto refID = addFileReference (opts.path); | |||
| if (shouldBeCompiled) | |||
| if (opts.compile || opts.addToXcodeResources) | |||
| { | |||
| addBuildFile (pathAsString, refID, true, inhibitWarnings, xcodeTarget, compilerFlags); | |||
| } | |||
| else if (! shouldBeAddedToBinaryResources || shouldBeAddedToXcodeResources) | |||
| { | |||
| auto fileType = getFileType (path); | |||
| auto fileID = addBuildFile (FileOptions (opts).withFileRefID (refID)); | |||
| if (shouldBeAddedToXcodeResources) | |||
| if (opts.addToXcodeResources) | |||
| { | |||
| resourceIDs.add (addBuildFile (pathAsString, refID, false, false)); | |||
| resourceIDs.add (fileID); | |||
| resourceFileRefs.add (refID); | |||
| } | |||
| } | |||
| @@ -2866,16 +2877,50 @@ private: | |||
| return refID; | |||
| } | |||
| String addBuildFile (const FileOptions& opts) const | |||
| { | |||
| auto fileID = createID (opts.path + "buildref"); | |||
| if (opts.compile) | |||
| { | |||
| if (opts.xcodeTarget != nullptr) | |||
| opts.xcodeTarget->sourceIDs.add (fileID); | |||
| else | |||
| sourceIDs.add (fileID); | |||
| } | |||
| auto* v = new ValueTree (fileID); | |||
| v->setProperty ("isa", "PBXBuildFile", nullptr); | |||
| v->setProperty ("fileRef", opts.fileRefID.isEmpty() ? createFileRefID (opts.path) | |||
| : opts.fileRefID, | |||
| nullptr); | |||
| auto compilerFlags = [&opts] | |||
| { | |||
| return (opts.compilerFlags | |||
| + (opts.inhibitWarnings ? " -w" : String()) | |||
| + (opts.skipPCH ? " -D" + BuildConfiguration::getSkipPrecompiledHeaderDefine() : String())).trim(); | |||
| }(); | |||
| if (compilerFlags.isNotEmpty()) | |||
| v->setProperty ("settings", "{ COMPILER_FLAGS = \"" + compilerFlags + "\"; }", nullptr); | |||
| pbxBuildFiles.add (v); | |||
| return fileID; | |||
| } | |||
| String addRezFile (const Project::Item& projectItem, const build_tools::RelativePath& path) const | |||
| { | |||
| auto pathAsString = path.toUnixStyle(); | |||
| auto refID = addFileReference (path.toUnixStyle()); | |||
| if (projectItem.isModuleCode()) | |||
| { | |||
| if (auto* xcodeTarget = getTargetOfType (getProject().getTargetTypeFromFilePath (projectItem.getFile(), false))) | |||
| { | |||
| auto rezFileID = addBuildFile (pathAsString, refID, false, false, xcodeTarget); | |||
| auto rezFileID = addBuildFile (FileOptions().withRelativePath (path) | |||
| .withFileRefID (refID) | |||
| .withXcodeTarget (xcodeTarget)); | |||
| xcodeTarget->rezFileIDs.add (rezFileID); | |||
| return refID; | |||
| @@ -2907,7 +2952,7 @@ private: | |||
| build_tools::overwriteFileIfDifferentOrThrow (entitlementsFile, options.getEntitlementsFileContent()); | |||
| build_tools::RelativePath entitlementsPath (entitlementsFile, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); | |||
| addFile (entitlementsPath, false, false, false, false, nullptr, {}); | |||
| addFile (FileOptions().withRelativePath (entitlementsPath)); | |||
| } | |||
| String addProjectItem (const Project::Item& projectItem) const | |||
| @@ -2951,12 +2996,14 @@ private: | |||
| if (projectItem.isModuleCode() && projectItem.shouldBeCompiled()) | |||
| xcodeTarget = getTargetOfType (project.getTargetTypeFromFilePath (projectItem.getFile(), false)); | |||
| return addFile (path, projectItem.shouldBeCompiled(), | |||
| projectItem.shouldBeAddedToBinaryResources(), | |||
| projectItem.shouldBeAddedToXcodeResources(), | |||
| projectItem.shouldInhibitWarnings(), | |||
| xcodeTarget, | |||
| compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get()); | |||
| return addFile (FileOptions().withRelativePath (path) | |||
| .withCompilerFlags (compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get()) | |||
| .withCompilationEnabled (projectItem.shouldBeCompiled()) | |||
| .withAddToBinaryResourcesEnabled (projectItem.shouldBeAddedToBinaryResources()) | |||
| .withAddToXcodeResourcesEnabled (projectItem.shouldBeAddedToXcodeResources()) | |||
| .withInhibitWarningsEnabled (projectItem.shouldInhibitWarnings()) | |||
| .withSkipPCHEnabled (isPCHEnabledForAnyConfigurations() && projectItem.shouldSkipPCH()) | |||
| .withXcodeTarget (xcodeTarget)); | |||
| } | |||
| return {}; | |||
| @@ -2978,7 +3025,8 @@ private: | |||
| addFileReference (((File::isAbsolutePath (frameworkName) || isRelativePath) ? "" : "${SDKROOT}/") + path); | |||
| frameworkFileIDs.add (fileRefID); | |||
| return addBuildFile (path, fileRefID, false, false); | |||
| return addBuildFile (FileOptions().withPath (path) | |||
| .withFileRefID (fileRefID)); | |||
| } | |||
| String addCustomFramework (String frameworkPath) const | |||
| @@ -2988,19 +3036,20 @@ private: | |||
| auto fileRefID = createFileRefID (frameworkPath); | |||
| auto fileType = getFileType (build_tools::RelativePath (frameworkPath, build_tools::RelativePath::projectFolder)); | |||
| auto fileType = getFileType (frameworkPath); | |||
| addFileOrFolderReference (frameworkPath, "<group>", fileType); | |||
| frameworkFileIDs.add (fileRefID); | |||
| return addBuildFile (frameworkPath, fileRefID, false, false); | |||
| return addBuildFile (FileOptions().withPath (frameworkPath) | |||
| .withFileRefID (fileRefID)); | |||
| } | |||
| String addEmbeddedFramework (const String& path) const | |||
| { | |||
| auto fileRefID = createFileRefID (path); | |||
| auto fileType = getFileType (build_tools::RelativePath (path, build_tools::RelativePath::projectFolder)); | |||
| auto fileType = getFileType (path); | |||
| addFileOrFolderReference (path, "<group>", fileType); | |||
| auto fileID = createID (path + "buildref"); | |||
| @@ -3213,13 +3262,16 @@ private: | |||
| addLaunchStoryboardFileReference (build_tools::RelativePath (storyboardFile, | |||
| getTargetFolder(), | |||
| build_tools::RelativePath::buildTargetFolder).toUnixStyle()); | |||
| build_tools::RelativePath::buildTargetFolder)); | |||
| } | |||
| void addLaunchStoryboardFileReference (const String& relativePath) const | |||
| void addLaunchStoryboardFileReference (const build_tools::RelativePath& relativePath) const | |||
| { | |||
| auto refID = addFileReference (relativePath); | |||
| auto fileID = addBuildFile (relativePath, refID, false, false); | |||
| auto path = relativePath.toUnixStyle(); | |||
| auto refID = addFileReference (path); | |||
| auto fileID = addBuildFile (FileOptions().withPath (path) | |||
| .withFileRefID (refID)); | |||
| resourceIDs.add (fileID); | |||
| resourceFileRefs.add (refID); | |||
| @@ -3231,7 +3283,7 @@ private: | |||
| getTargetFolder(), | |||
| project.getProjectFilenameRootString()); | |||
| addFileReference (assetsPath.toUnixStyle()); | |||
| resourceIDs.add (addBuildFile (assetsPath, false, false)); | |||
| resourceIDs.add (addBuildFile (FileOptions().withRelativePath (assetsPath))); | |||
| resourceFileRefs.add (createFileRefID (assetsPath)); | |||
| } | |||
| @@ -3264,8 +3316,8 @@ private: | |||
| } | |||
| String createFileRefID (const build_tools::RelativePath& path) const { return createFileRefID (path.toUnixStyle()); } | |||
| String createFileRefID (const String& path) const { return createID ("__fileref_" + path); } | |||
| String getIDForGroup (const Project::Item& item) const { return createID (item.getID()); } | |||
| String createFileRefID (const String& path) const { return createID ("__fileref_" + path); } | |||
| String getIDForGroup (const Project::Item& item) const { return createID (item.getID()); } | |||
| bool shouldFileBeCompiledByDefault (const File& file) const override | |||
| { | |||
| @@ -845,17 +845,19 @@ bool ProjectExporter::ConstConfigIterator::next() | |||
| //============================================================================== | |||
| ProjectExporter::BuildConfiguration::BuildConfiguration (Project& p, const ValueTree& configNode, const ProjectExporter& e) | |||
| : config (configNode), project (p), exporter (e), | |||
| isDebugValue (config, Ids::isDebug, getUndoManager(), getValue (Ids::isDebug)), | |||
| configNameValue (config, Ids::name, getUndoManager(), "Build Configuration"), | |||
| targetNameValue (config, Ids::targetName, getUndoManager(), project.getProjectFilenameRootString()), | |||
| targetBinaryPathValue (config, Ids::binaryPath, getUndoManager()), | |||
| recommendedWarningsValue (config, Ids::recommendedWarnings, getUndoManager()), | |||
| optimisationLevelValue (config, Ids::optimisation, getUndoManager()), | |||
| linkTimeOptimisationValue (config, Ids::linkTimeOptimisation, getUndoManager(), ! isDebug()), | |||
| ppDefinesValue (config, Ids::defines, getUndoManager()), | |||
| headerSearchPathValue (config, Ids::headerPath, getUndoManager()), | |||
| librarySearchPathValue (config, Ids::libraryPath, getUndoManager()), | |||
| userNotesValue (config, Ids::userNotes, getUndoManager()) | |||
| isDebugValue (config, Ids::isDebug, getUndoManager(), getValue (Ids::isDebug)), | |||
| configNameValue (config, Ids::name, getUndoManager(), "Build Configuration"), | |||
| targetNameValue (config, Ids::targetName, getUndoManager(), project.getProjectFilenameRootString()), | |||
| targetBinaryPathValue (config, Ids::binaryPath, getUndoManager()), | |||
| recommendedWarningsValue (config, Ids::recommendedWarnings, getUndoManager()), | |||
| optimisationLevelValue (config, Ids::optimisation, getUndoManager()), | |||
| linkTimeOptimisationValue (config, Ids::linkTimeOptimisation, getUndoManager(), ! isDebug()), | |||
| ppDefinesValue (config, Ids::defines, getUndoManager()), | |||
| headerSearchPathValue (config, Ids::headerPath, getUndoManager()), | |||
| librarySearchPathValue (config, Ids::libraryPath, getUndoManager()), | |||
| userNotesValue (config, Ids::userNotes, getUndoManager()), | |||
| usePrecompiledHeaderFileValue (config, Ids::usePrecompiledHeaderFile, getUndoManager(), false), | |||
| precompiledHeaderFileValue (config, Ids::precompiledHeaderFile, getUndoManager()) | |||
| { | |||
| recommendedCompilerWarningFlags["LLVM"] = { "-Wall", "-Wshadow-all", "-Wshorten-64-to-32", "-Wstrict-aliasing", "-Wuninitialized", "-Wunused-parameter", | |||
| "-Wconversion", "-Wsign-compare", "-Wint-conversion", "-Wconditional-uninitialized", "-Woverloaded-virtual", | |||
| @@ -960,6 +962,22 @@ void ProjectExporter::BuildConfiguration::createPropertyEditors (PropertyListBui | |||
| props.add (new ChoicePropertyComponent (linkTimeOptimisationValue, "Link-Time Optimisation"), | |||
| "Enable this to perform link-time code optimisation. This is recommended for release builds."); | |||
| if (exporter.supportsPrecompiledHeaders()) | |||
| { | |||
| props.add (new ChoicePropertyComponent (usePrecompiledHeaderFileValue, "Use Precompiled Header"), | |||
| "Enable this to turn on precompiled header support for this configuration. Use the setting " | |||
| "below to specify the header file to use."); | |||
| auto quotedHeaderFileName = (getPrecompiledHeaderFilename() + ".h").quoted(); | |||
| props.add (new FilePathPropertyComponentWithEnablement (precompiledHeaderFileValue, usePrecompiledHeaderFileValue, | |||
| "Precompiled Header File", false, true, "*", project.getProjectFolder()), | |||
| "Specify an input header file that will be used to generate a file named " + quotedHeaderFileName + " which is used to generate the " | |||
| "PCH file artifact for this exporter configuration. This file can be an absolute path, or relative to the jucer project folder. " | |||
| "The " + quotedHeaderFileName + " file will be force included to all source files unless the \"Skip PCH\" setting has been enabled. " | |||
| "The generated header will be written on project save and placed in the target folder for this exporter."); | |||
| } | |||
| createConfigProperties (props); | |||
| props.add (new TextPropertyComponent (userNotesValue, "Notes", 32768, true), | |||
| @@ -1010,6 +1028,31 @@ StringArray ProjectExporter::BuildConfiguration::getLibrarySearchPaths() const | |||
| return s; | |||
| } | |||
| String ProjectExporter::BuildConfiguration::getPrecompiledHeaderFileContent() const | |||
| { | |||
| if (shouldUsePrecompiledHeaderFile()) | |||
| { | |||
| auto f = project.getProjectFolder().getChildFile (precompiledHeaderFileValue.get().toString()); | |||
| if (f.existsAsFile() && f.hasFileExtension (headerFileExtensions)) | |||
| { | |||
| MemoryOutputStream content; | |||
| content.setNewLineString (exporter.getNewLineString()); | |||
| writeAutoGenWarningComment (content); | |||
| content << "*/" << newLine << newLine | |||
| << "#ifndef " << getSkipPrecompiledHeaderDefine() << newLine << newLine | |||
| << f.loadFileAsString() << newLine | |||
| << "#endif" << newLine; | |||
| return content.toString(); | |||
| } | |||
| } | |||
| return {}; | |||
| } | |||
| String ProjectExporter::getExternalLibraryFlags (const BuildConfiguration& config) const | |||
| { | |||
| auto libraries = StringArray::fromTokens (getExternalLibrariesString(), ";\n", "\"'"); | |||
| @@ -87,7 +87,10 @@ public: | |||
| virtual bool isOSX() const = 0; | |||
| virtual bool isiOS() const = 0; | |||
| virtual String getDescription() { return {}; } | |||
| virtual String getNewLineString() const = 0; | |||
| virtual String getDescription() { return {}; } | |||
| virtual bool supportsPrecompiledHeaders() const { return false; } | |||
| //============================================================================== | |||
| // cross-platform audio plug-ins supported by exporter | |||
| @@ -246,7 +249,12 @@ public: | |||
| String getLibrarySearchPathString() const { return librarySearchPathValue.get(); } | |||
| StringArray getLibrarySearchPaths() const; | |||
| String getGCCLibraryPathFlags() const; | |||
| String getPrecompiledHeaderFilename() const { return "JucePrecompiledHeader_" + getName(); } | |||
| static String getSkipPrecompiledHeaderDefine() { return "JUCE_SKIP_PRECOMPILED_HEADER"; } | |||
| bool shouldUsePrecompiledHeaderFile() const { return usePrecompiledHeaderFileValue.get(); } | |||
| String getPrecompiledHeaderFileContent() const; | |||
| //============================================================================== | |||
| Value getValue (const Identifier& nm) { return config.getPropertyAsValue (nm, getUndoManager()); } | |||
| @@ -267,7 +275,8 @@ public: | |||
| protected: | |||
| ValueWithDefault isDebugValue, configNameValue, targetNameValue, targetBinaryPathValue, recommendedWarningsValue, optimisationLevelValue, | |||
| linkTimeOptimisationValue, ppDefinesValue, headerSearchPathValue, librarySearchPathValue, userNotesValue; | |||
| linkTimeOptimisationValue, ppDefinesValue, headerSearchPathValue, librarySearchPathValue, userNotesValue, | |||
| usePrecompiledHeaderFileValue, precompiledHeaderFileValue; | |||
| private: | |||
| std::map<String, StringArray> recommendedCompilerWarningFlags; | |||
| @@ -349,6 +358,16 @@ public: | |||
| gccOfast = 6 | |||
| }; | |||
| bool isPCHEnabledForAnyConfigurations() const | |||
| { | |||
| if (supportsPrecompiledHeaders()) | |||
| for (ConstConfigIterator config (*this); config.next();) | |||
| if (config->shouldUsePrecompiledHeaderFile()) | |||
| return true; | |||
| return false; | |||
| } | |||
| protected: | |||
| //============================================================================== | |||
| String name; | |||
| @@ -313,14 +313,6 @@ Result ProjectSaver::saveProject (ProjectExporter* specifiedExporterToSave) | |||
| } | |||
| //============================================================================== | |||
| static void writeAutoGenWarningComment (OutputStream& out) | |||
| { | |||
| out << "/*" << newLine << newLine | |||
| << " IMPORTANT! This file is auto-generated each time you save your" << newLine | |||
| << " project - if you alter its contents, your changes may be overwritten!" << newLine | |||
| << newLine; | |||
| } | |||
| void ProjectSaver::writePluginDefines (MemoryOutputStream& out) const | |||
| { | |||
| const auto pluginDefines = getAudioPluginDefines(); | |||
| @@ -329,6 +321,7 @@ void ProjectSaver::writePluginDefines (MemoryOutputStream& out) const | |||
| return; | |||
| writeAutoGenWarningComment (out); | |||
| out << "*/" << newLine << newLine | |||
| << "#pragma once" << newLine << newLine | |||
| << pluginDefines << newLine; | |||
| @@ -248,6 +248,15 @@ bool fileNeedsCppSyntaxHighlighting (const File& file) | |||
| && String (fileStart).trimStart().startsWith ("// -*- C++ -*-"); | |||
| } | |||
| //============================================================================== | |||
| void writeAutoGenWarningComment (OutputStream& outStream) | |||
| { | |||
| outStream << "/*" << newLine << newLine | |||
| << " IMPORTANT! This file is auto-generated each time you save your" << newLine | |||
| << " project - if you alter its contents, your changes may be overwritten!" << newLine | |||
| << newLine; | |||
| } | |||
| //============================================================================== | |||
| StringArray getJUCEModules() noexcept | |||
| { | |||
| @@ -54,6 +54,8 @@ void setValueIfVoid (Value value, const var& defaultValue); | |||
| bool fileNeedsCppSyntaxHighlighting (const File& file); | |||
| void writeAutoGenWarningComment (OutputStream& outStream); | |||
| StringArray getJUCEModules() noexcept; | |||
| bool isJUCEModule (const String& moduleID) noexcept; | |||
| @@ -49,6 +49,8 @@ namespace Ids | |||
| DECLARE_ID (companyEmail); | |||
| DECLARE_ID (useAppConfig); | |||
| DECLARE_ID (addUsingNamespaceToJuceHeader); | |||
| DECLARE_ID (usePrecompiledHeaderFile); | |||
| DECLARE_ID (precompiledHeaderFile); | |||
| DECLARE_ID (displaySplashScreen); | |||
| DECLARE_ID (splashScreenColour); | |||
| DECLARE_ID (position); | |||
| @@ -160,6 +162,7 @@ namespace Ids | |||
| DECLARE_ID (aaxFolder); | |||
| DECLARE_ID (compile); | |||
| DECLARE_ID (noWarnings); | |||
| DECLARE_ID (skipPCH); | |||
| DECLARE_ID (resource); | |||
| DECLARE_ID (xcodeResource); | |||
| DECLARE_ID (xcodeValidArchs); | |||
| @@ -34,7 +34,7 @@ | |||
| */ | |||
| class FilePathPropertyComponent : public PropertyComponent, | |||
| public FileDragAndDropTarget, | |||
| private Value::Listener | |||
| protected Value::Listener | |||
| { | |||
| public: | |||
| FilePathPropertyComponent (Value valueToControl, const String& propertyName, bool isDir, bool thisOS = true, | |||
| @@ -92,6 +92,12 @@ public: | |||
| repaint(); | |||
| } | |||
| protected: | |||
| void valueChanged (Value&) override | |||
| { | |||
| updateEditorColour(); | |||
| } | |||
| private: | |||
| //============================================================================== | |||
| void init() | |||
| @@ -165,11 +171,6 @@ private: | |||
| } | |||
| } | |||
| void valueChanged (Value&) override | |||
| { | |||
| updateEditorColour(); | |||
| } | |||
| void lookAndFeelChanged() override | |||
| { | |||
| browseButton.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId)); | |||
| @@ -191,3 +192,40 @@ private: | |||
| //============================================================================== | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilePathPropertyComponent) | |||
| }; | |||
| //============================================================================== | |||
| class FilePathPropertyComponentWithEnablement : public FilePathPropertyComponent | |||
| { | |||
| public: | |||
| FilePathPropertyComponentWithEnablement (ValueWithDefault& valueToControl, | |||
| ValueWithDefault valueToListenTo, | |||
| const String& propertyName, | |||
| bool isDir, | |||
| bool thisOS = true, | |||
| const String& wildcardsToUse = "*", | |||
| const File& relativeRoot = File()) | |||
| : FilePathPropertyComponent (valueToControl, | |||
| propertyName, | |||
| isDir, | |||
| thisOS, | |||
| wildcardsToUse, | |||
| relativeRoot), | |||
| valueWithDefault (valueToListenTo), | |||
| value (valueToListenTo.getPropertyAsValue()) | |||
| { | |||
| value.addListener (this); | |||
| valueChanged (value); | |||
| } | |||
| ~FilePathPropertyComponentWithEnablement() override { value.removeListener (this); } | |||
| private: | |||
| void valueChanged (Value& v) override | |||
| { | |||
| FilePathPropertyComponent::valueChanged (v); | |||
| setEnabled (valueWithDefault.get()); | |||
| } | |||
| ValueWithDefault valueWithDefault; | |||
| Value value; | |||
| }; | |||