mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Projucer: Add embedded Linux subprocess for WebView support
This commit is contained in:
parent
f9ff497978
commit
31f94c2e28
7 changed files with 878 additions and 23 deletions
|
|
@ -147,6 +147,7 @@ juce_add_binary_data(ProjucerData SOURCES
|
|||
Source/BinaryData/gradle/gradle-wrapper.jar
|
||||
Source/BinaryData/gradle/gradlew
|
||||
Source/BinaryData/gradle/gradlew.bat
|
||||
Source/BinaryData/juce_SimpleBinaryBuilder.cpp
|
||||
|
||||
../Build/CMake/JuceLV2Defines.h.in
|
||||
../Build/CMake/LaunchScreen.storyboard
|
||||
|
|
@ -156,7 +157,8 @@ juce_add_binary_data(ProjucerData SOURCES
|
|||
../Build/CMake/PIPConsole.cpp.in
|
||||
../Build/CMake/RecentFilesMenuTemplate.nib
|
||||
../Build/CMake/UnityPluginGUIScript.cs.in
|
||||
../Build/CMake/juce_runtime_arch_detection.cpp)
|
||||
../Build/CMake/juce_runtime_arch_detection.cpp
|
||||
../Build/CMake/juce_LinuxSubprocessHelper.cpp)
|
||||
|
||||
target_link_libraries(Projucer PRIVATE
|
||||
ProjucerData
|
||||
|
|
|
|||
|
|
@ -299,6 +299,10 @@
|
|||
file="Source/BinaryData/colourscheme_light.xml"/>
|
||||
<FILE id="SDFoQY" name="juce_runtime_arch_detection.cpp" compile="0"
|
||||
resource="1" file="../Build/CMake/juce_runtime_arch_detection.cpp"/>
|
||||
<FILE id="m0ZzB2" name="juce_LinuxSubprocessHelper.cpp" compile="0"
|
||||
resource="1" file="../Build/CMake/juce_LinuxSubprocessHelper.cpp"/>
|
||||
<FILE id="OMFBxs" name="juce_SimpleBinaryBuilder.cpp" compile="0" resource="1"
|
||||
file="Source/BinaryData/juce_SimpleBinaryBuilder.cpp"/>
|
||||
</GROUP>
|
||||
<GROUP id="{A5AE7471-B900-FD9D-8DE7-2FB68D11AE30}" name="CodeEditor">
|
||||
<FILE id="w3ka6n" name="jucer_DocumentEditorComponent.cpp" compile="1"
|
||||
|
|
|
|||
375
extras/Projucer/Source/BinaryData/juce_SimpleBinaryBuilder.cpp
Normal file
375
extras/Projucer/Source/BinaryData/juce_SimpleBinaryBuilder.cpp
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
//==============================================================================
|
||||
struct FileHelpers
|
||||
{
|
||||
static std::string getCurrentWorkingDirectory()
|
||||
{
|
||||
std::vector<char> buffer (1024);
|
||||
|
||||
while (getcwd (buffer.data(), buffer.size() - 1) == nullptr && errno == ERANGE)
|
||||
buffer.resize (buffer.size() * 2 / 3);
|
||||
|
||||
return { buffer.data() };
|
||||
}
|
||||
|
||||
static bool endsWith (const std::string& s, char c)
|
||||
{
|
||||
if (s.length() == 0)
|
||||
return false;
|
||||
|
||||
return *s.rbegin() == c;
|
||||
};
|
||||
|
||||
static std::string appendedPaths (const std::string& first, const std::string& second)
|
||||
{
|
||||
return endsWith (first, '/') ? first + second : first + "/" + second;
|
||||
}
|
||||
|
||||
static bool exists (const std::string& path)
|
||||
{
|
||||
return ! path.empty() && access (path.c_str(), F_OK) == 0;
|
||||
}
|
||||
|
||||
static bool deleteFile (const std::string& path)
|
||||
{
|
||||
if (! exists (path))
|
||||
return true;
|
||||
|
||||
return remove (path.c_str()) == 0;
|
||||
}
|
||||
|
||||
static std::string getFilename (const std::string& path)
|
||||
{
|
||||
return { std::find_if (path.rbegin(), path.rend(), [] (auto c) { return c == '/'; }).base(),
|
||||
path.end() };
|
||||
}
|
||||
|
||||
static bool isDirectory (const std::string& path)
|
||||
{
|
||||
struct stat64 info;
|
||||
|
||||
return ! path.empty()
|
||||
&& stat64 (path.c_str(), &info) == 0
|
||||
&& ((info.st_mode & S_IFDIR) != 0);
|
||||
}
|
||||
|
||||
static std::string getParentDirectory (const std::string& path)
|
||||
{
|
||||
std::string p { path.begin(),
|
||||
std::find_if (path.rbegin(),
|
||||
path.rend(),
|
||||
[] (auto c) { return c == '/'; }).base() };
|
||||
|
||||
// Trim the ending slash, but only if not root
|
||||
if (endsWith (p, '/') && p.length() > 1)
|
||||
return { p.begin(), p.end() - 1 };
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static bool createDirectory (const std::string& path)
|
||||
{
|
||||
if (isDirectory (path))
|
||||
return true;
|
||||
|
||||
const auto parentDir = getParentDirectory (path);
|
||||
|
||||
if (path == parentDir)
|
||||
return false;
|
||||
|
||||
if (createDirectory (parentDir))
|
||||
return mkdir (path.c_str(), 0777) != -1;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct StringHelpers
|
||||
{
|
||||
static bool isQuoteCharacter (char c)
|
||||
{
|
||||
return c == '"' || c == '\'';
|
||||
}
|
||||
|
||||
static std::string unquoted (const std::string& str)
|
||||
{
|
||||
if (str.length() == 0 || (! isQuoteCharacter (str[0])))
|
||||
return str;
|
||||
|
||||
return str.substr (1, str.length() - (isQuoteCharacter (str[str.length() - 1]) ? 1 : 0));
|
||||
}
|
||||
|
||||
static void ltrim (std::string& s)
|
||||
{
|
||||
s.erase (s.begin(), std::find_if (s.begin(), s.end(), [] (int c) { return ! std::isspace (c); }));
|
||||
}
|
||||
|
||||
static void rtrim (std::string& s)
|
||||
{
|
||||
s.erase (std::find_if (s.rbegin(), s.rend(), [] (int c) { return ! std::isspace (c); }).base(), s.end());
|
||||
}
|
||||
|
||||
static std::string trimmed (const std::string& str)
|
||||
{
|
||||
auto result = str;
|
||||
ltrim (result);
|
||||
rtrim (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string replaced (const std::string& str, char charToReplace, char replaceWith)
|
||||
{
|
||||
auto result = str;
|
||||
std::replace (result.begin(), result.end(), charToReplace, replaceWith);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static bool addFile (const std::string& filePath,
|
||||
const std::string& binaryNamespace,
|
||||
std::ofstream& headerStream,
|
||||
std::ofstream& cppStream,
|
||||
bool verbose)
|
||||
{
|
||||
std::ifstream fileStream (filePath, std::ios::in | std::ios::binary | std::ios::ate);
|
||||
|
||||
if (! fileStream.is_open())
|
||||
{
|
||||
std::cerr << "Failed to open input file " << filePath << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<char> buffer ((size_t) fileStream.tellg());
|
||||
fileStream.seekg (0);
|
||||
fileStream.read (buffer.data(), static_cast<std::streamsize> (buffer.size()));
|
||||
|
||||
const auto variableName = StringHelpers::replaced (StringHelpers::replaced (FileHelpers::getFilename (filePath),
|
||||
' ',
|
||||
'_'),
|
||||
'.',
|
||||
'_');
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
std::cout << "Adding " << variableName << ": "
|
||||
<< buffer.size() << " bytes" << std::endl;
|
||||
}
|
||||
|
||||
headerStream << " extern const char* " << variableName << ";" << std::endl
|
||||
<< " const int " << variableName << "Size = "
|
||||
<< buffer.size() << ";" << std::endl;
|
||||
|
||||
cppStream << "static const unsigned char temp0[] = {";
|
||||
|
||||
auto* data = (const uint8_t*) buffer.data();
|
||||
|
||||
for (size_t i = 0; i < buffer.size() - 1; ++i)
|
||||
{
|
||||
cppStream << (int) data[i] << ",";
|
||||
|
||||
if ((i % 40) == 39)
|
||||
cppStream << std::endl << " ";
|
||||
}
|
||||
|
||||
cppStream << (int) data[buffer.size() - 1] << ",0,0};" << std::endl;
|
||||
cppStream << "const char* " << binaryNamespace << "::" << variableName
|
||||
<< " = (const char*) temp0" << ";" << std::endl << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class Arguments
|
||||
{
|
||||
public:
|
||||
enum class PositionalArguments
|
||||
{
|
||||
sourceFile = 0,
|
||||
targetDirectory,
|
||||
targetFilename,
|
||||
binaryNamespace
|
||||
};
|
||||
|
||||
static std::optional<Arguments> create (int argc, char* argv[])
|
||||
{
|
||||
std::vector<std::string> arguments;
|
||||
bool verbose = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string arg { argv[i] };
|
||||
|
||||
if (arg == "-v" || arg == "--verbose")
|
||||
verbose = true;
|
||||
else
|
||||
arguments.emplace_back (std::move (arg));
|
||||
}
|
||||
|
||||
if (arguments.size() != static_cast<size_t> (PositionalArguments::binaryNamespace) + 1)
|
||||
return std::nullopt;
|
||||
|
||||
return Arguments { std::move (arguments), verbose };
|
||||
}
|
||||
|
||||
std::string get (PositionalArguments argument) const
|
||||
{
|
||||
return arguments[static_cast<size_t> (argument)];
|
||||
}
|
||||
|
||||
bool isVerbose() const
|
||||
{
|
||||
return verbose;
|
||||
}
|
||||
|
||||
private:
|
||||
Arguments (std::vector<std::string> args, bool verboseIn)
|
||||
: arguments (std::move (args)), verbose (verboseIn)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<std::string> arguments;
|
||||
bool verbose = false;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
const auto arguments = Arguments::create (argc, argv);
|
||||
|
||||
if (! arguments.has_value())
|
||||
{
|
||||
std::cout << " Usage: SimpleBinaryBuilder [-v | --verbose] sourcefile targetdirectory targetfilename namespace"
|
||||
<< std::endl << std::endl
|
||||
<< " SimpleBinaryBuilder will encode the provided source file into" << std::endl
|
||||
<< " two files called (targetfilename).cpp and (targetfilename).h," << std::endl
|
||||
<< " which it will write into the specified target directory." << std::endl
|
||||
<< " The target directory will be automatically created if necessary. The binary" << std::endl
|
||||
<< " resource will be available in the given namespace." << std::endl << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto currentWorkingDirectory = FileHelpers::getCurrentWorkingDirectory();
|
||||
|
||||
using ArgType = Arguments::PositionalArguments;
|
||||
|
||||
const auto sourceFile = FileHelpers::appendedPaths (currentWorkingDirectory,
|
||||
StringHelpers::unquoted (arguments->get (ArgType::sourceFile)));
|
||||
|
||||
if (! FileHelpers::exists (sourceFile))
|
||||
{
|
||||
std::cerr << "Source file doesn't exist: "
|
||||
<< sourceFile
|
||||
<< std::endl << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto targetDirectory = FileHelpers::appendedPaths (currentWorkingDirectory,
|
||||
StringHelpers::unquoted (arguments->get (ArgType::targetDirectory)));
|
||||
|
||||
if (! FileHelpers::exists (targetDirectory))
|
||||
{
|
||||
if (! FileHelpers::createDirectory (targetDirectory))
|
||||
{
|
||||
std::cerr << "Failed to create target directory: " << targetDirectory << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const auto className = StringHelpers::trimmed (arguments->get (ArgType::targetFilename));
|
||||
const auto binaryNamespace = StringHelpers::trimmed (arguments->get (ArgType::binaryNamespace));
|
||||
|
||||
const auto headerFilePath = FileHelpers::appendedPaths (targetDirectory, className + ".h");
|
||||
const auto cppFilePath = FileHelpers::appendedPaths (targetDirectory, className + ".cpp");
|
||||
|
||||
if (arguments->isVerbose())
|
||||
{
|
||||
std::cout << "Creating " << headerFilePath
|
||||
<< " and " << cppFilePath
|
||||
<< " from file " << sourceFile
|
||||
<< "..." << std::endl << std::endl;
|
||||
}
|
||||
|
||||
if (! FileHelpers::deleteFile (headerFilePath))
|
||||
{
|
||||
std::cerr << "Failed to remove old header file: " << headerFilePath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! FileHelpers::deleteFile (cppFilePath))
|
||||
{
|
||||
std::cerr << "Failed to remove old source file: " << cppFilePath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ofstream header (headerFilePath);
|
||||
|
||||
if (! header.is_open())
|
||||
{
|
||||
std::cerr << "Failed to open " << headerFilePath << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ofstream cpp (cppFilePath);
|
||||
|
||||
if (! cpp.is_open())
|
||||
{
|
||||
std::cerr << "Failed to open " << headerFilePath << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
header << "/* (Auto-generated binary data file). */" << std::endl << std::endl
|
||||
<< "#pragma once" << std::endl << std::endl
|
||||
<< "namespace " << binaryNamespace << std::endl
|
||||
<< "{" << std::endl;
|
||||
|
||||
cpp << "/* (Auto-generated binary data file). */" << std::endl << std::endl
|
||||
<< "#include " << std::quoted (className + ".h") << std::endl << std::endl;
|
||||
|
||||
if (! addFile (sourceFile, binaryNamespace, header, cpp, arguments->isVerbose()))
|
||||
return 1;
|
||||
|
||||
header << "}" << std::endl << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -157,11 +157,15 @@ public:
|
|||
addVersion (xml);
|
||||
createProject (*xml.createNewChildElement ("Project"));
|
||||
writeXmlOrThrow (xml, cbpFile, "UTF-8", 10, true);
|
||||
|
||||
linuxSubprocessHelperProperties.deployLinuxSubprocessHelperSourceFilesIfNecessary();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override
|
||||
{
|
||||
linuxSubprocessHelperProperties.addToExtraSearchPathsIfNecessary();
|
||||
|
||||
// add shared code target first as order matters for Codeblocks
|
||||
if (shouldBuildTargetType (build_tools::ProjectType::Target::SharedCodeTarget))
|
||||
targets.add (new CodeBlocksTarget (*this, build_tools::ProjectType::Target::SharedCodeTarget));
|
||||
|
|
@ -246,6 +250,18 @@ private:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
enum class IsDynamicLibrary
|
||||
{
|
||||
no,
|
||||
yes
|
||||
};
|
||||
|
||||
enum class ShouldBeCompiled
|
||||
{
|
||||
no,
|
||||
yes
|
||||
};
|
||||
|
||||
class CodeBlocksTarget : public build_tools::ProjectType::Target
|
||||
{
|
||||
public:
|
||||
|
|
@ -299,14 +315,130 @@ private:
|
|||
return {};
|
||||
}
|
||||
|
||||
bool isDynamicLibrary() const
|
||||
IsDynamicLibrary isDynamicLibrary() const
|
||||
{
|
||||
return (type == DynamicLibrary || type == VSTPlugIn);
|
||||
return (type == DynamicLibrary || type == VSTPlugIn) ? IsDynamicLibrary::yes
|
||||
: IsDynamicLibrary::no;
|
||||
}
|
||||
|
||||
const CodeBlocksProjectExporter& exporter;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class LinuxSubprocessHelperTarget
|
||||
{
|
||||
public:
|
||||
enum class HelperType
|
||||
{
|
||||
linuxSubprocessHelper,
|
||||
simpleBinaryBuilder
|
||||
};
|
||||
|
||||
LinuxSubprocessHelperTarget (const CodeBlocksProjectExporter& exporter, HelperType helperTypeIn)
|
||||
: owner (exporter),
|
||||
helperType (helperTypeIn)
|
||||
{
|
||||
}
|
||||
|
||||
String getTargetNameForConfiguration (const BuildConfiguration& config) const
|
||||
{
|
||||
return getName (helperType) + " | " + config.getName();
|
||||
}
|
||||
|
||||
void addTarget (XmlElement& xml, const BuildConfiguration& config) const
|
||||
{
|
||||
xml.setAttribute ("title", getTargetNameForConfiguration (config));
|
||||
auto* output = xml.createNewChildElement ("Option");
|
||||
output->setAttribute ("output", getOutput (helperType, config));
|
||||
xml.createNewChildElement ("Option")->setAttribute ("object_output",
|
||||
"obj/" + File::createLegalFileName (config.getName().trim()));
|
||||
xml.createNewChildElement ("Option")->setAttribute ("type", getTypeIndex (type));
|
||||
xml.createNewChildElement ("Option")->setAttribute ("compiler", "gcc");
|
||||
|
||||
const auto isDynamicLibrary = IsDynamicLibrary::no;
|
||||
|
||||
{
|
||||
auto* compiler = xml.createNewChildElement ("Compiler");
|
||||
|
||||
for (auto flag : owner.getCompilerFlags (config, isDynamicLibrary))
|
||||
owner.setAddOption (*compiler, "option", flag);
|
||||
}
|
||||
|
||||
{
|
||||
auto* linker = xml.createNewChildElement ("Linker");
|
||||
|
||||
for (auto& flag : owner.getLinkerFlags (config, isDynamicLibrary))
|
||||
owner.setAddOption (*linker, "option", flag);
|
||||
}
|
||||
|
||||
if (helperType == HelperType::simpleBinaryBuilder)
|
||||
{
|
||||
auto* postBuildCommands = xml.createNewChildElement ("ExtraCommands");
|
||||
|
||||
const auto binaryDataSource = owner.linuxSubprocessHelperProperties
|
||||
.getLinuxSubprocessHelperBinaryDataSource();
|
||||
|
||||
owner.setAddOption (*postBuildCommands,
|
||||
"after",
|
||||
getOutput (HelperType::simpleBinaryBuilder, config)
|
||||
+ " " + getOutput (HelperType::linuxSubprocessHelper, config)
|
||||
+ " pre_build"
|
||||
+ " " + binaryDataSource.getFileNameWithoutExtension().quoted()
|
||||
+ " LinuxSubprocessHelperBinaryData");
|
||||
}
|
||||
}
|
||||
|
||||
void addCompileUnits (XmlElement& xml) const
|
||||
{
|
||||
const auto file = getSource (helperType);
|
||||
auto* unit = xml.createNewChildElement ("Unit");
|
||||
unit->setAttribute ("filename", file.toUnixStyle());
|
||||
|
||||
for (ConstConfigIterator config (owner); config.next();)
|
||||
{
|
||||
auto targetName = getTargetNameForConfiguration (*config);
|
||||
unit->createNewChildElement ("Option")->setAttribute ("target", targetName);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
build_tools::RelativePath getSource (HelperType helperTypeForSource) const
|
||||
{
|
||||
if (helperTypeForSource == HelperType::linuxSubprocessHelper)
|
||||
return owner.linuxSubprocessHelperProperties.getLinuxSubprocessHelperSource();
|
||||
|
||||
return owner.linuxSubprocessHelperProperties.getSimpleBinaryBuilderSource();
|
||||
}
|
||||
|
||||
String getName (HelperType helperTypeForName) const
|
||||
{
|
||||
return LinuxSubprocessHelperProperties::getBinaryNameFromSource (getSource (helperTypeForName));
|
||||
}
|
||||
|
||||
String getOutput (HelperType helperTypeForOutput, const BuildConfiguration& config) const
|
||||
{
|
||||
return owner.getOutputPathForConfig (config) + "/" + getName (helperTypeForOutput);
|
||||
}
|
||||
|
||||
const CodeBlocksProjectExporter& owner;
|
||||
HelperType helperType;
|
||||
build_tools::ProjectType::Target::Type type = build_tools::ProjectType::Target::ConsoleApp;
|
||||
};
|
||||
|
||||
void addSubprocessHelperBinarySourceCompileUnit (XmlElement& xml) const
|
||||
{
|
||||
auto* unit = xml.createNewChildElement ("Unit");
|
||||
const auto binaryDataSource = linuxSubprocessHelperProperties.getLinuxSubprocessHelperBinaryDataSource();
|
||||
unit->setAttribute ("filename", binaryDataSource.toUnixStyle());
|
||||
|
||||
for (ConstConfigIterator config (*this); config.next();)
|
||||
{
|
||||
const auto& target = getTargetForFile (resolveRelativePath (binaryDataSource), ShouldBeCompiled::yes);
|
||||
const auto targetName = target.getTargetNameForConfiguration (*config);
|
||||
unit->createNewChildElement ("Option")->setAttribute ("target", targetName);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void addVersion (XmlElement& xml) const
|
||||
{
|
||||
|
|
@ -372,7 +504,7 @@ private:
|
|||
return getCleanedStringArray (defs);
|
||||
}
|
||||
|
||||
StringArray getCompilerFlags (const BuildConfiguration& config, CodeBlocksTarget& target) const
|
||||
StringArray getCompilerFlags (const BuildConfiguration& config, IsDynamicLibrary isDynamicLibrary) const
|
||||
{
|
||||
StringArray flags;
|
||||
|
||||
|
|
@ -409,7 +541,7 @@ private:
|
|||
|
||||
if (config.exporter.isLinux())
|
||||
{
|
||||
if (target.isDynamicLibrary() || getProject().isAudioPluginProject())
|
||||
if (isDynamicLibrary == IsDynamicLibrary::yes || getProject().isAudioPluginProject())
|
||||
flags.add ("-fPIC");
|
||||
|
||||
auto packages = config.exporter.getLinuxPackages (PackageDependencyType::compile);
|
||||
|
|
@ -432,7 +564,7 @@ private:
|
|||
return getCleanedStringArray (flags);
|
||||
}
|
||||
|
||||
StringArray getLinkerFlags (const BuildConfiguration& config, CodeBlocksTarget& target) const
|
||||
StringArray getLinkerFlags (const BuildConfiguration& config, IsDynamicLibrary isDynamicLibrary) const
|
||||
{
|
||||
auto flags = makefileExtraLinkerFlags;
|
||||
|
||||
|
|
@ -449,7 +581,7 @@ private:
|
|||
|
||||
if (config.exporter.isLinux())
|
||||
{
|
||||
if (target.isDynamicLibrary())
|
||||
if (isDynamicLibrary == IsDynamicLibrary::yes)
|
||||
flags.add ("-shared");
|
||||
|
||||
auto packages = config.exporter.getLinuxPackages (PackageDependencyType::link);
|
||||
|
|
@ -509,21 +641,23 @@ private:
|
|||
return 0;
|
||||
}
|
||||
|
||||
String getOutputPathForTarget (CodeBlocksTarget& target, const BuildConfiguration& config) const
|
||||
String getOutputPathForConfig (const BuildConfiguration& config) const
|
||||
{
|
||||
String outputPath;
|
||||
if (config.getTargetBinaryRelativePathString().isNotEmpty())
|
||||
{
|
||||
build_tools::RelativePath binaryPath (config.getTargetBinaryRelativePathString(), build_tools::RelativePath::projectFolder);
|
||||
binaryPath = binaryPath.rebased (projectFolder, getTargetFolder(), build_tools::RelativePath::buildTargetFolder);
|
||||
outputPath = config.getTargetBinaryRelativePathString();
|
||||
}
|
||||
else
|
||||
{
|
||||
outputPath ="bin/" + File::createLegalFileName (config.getName().trim());
|
||||
return config.getTargetBinaryRelativePathString();
|
||||
}
|
||||
|
||||
return outputPath + "/" + replacePreprocessorTokens (config, config.getTargetBinaryNameString() + target.getTargetSuffix());
|
||||
return "bin/" + File::createLegalFileName (config.getName().trim());
|
||||
}
|
||||
|
||||
String getOutputPathForTarget (CodeBlocksTarget& target, const BuildConfiguration& config) const
|
||||
{
|
||||
return getOutputPathForConfig (config)
|
||||
+ "/"
|
||||
+ replacePreprocessorTokens (config, config.getTargetBinaryNameString() + target.getTargetSuffix());
|
||||
}
|
||||
|
||||
String getSharedCodePath (const BuildConfiguration& config) const
|
||||
|
|
@ -584,7 +718,7 @@ private:
|
|||
flags.add ("-D" + def);
|
||||
}
|
||||
|
||||
flags.addArray (getCompilerFlags (config, target));
|
||||
flags.addArray (getCompilerFlags (config, target.isDynamicLibrary()));
|
||||
|
||||
for (auto flag : flags)
|
||||
setAddOption (*compiler, "option", flag);
|
||||
|
|
@ -604,7 +738,7 @@ private:
|
|||
if (getProject().isAudioPluginProject() && target.type != build_tools::ProjectType::Target::SharedCodeTarget)
|
||||
setAddOption (*linker, "option", getSharedCodePath (config).quoted());
|
||||
|
||||
for (auto& flag : getLinkerFlags (config, target))
|
||||
for (auto& flag : getLinkerFlags (config, target.isDynamicLibrary()))
|
||||
setAddOption (*linker, "option", flag);
|
||||
|
||||
const StringArray& libs = isWindows() ? mingwLibs : linuxLibs;
|
||||
|
|
@ -623,9 +757,15 @@ private:
|
|||
auto* build = xml.createNewChildElement ("Build");
|
||||
|
||||
for (ConstConfigIterator config (*this); config.next();)
|
||||
{
|
||||
if (linuxSubprocessHelperProperties.shouldUseLinuxSubprocessHelper())
|
||||
for (const auto& helperTarget : helperTargets)
|
||||
helperTarget.addTarget (*build->createNewChildElement ("Target"), *config);
|
||||
|
||||
for (auto target : targets)
|
||||
if (target->type != build_tools::ProjectType::Target::AggregateTarget)
|
||||
createBuildTarget (*build->createNewChildElement ("Target"), *target, *config);
|
||||
}
|
||||
}
|
||||
|
||||
void addVirtualTargets (XmlElement& xml) const
|
||||
|
|
@ -636,6 +776,10 @@ private:
|
|||
{
|
||||
StringArray allTargets;
|
||||
|
||||
if (linuxSubprocessHelperProperties.shouldUseLinuxSubprocessHelper())
|
||||
for (const auto& target : helperTargets)
|
||||
allTargets.add (target.getTargetNameForConfiguration (*config));
|
||||
|
||||
for (auto target : targets)
|
||||
if (target->type != build_tools::ProjectType::Target::AggregateTarget)
|
||||
allTargets.add (target->getTargetNameForConfiguration (*config));
|
||||
|
|
@ -726,19 +870,26 @@ private:
|
|||
return *targets[0];
|
||||
}
|
||||
|
||||
CodeBlocksTarget& getTargetForProjectItem (const Project::Item& projectItem) const
|
||||
CodeBlocksTarget& getTargetForFile (const File& file, ShouldBeCompiled shouldBeCompiled) const
|
||||
{
|
||||
if (getProject().isAudioPluginProject())
|
||||
{
|
||||
if (! projectItem.shouldBeCompiled())
|
||||
if (shouldBeCompiled == ShouldBeCompiled::no)
|
||||
return getTargetWithType (build_tools::ProjectType::Target::SharedCodeTarget);
|
||||
|
||||
return getTargetWithType (getProject().getTargetTypeFromFilePath (projectItem.getFile(), true));
|
||||
return getTargetWithType (getProject().getTargetTypeFromFilePath (file, true));
|
||||
}
|
||||
|
||||
return getMainTarget();
|
||||
}
|
||||
|
||||
CodeBlocksTarget& getTargetForProjectItem (const Project::Item& projectItem) const
|
||||
{
|
||||
return getTargetForFile (projectItem.getFile(),
|
||||
projectItem.shouldBeCompiled() ? ShouldBeCompiled::yes
|
||||
: ShouldBeCompiled::no);
|
||||
}
|
||||
|
||||
void addCompileUnits (const Project::Item& projectItem, XmlElement& xml) const
|
||||
{
|
||||
if (projectItem.isGroup())
|
||||
|
|
@ -787,6 +938,12 @@ private:
|
|||
|
||||
void addCompileUnits (XmlElement& xml) const
|
||||
{
|
||||
if (linuxSubprocessHelperProperties.shouldUseLinuxSubprocessHelper())
|
||||
for (const auto& helperTarget : helperTargets)
|
||||
helperTarget.addCompileUnits (xml);
|
||||
|
||||
addSubprocessHelperBinarySourceCompileUnit (xml);
|
||||
|
||||
for (int i = 0; i < getAllGroups().size(); ++i)
|
||||
addCompileUnits (getAllGroups().getReference(i), xml);
|
||||
|
||||
|
|
@ -825,5 +982,9 @@ private:
|
|||
|
||||
OwnedArray<CodeBlocksTarget> targets;
|
||||
|
||||
// The order of these targets is significant, as latter targets depend on earlier ones
|
||||
const LinuxSubprocessHelperTarget helperTargets[2] { { *this, LinuxSubprocessHelperTarget::HelperType::linuxSubprocessHelper },
|
||||
{ *this, LinuxSubprocessHelperTarget::HelperType::simpleBinaryBuilder } };
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (CodeBlocksProjectExporter)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -295,7 +295,26 @@ public:
|
|||
|
||||
for (auto& [path, flags] : filesToCompile)
|
||||
{
|
||||
out << "$(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (path)) << ": " << escapeQuotesAndSpaces (path.toUnixStyle()) << newLine
|
||||
const auto additionalTargetDependencies = [&path = path, this]
|
||||
{
|
||||
if ( owner.linuxSubprocessHelperProperties.shouldUseLinuxSubprocessHelper()
|
||||
&& path.getFileName().contains ("include_juce_gui_extra.cpp"))
|
||||
{
|
||||
return owner.linuxSubprocessHelperProperties
|
||||
.getLinuxSubprocessHelperBinaryDataSource()
|
||||
.toUnixStyle();
|
||||
}
|
||||
|
||||
return String{};
|
||||
}();
|
||||
|
||||
const auto prependedWithSpaceIfNotEmpty = [] (auto s)
|
||||
{
|
||||
return s.isEmpty() ? s : " " + s;
|
||||
};
|
||||
|
||||
out << "$(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (path)) << ": " << escapeQuotesAndSpaces (path.toUnixStyle())
|
||||
<< prependedWithSpaceIfNotEmpty (additionalTargetDependencies) << newLine
|
||||
<< "\t-$(V_AT)mkdir -p $(@D)" << newLine
|
||||
<< "\t@echo \"Compiling " << path.getFileName() << "\"" << newLine
|
||||
<< (path.hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS) " : "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) ")
|
||||
|
|
@ -530,11 +549,15 @@ public:
|
|||
build_tools::overwriteFileIfDifferentOrThrow (helperDir.getChildFile ("arch_detection.cpp"),
|
||||
BinaryData::juce_runtime_arch_detection_cpp);
|
||||
}
|
||||
|
||||
linuxSubprocessHelperProperties.deployLinuxSubprocessHelperSourceFilesIfNecessary();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override
|
||||
{
|
||||
linuxSubprocessHelperProperties.addToExtraSearchPathsIfNecessary();
|
||||
|
||||
callForAllSupportedTargets ([this] (build_tools::ProjectType::Target::Type targetType)
|
||||
{
|
||||
targets.insert (targetType == build_tools::ProjectType::Target::AggregateTarget ? 0 : -1,
|
||||
|
|
@ -886,7 +909,21 @@ private:
|
|||
|
||||
out << newLine;
|
||||
|
||||
out << " CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)" << newLine
|
||||
const auto preBuildDirectory = [&]() -> String
|
||||
{
|
||||
if (linuxSubprocessHelperProperties.shouldUseLinuxSubprocessHelper())
|
||||
{
|
||||
using LSHP = LinuxSubprocessHelperProperties;
|
||||
const auto dataSource = linuxSubprocessHelperProperties.getLinuxSubprocessHelperBinaryDataSource();
|
||||
|
||||
if (auto preBuildDir = LSHP::getParentDirectoryRelativeToBuildTargetFolder (dataSource))
|
||||
return " " + *preBuildDir;
|
||||
}
|
||||
|
||||
return "";
|
||||
}();
|
||||
|
||||
out << " CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)" << preBuildDirectory << newLine
|
||||
<< "endif" << newLine
|
||||
<< newLine;
|
||||
}
|
||||
|
|
@ -964,6 +1001,94 @@ private:
|
|||
out << newLine;
|
||||
}
|
||||
|
||||
/* These targets are responsible for building the juce_linux_subprocess_helper, the
|
||||
juce_simple_binary_builder, and then using the binary builder to create embeddable .h and .cpp
|
||||
files from the linux subprocess helper.
|
||||
*/
|
||||
void writeSubprocessHelperTargets (OutputStream& out) const
|
||||
{
|
||||
using LSHP = LinuxSubprocessHelperProperties;
|
||||
|
||||
const auto ensureDirs = [] (auto& outStream, std::vector<String> dirs)
|
||||
{
|
||||
for (const auto& dir : dirs)
|
||||
outStream << "\t-$(V_AT)mkdir -p " << dir << newLine;
|
||||
};
|
||||
|
||||
const auto makeTarget = [&ensureDirs] (auto& outStream, String input, String output)
|
||||
{
|
||||
const auto isObjectTarget = output.endsWith (".o");
|
||||
const auto isSourceInput = input.endsWith (".cpp");
|
||||
|
||||
const auto targetOutput = isObjectTarget ? "$(JUCE_OBJDIR)/" + output : output;
|
||||
|
||||
outStream << (isObjectTarget ? "$(JUCE_OBJDIR)/" : "") << output << ": " << input << newLine;
|
||||
|
||||
const auto createBuildTargetRelative = [] (auto path)
|
||||
{
|
||||
return build_tools::RelativePath { path, build_tools::RelativePath::buildTargetFolder };
|
||||
};
|
||||
|
||||
if (isObjectTarget)
|
||||
ensureDirs (outStream, { "$(JUCE_OBJDIR)" });
|
||||
else if (auto outputParentFolder = LSHP::getParentDirectoryRelativeToBuildTargetFolder (createBuildTargetRelative (output)))
|
||||
ensureDirs (outStream, { *outputParentFolder });
|
||||
|
||||
outStream << (isObjectTarget ? "\t@echo \"Compiling " : "\t@echo \"Linking ")
|
||||
<< (isObjectTarget ? input : output) << "\"" << newLine
|
||||
<< "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) -o " << targetOutput.quoted()
|
||||
<< " " << (isSourceInput ? "-c \"$<\"" : input.quoted());
|
||||
|
||||
if (! isObjectTarget)
|
||||
outStream << " $(JUCE_LDFLAGS)";
|
||||
|
||||
outStream << " $(TARGET_ARCH)" << newLine << newLine;
|
||||
|
||||
return targetOutput;
|
||||
};
|
||||
|
||||
const auto subprocessHelperSource = linuxSubprocessHelperProperties.getLinuxSubprocessHelperSource();
|
||||
|
||||
const auto subprocessHelperObj = makeTarget (out,
|
||||
subprocessHelperSource.toUnixStyle(),
|
||||
getObjectFileFor (subprocessHelperSource));
|
||||
|
||||
const auto subprocessHelperPath = makeTarget (out,
|
||||
subprocessHelperObj,
|
||||
"$(JUCE_BINDIR)/" + LSHP::getBinaryNameFromSource (subprocessHelperSource));
|
||||
|
||||
const auto binaryBuilderSource = linuxSubprocessHelperProperties.getSimpleBinaryBuilderSource();
|
||||
|
||||
const auto binaryBuilderObj = makeTarget (out,
|
||||
binaryBuilderSource.toUnixStyle(),
|
||||
getObjectFileFor (binaryBuilderSource));
|
||||
|
||||
const auto binaryBuilderPath = makeTarget (out,
|
||||
binaryBuilderObj,
|
||||
"$(JUCE_BINDIR)/" + LSHP::getBinaryNameFromSource (binaryBuilderSource));
|
||||
|
||||
const auto binaryDataSource = linuxSubprocessHelperProperties.getLinuxSubprocessHelperBinaryDataSource();
|
||||
jassert (binaryDataSource.getRoot() == build_tools::RelativePath::buildTargetFolder);
|
||||
|
||||
out << binaryDataSource.toUnixStyle() << ": " << subprocessHelperPath
|
||||
<< " " << binaryBuilderPath
|
||||
<< newLine;
|
||||
|
||||
const auto binarySourceDir = [&]() -> String
|
||||
{
|
||||
if (const auto p = LSHP::getParentDirectoryRelativeToBuildTargetFolder (binaryDataSource))
|
||||
return *p;
|
||||
|
||||
return ".";
|
||||
}();
|
||||
|
||||
out << "\t$(V_AT)" << binaryBuilderPath.quoted() << " " << subprocessHelperPath.quoted()
|
||||
<< " " << binarySourceDir.quoted() << " " << binaryDataSource.getFileNameWithoutExtension().quoted()
|
||||
<< " LinuxSubprocessHelperBinaryData" << newLine;
|
||||
|
||||
out << newLine;
|
||||
}
|
||||
|
||||
void writeMakefile (OutputStream& out) const
|
||||
{
|
||||
out << "# Automatically generated makefile, created by the Projucer" << newLine
|
||||
|
|
@ -1039,6 +1164,14 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
if (( targetType == MakefileTarget::SharedCodeTarget
|
||||
|| targetType == MakefileTarget::StaticLibrary
|
||||
|| targetType == MakefileTarget::DynamicLibrary)
|
||||
&& linuxSubprocessHelperProperties.shouldUseLinuxSubprocessHelper())
|
||||
{
|
||||
targetFiles.emplace_back (linuxSubprocessHelperProperties.getLinuxSubprocessHelperBinaryDataSource(), "");
|
||||
}
|
||||
|
||||
if (targetType == MakefileTarget::LV2TurtleProgram)
|
||||
{
|
||||
targetFiles.emplace_back (getLV2TurtleDumpProgramSource().rebased (projectFolder,
|
||||
|
|
@ -1067,6 +1200,9 @@ private:
|
|||
<< "\t$(V_AT)printf \"int main() { return 0; }\" | $(CXX) -x c++ -o $(@D)/execinfo.x -lexecinfo - >/dev/null 2>&1 && printf -- \"-lexecinfo\" > \"$@\" || touch \"$@\"" << newLine
|
||||
<< newLine;
|
||||
|
||||
if (linuxSubprocessHelperProperties.shouldUseLinuxSubprocessHelper())
|
||||
writeSubprocessHelperTargets (out);
|
||||
|
||||
out << "clean:" << newLine
|
||||
<< "\t@echo Cleaning " << projectName << newLine
|
||||
<< "\t$(V_AT)$(CLEANCMD)" << newLine
|
||||
|
|
|
|||
|
|
@ -234,6 +234,32 @@ build_tools::RelativePath ProjectExporter::rebaseFromProjectFolderToBuildTarget
|
|||
return path.rebased (project.getProjectFolder(), getTargetFolder(), build_tools::RelativePath::buildTargetFolder);
|
||||
}
|
||||
|
||||
build_tools::RelativePath ProjectExporter::rebaseFromBuildTargetToProjectFolder (const build_tools::RelativePath& path) const
|
||||
{
|
||||
jassert (path.getRoot() == build_tools::RelativePath::buildTargetFolder);
|
||||
return path.rebased (getTargetFolder(), project.getProjectFolder(), build_tools::RelativePath::projectFolder);
|
||||
}
|
||||
|
||||
File ProjectExporter::resolveRelativePath (const build_tools::RelativePath& path) const
|
||||
{
|
||||
if (path.isAbsolute())
|
||||
return path.toUnixStyle();
|
||||
|
||||
switch (path.getRoot())
|
||||
{
|
||||
case build_tools::RelativePath::buildTargetFolder:
|
||||
return getTargetFolder().getChildFile (path.toUnixStyle());
|
||||
|
||||
case build_tools::RelativePath::projectFolder:
|
||||
return project.getProjectFolder().getChildFile (path.toUnixStyle());
|
||||
|
||||
case build_tools::RelativePath::unknown:
|
||||
jassertfalse;
|
||||
}
|
||||
|
||||
return path.toUnixStyle();
|
||||
}
|
||||
|
||||
bool ProjectExporter::shouldFileBeCompiledByDefault (const File& file) const
|
||||
{
|
||||
return file.hasFileExtension (cOrCppFileExtensions)
|
||||
|
|
@ -497,6 +523,8 @@ void ProjectExporter::addTargetSpecificPreprocessorDefs (StringPairArray& defs,
|
|||
{
|
||||
defs.set ("JucePlugin_Enable_ARA", "1");
|
||||
}
|
||||
|
||||
linuxSubprocessHelperProperties.setCompileDefinitionIfNecessary (defs);
|
||||
}
|
||||
|
||||
void ProjectExporter::addDefaultPreprocessorDefs (StringPairArray& defs) const
|
||||
|
|
@ -545,7 +573,7 @@ Project::Item& ProjectExporter::getModulesGroup()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool isWebBrowserComponentEnabled (Project& project)
|
||||
static bool isWebBrowserComponentEnabled (const Project& project)
|
||||
{
|
||||
static String guiExtrasModule ("juce_gui_extra");
|
||||
|
||||
|
|
@ -608,6 +636,7 @@ void ProjectExporter::addToModuleLibPaths (const build_tools::RelativePath& path
|
|||
|
||||
void ProjectExporter::addToExtraSearchPaths (const build_tools::RelativePath& pathFromProjectFolder, int index)
|
||||
{
|
||||
jassert (pathFromProjectFolder.getRoot() == build_tools::RelativePath::projectFolder);
|
||||
addProjectPathToBuildPathList (extraSearchPaths, pathFromProjectFolder, index);
|
||||
}
|
||||
|
||||
|
|
@ -1083,3 +1112,115 @@ String ProjectExporter::getExternalLibraryFlags (const BuildConfiguration& confi
|
|||
|
||||
return {};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
LinuxSubprocessHelperProperties::LinuxSubprocessHelperProperties (ProjectExporter& projectExporter)
|
||||
: owner (projectExporter)
|
||||
{}
|
||||
|
||||
bool LinuxSubprocessHelperProperties::shouldUseLinuxSubprocessHelper() const
|
||||
{
|
||||
const auto& project = owner.getProject();
|
||||
const auto& projectType = project.getProjectType();
|
||||
|
||||
return owner.isLinux()
|
||||
&& isWebBrowserComponentEnabled (project)
|
||||
&& ! (projectType.isCommandLineApp())
|
||||
&& ! (projectType.isGUIApplication());
|
||||
}
|
||||
|
||||
void LinuxSubprocessHelperProperties::deployLinuxSubprocessHelperSourceFilesIfNecessary() const
|
||||
{
|
||||
if (shouldUseLinuxSubprocessHelper())
|
||||
{
|
||||
const auto deployHelperSourceFile = [] (auto& sourcePath, auto& contents)
|
||||
{
|
||||
if (! sourcePath.isRoot() && ! sourcePath.getParentDirectory().exists())
|
||||
{
|
||||
sourcePath.getParentDirectory().createDirectory();
|
||||
}
|
||||
|
||||
build_tools::overwriteFileIfDifferentOrThrow (sourcePath, contents);
|
||||
};
|
||||
|
||||
const std::pair<File, const char*> sources[]
|
||||
{
|
||||
{ owner.resolveRelativePath (getSimpleBinaryBuilderSource()), BinaryData::juce_SimpleBinaryBuilder_cpp },
|
||||
{ owner.resolveRelativePath (getLinuxSubprocessHelperSource()), BinaryData::juce_LinuxSubprocessHelper_cpp }
|
||||
};
|
||||
|
||||
for (const auto& [path, source] : sources)
|
||||
{
|
||||
deployHelperSourceFile (path, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
build_tools::RelativePath LinuxSubprocessHelperProperties::getLinuxSubprocessHelperSource() const
|
||||
{
|
||||
return build_tools::RelativePath { "make_helpers", build_tools::RelativePath::buildTargetFolder }
|
||||
.getChildFile ("juce_LinuxSubprocessHelper.cpp");
|
||||
}
|
||||
|
||||
void LinuxSubprocessHelperProperties::setCompileDefinitionIfNecessary (StringPairArray& defs) const
|
||||
{
|
||||
if (shouldUseLinuxSubprocessHelper())
|
||||
defs.set (useLinuxSubprocessHelperCompileDefinition, "1");
|
||||
}
|
||||
|
||||
build_tools::RelativePath LinuxSubprocessHelperProperties::getSimpleBinaryBuilderSource() const
|
||||
{
|
||||
return build_tools::RelativePath { "make_helpers", build_tools::RelativePath::buildTargetFolder }
|
||||
.getChildFile ("juce_SimpleBinaryBuilder.cpp");
|
||||
}
|
||||
|
||||
build_tools::RelativePath LinuxSubprocessHelperProperties::getLinuxSubprocessHelperBinaryDataSource() const
|
||||
{
|
||||
return build_tools::RelativePath ("pre_build", juce::build_tools::RelativePath::buildTargetFolder)
|
||||
.getChildFile ("juce_LinuxSubprocessHelperBinaryData.cpp");
|
||||
}
|
||||
|
||||
void LinuxSubprocessHelperProperties::addToExtraSearchPathsIfNecessary() const
|
||||
{
|
||||
if (shouldUseLinuxSubprocessHelper())
|
||||
{
|
||||
const auto subprocessHelperBinaryDir = getLinuxSubprocessHelperBinaryDataSource().getParentDirectory();
|
||||
owner.addToExtraSearchPaths (owner.rebaseFromBuildTargetToProjectFolder (subprocessHelperBinaryDir));
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<String> LinuxSubprocessHelperProperties::getParentDirectoryRelativeToBuildTargetFolder (build_tools::RelativePath rp)
|
||||
{
|
||||
jassert (rp.getRoot() == juce::build_tools::RelativePath::buildTargetFolder);
|
||||
const auto parentDir = rp.getParentDirectory().toUnixStyle();
|
||||
return parentDir == rp.toUnixStyle() ? std::nullopt : std::make_optional (parentDir);
|
||||
}
|
||||
|
||||
String LinuxSubprocessHelperProperties::makeSnakeCase (const String& s)
|
||||
{
|
||||
String result;
|
||||
result.preallocateBytes (128);
|
||||
|
||||
bool previousCharacterUnderscore = false;
|
||||
|
||||
for (const auto c : s)
|
||||
{
|
||||
if ( CharacterFunctions::isUpperCase (c)
|
||||
&& result.length() != 0
|
||||
&& ! (previousCharacterUnderscore))
|
||||
{
|
||||
result << "_";
|
||||
}
|
||||
|
||||
result << CharacterFunctions::toLowerCase (c);
|
||||
|
||||
previousCharacterUnderscore = c == '_';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String LinuxSubprocessHelperProperties::getBinaryNameFromSource (const build_tools::RelativePath& rp)
|
||||
{
|
||||
return makeSnakeCase (rp.getFileNameWithoutExtension());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,37 @@
|
|||
|
||||
class ProjectSaver;
|
||||
|
||||
class LinuxSubprocessHelperProperties
|
||||
{
|
||||
public:
|
||||
explicit LinuxSubprocessHelperProperties (ProjectExporter& projectExporter);
|
||||
|
||||
bool shouldUseLinuxSubprocessHelper() const;
|
||||
|
||||
void deployLinuxSubprocessHelperSourceFilesIfNecessary() const;
|
||||
|
||||
build_tools::RelativePath getLinuxSubprocessHelperSource() const;
|
||||
|
||||
void setCompileDefinitionIfNecessary (StringPairArray& defs) const;
|
||||
|
||||
build_tools::RelativePath getSimpleBinaryBuilderSource() const;
|
||||
|
||||
build_tools::RelativePath getLinuxSubprocessHelperBinaryDataSource() const;
|
||||
|
||||
void addToExtraSearchPathsIfNecessary() const;
|
||||
|
||||
static std::optional<String> getParentDirectoryRelativeToBuildTargetFolder (build_tools::RelativePath rp);
|
||||
|
||||
static String makeSnakeCase (const String& s);
|
||||
|
||||
static String getBinaryNameFromSource (const build_tools::RelativePath& rp);
|
||||
|
||||
static constexpr const char* useLinuxSubprocessHelperCompileDefinition = "JUCE_USE_EXTERNAL_TEMPORARY_SUBPROCESS";
|
||||
|
||||
private:
|
||||
ProjectExporter& owner;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ProjectExporter : private Value::Listener
|
||||
{
|
||||
|
|
@ -164,6 +195,8 @@ public:
|
|||
void updateOldModulePaths();
|
||||
|
||||
build_tools::RelativePath rebaseFromProjectFolderToBuildTarget (const build_tools::RelativePath& path) const;
|
||||
build_tools::RelativePath rebaseFromBuildTargetToProjectFolder (const build_tools::RelativePath& path) const;
|
||||
File resolveRelativePath (const build_tools::RelativePath&) const;
|
||||
void addToExtraSearchPaths (const build_tools::RelativePath& pathFromProjectFolder, int index = -1);
|
||||
void addToModuleLibPaths (const build_tools::RelativePath& pathFromProjectFolder);
|
||||
|
||||
|
|
@ -219,6 +252,9 @@ public:
|
|||
StringArray extraSearchPaths;
|
||||
StringArray moduleLibSearchPaths;
|
||||
|
||||
//==============================================================================
|
||||
const LinuxSubprocessHelperProperties linuxSubprocessHelperProperties { *this };
|
||||
|
||||
//==============================================================================
|
||||
class BuildConfiguration : public ReferenceCountedObject
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue