1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

CLion: Added support for application icons

This commit is contained in:
Tom Poole 2019-01-18 20:20:31 +00:00
parent e7750ecd92
commit 4d6921ff7d
3 changed files with 148 additions and 95 deletions

View file

@ -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))

View file

@ -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<const CodeBlocksBuildConfiguration*> (&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

View file

@ -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<Image> 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 <windows.h>" << 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<Image> 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 <windows.h>" << 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