diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h index cb9a9b2d8a..b567b291d3 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h @@ -149,8 +149,8 @@ public: << "Add these exporters to the project to enable CLion builds." << newLine << newLine << "Not all features of all the exporters are currently supported. Notable omissions are AUv3 " - << "plug-ins, embedding resources and fat binaries on MacOS, and adding application icons. On " - << "Windows the CLion exporter requires a GCC-based compiler like MinGW."; + << "plug-ins, embedding resources and fat binaries on MacOS. On Windows the CLion exporter " + << "requires a GCC-based compiler like MinGW."; return description; } @@ -372,16 +372,47 @@ private: out << " " << fileInfo.first.quoted() << newLine; auto isCMakeBundle = exporter.isXcode() && target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle; - String pkgInfoPath = File (getTargetFolder().getChildFile ("PkgInfo")).getFullPathName().quoted(); + auto pkgInfoPath = String ("PkgInfo").quoted(); if (isCMakeBundle) out << " " << pkgInfoPath << newLine; + auto xcodeIcnsFilePath = [&] () -> String + { + if (exporter.isXcode() && target->getTargetFileType() == ProjectType::Target::TargetFileType::executable) + { + auto xcodeIcnsFile = getTargetFolder().getParentDirectory() + .getChildFile ("MacOSX") + .getChildFile ("Icon.icns"); + + if (xcodeIcnsFile.existsAsFile()) + return xcodeIcnsFile.getRelativePathFrom (getTargetFolder()).quoted(); + } + + return {}; + }(); + + if (xcodeIcnsFilePath.isNotEmpty()) + out << " " << xcodeIcnsFilePath << newLine; + + if (exporter.isCodeBlocks() && target->getTargetFileType() == ProjectType::Target::TargetFileType::executable) + { + auto windowsRcFile = getTargetFolder().getParentDirectory() + .getChildFile ("CodeBlocksWindows") + .getChildFile ("resources.rc"); + + if (windowsRcFile.existsAsFile()) + out << " " << windowsRcFile.getRelativePathFrom (getTargetFolder()).quoted() << newLine; + } + out << ")" << newLine << newLine; if (isCMakeBundle) out << "set_source_files_properties (" << pkgInfoPath << " PROPERTIES MACOSX_PACKAGE_LOCATION .)" << newLine; + if (xcodeIcnsFilePath.isNotEmpty()) + out << "set_source_files_properties (" << xcodeIcnsFilePath << " PROPERTIES MACOSX_PACKAGE_LOCATION \"Resources\")" << newLine; + for (auto& fileInfo : fileInfoList) if (! fileInfo.second) out << "set_source_files_properties (" << fileInfo.first.quoted() << " PROPERTIES HEADER_FILE_ONLY TRUE)" << newLine; @@ -643,7 +674,7 @@ private: if (! isWindowsAbsolutePath (path)) out << "${CMAKE_CURRENT_SOURCE_DIR}/"; - out << path.replace ("\\", "/") << "\\\"\"" << newLine; + out << path.replace ("\\", "/").unquoted() << "\\\"\"" << newLine; } for (auto& flag : exporter.getLinkerFlags (config, *target)) diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h index 30c7bd0437..17031263f7 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h @@ -26,6 +26,7 @@ #pragma once +#include "jucer_ProjectExport_MSVC.h" //============================================================================== class CodeBlocksProjectExporter : public ProjectExporter @@ -396,6 +397,7 @@ private: StringArray getCompilerFlags (const BuildConfiguration& config, CodeBlocksTarget& target) const { StringArray flags; + if (auto* codeBlocksConfig = dynamic_cast (&config)) flags.add (codeBlocksConfig->getArchitectureTypeString()); @@ -793,10 +795,27 @@ private: } } + bool hasResourceFile() const + { + return ! projectType.isStaticLibrary(); + } + void addCompileUnits (XmlElement& xml) const { for (int i = 0; i < getAllGroups().size(); ++i) addCompileUnits (getAllGroups().getReference(i), xml); + + if (hasResourceFile()) + { + auto iconFile = getTargetFolder().getChildFile ("icon.ico"); + MSVCProjectExporterBase::writeIconFile (*this, iconFile); + auto rcFile = getTargetFolder().getChildFile ("resources.rc"); + MSVCProjectExporterBase::createRCFile (project, iconFile, rcFile); + + auto* unit = xml.createNewChildElement ("Unit"); + unit->setAttribute ("filename", rcFile.getFileName()); + unit->createNewChildElement ("Option")->setAttribute ("compilerVar", "WINDRES"); + } } void createProject (XmlElement& xml) const diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h index d91c934d87..b57e7ef687 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h @@ -698,7 +698,7 @@ public: } } - if (getOwner().iconFile != File()) + if (getOwner().iconFile.existsAsFile()) { auto* e = otherFilesGroup->createNewChildElement ("None"); e->setAttribute ("Include", prependDot (getOwner().iconFile.getFileName())); @@ -884,7 +884,7 @@ public: addFilesToFilter (group, group.getName(), *cpps, *headers, *otherFilesGroup, *groupsXml); } - if (getOwner().iconFile.exists()) + if (getOwner().iconFile.existsAsFile()) { auto* e = otherFilesGroup->createNewChildElement ("None"); e->setAttribute ("Include", prependDot (getOwner().iconFile.getFileName())); @@ -1434,6 +1434,94 @@ public: return false; } + static void writeIconFile (const ProjectExporter& exporter, const File& iconFile) + { + Array images; + int sizes[] = { 16, 32, 48, 256 }; + + for (int i = 0; i < numElementsInArray (sizes); ++i) + { + auto im = exporter.getBestIconForSize (sizes[i], true); + + if (im.isValid()) + images.add (im); + } + + if (images.size() > 0) + { + MemoryOutputStream mo; + writeIconFile (images, mo); + overwriteFileIfDifferentOrThrow (iconFile, mo); + } + } + + static void writeRCValue (MemoryOutputStream& mo, const String& name, const String& value) + { + if (value.isNotEmpty()) + mo << " VALUE \"" << name << "\", \"" + << CppTokeniserFunctions::addEscapeChars (value) << "\\0\"" << newLine; + } + + static void createRCFile (const Project& project, const File& iconFile, const File& rcFile) + { + auto version = project.getVersionString(); + + MemoryOutputStream mo; + + mo << "#ifdef JUCE_USER_DEFINED_RC_FILE" << newLine + << " #include JUCE_USER_DEFINED_RC_FILE" << newLine + << "#else" << newLine + << newLine + << "#undef WIN32_LEAN_AND_MEAN" << newLine + << "#define WIN32_LEAN_AND_MEAN" << newLine + << "#include " << newLine + << newLine + << "VS_VERSION_INFO VERSIONINFO" << newLine + << "FILEVERSION " << getCommaSeparatedVersionNumber (version) << newLine + << "BEGIN" << newLine + << " BLOCK \"StringFileInfo\"" << newLine + << " BEGIN" << newLine + << " BLOCK \"040904E4\"" << newLine + << " BEGIN" << newLine; + + writeRCValue (mo, "CompanyName", project.getCompanyNameString()); + writeRCValue (mo, "LegalCopyright", project.getCompanyCopyrightString()); + writeRCValue (mo, "FileDescription", project.getProjectNameString()); + writeRCValue (mo, "FileVersion", version); + writeRCValue (mo, "ProductName", project.getProjectNameString()); + writeRCValue (mo, "ProductVersion", version); + + mo << " END" << newLine + << " END" << newLine + << newLine + << " BLOCK \"VarFileInfo\"" << newLine + << " BEGIN" << newLine + << " VALUE \"Translation\", 0x409, 1252" << newLine + << " END" << newLine + << "END" << newLine + << newLine + << "#endif" << newLine; + + if (iconFile.existsAsFile()) + mo << newLine + << "IDI_ICON1 ICON DISCARDABLE " << iconFile.getFileName().quoted() + << newLine + << "IDI_ICON2 ICON DISCARDABLE " << iconFile.getFileName().quoted(); + + overwriteFileIfDifferentOrThrow (rcFile, mo); + } + + static String getCommaSeparatedVersionNumber (const String& version) + { + auto versionParts = StringArray::fromTokens (version, ",.", ""); + versionParts.trim(); + versionParts.removeEmptyStrings(); + while (versionParts.size() < 4) + versionParts.add ("0"); + + return versionParts.joinIntoString (","); + } + private: //============================================================================== String createRebasedPath (const RelativePath& path) const @@ -1722,98 +1810,13 @@ protected: { if (hasResourceFile()) { - Array images; - int sizes[] = { 16, 32, 48, 256 }; - - for (int i = 0; i < numElementsInArray (sizes); ++i) - { - auto im = getBestIconForSize (sizes[i], true); - if (im.isValid()) - images.add (im); - } - - if (images.size() > 0) - { - iconFile = getTargetFolder().getChildFile ("icon.ico"); - - MemoryOutputStream mo; - writeIconFile (images, mo); - overwriteFileIfDifferentOrThrow (iconFile, mo); - } - - createRCFile(); + iconFile = getTargetFolder().getChildFile ("icon.ico"); + writeIconFile (*this, iconFile); + rcFile = getTargetFolder().getChildFile ("resources.rc"); + createRCFile (project, iconFile, rcFile); } } - void createRCFile() const - { - rcFile = getTargetFolder().getChildFile ("resources.rc"); - - auto version = project.getVersionString(); - - MemoryOutputStream mo; - - mo << "#ifdef JUCE_USER_DEFINED_RC_FILE" << newLine - << " #include JUCE_USER_DEFINED_RC_FILE" << newLine - << "#else" << newLine - << newLine - << "#undef WIN32_LEAN_AND_MEAN" << newLine - << "#define WIN32_LEAN_AND_MEAN" << newLine - << "#include " << newLine - << newLine - << "VS_VERSION_INFO VERSIONINFO" << newLine - << "FILEVERSION " << getCommaSeparatedVersionNumber (version) << newLine - << "BEGIN" << newLine - << " BLOCK \"StringFileInfo\"" << newLine - << " BEGIN" << newLine - << " BLOCK \"040904E4\"" << newLine - << " BEGIN" << newLine; - - writeRCValue (mo, "CompanyName", project.getCompanyNameString()); - writeRCValue (mo, "LegalCopyright", project.getCompanyCopyrightString()); - writeRCValue (mo, "FileDescription", project.getProjectNameString()); - writeRCValue (mo, "FileVersion", version); - writeRCValue (mo, "ProductName", project.getProjectNameString()); - writeRCValue (mo, "ProductVersion", version); - - mo << " END" << newLine - << " END" << newLine - << newLine - << " BLOCK \"VarFileInfo\"" << newLine - << " BEGIN" << newLine - << " VALUE \"Translation\", 0x409, 1252" << newLine - << " END" << newLine - << "END" << newLine - << newLine - << "#endif" << newLine; - - if (iconFile != File()) - mo << newLine - << "IDI_ICON1 ICON DISCARDABLE " << iconFile.getFileName().quoted() - << newLine - << "IDI_ICON2 ICON DISCARDABLE " << iconFile.getFileName().quoted(); - - overwriteFileIfDifferentOrThrow (rcFile, mo); - } - - static void writeRCValue (MemoryOutputStream& mo, const String& name, const String& value) - { - if (value.isNotEmpty()) - mo << " VALUE \"" << name << "\", \"" - << CppTokeniserFunctions::addEscapeChars (value) << "\\0\"" << newLine; - } - - static String getCommaSeparatedVersionNumber (const String& version) - { - auto versionParts = StringArray::fromTokens (version, ",.", ""); - versionParts.trim(); - versionParts.removeEmptyStrings(); - while (versionParts.size() < 4) - versionParts.add ("0"); - - return versionParts.joinIntoString (","); - } - static String prependDot (const String& filename) { return FileHelpers::isAbsolutePath (filename) ? filename