This commit is contained in:
2025-05-15 13:40:41 -04:00
commit 2af286fe0e
107 changed files with 8879 additions and 0 deletions

View File

@ -0,0 +1,82 @@
/*
==============================================================================
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.
==============================================================================
*/
#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
#if defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
#error JUCE_ARCH aarch64
#elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 8) || defined(__ARMv8__) || defined(__ARMv8_A__)
#error JUCE_ARCH armv8l
#elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 7) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7) || defined(__CORE_CORTEXA__)
#error JUCE_ARCH armv7l
#elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 6) || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6M__)
#error JUCE_ARCH armv6l
#elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 5) || defined(__ARM_ARCH_5TEJ__)
#error JUCE_ARCH armv5l
#else
#error JUCE_ARCH arm
#endif
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
#error JUCE_ARCH i386
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
#error JUCE_ARCH x86_64
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
#error JUCE_ARCH ia64
#elif defined(__mips) || defined(__mips__) || defined(_M_MRX000)
#if defined(_MIPS_ARCH_MIPS64) || defined(__mips64)
#error JUCE_ARCH mips64
#else
#error JUCE_ARCH mips
#endif
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_M_MPPC) || defined(_M_PPC)
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
#error JUCE_ARCH ppc64
#else
#error JUCE_ARCH ppc
#endif
#elif defined(__riscv)
#if __riscv_xlen == 64
#error JUCE_ARCH riscv64
#else
#error JUCE_ARCH riscv
#endif
#else
#error JUCE_ARCH unknown
#endif

View File

@ -0,0 +1,36 @@
/*
==============================================================================
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 <dlfcn.h>
int main (int argc, const char* const* argv)
{
if (argc >= 3)
if (auto* handle = dlopen (argv[1], RTLD_LAZY))
if (auto* function = reinterpret_cast<int (*) (int, const char* const*)> (dlsym (handle, argv[2])))
return function (argc - 3, argv + 3);
return 1;
}

View File

@ -0,0 +1,381 @@
/*
==============================================================================
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)
{
#if defined (__FreeBSD__) || defined (__OpenBSD__)
#define JUCE_STAT stat
#else
#define JUCE_STAT stat64
#endif
struct JUCE_STAT info;
return ! path.empty()
&& JUCE_STAT (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;
}