From 9d85206e953eb1fbf20a88c253bca22b6b14eeee Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Fri, 26 Jun 2026 03:13:19 +0200 Subject: [PATCH 01/15] Append the architecture name to loader binaries, implement box64 fallback, detect armhf multiarch support --- CMakeLists.txt | 71 +-- src/engine/framework/VirtualMachine.cpp | 491 +++++++++++++----- .../nacl_multiarch.cpp} | 20 +- 3 files changed, 408 insertions(+), 174 deletions(-) rename tools/{nacl_helper_bootstrap-armhf/nacl_helper_bootstrap-armhf.cpp => nacl_multiarch/nacl_multiarch.cpp} (84%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65ff1a430b..91a484f9d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,33 +397,33 @@ if (DEPS_DIR) if (NOT EXISTS ${DEPS_DIR}) file(MAKE_DIRECTORY ${EXTERNAL_DEPS_DIR}) get_filename_component(BASENAME ${DEPS_DIR} NAME) - set(DEPS_FILENAME "${BASENAME}${DEPS_EXT}") - - # Download test DEPS archive if DEPS archive isn't available yet. - # This makes possible to get the CI working before releasing the DEPS archive. - foreach(REMOTE_BASEURL https://dl.unvanquished.net/deps;https://dl.unvanquished.net/test/deps) - set(REMOTE "${REMOTE_BASEURL}/${DEPS_FILENAME}") - message(STATUS "Downloading dependencies from '${REMOTE}'") - - file(DOWNLOAD "${REMOTE}" "${OBJ_DIR}/${DEPS_FILENAME}" - SHOW_PROGRESS - STATUS DOWNLOAD_RESULT - LOG DOWNLOAD_LOG - ) - - list(GET DOWNLOAD_RESULT 0 DOWNLOAD_STATUS) - list(GET DOWNLOAD_RESULT 1 DOWNLOAD_STRING) - - if (DOWNLOAD_STATUS EQUAL 0) - break() - else () - message(WARNING "Error downloading '${REMOTE}': - Status code: ${DOWNLOAD_STATUS} - Error string: ${DOWNLOAD_STRING} - Download log: ${DOWNLOAD_LOG}" - ) - endif() - endforeach() + set(DEPS_FILENAME "${BASENAME}${DEPS_EXT}") + + # Download test DEPS archive if DEPS archive isn't available yet. + # This makes possible to get the CI working before releasing the DEPS archive. + foreach(REMOTE_BASEURL https://dl.unvanquished.net/deps;https://dl.unvanquished.net/test/deps) + set(REMOTE "${REMOTE_BASEURL}/${DEPS_FILENAME}") + message(STATUS "Downloading dependencies from '${REMOTE}'") + + file(DOWNLOAD "${REMOTE}" "${OBJ_DIR}/${DEPS_FILENAME}" + SHOW_PROGRESS + STATUS DOWNLOAD_RESULT + LOG DOWNLOAD_LOG + ) + + list(GET DOWNLOAD_RESULT 0 DOWNLOAD_STATUS) + list(GET DOWNLOAD_RESULT 1 DOWNLOAD_STRING) + + if (DOWNLOAD_STATUS EQUAL 0) + break() + else () + message(WARNING "Error downloading '${REMOTE}': + Status code: ${DOWNLOAD_STATUS} + Error string: ${DOWNLOAD_STRING} + Download log: ${DOWNLOAD_LOG}" + ) + endif() + endforeach() if (NOT DOWNLOAD_STATUS EQUAL 0) message(FATAL_ERROR "Failed to download '${DEPS_FILENAME}'") @@ -973,7 +973,7 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER add_custom_command(TARGET runtime_deps PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DEPS_DIR}/nacl_loader${CMAKE_EXECUTABLE_SUFFIX} - ${FULL_OUTPUT_DIR}/nacl_loader${CMAKE_EXECUTABLE_SUFFIX} + ${FULL_OUTPUT_DIR}/nacl_loader-${DAEMON_NACL_ARCH_NAME}${CMAKE_EXECUTABLE_SUFFIX} ) add_custom_command(TARGET runtime_deps PRE_BUILD @@ -985,25 +985,28 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER # Linux uses a bootstrap program to reserve address space if (YOKAI_TARGET_SYSTEM_LINUX_COMPATIBILITY) if (YOKAI_TARGET_ARCH_ARM64) - add_executable(nacl_helper_bootstrap-armhf tools/nacl_helper_bootstrap-armhf/nacl_helper_bootstrap-armhf.cpp) - add_dependencies(runtime_deps nacl_helper_bootstrap-armhf) + add_executable(nacl_multiarch-${DAEMON_NACL_ARCH_NAME} + tools/nacl_multiarch/nacl_multiarch.cpp + ${BUILDINFOLIST} + ) + add_dependencies(runtime_deps nacl_multiarch-${DAEMON_NACL_ARCH_NAME}) add_custom_command(TARGET runtime_deps PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory - ${FULL_OUTPUT_DIR}/lib-armhf + ${FULL_OUTPUT_DIR}/lib-${DAEMON_NACL_ARCH_NAME} ) add_custom_command(TARGET runtime_deps PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory - ${DEPS_DIR}/lib-armhf - ${FULL_OUTPUT_DIR}/lib-armhf + ${DEPS_DIR}/linux-${DAEMON_NACL_ARCH_NAME} + ${FULL_OUTPUT_DIR}/linux-${DAEMON_NACL_ARCH_NAME} ) endif() add_custom_command(TARGET runtime_deps PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DEPS_DIR}/nacl_helper_bootstrap - ${FULL_OUTPUT_DIR}/nacl_helper_bootstrap + ${FULL_OUTPUT_DIR}/nacl_helper_bootstrap-${DAEMON_NACL_ARCH_NAME} ) endif() diff --git a/src/engine/framework/VirtualMachine.cpp b/src/engine/framework/VirtualMachine.cpp index df2739b9f3..dec5dc0bd5 100644 --- a/src/engine/framework/VirtualMachine.cpp +++ b/src/engine/framework/VirtualMachine.cpp @@ -75,12 +75,28 @@ static Cvar::Cvar workaround_naclSystem_freebsd_disableQualification( "Disable platform qualification when running Linux NaCl loader on FreeBSD through Linuxulator", Cvar::NONE, true); +#if defined(DAEMON_NACL_RUNTIME_ENABLED) +// Many BSDs have a Linuxulator, for now we only tested one. +#if defined(__linux__) || defined(__FreeBSD__) +#define DAEMON_NACL_RUNTIME_LINUX +#define DAEMON_NACL_BOOSTRAP_ENABLED +#endif // defined(__linux__) || defined(DAEMON_LINUXULATOR) +#endif // defined(DAEMON_NACL_RUNTIME_ENABLED) + +#if defined(DAEMON_NACL_RUNTIME_ENABLED) #if defined(DAEMON_NACL_BOX64_EMULATION) static Cvar::Cvar workaround_box64_disableQualification( "workaround.box64.disableQualification", "Disable platform qualification when running amd64 NaCl loader under Box64 emulation", Cvar::NONE, true); +#if defined(YOKAI_ARCH_ARM64) +static Cvar::Cvar workaround_box64_preferArmhf( + "workaround.box64.preferArmhf", + "Prefer armhf multiarch when available over Box64 emulation", + Cvar::NONE, true); +#endif // defined(YOKAI_ARCH_ARM64) + static Cvar::Cvar workaround_box64_disableBootstrap( "workaround.box64.disableBootstrap", "Disable NaCl bootstrap helper when using Box64 emulation", @@ -88,14 +104,41 @@ static Cvar::Cvar workaround_box64_disableBootstrap( static Cvar::Cvar vm_box64_path( "vm.box64.path", - "Path to the box64 binary for NaCl emulation (empty = search PATH)", + "Path to the box64 binary for NaCl emulation (empty = use provided one or search PATH if missing)", Cvar::NONE, ""); -// Resolve box64 binary path by searching PATH if not explicitly set. -static std::string ResolveBox64Path() { - std::string path = vm_box64_path.Get(); - if (!path.empty()) { - return path; +// Resolve box64 binary path by looking for a provided one or searching PATH if not explicitly set. +static std::string ResolveBox64Path(std::string naclPath) { + std::string requestedPath = vm_box64_path.Get(); + + if (requestedPath.empty()) { + std::string providedPath = FS::Path::Build(naclPath, "box64"); + + if (FS::RawPath::FileExists(providedPath)) { + const std::string libs_linux_amd64 = "libs-linux-amd64"; + const std::string libgcc_linux_amd64 = "libgcc_s.so.1"; + + std::string libsDirPath = FS::Path::Build(naclPath, libs_linux_amd64); + std::string libGccPath = FS::Path::Build(libsDirPath, libgcc_linux_amd64); + + if (FS::RawPath::FileExists(libGccPath)) { + Sys::SetEnv("BOX64_LD_LIBRARY_PATH", libsDirPath.c_str()); + } + else { + Log::Warn("Using provided Box64 executable but the libraries are missing."); + } + + return providedPath; + } + + Log::Warn("Box64 emulation is enabled but the executable is not provided with the engine: %s", providedPath); + } + + if (!FS::RawPath::FileExists(requestedPath)) { + Sys::Error("Box64 emulation is enabled but the requested executable is missing: %s", requestedPath); + } + else { + return requestedPath; } const char* envPath = getenv("PATH"); @@ -121,34 +164,39 @@ static std::string ResolveBox64Path() { "Install Box64 or set vm.box64.path to the full path of the box64 binary."); return ""; // unreachable } -#endif - -static Cvar::Cvar vm_nacl_qualification( - "vm.nacl.qualification", - "Enable NaCl loader platform qualification", - Cvar::INIT, true); - -static Cvar::Cvar vm_nacl_bootstrap( - "vm.nacl.bootstrap", - "Use NaCl bootstrap helper", - Cvar::INIT, true); - -static Cvar::Cvar vm_timeout( - "vm.timeout", - "Receive timeout in seconds", - Cvar::NONE, 2); +#endif // DAEMON_NACL_BOX64_EMULATION +#endif // DAEMON_NACL_RUNTIME_ENABLED #if defined(DAEMON_NACL_RUNTIME_ENABLED) static Cvar::Cvar vm_nacl_available( "vm.nacl.available", "Whether NaCl runtime is available on this platform", Cvar::ROM, true); -#else +#else // !defined(DAEMON_NACL_RUNTIME_ENABLED) static Cvar::Cvar vm_nacl_available( "vm.nacl.available", "Whether NaCl runtime is available on this platform", Cvar::ROM, false); -#endif +#endif // !defined(DAEMON_NACL_RUNTIME_ENABLED) + +#if defined(DAEMON_NACL_RUNTIME_ENABLED) +static Cvar::Cvar vm_timeout( + "vm.timeout", + "Receive timeout in seconds", + Cvar::NONE, 2); + +static Cvar::Cvar vm_nacl_qualification( + "vm.nacl.qualification", + "Enable NaCl loader platform qualification", + Cvar::INIT, true); +#endif // defined(DAEMON_NACL_RUNTIME_ENABLED) + +#if defined(DAEMON_NACL_BOOSTRAP_ENABLED) +static Cvar::Cvar vm_nacl_bootstrap( + "vm.nacl.bootstrap", + "Use NaCl bootstrap helper", + Cvar::INIT, true); +#endif // defined(DAEMON_NACL_BOOSTRAP_ENABLED) namespace VM { @@ -300,36 +348,228 @@ static std::pair InternalLoadModule(std::pair(probe.data()), + nullptr, + }; + + execve(probe.data(), argv, environ); + + switch (errno) + { + case ENOEXEC: + // The kernel cannot execute the probe. + _exit(100); + + case ENOENT: + case EACCES: + // Missing or inaccessible probe. + _exit(101); + + default: + _exit(102); + } + } + + int status; + if (waitpid(pid, &status, 0) < 0) { + return ExeSupport::Unknown; + } + + if (!WIFEXITED(status)) { + return ExeSupport::Unknown; + } + + switch (WEXITSTATUS(status)) + { + case 100: + return ExeSupport::Unsupported; + + case 101: + case 102: + return ExeSupport::Unknown; + + default: + // The probe has been executed properly. + return ExeSupport::Supported; + } +} +#endif // defined(DAEMON_NACL_RUNTIME_LINUX) && defined(NACL_ARCH_ARM64) + +#if defined(DAEMON_NACL_RUNTIME_ENABLED) static std::pair CreateNaClVM(std::pair pair, Str::StringRef name, bool debug, bool extract, int debugLoader) { CheckMinAddressSysctlTooLarge(); const std::string& libPath = FS::GetLibPath(); -#ifdef DAEMON_NACL_RUNTIME_PATH - const char* naclPath = DAEMON_NACL_RUNTIME_PATH_STRING; -#else - const std::string& naclPath = libPath; -#endif std::vector args; char rootSocketRedir[32]; - std::string module, nacl_loader, irt, bootstrap, modulePath, verbosity; FS::File stderrRedirect; -#if defined(DAEMON_NACL_BOX64_EMULATION) - std::string box64Path; - bool usingBox64 = false; -#endif + bool inheritEnvironment = false; + + std::string module, nacl_loader, irt, arch, modulePath, verbosity; + +#if defined(DAEMON_NACL_RUNTIME_PATH) + const char* naclPath = DAEMON_NACL_RUNTIME_PATH_STRING; +#else // !defined(DAEMON_NACL_RUNTIME_PATH) + const std::string& naclPath = libPath; +#endif // !defined(DAEMON_NACL_RUNTIME_PATH) + #if !defined(_WIN32) || defined(_WIN64) - constexpr bool win32Force64Bit = false; -#else + constexpr bool i686ForceAmd64 = false; +#else // !( !defined(_WIN32) || defined(_WIN64) ) // On Windows, even if we are running a 32-bit engine, we must use the // 64-bit nacl_loader if the host operating system is 64-bit. SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); - const bool win32Force64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; + constexpr bool i686ForceAmd64 = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; +#endif // !( !defined(_WIN32) || defined(_WIN64) ) + +#if defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) + std::string multiarchPath; + constexpr bool hasMultiarch = true; +#else + constexpr bool hasMultiarch = false; +#endif + +#if defined(DAEMON_NACL_BOOSTRAP_ENABLED) + std::string bootstrapPath; + constexpr bool hasBootstrap = true; +#else // !defined(DAEMON_NACL_BOOSTRAP_ENABLED) + constexpr bool hasBootstrap = false; +#endif // !defined(DAEMON_NACL_BOOSTRAP_ENABLED) + +#if defined(DAEMON_NACL_BOX64_EMULATION) + std::string box64Path; + constexpr bool hasBox64 = true; +#else // !defined(DAEMON_NACL_BOX64_EMULATION) + constexpr bool hasBox64 = false; +#endif // !defined(DAEMON_NACL_BOX64_EMULATION) + +#if defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) + /* We later turn this boolean off when we detect armhf support is not + provided on arm64. */ + bool hasArmhf = true; +#endif // !defined(YOKAI_ARCH_ARMHF) + + bool useBox64 = hasBox64; + +#if defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) + const std::string libs_linux_armhf = "linux-armhf"; + const std::string libld_linux_armhf = "ld-linux"; + + std::string libsDirPath = FS::Path::Build(libPath, libs_linux_armhf); + std::string libLoaderPath = FS::Path::Build(libsDirPath, libld_linux_armhf); + + switch (CheckExeSupport(libLoaderPath)) + { + case ExeSupport::Supported: + Log::Notice("Working armhf multiarch support."); + break; + + case ExeSupport::Unsupported: + Log::Notice("Unsupported armhf multiarch."); + hasArmhf = false; + break; + + case ExeSupport::Unknown: + Log::Warn("Could not determine armhf multiarch support."); + hasArmhf = false; + break; + } + +#if defined(DAEMON_NACL_BOX64_EMULATION) + if (hasArmhf) { + if (workaround_box64_preferArmhf.Get()) { + Log::Notice("Preferring armhf multiarch over Box64 emulation."); + useBox64 = false; + } + } +#endif // defined(DAEMON_NACL_BOX64_EMULATION) + + bool useMultiarch = hasMultiarch; + + if (hasMultiarch && useBox64) { + useMultiarch = false; + } +#endif // defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) + + bool useBootstrap = hasBootstrap; + +#if defined(DAEMON_NACL_BOOSTRAP_ENABLED) + + if (hasBootstrap) { + if (!vm_nacl_bootstrap.Get()) { + useBootstrap = false; + } + +#if defined(DAEMON_NACL_BOX64_EMULATION) + /* Use Box64 to run the x86_64 NaCl loader on non-x86 architectures. + The bootstrap helper uses a double-exec pattern that Box64 cannot handle, + so we skip it and prepend "box64" to the nacl_loader command instead. */ + if (useBootstrap + && useBox64 + && workaround_box64_disableBootstrap.Get()) { + useBootstrap = false; + } +#endif // defined(DAEMON_NACL_BOX64_EMULATION) + } +#endif // defined(DAEMON_NACL_BOOSTRAP_ENABLED) + + if (useBox64 || i686ForceAmd64) { + arch = "amd64"; + } + else { + arch = DAEMON_NACL_ARCH_STRING; + } + + module = Str::Format("%s-%s.nexe", name, arch); + irt = FS::Path::Build(naclPath, Str::Format("irt_core-%s.nexe", arch)); + nacl_loader = FS::Path::Build(naclPath, Str::Format("nacl_loader-%s%s", arch, EXE_EXT)); + +#if defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) + if (useMultiarch) { + multiarchPath = FS::Path::Build(naclPath, Str::Format("nacl_multiarch-%s", arch)); + } +#endif + +#if defined(DAEMON_NACL_BOOSTRAP_ENABLED) + if (useBootstrap) { + bootstrapPath = FS::Path::Build(naclPath, Str::Format("nacl_helper_bootstrap-%s", arch)); + } #endif // Extract the nexe from the pak so that nacl_loader can load it - module = win32Force64Bit - ? name + "-amd64.nexe" - : Str::Format("%s-%s.nexe", name, DAEMON_NACL_ARCH_STRING); if (extract) { try { FS::File out = FS::HomePath::OpenWrite(module); @@ -347,10 +587,6 @@ static std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair Error while loading "sgame-armhf.nexe": CPU model is not supported + > Error while loading "sgame-armhf.nexe": CPU model is not supported - From nacl_loader --help we can read: + From nacl_loader --help we can read: - > -Q disable platform qualification (dangerous!) + > -Q disable platform qualification (dangerous!) - When this option is enabled, nacl_loader will print: + When this option is enabled, nacl_loader will print: - > PLATFORM QUALIFICATION DISABLED BY -Q - Native Client's sandbox will be unreliable! + > PLATFORM QUALIFICATION DISABLED BY -Q - Native Client's sandbox will be unreliable! - But the nexe will load and run. */ + But the nexe will load and run. */ - if (onArm64) { - Log::Warn("Disabling NaCL platform qualification on arm64 kernel architecture."); - enableQualification = false; - } + if (onArm64) { + Log::Warn("Disabling NaCl platform qualification on arm64 kernel architecture."); + enableQualification = false; } -#endif + } +#endif // defined(__linux__) && (defined(YOKAI_ARCH_ARM64) || defined(YOKAI_ARCH_ARMHF)) + +#if defined(DAEMON_NACL_BOX64_EMULATION) + if (enableQualification + && useBox64 + && workaround_box64_disableQualification.Get()) { + /* When running the amd64 NaCl loader under Box64, the loader's + platform qualification will fail because the CPU is not actually x86_64. + Disabling qualification allows the emulated loader to proceed. */ + + Log::Warn("Disabling NaCl platform qualification for Box64 emulation."); + enableQualification = false; + } +#endif // defined(DAEMON_NACL_BOX64_EMULATION) #if defined(__FreeBSD__) + if (enableQualification + && workaround_naclSystem_freebsd_disableQualification.Get()) { /* While it is possible to build a native FreeBSD engine, the only available NaCl loader is the Linux one, which can run on Linuxulator (the FreeBSD Linux compatibility layer). @@ -466,26 +708,10 @@ static std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair CreateNativeVM(std::pair pair, Str::StringRef name, bool debug) { const std::string& libPath = FS::GetLibPath(); @@ -622,7 +845,9 @@ void VMBase::Create() } #endif if (type == TYPE_NACL || type == TYPE_NACL_LIBPATH) { +#if defined(DAEMON_NACL_RUNTIME_ENABLED) std::tie(processHandle, rootSocket) = CreateNaClVM(std::move(pair), name, params.debug.Get(), type == TYPE_NACL, params.debugLoader.Get()); +#endif // defined(DAEMON_NACL_RUNTIME_ENABLED) } else if (type == TYPE_NATIVE_EXE) { std::tie(processHandle, rootSocket) = CreateNativeVM(std::move(pair), name, params.debug.Get()); } else { diff --git a/tools/nacl_helper_bootstrap-armhf/nacl_helper_bootstrap-armhf.cpp b/tools/nacl_multiarch/nacl_multiarch.cpp similarity index 84% rename from tools/nacl_helper_bootstrap-armhf/nacl_helper_bootstrap-armhf.cpp rename to tools/nacl_multiarch/nacl_multiarch.cpp index ec16447482..ae7d8755d4 100644 --- a/tools/nacl_helper_bootstrap-armhf/nacl_helper_bootstrap-armhf.cpp +++ b/tools/nacl_multiarch/nacl_multiarch.cpp @@ -35,7 +35,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include "YokaiBuildInfo/DaemonEngine.h" + int main(int argc, char *argv[]) { + if (argc < 2) { + printf("nacl_multiarch-%s: missing command line\n", DAEMON_NACL_ARCH_STRING); + return 1; + } + char *directory = dirname(strdup(argv[0])); int err = chdir(directory); @@ -44,19 +51,18 @@ int main(int argc, char *argv[]) { return err; } - err = putenv(strdup("LD_LIBRARY_PATH=lib-armhf")); + char env[100]; + sprintf(env, "LD_LIBRARY_PATH=libs-linux-%s", DAEMON_NACL_ARCH_STRING); + + err = putenv(strdup(env)); if (err != 0) { return err; } - char *helper = strdup("./nacl_helper_bootstrap"); - argv[0] = helper; - - execv(helper, argv); + execv(argv[1], &argv[1]); // The execv() function returns only if an error has occurred. - printf("nacl_helper_bootstrap-armhf: %s\n", strerror(errno)); - + printf("nacl_multiarch-%s: %s\n", DAEMON_NACL_ARCH_STRING, strerror(errno)); return 1; } From 0d535d1ff0a7002a028cbaaf018476a1138bebcd Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Fri, 26 Jun 2026 04:12:38 +0200 Subject: [PATCH 02/15] cmake,VirtualMachine: add architecture suffix to the loader --- CMakeLists.txt | 9 +- src/engine/framework/VirtualMachine.cpp | 150 +++++++++++------------- 2 files changed, 68 insertions(+), 91 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91a484f9d1..7da7b66b71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -972,7 +972,7 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER # The NaCl loader and IRT are required to load .nexe files add_custom_command(TARGET runtime_deps PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${DEPS_DIR}/nacl_loader${CMAKE_EXECUTABLE_SUFFIX} + ${DEPS_DIR}/nacl_loader-${DAEMON_NACL_ARCH_NAME}${CMAKE_EXECUTABLE_SUFFIX} ${FULL_OUTPUT_DIR}/nacl_loader-${DAEMON_NACL_ARCH_NAME}${CMAKE_EXECUTABLE_SUFFIX} ) @@ -991,15 +991,10 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER ) add_dependencies(runtime_deps nacl_multiarch-${DAEMON_NACL_ARCH_NAME}) - add_custom_command(TARGET runtime_deps PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory - ${FULL_OUTPUT_DIR}/lib-${DAEMON_NACL_ARCH_NAME} - ) - add_custom_command(TARGET runtime_deps PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPS_DIR}/linux-${DAEMON_NACL_ARCH_NAME} - ${FULL_OUTPUT_DIR}/linux-${DAEMON_NACL_ARCH_NAME} + ${FULL_OUTPUT_DIR}/libs-linux-${DAEMON_NACL_ARCH_NAME} ) endif() diff --git a/src/engine/framework/VirtualMachine.cpp b/src/engine/framework/VirtualMachine.cpp index dec5dc0bd5..8ddab6486f 100644 --- a/src/engine/framework/VirtualMachine.cpp +++ b/src/engine/framework/VirtualMachine.cpp @@ -90,13 +90,6 @@ static Cvar::Cvar workaround_box64_disableQualification( "Disable platform qualification when running amd64 NaCl loader under Box64 emulation", Cvar::NONE, true); -#if defined(YOKAI_ARCH_ARM64) -static Cvar::Cvar workaround_box64_preferArmhf( - "workaround.box64.preferArmhf", - "Prefer armhf multiarch when available over Box64 emulation", - Cvar::NONE, true); -#endif // defined(YOKAI_ARCH_ARM64) - static Cvar::Cvar workaround_box64_disableBootstrap( "workaround.box64.disableBootstrap", "Disable NaCl bootstrap helper when using Box64 emulation", @@ -168,16 +161,15 @@ static std::string ResolveBox64Path(std::string naclPath) { #endif // DAEMON_NACL_RUNTIME_ENABLED #if defined(DAEMON_NACL_RUNTIME_ENABLED) -static Cvar::Cvar vm_nacl_available( - "vm.nacl.available", - "Whether NaCl runtime is available on this platform", - Cvar::ROM, true); +static constexpr bool vmAvailable = true; #else // !defined(DAEMON_NACL_RUNTIME_ENABLED) +static constexpr bool vmAvailable = false; +#endif // !defined(DAEMON_NACL_RUNTIME_ENABLED) + static Cvar::Cvar vm_nacl_available( "vm.nacl.available", "Whether NaCl runtime is available on this platform", - Cvar::ROM, false); -#endif // !defined(DAEMON_NACL_RUNTIME_ENABLED) + Cvar::ROM, vmAvailable); #if defined(DAEMON_NACL_RUNTIME_ENABLED) static Cvar::Cvar vm_timeout( @@ -191,6 +183,15 @@ static Cvar::Cvar vm_nacl_qualification( Cvar::INIT, true); #endif // defined(DAEMON_NACL_RUNTIME_ENABLED) +#if defined(DAEMON_NACL_RUNTIME_ENABLED) +#if defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) +static Cvar::Cvar vm_nacl_multiarch( + "vm.nacl.multiarch", + "Use multiarch to run the NaCl loader when needed and available", + Cvar::INIT, true); +#endif // defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) +#endif // defined(DAEMON_NACL_RUNTIME_ENABLED) + #if defined(DAEMON_NACL_BOOSTRAP_ENABLED) static Cvar::Cvar vm_nacl_bootstrap( "vm.nacl.bootstrap", @@ -437,8 +438,6 @@ static std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair CreateNaClVM(std::pairpath.c_str()); - FS::PakPath::CopyFile(module, out); + FS::File out = FS::HomePath::OpenWrite(moduleName); + if (const FS::LoadedPakInfo* pak = FS::PakPath::LocateFile(moduleName)) + Log::Notice("Extracting VM module %s from %s...", moduleName.c_str(), pak->path.c_str()); + FS::PakPath::CopyFile(moduleName, out); out.Close(); } catch (std::system_error& err) { - Sys::Drop("VM: Failed to extract VM module %s: %s", module, err.what()); + Sys::Drop("VM: Failed to extract VM module %s: %s", moduleName, err.what()); } - modulePath = FS::Path::Build(FS::GetHomePath(), module); + modulePath = FS::Path::Build(FS::GetHomePath(), moduleName); } else { - modulePath = FS::Path::Build(libPath, module); + modulePath = FS::Path::Build(libPath, moduleName); } // Generate command line @@ -600,37 +577,40 @@ static std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair Date: Mon, 29 Jun 2026 04:07:58 +0200 Subject: [PATCH 03/15] cmake: use box64 on loong64 --- cmake/DaemonNaclHost.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/DaemonNaclHost.cmake b/cmake/DaemonNaclHost.cmake index 7172e71d55..164fdf3071 100644 --- a/cmake/DaemonNaclHost.cmake +++ b/cmake/DaemonNaclHost.cmake @@ -30,7 +30,7 @@ function(daemon_detect_nacl_arch) if (YOKAI_TARGET_SYSTEM_LINUX_COMPATIBILITY OR YOKAI_TARGET_SYSTEM_XDG_COMPATIBILITY) set(armhf_usage "arm64" "armel") - set(box64_usage "ppc64el" "riscv64") + set(box64_usage "ppc64el" "riscv64" "loong64") if ("${target_arch}" IN_LIST armhf_usage) # Load 32-bit armhf nexe on 64-bit arm64 engine on Linux with multiarch. From 85d3a8e3b49344e0e585c3dde6ce6beb50f6ba90 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Fri, 3 Jul 2026 12:40:34 +0200 Subject: [PATCH 04/15] cmake: rework the code enabling nexe build when there is an nacl sdk, taking saigo in account --- cmake/DaemonGame.cmake | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmake/DaemonGame.cmake b/cmake/DaemonGame.cmake index f6adde3c7c..c571e9c90d 100644 --- a/cmake/DaemonGame.cmake +++ b/cmake/DaemonGame.cmake @@ -68,10 +68,16 @@ set(SHAREDLIST_sgame # Function to setup all the Sgame/Cgame libraries include(CMakeParseArguments) -# The NaCl SDK only runs on amd64 or i686. if (NOT FORK EQUAL 2) - if (CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME + if (USE_NACL_SAIGO) + set(HAS_NACL_SDK ON) + elseif (CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME AND (YOKAI_TARGET_ARCH_AMD64 OR YOKAI_TARGET_ARCH_I686)) + # The PNaCl SDK only runs on amd64 or i686. + set(HAS_NACL_SDK ON) + endif() + + if (HAS_NACL_SDK) # can be loaded by daemon with vm.[sc]game.type 0 or 1 option(BUILD_GAME_NACL "Build the NaCl \"pexe\" and \"nexe\" gamelogic modules for enabled architecture targets, required to host mods." OFF) @@ -92,7 +98,7 @@ if (NOT FORK EQUAL 2) foreach(NACL_TARGET ${NACL_TARGETS}) set(IS_NACL_VALID_TARGET OFF) foreach(NACL_VALID_TARGET ${NACL_ALL_TARGETS}) - if(NACL_TARGET STREQUAL NACL_VALID_TARGET) + if (NACL_TARGET STREQUAL NACL_VALID_TARGET) set(IS_NACL_VALID_TARGET ON) endif() endforeach() From d0ff00176ecc4ab742783e77d4c09942fef6161b Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Fri, 3 Jul 2026 07:34:38 +0200 Subject: [PATCH 05/15] cmake: implement multi nexe --- CMakeLists.txt | 69 ++++++++++--------- cmake/DaemonGame.cmake | 51 ++++++++------ ...ost.cmake => DaemonNaclArchitecture.cmake} | 66 +++++++++++------- 3 files changed, 108 insertions(+), 78 deletions(-) rename cmake/{DaemonNaclHost.cmake => DaemonNaclArchitecture.cmake} (68%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7da7b66b71..d2b6369b17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,13 @@ if (Daemon_OUT) endif() include(Yokai/All) -include(DaemonNaclHost) + +include(DaemonNaclArchitecture) + +daemon_detect_nacl_arch("${YOKAI_TARGET_ARCH_NAME}") + +# Add printable strings to the executable. +yokai_add_buildinfo("char*" "DAEMON_NACL_ARCH_STRING" "\"${DAEMON_NACL_ARCH_NAME}\"") ################################################################################ # Configuration options @@ -969,22 +975,33 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER add_custom_target(runtime_deps) set_target_properties(runtime_deps PROPERTIES FOLDER "CMakePlumbing") - # The NaCl loader and IRT are required to load .nexe files - add_custom_command(TARGET runtime_deps PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${DEPS_DIR}/nacl_loader-${DAEMON_NACL_ARCH_NAME}${CMAKE_EXECUTABLE_SUFFIX} - ${FULL_OUTPUT_DIR}/nacl_loader-${DAEMON_NACL_ARCH_NAME}${CMAKE_EXECUTABLE_SUFFIX} - ) + foreach(arch_name IN LISTS DAEMON_NACL_ARCH_NAME_LIST) + # The NaCl loader and IRT are required to load .nexe files + if (YOKAI_TARGET_SYSTEM_WINDOWS AND YOKAI_TARGET_ARCH_I686 AND "${arch_name}" STREQUAL "amd64") + # Backport compatibility until the external_deps script properly suffixes names in the archives. + add_custom_command(TARGET runtime_deps PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${DEPS_DIR}/nacl_loader-${arch_name}${CMAKE_EXECUTABLE_SUFFIX} + ${FULL_OUTPUT_DIR}/nacl_loader-${arch_name}${CMAKE_EXECUTABLE_SUFFIX} + ) + else() + add_custom_command(TARGET runtime_deps PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${DEPS_DIR}/nacl_loader${CMAKE_EXECUTABLE_SUFFIX} + ${FULL_OUTPUT_DIR}/nacl_loader-${arch_name}${CMAKE_EXECUTABLE_SUFFIX} + ) + endif() - add_custom_command(TARGET runtime_deps PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${DEPS_DIR}/irt_core-${DAEMON_NACL_ARCH_NAME}.nexe - ${FULL_OUTPUT_DIR}/irt_core-${DAEMON_NACL_ARCH_NAME}.nexe - ) + add_custom_command(TARGET runtime_deps PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${DEPS_DIR}/irt_core-${arch_name}.nexe + ${FULL_OUTPUT_DIR}/irt_core-${arch_name}.nexe + ) + endforeach() # Linux uses a bootstrap program to reserve address space if (YOKAI_TARGET_SYSTEM_LINUX_COMPATIBILITY) - if (YOKAI_TARGET_ARCH_ARM64) + if (DAEMON_NACL_MULTIARCH) add_executable(nacl_multiarch-${DAEMON_NACL_ARCH_NAME} tools/nacl_multiarch/nacl_multiarch.cpp ${BUILDINFOLIST} @@ -998,25 +1015,13 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER ) endif() - add_custom_command(TARGET runtime_deps PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${DEPS_DIR}/nacl_helper_bootstrap - ${FULL_OUTPUT_DIR}/nacl_helper_bootstrap-${DAEMON_NACL_ARCH_NAME} - ) - endif() - - # Win32 requires nacl_loader_amd64.exe in order to run on Win64 - if (YOKAI_TARGET_SYSTEM_WINDOWS AND YOKAI_TARGET_ARCH_I686) - add_custom_command(TARGET runtime_deps PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${DEPS_DIR}/nacl_loader-amd64${CMAKE_EXECUTABLE_SUFFIX} - ${FULL_OUTPUT_DIR}/nacl_loader-amd64${CMAKE_EXECUTABLE_SUFFIX} - ) - add_custom_command(TARGET runtime_deps PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${DEPS_DIR}/irt_core-amd64.nexe - ${FULL_OUTPUT_DIR}/irt_core-amd64.nexe - ) + foreach(arch_name IN LISTS DAEMON_NACL_ARCH_NAME_LIST) + add_custom_command(TARGET runtime_deps PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${DEPS_DIR}/nacl_helper_bootstrap + ${FULL_OUTPUT_DIR}/nacl_helper_bootstrap-${arch_name} + ) + endforeach() endif() # Mac requires some libraries from external_deps diff --git a/cmake/DaemonGame.cmake b/cmake/DaemonGame.cmake index c571e9c90d..053f44a567 100644 --- a/cmake/DaemonGame.cmake +++ b/cmake/DaemonGame.cmake @@ -78,35 +78,46 @@ if (NOT FORK EQUAL 2) endif() if (HAS_NACL_SDK) + include(DaemonNaclArchitecture) + # can be loaded by daemon with vm.[sc]game.type 0 or 1 option(BUILD_GAME_NACL "Build the NaCl \"pexe\" and \"nexe\" gamelogic modules for enabled architecture targets, required to host mods." OFF) set(NACL_ALL_TARGETS "amd64;i686;armhf") - set(BUILD_GAME_NACL_TARGETS "all" CACHE STRING "Enabled NaCl \"nexe\" architecture targets, values: ${NACL_ALL_TARGETS}, all, native, none.") + set(BUILD_GAME_NACL_TARGETS "all" CACHE STRING "Enabled NaCl \"nexe\" architecture targets, values: ${NACL_ALL_TARGETS};all;native;none") mark_as_advanced(BUILD_GAME_NACL_TARGETS) - if (BUILD_GAME_NACL_TARGETS STREQUAL "all") - set(NACL_TARGETS "${NACL_ALL_TARGETS}") - elseif (BUILD_GAME_NACL_TARGETS STREQUAL "native") - set(NACL_TARGETS "${YOKAI_TARGET_ARCH_NAME}") - elseif (BUILD_GAME_NACL_TARGETS STREQUAL "none") - set(NACL_TARGETS "") - else() - set(NACL_TARGETS "${BUILD_GAME_NACL_TARGETS}") - endif() + if (BUILD_GAME_NACL) + foreach(nacl_target ${BUILD_GAME_NACL_TARGETS}) + if (BUILD_GAME_NACL_TARGETS STREQUAL "all") + list(APPEND nacl_target_list ${NACL_ALL_TARGETS}) + elseif (BUILD_GAME_NACL_TARGETS STREQUAL "native") + list(APPEND nacl_target_list "${YOKAI_TARGET_ARCH_NAME}") + elseif (BUILD_GAME_NACL_TARGETS STREQUAL "none") + set(nacl_target_list "") + else() + list(APPEND nacl_target_list "${nacl_target}") + endif() + endforeach() + + foreach(nacl_target IN LISTS nacl_target_list) + daemon_detect_nacl_arch("${nacl_target}") - foreach(NACL_TARGET ${NACL_TARGETS}) - set(IS_NACL_VALID_TARGET OFF) - foreach(NACL_VALID_TARGET ${NACL_ALL_TARGETS}) - if (NACL_TARGET STREQUAL NACL_VALID_TARGET) - set(IS_NACL_VALID_TARGET ON) + foreach(detected_target IN LISTS DAEMON_NACL_ARCH_NAME_LIST) + if (NOT "${detected_target}" IN_LIST NACL_TARGETS) + list(APPEND NACL_TARGETS ${detected_target}) + endif() + endforeach() + endforeach() + + foreach(nacl_target IN LISTS NACL_TARGETS) + if (NOT nacl_target IN_LIST NACL_ALL_TARGETS) + message(FATAL_ERROR "Invalid NaCl target ${nacl_target}, must be one of ${NACL_ALL_TARGETS}") endif() endforeach() - if (NOT IS_NACL_VALID_TARGET) - message(FATAL_ERROR "Invalid NaCl target ${NACL_TARGET}, must be one of ${NACL_ALL_TARGETS}") - endif() - endforeach() + message(STATUS "Building NaCl targets: ${NACL_TARGETS}") + endif() else() set(BUILD_GAME_NACL OFF) set(NACL_TARGETS "") @@ -213,7 +224,7 @@ function(GAMEMODULE) add_custom_target(nacl-vms ALL) unset(NACL_VMS_PROJECTS) - foreach(NACL_TARGET ${NACL_TARGETS}) + foreach(NACL_TARGET IN LISTS NACL_TARGETS) if (NACL_TARGET STREQUAL "i686") set(SAIGO_ARCH "i686") elseif (NACL_TARGET STREQUAL "amd64") diff --git a/cmake/DaemonNaclHost.cmake b/cmake/DaemonNaclArchitecture.cmake similarity index 68% rename from cmake/DaemonNaclHost.cmake rename to cmake/DaemonNaclArchitecture.cmake index 164fdf3071..e0666c193b 100644 --- a/cmake/DaemonNaclHost.cmake +++ b/cmake/DaemonNaclArchitecture.cmake @@ -24,60 +24,74 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -function(daemon_detect_nacl_arch) - set(target_arch "${YOKAI_TARGET_ARCH_NAME}") - set(nacl_arch "${target_arch}") +function(daemon_detect_nacl_arch target_arch) + macro(add_nacl_arch arch_name) + list(APPEND nacl_arch_list "${arch_name}") + endmacro() + + # NaCl runtime is only available on architectures that have a NaCl loader. + set(nacl_runtime_arch "amd64" "i686" "armhf") + + if (YOKAI_TARGET_SYSTEM_WINDOWS) + if("${target_arch}" STREQUAL "amd64") + add_nacl_arch("${target_arch}") + elseif("${target_arch}" STREQUAL "i686") + # Win32 requires nacl_loader-amd64.exe in order to run on Win64 + add_nacl_arch("${target_arch}") + add_nacl_arch("amd64") + endif() + elseif (YOKAI_TARGET_SYSTEM_LINUX_COMPATIBILITY OR YOKAI_TARGET_SYSTEM_XDG_COMPATIBILITY) + if ("${target_arch}" IN_LIST nacl_runtime_arch) + add_nacl_arch("${target_arch}") + endif() - if (YOKAI_TARGET_SYSTEM_LINUX_COMPATIBILITY OR YOKAI_TARGET_SYSTEM_XDG_COMPATIBILITY) set(armhf_usage "arm64" "armel") set(box64_usage "ppc64el" "riscv64" "loong64") if ("${target_arch}" IN_LIST armhf_usage) + set(DAEMON_NACL_MULTIARCH ON) + # Load 32-bit armhf nexe on 64-bit arm64 engine on Linux with multiarch. # The nexe is system agnostic so there should be no difference with armel. - set(nacl_arch "armhf") - elseif ("${target_arch}" IN_LIST box64_usage) + add_nacl_arch("armhf") + endif() + + if ("${target_arch}" IN_LIST box64_usage) option(DAEMON_NACL_BOX64_EMULATION "Use Box64 to emulate x86_64 NaCl loader on unsupported platforms" ON) + if (DAEMON_NACL_BOX64_EMULATION) # Use Box64 to run x86_64 NaCl loader and amd64 nexe. # Box64 must be installed and available in PATH at runtime. - set(nacl_arch "amd64") + add_nacl_arch("amd64") add_definitions(-DDAEMON_NACL_BOX64_EMULATION) endif() endif() elseif (YOKAI_TARGET_SYSTEM_MACOS) - if ("${target_arch}" STREQUAL "arm64") + if ("${target_arch}" STREQUAL "amd64") + add_nacl_arch("${target_arch}") + elseif ("${target_arch}" STREQUAL "arm64") # You can get emulated NaCl going like this: # cp external_deps/macos-amd64-default_10/{nacl_loader,irt_core-amd64.nexe} build/ - set(nacl_arch "amd64") + add_nacl_arch("amd64") endif() endif() - string(TOUPPER "${nacl_arch}" nacl_arch_upper) + if (nacl_arch_list) + message(STATUS "Available NaCl architectures: ${nacl_arch_list}") - # NaCl runtime is only available on architectures that have a NaCl loader. - set(nacl_runtime_arch "amd64" "i686" "armhf") - if ("${nacl_arch}" IN_LIST nacl_runtime_arch) - message(STATUS "Detected NaCl architecture: ${nacl_arch}") + list(GET nacl_arch_list 0 nacl_arch) + + message(STATUS "Primary NaCl architecture: ${nacl_arch}") add_definitions(-DDAEMON_NACL_RUNTIME_ENABLED) else() set(nacl_arch "unknown") - message(STATUS "No NaCl architecture detected") + message(STATUS "No known NaCl architecture") endif() # The DAEMON_NACL_ARCH_NAME variable contributes to the nexe file name. set(DAEMON_NACL_ARCH_NAME "${nacl_arch}" PARENT_SCOPE) - - set(DAEMON_NACL_ARCH_NAME_UPPER "${nacl_arch_upper}" PARENT_SCOPE) + # Those names are used to copy the loader and the IRT binaries. + set(DAEMON_NACL_ARCH_NAME_LIST "${nacl_arch_list}" PARENT_SCOPE) endfunction() - -daemon_detect_nacl_arch() - -# Makes possible to do that in CMake code: -# > if (DAEMON_NACL_ARCH_ARMHF) -set("DAEMON_NACL_ARCH_${DAEMON_NACL_ARCH_NAME_UPPER}" ON) - -# Add printable strings to the executable. -yokai_add_buildinfo("char*" "DAEMON_NACL_ARCH_STRING" "\"${DAEMON_NACL_ARCH_NAME}\"") From 3941ebc843dc4bd6f7ea296d3ad796c538a6c343 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 4 Jul 2026 14:19:36 +0200 Subject: [PATCH 06/15] cmake: reword DaemonFlags a bit --- cmake/DaemonFlags.cmake | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cmake/DaemonFlags.cmake b/cmake/DaemonFlags.cmake index 179835ddca..f999e5e272 100644 --- a/cmake/DaemonFlags.cmake +++ b/cmake/DaemonFlags.cmake @@ -260,10 +260,14 @@ if (USE_FLOAT_EXCEPTIONS) add_definitions(-DDAEMON_USE_FLOAT_EXCEPTIONS) endif() -if (NOT NACL AND BUILD_CLIENT) +if (NOT YOKAI_TARGET_SYSTEM_NACL AND BUILD_CLIENT) option(USE_OPENMP "Use OpenMP to parallelize some tasks" OFF) endif() +if (NOT YOKAI_TARGET_SYSTEM_NACL AND BUILD_CLIENT AND USE_OPENMP) + set(ENABLE_OPENMP ON) +endif() + if (YOKAI_CXX_COMPILER_MSVC_COMPATIBILITY) if (YOKAI_CXX_COMPILER_MSVC) # /MP doesn't do anything and prints a warning in the Clang clone. @@ -275,7 +279,7 @@ if (YOKAI_CXX_COMPILER_MSVC_COMPATIBILITY) set_cxx_flag("/std:c++23preview") endif() - if (NOT NACL AND BUILD_CLIENT AND USE_OPENMP) + if (ENABLE_OPENMP) # Flag checks doen't work with MSVC so we assume it's there. set(OPENMP_COMPILE_FLAG "/openmp") endif() @@ -385,7 +389,7 @@ else() endif() endif() - if (NOT NACL AND BUILD_CLIENT AND USE_OPENMP) + if (ENABLE_OPENMP) check_CXX_compiler_flag("-fopenmp" FLAG_FOPENMP) if (FLAG_FOPENMP) @@ -396,7 +400,7 @@ else() endif() endif() - if (YOKAI_TARGET_SYSTEM_NACL AND USE_NACL_SAIGO AND DAEMON_NACL_ARCH_ARMHF) + if (YOKAI_TARGET_SYSTEM_NACL AND YOKAI_CXX_COMPILER_SAIGO AND YOKAI_TARGET_ARCH_ARMHF) # Saigo produces broken arm builds when optimizing them. # See: https://github.com/Unvanquished/Unvanquished/issues/3297 # When setting this clang-specific option, we don't have to care @@ -445,7 +449,7 @@ else() try_flag(WARNINGS "-Werror") endif() - if (YOKAI_TARGET_SYSTEM_NACL AND NOT USE_NACL_SAIGO) + if (YOKAI_TARGET_SYSTEM_NACL AND YOKAI_CXX_COMPILER_PNACL) # PNaCl only supports libc++ as standard library. set_c_cxx_flag("-stdlib=libc++") set_c_cxx_flag("--pnacl-allow-exceptions") @@ -508,7 +512,7 @@ else() # Don't set _FORTIFY_SOURCE in debug builds. endif() - if (NOT NACL) + if (NOT YOKAI_TARGET_SYSTEM_NACL) # Saigo reports weird errors when building some cgame and sgame arm nexe with PIC: # > error: Cannot represent a difference across sections # > error: expected relocatable expression From 5d1c0aba6ba59dbe3b6166bf67ba6ffc0a231241 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 4 Jul 2026 10:57:36 +0200 Subject: [PATCH 07/15] cmake: deeply rewrite the NaCl toolchains --- CMakeLists.txt | 28 ++--- cmake/DaemonGame.cmake | 87 +++++++------ cmake/DaemonNacl.cmake | 81 ------------ cmake/DaemonNaclFlags.cmake | 75 +++++++++++ cmake/DaemonPNaClFinalize.cmake | 79 ++++++++++++ cmake/DaemonSaigoFinalize.cmake | 56 +++++++++ cmake/cross-toolchain-pnacl.cmake | 106 ++++++++++++++++ cmake/cross-toolchain-saigo-amd64.cmake | 28 +++++ cmake/cross-toolchain-saigo-armhf.cmake | 28 +++++ cmake/cross-toolchain-saigo-common.cmake | 79 ++++++++++++ cmake/cross-toolchain-saigo-i686.cmake | 39 ++++++ cmake/toolchain-pnacl.cmake | 151 ----------------------- cmake/toolchain-saigo.cmake | 75 ----------- 13 files changed, 554 insertions(+), 358 deletions(-) delete mode 100644 cmake/DaemonNacl.cmake create mode 100644 cmake/DaemonNaclFlags.cmake create mode 100644 cmake/DaemonPNaClFinalize.cmake create mode 100644 cmake/DaemonSaigoFinalize.cmake create mode 100644 cmake/cross-toolchain-pnacl.cmake create mode 100644 cmake/cross-toolchain-saigo-amd64.cmake create mode 100644 cmake/cross-toolchain-saigo-armhf.cmake create mode 100644 cmake/cross-toolchain-saigo-common.cmake create mode 100644 cmake/cross-toolchain-saigo-i686.cmake delete mode 100644 cmake/toolchain-pnacl.cmake delete mode 100644 cmake/toolchain-saigo.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d2b6369b17..f012339cb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,12 +77,14 @@ endif() include(Yokai/All) -include(DaemonNaclArchitecture) +if (NOT YOKAI_TARGET_SYSTEM_NACL) + include(DaemonNaclArchitecture) -daemon_detect_nacl_arch("${YOKAI_TARGET_ARCH_NAME}") + daemon_detect_nacl_arch("${YOKAI_TARGET_ARCH_NAME}") -# Add printable strings to the executable. -yokai_add_buildinfo("char*" "DAEMON_NACL_ARCH_STRING" "\"${DAEMON_NACL_ARCH_NAME}\"") + # Add printable strings to the executable. + yokai_add_buildinfo("char*" "DAEMON_NACL_ARCH_STRING" "\"${DAEMON_NACL_ARCH_NAME}\"") +endif() ################################################################################ # Configuration options @@ -271,6 +273,12 @@ endif() option(USE_EXTERNAL_DEPS_LIBS "Build and link against libraries from the EXTERNAL_DEPS_DIR" ${DEFAULT_USE_EXTERNAL_DEPS_LIBS}) +set(PNACLSDK_PREFIX "${DEPS_DIR}/pnacl" CACHE PATH "PNaCl SDK path") +mark_as_advanced(PNACLSDK_PREFIX) + +set(SAIGOSDK_PREFIX "${DEPS_DIR}/saigo_newlib" CACHE PATH "Saigo NaCl SDK path") +mark_as_advanced(SAIGOSDK_PREFIX) + if (USE_EXTERNAL_DEPS AND NOT YOKAI_TARGET_SYSTEM_NACL) if (DEPS_DIR) message(STATUS "Using external deps dir: ${DEPS_DIR}") @@ -297,6 +305,7 @@ endif() # meaning we have to detect useless engine compiler to set # useless engine flags when only building vms. include(DaemonFlags) +include(DaemonNaclFlags) # FIXME: Once engine flags would be only set when building the engine # this would be likely unused by vms as they are built by DaemonGame. @@ -468,7 +477,6 @@ endif() # LIBS_BASE, LIBS_ENGINE_BASE LIBS_ENGINE, LIBS_BASECLIENT, LIBS_CLIENT # Native client -include(DaemonNacl) if (YOKAI_TARGET_SYSTEM_NACL) add_library(srclibs-nacl-module EXCLUDE_FROM_ALL ${NACLLIST_MODULE}) set(LIBS_BASE ${LIBS_BASE} srclibs-nacl-module) @@ -489,16 +497,6 @@ elseif (YOKAI_TARGET_SYSTEM_NACL) find_library(NACL_EXCEPTION nacl_exception) find_library(NACL_MINIDUMP minidump_generator) - # HACK: To be removed when Saigo is repackaged properly. - if (NOT NACL_MINIDUMP - # NACL_TARGET is specific to Saigo, PNaCl target is le32 and doesn't set NACL_TARGET. - AND "${NACL_TARGET}" STREQUAL "i686" - # x86_64-nacl/lib32 is specific to Google build, other builds may provide i686-nacl/lib instead. - AND EXISTS "${DEPS_DIR}/saigo_newlib/x86_64-nacl/lib32") - set(NACL_EXCEPTION "${DEPS_DIR}/saigo_newlib/x86_64-nacl/lib32/libnacl_exception.a") - set(NACL_MINIDUMP "${DEPS_DIR}/saigo_newlib/x86_64-nacl/lib32/libminidump_generator.a") - endif() - set(LIBS_BASE ${LIBS_BASE} ${NACL_MINIDUMP} ${NACL_EXCEPTION}) else() find_library(LIBM m) diff --git a/cmake/DaemonGame.cmake b/cmake/DaemonGame.cmake index 053f44a567..8a4cc2e4ff 100644 --- a/cmake/DaemonGame.cmake +++ b/cmake/DaemonGame.cmake @@ -44,9 +44,9 @@ include(Yokai/All) # Do not report unused native compiler if native vms are not built. # If only NACL vms are built, this will be reported in chainloaded build. -if (BUILD_GAME_NATIVE_DLL OR BUILD_GAME_NATIVE_EXE OR NACL) - include(DaemonNacl) +if (BUILD_GAME_NATIVE_DLL OR BUILD_GAME_NATIVE_EXE OR GAME_BUILD_SUBINVOCATION) include(DaemonFlags) + include(DaemonNaclFlags) endif() # Source lists for src/shared @@ -68,7 +68,11 @@ set(SHAREDLIST_sgame # Function to setup all the Sgame/Cgame libraries include(CMakeParseArguments) -if (NOT FORK EQUAL 2) +list(APPEND NACL_ALL_TARGETS "amd64" "i686" "armhf") + +if (NOT GAME_BUILD_SUBINVOCATION) + option(USE_NACL_SAIGO "Use the Saigo toolchain to build NaCl executables" OFF) + if (USE_NACL_SAIGO) set(HAS_NACL_SDK ON) elseif (CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME @@ -77,23 +81,24 @@ if (NOT FORK EQUAL 2) set(HAS_NACL_SDK ON) endif() + list(APPEND NACL_ALL_TARGETS "amd64" "i686" "armhf") + if (HAS_NACL_SDK) include(DaemonNaclArchitecture) # can be loaded by daemon with vm.[sc]game.type 0 or 1 option(BUILD_GAME_NACL "Build the NaCl \"pexe\" and \"nexe\" gamelogic modules for enabled architecture targets, required to host mods." OFF) - set(NACL_ALL_TARGETS "amd64;i686;armhf") set(BUILD_GAME_NACL_TARGETS "all" CACHE STRING "Enabled NaCl \"nexe\" architecture targets, values: ${NACL_ALL_TARGETS};all;native;none") mark_as_advanced(BUILD_GAME_NACL_TARGETS) if (BUILD_GAME_NACL) foreach(nacl_target ${BUILD_GAME_NACL_TARGETS}) - if (BUILD_GAME_NACL_TARGETS STREQUAL "all") + if ("${nacl_target}" STREQUAL "all") list(APPEND nacl_target_list ${NACL_ALL_TARGETS}) - elseif (BUILD_GAME_NACL_TARGETS STREQUAL "native") + elseif ("${nacl_target}" STREQUAL "native") list(APPEND nacl_target_list "${YOKAI_TARGET_ARCH_NAME}") - elseif (BUILD_GAME_NACL_TARGETS STREQUAL "none") + elseif ("${nacl_target}" STREQUAL "none") set(nacl_target_list "") else() list(APPEND nacl_target_list "${nacl_target}") @@ -105,7 +110,7 @@ if (NOT FORK EQUAL 2) foreach(detected_target IN LISTS DAEMON_NACL_ARCH_NAME_LIST) if (NOT "${detected_target}" IN_LIST NACL_TARGETS) - list(APPEND NACL_TARGETS ${detected_target}) + list(APPEND NACL_TARGETS "${detected_target}") endif() endforeach() endforeach() @@ -151,7 +156,7 @@ function(buildGameModule module_slug) if (module_slug STREQUAL "nacl") set_target_properties(${module_target} PROPERTIES OUTPUT_NAME "${GAMEMODULE_NAME}" - SUFFIX "${PLATFORM_EXE_SUFFIX}") + SUFFIX "${NACL_EXECUTABLE_SUFFIX}") target_link_libraries(${module_target} ${GAMEMODULE_LIBS} ${LIBS_BASE}) else() @@ -167,13 +172,13 @@ function(gameSubProject) BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${NACL_VMS_PROJECT} CMAKE_GENERATOR ${VM_GENERATOR} CMAKE_ARGS - -DFORK=2 - -DDAEMON_DIR=${Daemon_SOURCE_DIR} - -DDEPS_DIR=${DEPS_DIR} + "-DDAEMON_DIR=${Daemon_SOURCE_DIR}" + "-DDEPS_DIR=${DEPS_DIR}" -DBUILD_CLIENT=OFF -DBUILD_TTY_CLIENT=OFF -DBUILD_SERVER=OFF - -DBUILD_DUMMY_GAMELOGIC=${BUILD_DUMMY_GAMELOGIC} + "-DBUILD_DUMMY_GAMELOGIC=${BUILD_DUMMY_GAMELOGIC}" + -DGAME_BUILD_SUBINVOCATION=ON ${ARGV} ${INHERITED_OPTION_ARGS} INSTALL_COMMAND "" @@ -203,8 +208,9 @@ function(GAMEMODULE) buildGameModule("native-exe") endif() - if (NOT FORK) # create the nacl-vms target only the first time that GAMEMODULE is called - set(FORK 1 PARENT_SCOPE) + if (NOT NACL_VMS_TARGET_CREATED AND NOT GAME_BUILD_SUBINVOCATION) + # Create the nacl-vms target only the first time that GAMEMODULE is called. + set(NACL_VMS_TARGET_CREATED ON PARENT_SCOPE) if (CMAKE_GENERATOR MATCHES "Visual Studio") set(VM_GENERATOR "NMake Makefiles") @@ -219,34 +225,29 @@ function(GAMEMODULE) "-D${inherited_option}=${${inherited_option}}") endforeach(inherited_option) - if (BUILD_GAME_NACL) + if (BUILD_GAME_NACL AND NOT YOKAI_TARGET_SYSTEM_NACL) if (USE_NACL_SAIGO) add_custom_target(nacl-vms ALL) unset(NACL_VMS_PROJECTS) - foreach(NACL_TARGET IN LISTS NACL_TARGETS) - if (NACL_TARGET STREQUAL "i686") - set(SAIGO_ARCH "i686") - elseif (NACL_TARGET STREQUAL "amd64") - set(SAIGO_ARCH "x86_64") - elseif (NACL_TARGET STREQUAL "armhf") - set(SAIGO_ARCH "arm") - else() + foreach(nacl_target IN LISTS NACL_TARGETS) + if (NOT nacl_target IN_LIST NACL_ALL_TARGETS) message(FATAL_ERROR "Unknown NaCl architecture ${NACL_TARGET}") endif() - set(NACL_VMS_PROJECT nacl-vms-${NACL_TARGET}) + set(NACL_VMS_PROJECT nacl-vms-${nacl_target}) list(APPEND NACL_VMS_PROJECTS ${NACL_VMS_PROJECT}) add_dependencies(nacl-vms ${NACL_VMS_PROJECT}) + # TODO: Remove USE_NACL_SAIGO once the game uses YOKAI_TARGET_SYSTEM_NACL. gameSubProject( - -DCMAKE_TOOLCHAIN_FILE=${Daemon_SOURCE_DIR}/cmake/toolchain-saigo.cmake + "-DCMAKE_TOOLCHAIN_FILE=${Daemon_SOURCE_DIR}/cmake/cross-toolchain-saigo-${nacl_target}.cmake" + "-DSAIGOSDK_PREFIX=${SAIGOSDK_PREFIX}" + -DUSE_NACL_SAIGO=ON -DBUILD_GAME_NACL=ON -DBUILD_GAME_NATIVE_DLL=OFF -DBUILD_GAME_NATIVE_EXE=OFF -DUSE_NACL_SAIGO=ON - -DSAIGO_ARCH=${SAIGO_ARCH} - -DNACL_TARGET=${NACL_TARGET} ) endforeach() else() @@ -257,19 +258,21 @@ function(GAMEMODULE) string(REPLACE ";" "," NACL_TARGETS_STRING "${NACL_TARGETS}") gameSubProject( - -DCMAKE_TOOLCHAIN_FILE=${Daemon_SOURCE_DIR}/cmake/toolchain-pnacl.cmake + "-DCMAKE_TOOLCHAIN_FILE=${Daemon_SOURCE_DIR}/cmake/cross-toolchain-pnacl.cmake" + "-DPNACLSDK_PREFIX=${PNACLSDK_PREFIX}" + -DUSE_NACL_SAIGO=OFF -DBUILD_GAME_NACL=ON -DBUILD_GAME_NATIVE_DLL=OFF -DBUILD_GAME_NATIVE_EXE=OFF - -DNACL_TARGETS_STRING=${NACL_TARGETS_STRING} + "-DNACL_TARGETS_STRING=${NACL_TARGETS_STRING}" ) endif() endif() set(NACL_VMS_PROJECTS ${NACL_VMS_PROJECTS} PARENT_SCOPE) - elseif (FORK EQUAL 2) # we are in the CMake sub-invocation for NaCl + elseif (GAME_BUILD_SUBINVOCATION) if (BUILD_GAME_NACL) - if (USE_NACL_SAIGO) + if (YOKAI_CXX_COMPILER_SAIGO) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) else() # Put the .nexe and .pexe files in the same directory as the engine. @@ -278,16 +281,28 @@ function(GAMEMODULE) buildGameModule("nacl") - if (USE_NACL_SAIGO) + if (YOKAI_CXX_COMPILER_SAIGO) + include(DaemonSaigoFinalize) + # Finalize NaCl executables for supported architectures. - saigo_finalize(${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/.. ${GAMEMODULE_NAME} ${NACL_TARGET}) + saigo_finalize( + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + "${GAMEMODULE_NAME}" + "${YOKAI_TARGET_ARCH_NAME}" + ) else() + include(DaemonPNaClFinalize) + # Revert a workaround for a bug where CMake ExternalProject lists-as-args are cut on first “;” string(REPLACE "," ";" NACL_TARGETS "${NACL_TARGETS_STRING}") # Generate NaCl executables for supported architectures. - foreach(NACL_TARGET ${NACL_TARGETS}) - pnacl_finalize(${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${GAMEMODULE_NAME} ${NACL_TARGET}) + foreach(nacl_target ${NACL_TARGETS}) + pnacl_finalize( + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + "${GAMEMODULE_NAME}" + "${nacl_target}" + ) endforeach() endif() endif() diff --git a/cmake/DaemonNacl.cmake b/cmake/DaemonNacl.cmake deleted file mode 100644 index e37bf06844..0000000000 --- a/cmake/DaemonNacl.cmake +++ /dev/null @@ -1,81 +0,0 @@ -# Daemon BSD Source Code -# Copyright (c) 2013-2016, Daemon Developers -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Daemon developers nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Native client - -option(USE_NACL_SAIGO "Use Saigo toolchain to build NaCl executables" OFF) - -if (YOKAI_TARGET_SYSTEM_NACL) - # Build nexe binary. - if(USE_NACL_SAIGO) - if (NACL_TARGET STREQUAL "amd64") - add_definitions(-DNACL_BUILD_ARCH=x86) - add_definitions(-DNACL_BUILD_SUBARCH=64) - elseif (NACL_TARGET STREQUAL "i686") - add_definitions(-DNACL_BUILD_ARCH=x86) - add_definitions(-DNACL_BUILD_SUBARCH=32) - elseif (NACL_TARGET STREQUAL "armhf") - add_definitions(-DNACL_BUILD_ARCH=arm) - else() - message(FATAL_ERROR "Unsupported architecture ${NACL_TARGET}") - endif() - else() - # Those defines looks to be meaningless to produce arch-independent pexe - # with PNaCl but they must be set to anything supported by native builds. - # This requirement looks to be a PNaCl bug. - add_definitions( -DNACL_BUILD_ARCH=x86 ) - add_definitions( -DNACL_BUILD_SUBARCH=64 ) - endif() -else() - # Build native dll or native exe. - if (YOKAI_TARGET_SYSTEM_MACOS) - add_definitions( -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_ANDROID=0 -DNACL_FREEBSD=0 -DNACL_OSX=1 ) - elseif (YOKAI_TARGET_SYSTEM_LINUX) - add_definitions( -DNACL_WINDOWS=0 -DNACL_LINUX=1 -DNACL_ANDROID=0 -DNACL_FREEBSD=0 -DNACL_OSX=0 ) - elseif (YOKAI_TARGET_SYSTEM_FREEBSD) - add_definitions( -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_ANDROID=0 -DNACL_FREEBSD=1 -DNACL_OSX=0 ) - elseif (YOKAI_TARGET_SYSTEM_WINDOWS) - add_definitions( -DNACL_WINDOWS=1 -DNACL_LINUX=0 -DNACL_ANDROID=0 -DNACL_FREEBSD=0 -DNACL_OSX=0 ) - endif() - - if (YOKAI_TARGET_ARCH_AMD64) - add_definitions( -DNACL_BUILD_ARCH=x86 ) - add_definitions( -DNACL_BUILD_SUBARCH=64 ) - elseif (YOKAI_TARGET_ARCH_I686) - add_definitions( -DNACL_BUILD_ARCH=x86 ) - add_definitions( -DNACL_BUILD_SUBARCH=32 ) - elseif (YOKAI_TARGET_ARCH_ARMHF) - add_definitions( -DNACL_BUILD_ARCH=arm ) - else() - # NaCl does not support this architecture natively, but these defines must - # be set because nacl_config.h is included unconditionally. Use dummy x86 - # values as PNaCl does for architecture-independent builds. - add_definitions( -DNACL_BUILD_ARCH=x86 ) - add_definitions( -DNACL_BUILD_SUBARCH=64 ) - endif() -endif() - -include_directories( ${LIB_DIR}/nacl ) diff --git a/cmake/DaemonNaclFlags.cmake b/cmake/DaemonNaclFlags.cmake new file mode 100644 index 0000000000..cbdc4b5a3f --- /dev/null +++ b/cmake/DaemonNaclFlags.cmake @@ -0,0 +1,75 @@ +# Daemon BSD Source Code +# Copyright (c) 2013-2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Native Client build configuration. + +if (YOKAI_TARGET_SYSTEM_NACL) + # Build nexe binary. + + if (YOKAI_CXX_COMPILER_SAIGO) + if (YOKAI_TARGET_ARCH_AMD64) + add_definitions(-DNACL_BUILD_ARCH=x86 -DNACL_BUILD_SUBARCH=64) + elseif (YOKAI_TARGET_ARCH_I686) + add_definitions(-DNACL_BUILD_ARCH=x86 -DNACL_BUILD_SUBARCH=32) + elseif (YOKAI_TARGET_ARCH_ARMHF) + add_definitions(-DNACL_BUILD_ARCH=arm) + else() + message(FATAL_ERROR "Unsupported architecture ${NACL_TARGET}") + endif() + else() + # Those defines looks to be meaningless to produce arch-independent pexe + # with PNaCl but they must be set to anything supported by native builds. + # This requirement looks to be a PNaCl bug. + add_definitions(-DNACL_BUILD_ARCH=x86 -DNACL_BUILD_SUBARCH=64) + endif() +else() + # Build native dll or native exe. + + if (YOKAI_TARGET_SYSTEM_MACOS) + add_definitions(-DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_ANDROID=0 -DNACL_FREEBSD=0 -DNACL_OSX=1) + elseif (YOKAI_TARGET_SYSTEM_LINUX) + add_definitions(-DNACL_WINDOWS=0 -DNACL_LINUX=1 -DNACL_ANDROID=0 -DNACL_FREEBSD=0 -DNACL_OSX=0) + elseif (YOKAI_TARGET_SYSTEM_FREEBSD) + add_definitions(-DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_ANDROID=0 -DNACL_FREEBSD=1 -DNACL_OSX=0) + elseif (YOKAI_TARGET_SYSTEM_WINDOWS) + add_definitions(-DNACL_WINDOWS=1 -DNACL_LINUX=0 -DNACL_ANDROID=0 -DNACL_FREEBSD=0 -DNACL_OSX=0) + endif() + + if (YOKAI_TARGET_ARCH_AMD64) + add_definitions(-DNACL_BUILD_ARCH=x86 -DNACL_BUILD_SUBARCH=64) + elseif (YOKAI_TARGET_ARCH_I686) + add_definitions(-DNACL_BUILD_ARCH=x86 -DNACL_BUILD_SUBARCH=32) + elseif (YOKAI_TARGET_ARCH_ARMHF) + add_definitions(-DNACL_BUILD_ARCH=arm) + else() + # NaCl does not support this architecture natively, but these defines must + # be set because nacl_config.h is included unconditionally. Use dummy x86 + # values as PNaCl does for architecture-independent builds. + add_definitions(-DNACL_BUILD_ARCH=x86 -DNACL_BUILD_SUBARCH=64) + endif() +endif() + +include_directories(${LIB_DIR}/nacl) diff --git a/cmake/DaemonPNaClFinalize.cmake b/cmake/DaemonPNaClFinalize.cmake new file mode 100644 index 0000000000..2130490030 --- /dev/null +++ b/cmake/DaemonPNaClFinalize.cmake @@ -0,0 +1,79 @@ +# Daemon BSD Source Code +# Copyright (c) 2013-2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +function(pnacl_finalize dir module arch) + include(DaemonBuildTypeGeneratorExpression) + + set(PNACL_TRANSLATE_OPTIONS + --allow-llvm-bitcode-input # FIXME: finalize as part of the build process + --pnacl-allow-exceptions + $<${RELEASE_GENEXP_COND}:-O3> + $<${DEBUG_GENEXP_COND}:-O0> + $<${RELWITHDEBINFO_GENEXP_COND}:-O2> + $<${MINSIZEREL_GENEXP_COND}:-O2> + ) + set(PEXE "${dir}/${module}${NACL_EXECUTABLE_SUFFIX}") + set(NEXE "${dir}/${module}-${arch}${NACL_TRANSLATED_EXECUTABLE_SUFFIX}") + set(STRIPPED_NEXE "${dir}/${module}-${arch}-stripped${NACL_TRANSLATED_EXECUTABLE_SUFFIX}") + + if (arch STREQUAL "i686") + set(PNACL_ARCH "i686") + elseif (arch STREQUAL "amd64") + set(PNACL_ARCH "x86-64") + elseif (arch STREQUAL "armhf") + set(PNACL_ARCH "arm") + else() + message(FATAL_ERROR "Unknown NaCl architecture ${arch}") + endif() + + add_custom_command( + OUTPUT ${NEXE} + COMMENT "Translating ${module} (${arch})" + DEPENDS ${PEXE} + COMMAND + ${PNACLPYTHON_PREFIX2} + "${PNACL_TRANSLATE}" + ${PNACL_TRANSLATE_OPTIONS} + -arch "${PNACL_ARCH}" + "${PEXE}" + -o "${NEXE}" + ) + + add_custom_command( + OUTPUT "${STRIPPED_NEXE}" + COMMENT "Stripping ${module} (${arch})" + DEPENDS "${NEXE}" + COMMAND + ${PNACLPYTHON_PREFIX2} + "${CMAKE_STRIP}" + -s + "${NEXE}" + -o "${STRIPPED_NEXE}" + ) + + add_custom_target("${module}-${arch}" ALL DEPENDS "${STRIPPED_NEXE}") + add_dependencies("${module}-${arch}" "${module}-nacl") +endfunction() diff --git a/cmake/DaemonSaigoFinalize.cmake b/cmake/DaemonSaigoFinalize.cmake new file mode 100644 index 0000000000..01f1cf1da5 --- /dev/null +++ b/cmake/DaemonSaigoFinalize.cmake @@ -0,0 +1,56 @@ +# Daemon BSD Source Code +# Copyright (c) 2023-2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +function(saigo_finalize dir module arch) + set(SUBPROJECT_NEXE "${dir}/${module}${NACL_EXECUTABLE_SUFFIX}") + set(NEXE "${dir}/../${module}-${arch}${NACL_EXECUTABLE_SUFFIX}") + set(STRIPPED_NEXE "${dir}/../${module}-${arch}-stripped${NACL_EXECUTABLE_SUFFIX}") + + add_custom_command( + OUTPUT "${NEXE}" + COMMENT "Copying ${module} (${arch})" + DEPENDS "${SUBPROJECT_NEXE}" + COMMAND + ${CMAKE_COMMAND} + -E copy + "${SUBPROJECT_NEXE}" + "${NEXE}" + ) + + add_custom_command( + OUTPUT "${STRIPPED_NEXE}" + COMMENT "Stripping ${module} (${arch})" + DEPENDS "${NEXE}" + COMMAND + "${CMAKE_STRIP}" + -s + "${NEXE}" + -o "${STRIPPED_NEXE}" + ) + + add_custom_target("${module}-${arch}" ALL DEPENDS "${STRIPPED_NEXE}") + add_dependencies("${module}-${arch}" "${module}-nacl") +endfunction() diff --git a/cmake/cross-toolchain-pnacl.cmake b/cmake/cross-toolchain-pnacl.cmake new file mode 100644 index 0000000000..eb71dbc5cc --- /dev/null +++ b/cmake/cross-toolchain-pnacl.cmake @@ -0,0 +1,106 @@ +# Daemon BSD Source Code +# Copyright (c) 2013-2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# We can't use CMAKE_EXECUTABLE_SUFFIX because the Generic Platform will reset it +# and creating a Platform module for setting CMAKE_EXECUTABLE_SUFFIX is overkill. +set(NACL_EXECUTABLE_SUFFIX ".pexe") +set(NACL_TRANSLATED_EXECUTABLE_SUFFIX ".nexe") + +if (CMAKE_HOST_WIN32) + set(PNACL_EXECUTABLE_SUFFIX ".bat") +else() + set(PNACL_EXECUTABLE_SUFFIX "") +endif() + +set(PNACL_TRIPLET "pnacl") + +if ("${PNACLSDK_PREFIX}" STREQUAL "") + find_program(PATH_PNACL_CLANG NAMES "${PNACL_TRIPLET}-clang${PNACL_EXECUTABLE_SUFFIX}") + get_filename_component(PNACLSDK_PREFIX ${PATH_PNACL_CLANG} DIRECTORY) +endif() + +list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES PNACLSDK_PREFIX) + +set(CMAKE_SYSTEM_NAME "Generic") + +set(CMAKE_C_COMPILER "${PNACLSDK_PREFIX}/bin/${PNACL_TRIPLET}-clang${PNACL_EXECUTABLE_SUFFIX}") +set(CMAKE_CXX_COMPILER "${PNACLSDK_PREFIX}/bin/${PNACL_TRIPLET}-clang++${PNACL_EXECUTABLE_SUFFIX}") +set(CMAKE_AR "${PNACLSDK_PREFIX}/bin/${PNACL_TRIPLET}-ar${PNACL_EXECUTABLE_SUFFIX}" CACHE FILEPATH "Archiver" FORCE) +set(CMAKE_RANLIB "${PNACLSDK_PREFIX}/bin/${PNACL_TRIPLET}-ranlib${PNACL_EXECUTABLE_SUFFIX}") +set(PNACL_TRANSLATE "${PNACLSDK_PREFIX}/bin/${PNACL_TRIPLET}-translate${PNACL_EXECUTABLE_SUFFIX}") +set(CMAKE_STRIP "${PNACLSDK_PREFIX}/bin/${PNACL_TRIPLET}-strip${PNACL_EXECUTABLE_SUFFIX}") +set(CMAKE_FIND_ROOT_PATH "${PNACLSDK_PREFIX}/le32-nacl") + +set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 1) +set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES 1) +set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1) +set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1) +set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1) +set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@") +set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@") + +set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") +set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -DNDEBUG") +set(CMAKE_C_FLAGS_DEBUG_INIT "-g") + +set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "${CMAKE_C_FLAGS_MINSIZEREL_INIT}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "${CMAKE_C_FLAGS_DEBUG_INIT}") + +if (NOT CMAKE_HOST_WIN32) + find_package(Python) + + if (Python_Interpreter_FOUND) + set(PNACLPYTHON_PREFIX "env PNACLPYTHON=${Python_EXECUTABLE} ") + set(PNACLPYTHON_PREFIX2 env "PNACLPYTHON=${Python_EXECUTABLE} ") + message(STATUS "Using PNACL Python executable: ${Python_EXECUTABLE}") + else() + message(FATAL_ERROR "Please install python (and run in a python virtualenv if that's not enough).") + endif() +endif() + +# These commands can fail on windows if there is a space at the beginning +set(CMAKE_C_CREATE_STATIC_LIBRARY "${PNACLPYTHON_PREFIX} rc ") +set(CMAKE_CXX_CREATE_STATIC_LIBRARY "${PNACLPYTHON_PREFIX} rc ") + +set(CMAKE_C_COMPILE_OBJECT "${PNACLPYTHON_PREFIX} -o -c ") +set(CMAKE_CXX_COMPILE_OBJECT "${PNACLPYTHON_PREFIX} -o -c ") + +set(CMAKE_C_LINK_EXECUTABLE "${PNACLPYTHON_PREFIX} -o ") +set(CMAKE_CXX_LINK_EXECUTABLE "${PNACLPYTHON_PREFIX} -o ") + +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) + +set(NACL ON) + +set(CMAKE_C_FLAGS "") +set(CMAKE_CXX_FLAGS "") diff --git a/cmake/cross-toolchain-saigo-amd64.cmake b/cmake/cross-toolchain-saigo-amd64.cmake new file mode 100644 index 0000000000..c755d9b2b1 --- /dev/null +++ b/cmake/cross-toolchain-saigo-amd64.cmake @@ -0,0 +1,28 @@ +# Daemon BSD Source Code +# Copyright (c) 2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set(SAIGO_ARCH "x86_64") +include("${CMAKE_CURRENT_LIST_DIR}/cross-toolchain-saigo-common.cmake") diff --git a/cmake/cross-toolchain-saigo-armhf.cmake b/cmake/cross-toolchain-saigo-armhf.cmake new file mode 100644 index 0000000000..7197c47049 --- /dev/null +++ b/cmake/cross-toolchain-saigo-armhf.cmake @@ -0,0 +1,28 @@ +# Daemon BSD Source Code +# Copyright (c) 2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set(SAIGO_ARCH "arm") +include("${CMAKE_CURRENT_LIST_DIR}/cross-toolchain-saigo-common.cmake") diff --git a/cmake/cross-toolchain-saigo-common.cmake b/cmake/cross-toolchain-saigo-common.cmake new file mode 100644 index 0000000000..0c7a928e40 --- /dev/null +++ b/cmake/cross-toolchain-saigo-common.cmake @@ -0,0 +1,79 @@ +# Daemon BSD Source Code +# Copyright (c) 2023-2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# We can't use CMAKE_EXECUTABLE_SUFFIX because the Generic Platform will reset it +# and creating a Platform module for setting CMAKE_EXECUTABLE_SUFFIX is overkill. +set(NACL_EXECUTABLE_SUFFIX ".nexe") + +set(SAIGO_TRIPLET "${SAIGO_ARCH}-nacl") + +if ("${SAIGOSDK_PREFIX}" STREQUAL "") + find_program(PATH_SAIGO_CLANG NAMES "${SAIGO_TRIPLET}-clang") + get_filename_component(SAIGOSDK_PREFIX ${PATH_SAIGO_CLANG} DIRECTORY) +endif() + +list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES SAIGOSDK_PREFIX) + +set(CMAKE_SYSTEM_NAME "Generic") + +set(CMAKE_C_COMPILER "${SAIGOSDK_PREFIX}/bin/${SAIGO_TRIPLET}-clang") +set(CMAKE_CXX_COMPILER "${SAIGOSDK_PREFIX}/bin/${SAIGO_TRIPLET}-clang++") +set(CMAKE_AR "${SAIGOSDK_PREFIX}/bin/${SAIGO_TRIPLET}-ar" CACHE FILEPATH "Archiver" FORCE) +set(CMAKE_RANLIB "${SAIGOSDK_PREFIX}/bin/${SAIGO_TRIPLET}-ranlib") +set(CMAKE_STRIP "${SAIGOSDK_PREFIX}/bin/${SAIGO_TRIPLET}-strip") +set(CMAKE_FIND_ROOT_PATH "${SAIGOSDK_PREFIX}/${SAIGO_TRIPLET}") + +# Copy-pasted from the PNaCl toolchain, it's not sure we need it. +set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 1) +set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES 1) +set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1) +set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1) +set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1) +set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@") +set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@") + +# Copy-pasted from the PNaCl toolchain, it's not sure we need it. +# These commands can fail on windows if there is a space at the beginning +set(CMAKE_C_CREATE_STATIC_LIBRARY " rc ") +set(CMAKE_CXX_CREATE_STATIC_LIBRARY " rc ") + +set(CMAKE_C_COMPILE_OBJECT " -o -c ") +set(CMAKE_CXX_COMPILE_OBJECT " -o -c ") + +set(CMAKE_C_LINK_EXECUTABLE " -o ") +set(CMAKE_CXX_LINK_EXECUTABLE " -o ") + +# Copy-pasted from the PNaCl toolchain, it's not sure we need it. +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) + +set(NACL ON) + +set(CMAKE_C_FLAGS "") +set(CMAKE_CXX_FLAGS "") diff --git a/cmake/cross-toolchain-saigo-i686.cmake b/cmake/cross-toolchain-saigo-i686.cmake new file mode 100644 index 0000000000..1bd9b1f0c5 --- /dev/null +++ b/cmake/cross-toolchain-saigo-i686.cmake @@ -0,0 +1,39 @@ +# Daemon BSD Source Code +# Copyright (c) 2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set(SAIGO_ARCH "i686") +include("${CMAKE_CURRENT_LIST_DIR}/cross-toolchain-saigo-common.cmake") + +if (EXISTS "${SAIGOSDK_PREFIX}/x86_64-nacl/lib32") + # This will search libraries in paths in this order: + # - i686-nacl/lib + # - x86_64-nacl/lib32 + # - x86_64-nacl/lib + # The last path is wrong but is not used when the lib is found before, + # so it is meant to work on well-formed SDK installations. + list(APPEND CMAKE_FIND_ROOT_PATH "${SAIGOSDK_PREFIX}/x86_64-nacl") + set(CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX "32") +endif() diff --git a/cmake/toolchain-pnacl.cmake b/cmake/toolchain-pnacl.cmake deleted file mode 100644 index b19f61e8ec..0000000000 --- a/cmake/toolchain-pnacl.cmake +++ /dev/null @@ -1,151 +0,0 @@ -# Daemon BSD Source Code -# Copyright (c) 2013-2016, Daemon Developers -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Daemon developers nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set(PLATFORM_PREFIX ${DEPS_DIR}/pnacl/bin) -set(PLATFORM_TRIPLET "pnacl") - -if (WIN32) - set(PNACL_BIN_EXT ".bat") -else() - set(PNACL_BIN_EXT "") -endif() - -set(PLATFORM_EXE_SUFFIX ".pexe") - -set(CMAKE_SYSTEM_NAME "Generic") - -set(CMAKE_C_COMPILER "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-clang${PNACL_BIN_EXT}") -set(CMAKE_CXX_COMPILER "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-clang++${PNACL_BIN_EXT}") -set(CMAKE_AR "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-ar${PNACL_BIN_EXT}" CACHE FILEPATH "Archiver" FORCE) -set(CMAKE_RANLIB "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-ranlib${PNACL_BIN_EXT}") -set(PNACL_TRANSLATE "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-translate${PNACL_BIN_EXT}") -set(PNACL_STRIP "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-strip${PNACL_BIN_EXT}") -set(CMAKE_FIND_ROOT_PATH "${PLATFORM_PREFIX}/../le32-nacl") - -set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 1) -set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES 1) -set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1) -set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1) -set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1) -set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@") -set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@") - -set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") -set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") -set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -DNDEBUG") -set(CMAKE_C_FLAGS_DEBUG_INIT "-g") - -set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "${CMAKE_C_FLAGS_MINSIZEREL_INIT}") -set(CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT}") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}") -set(CMAKE_CXX_FLAGS_DEBUG_INIT "${CMAKE_C_FLAGS_DEBUG_INIT}") - -if (NOT CMAKE_HOST_WIN32) - find_package(Python) - - if (Python_Interpreter_FOUND) - set(PNACLPYTHON_PREFIX "env PNACLPYTHON=${Python_EXECUTABLE} ") - set(PNACLPYTHON_PREFIX2 env "PNACLPYTHON=${Python_EXECUTABLE} ") - message(STATUS "Using PNACL Python executable: ${Python_EXECUTABLE}") - else() - message(FATAL_ERROR "Please install python (and run in a python virtualenv if that's not enough).") - endif() -endif() - -# These commands can fail on windows if there is a space at the beginning -set(CMAKE_C_CREATE_STATIC_LIBRARY "${PNACLPYTHON_PREFIX} rc ") -set(CMAKE_CXX_CREATE_STATIC_LIBRARY "${PNACLPYTHON_PREFIX} rc ") - -set(CMAKE_C_COMPILE_OBJECT "${PNACLPYTHON_PREFIX} -o -c ") -set(CMAKE_CXX_COMPILE_OBJECT "${PNACLPYTHON_PREFIX} -o -c ") - -set(CMAKE_C_LINK_EXECUTABLE "${PNACLPYTHON_PREFIX} -o ") -set(CMAKE_CXX_LINK_EXECUTABLE "${PNACLPYTHON_PREFIX} -o ") - -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) - -set(NACL ON) - -set(CMAKE_C_FLAGS "") -set(CMAKE_CXX_FLAGS "") - -function(pnacl_finalize dir module arch) - include(DaemonBuildTypeGeneratorExpression) - - set(PNACL_TRANSLATE_OPTIONS - --allow-llvm-bitcode-input # FIXME: finalize as part of the build process - --pnacl-allow-exceptions - $<${RELEASE_GENEXP_COND}:-O3> - $<${DEBUG_GENEXP_COND}:-O0> - $<${RELWITHDEBINFO_GENEXP_COND}:-O2> - $<${MINSIZEREL_GENEXP_COND}:-O2> - ) - set(PEXE ${dir}/${module}.pexe) - set(NEXE ${dir}/${module}-${arch}.nexe) - set(STRIPPED_NEXE ${dir}/${module}-${arch}-stripped.nexe) - - if (arch STREQUAL "i686") - set(PNACL_ARCH "i686") - elseif (arch STREQUAL "amd64") - set(PNACL_ARCH "x86-64") - elseif (arch STREQUAL "armhf") - set(PNACL_ARCH "arm") - else() - message(FATAL_ERROR "Unknown NaCl architecture ${arch}") - endif() - - add_custom_command( - OUTPUT ${NEXE} - COMMENT "Translating ${module} (${arch})" - DEPENDS ${PEXE} - COMMAND - ${PNACLPYTHON_PREFIX2} - "${PNACL_TRANSLATE}" - ${PNACL_TRANSLATE_OPTIONS} - -arch ${PNACL_ARCH} - ${PEXE} - -o ${NEXE} - ) - - add_custom_command( - OUTPUT ${STRIPPED_NEXE} - COMMENT "Stripping ${module} (${arch})" - DEPENDS ${NEXE} - COMMAND - ${PNACLPYTHON_PREFIX2} - "${PNACL_STRIP}" - -s - ${NEXE} - -o ${STRIPPED_NEXE} - ) - - add_custom_target(${module}-${arch} ALL DEPENDS ${STRIPPED_NEXE}) - add_dependencies(${module}-${arch} ${module}-nacl) -endfunction() diff --git a/cmake/toolchain-saigo.cmake b/cmake/toolchain-saigo.cmake deleted file mode 100644 index 75374527b3..0000000000 --- a/cmake/toolchain-saigo.cmake +++ /dev/null @@ -1,75 +0,0 @@ -set(PLATFORM_PREFIX "${DEPS_DIR}/saigo_newlib/bin") -set(PLATFORM_TRIPLET "${SAIGO_ARCH}-nacl") -set(PLATFORM_EXE_SUFFIX ".nexe") - -set(CMAKE_SYSTEM_NAME "Generic") - -set(CMAKE_C_COMPILER "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-clang") -set(CMAKE_CXX_COMPILER "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-clang++") -set(CMAKE_AR "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-ar" CACHE FILEPATH "Archiver" FORCE) -set(CMAKE_RANLIB "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-ranlib") -set(SAIGO_STRIP "${PLATFORM_PREFIX}/${PLATFORM_TRIPLET}-strip") -set(CMAKE_FIND_ROOT_PATH "${PLATFORM_PREFIX}/../${PLATFORM_TRIPLET}") - -# Copy-pasted from the PNaCl toolchain, it's not sure we need it. -set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 1) -set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES 1) -set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1) -set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1) -set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1) -set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@") -set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@") - -# Copy-pasted from the PNaCl toolchain, it's not sure we need it. -# These commands can fail on windows if there is a space at the beginning -set(CMAKE_C_CREATE_STATIC_LIBRARY " rc ") -set(CMAKE_CXX_CREATE_STATIC_LIBRARY " rc ") - -set(CMAKE_C_COMPILE_OBJECT " -o -c ") -set(CMAKE_CXX_COMPILE_OBJECT " -o -c ") - -set(CMAKE_C_LINK_EXECUTABLE " -o ") -set(CMAKE_CXX_LINK_EXECUTABLE " -o ") - -# Copy-pasted from the PNaCl toolchain, it's not sure we need it. -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) - -set(NACL ON) - -set(CMAKE_C_FLAGS "") -set(CMAKE_CXX_FLAGS "") - -function(saigo_finalize dir module arch) - set(SUBPROJECT_NEXE ${dir}/nacl-vms-${arch}/${module}.nexe) - set(NEXE ${dir}/${module}-${arch}.nexe) - set(STRIPPED_NEXE ${dir}/${module}-${arch}-stripped.nexe) - - add_custom_command( - OUTPUT ${NEXE} - COMMENT "Copying ${module} (${arch})" - DEPENDS ${SUBPROJECT_NEXE} - COMMAND - ${CMAKE_COMMAND} - -E copy - ${SUBPROJECT_NEXE} - ${NEXE} - ) - - add_custom_command( - OUTPUT ${STRIPPED_NEXE} - COMMENT "Stripping ${module} (${arch})" - DEPENDS ${NEXE} - COMMAND - "${SAIGO_STRIP}" - -s - ${NEXE} - -o ${STRIPPED_NEXE} - ) - - add_custom_target(${module}-${arch} ALL DEPENDS ${STRIPPED_NEXE}) - add_dependencies(${module}-${arch} ${module}-nacl) -endfunction() From 3d6d7a3bb90353ea30df6818b4e1488f2e3ccf12 Mon Sep 17 00:00:00 2001 From: slipher Date: Thu, 30 Jul 2026 10:16:01 -0500 Subject: [PATCH 08/15] Refactor: function for Linux arm64 check for VM Co-authored-by: Thomas Debesse --- src/engine/framework/VirtualMachine.cpp | 29 +++++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/engine/framework/VirtualMachine.cpp b/src/engine/framework/VirtualMachine.cpp index 8ddab6486f..c8445dff27 100644 --- a/src/engine/framework/VirtualMachine.cpp +++ b/src/engine/framework/VirtualMachine.cpp @@ -226,6 +226,22 @@ static void CheckMinAddressSysctlTooLarge() #endif // __linux__ } +#if defined(DAEMON_NACL_RUNTIME_LINUX) && (defined(YOKAI_ARCH_ARM64) || defined(YOKAI_ARCH_ARMHF)) +static bool OnArm64() +{ +#if defined(YOKAI_ARCH_ARM64) + return true; +#elif defined(YOKAI_ARCH_ARMHF) + struct utsname buf; + if (!uname(&buf)) { + return !strcmp(buf.machine, "aarch64"); + } + + return false; +#endif // defined(YOKAI_ARCH_ARMHF) +} +#endif + // Platform-specific code to load a module static std::pair InternalLoadModule(std::pair pair, const char* const* args, bool reserve_mem, FS::File stderrRedirect = FS::File(), bool inheritEnvironment = false) { @@ -630,17 +646,6 @@ static std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair Date: Thu, 30 Jul 2026 11:28:20 -0500 Subject: [PATCH 09/15] Get rid of nacl_multiarch executable Set up the chdir and environment variable in posix_spawn. Fixes #1336. Co-authored-by: Thomas Debesse --- CMakeLists.txt | 8 +-- cmake/DaemonNaclArchitecture.cmake | 2 - src/engine/framework/VirtualMachine.cpp | 35 ++++--------- tools/nacl_multiarch/nacl_multiarch.cpp | 68 ------------------------- 4 files changed, 12 insertions(+), 101 deletions(-) delete mode 100644 tools/nacl_multiarch/nacl_multiarch.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f012339cb3..83ccdbfe1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1000,15 +1000,9 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER # Linux uses a bootstrap program to reserve address space if (YOKAI_TARGET_SYSTEM_LINUX_COMPATIBILITY) if (DAEMON_NACL_MULTIARCH) - add_executable(nacl_multiarch-${DAEMON_NACL_ARCH_NAME} - tools/nacl_multiarch/nacl_multiarch.cpp - ${BUILDINFOLIST} - ) - add_dependencies(runtime_deps nacl_multiarch-${DAEMON_NACL_ARCH_NAME}) - add_custom_command(TARGET runtime_deps PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory - ${DEPS_DIR}/linux-${DAEMON_NACL_ARCH_NAME} + ${DEPS_DIR}/libs-${DAEMON_NACL_ARCH_NAME} ${FULL_OUTPUT_DIR}/libs-linux-${DAEMON_NACL_ARCH_NAME} ) endif() diff --git a/cmake/DaemonNaclArchitecture.cmake b/cmake/DaemonNaclArchitecture.cmake index e0666c193b..f23685f86f 100644 --- a/cmake/DaemonNaclArchitecture.cmake +++ b/cmake/DaemonNaclArchitecture.cmake @@ -49,8 +49,6 @@ function(daemon_detect_nacl_arch target_arch) set(box64_usage "ppc64el" "riscv64" "loong64") if ("${target_arch}" IN_LIST armhf_usage) - set(DAEMON_NACL_MULTIARCH ON) - # Load 32-bit armhf nexe on 64-bit arm64 engine on Linux with multiarch. # The nexe is system agnostic so there should be no difference with armel. add_nacl_arch("armhf") diff --git a/src/engine/framework/VirtualMachine.cpp b/src/engine/framework/VirtualMachine.cpp index c8445dff27..6508acc659 100644 --- a/src/engine/framework/VirtualMachine.cpp +++ b/src/engine/framework/VirtualMachine.cpp @@ -183,15 +183,6 @@ static Cvar::Cvar vm_nacl_qualification( Cvar::INIT, true); #endif // defined(DAEMON_NACL_RUNTIME_ENABLED) -#if defined(DAEMON_NACL_RUNTIME_ENABLED) -#if defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) -static Cvar::Cvar vm_nacl_multiarch( - "vm.nacl.multiarch", - "Use multiarch to run the NaCl loader when needed and available", - Cvar::INIT, true); -#endif // defined(DAEMON_NACL_RUNTIME_LINUX) && defined(YOKAI_ARCH_ARM64) -#endif // defined(DAEMON_NACL_RUNTIME_ENABLED) - #if defined(DAEMON_NACL_BOOSTRAP_ENABLED) static Cvar::Cvar vm_nacl_bootstrap( "vm.nacl.bootstrap", @@ -349,11 +340,20 @@ static std::pair InternalLoadModule(std::pair("LD_LIBRARY_PATH=lib-armhf"); + + if (0 != posix_spawn_file_actions_addchdir_np(&fileActions, FS::GetLibPath().c_str())) { + Sys::Error("failed posix_spawn_file_actions_addchdir"); + } + } +#endif // By default, the child process gets an empty environment for sandboxing. // When Box64 emulation is used, the child needs to inherit the parent's // environment so Box64 can find its configuration (e.g. ~/.box64rc, HOME) // and honor settings like BOX64_DYNAREC_PERFMAP. - char* emptyEnv[] = {nullptr}; char** envp = inheritEnvironment ? environ : emptyEnv; int err = posix_spawn(&pid, args[0], &fileActions, nullptr, const_cast(args), envp); posix_spawn_file_actions_destroy(&fileActions); @@ -470,13 +470,10 @@ static std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair -#include -#include -#include -#include -#include - -#include "YokaiBuildInfo/DaemonEngine.h" - -int main(int argc, char *argv[]) { - if (argc < 2) { - printf("nacl_multiarch-%s: missing command line\n", DAEMON_NACL_ARCH_STRING); - return 1; - } - - char *directory = dirname(strdup(argv[0])); - - int err = chdir(directory); - - if (err != 0) { - return err; - } - - char env[100]; - sprintf(env, "LD_LIBRARY_PATH=libs-linux-%s", DAEMON_NACL_ARCH_STRING); - - err = putenv(strdup(env)); - - if (err != 0) { - return err; - } - - execv(argv[1], &argv[1]); - - // The execv() function returns only if an error has occurred. - printf("nacl_multiarch-%s: %s\n", DAEMON_NACL_ARCH_STRING, strerror(errno)); - return 1; -} From c1514edbd2d6e08182ac0af63b1be1536464f805 Mon Sep 17 00:00:00 2001 From: slipher Date: Mon, 7 Sep 2026 01:53:26 -0500 Subject: [PATCH 10/15] Don't use nacl_helper_bootstrap with x86-64 loader Remove cvars controlling whether the Linux bootstrap loader is used. Never use bootstrap with the amd64 loader. Always use bootstrap with 32-bit loaders. Co-authored-by: Thomas Debesse --- CMakeLists.txt | 14 +++++++----- src/engine/framework/VirtualMachine.cpp | 30 ++++--------------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 83ccdbfe1f..62996c75a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -997,7 +997,6 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER ) endforeach() - # Linux uses a bootstrap program to reserve address space if (YOKAI_TARGET_SYSTEM_LINUX_COMPATIBILITY) if (DAEMON_NACL_MULTIARCH) add_custom_command(TARGET runtime_deps PRE_BUILD @@ -1007,12 +1006,15 @@ if (DEPS_DIR AND HAS_NACL AND (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER ) endif() + # Linux uses a bootstrap program to reserve address space for 32-bit runtimes. foreach(arch_name IN LISTS DAEMON_NACL_ARCH_NAME_LIST) - add_custom_command(TARGET runtime_deps PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${DEPS_DIR}/nacl_helper_bootstrap - ${FULL_OUTPUT_DIR}/nacl_helper_bootstrap-${arch_name} - ) + if ("${arch_name}" IN_LIST "i686;armhf") + add_custom_command(TARGET runtime_deps PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${DEPS_DIR}/nacl_helper_bootstrap + ${FULL_OUTPUT_DIR}/nacl_helper_bootstrap-${arch_name} + ) + endif() endforeach() endif() diff --git a/src/engine/framework/VirtualMachine.cpp b/src/engine/framework/VirtualMachine.cpp index 6508acc659..456e492401 100644 --- a/src/engine/framework/VirtualMachine.cpp +++ b/src/engine/framework/VirtualMachine.cpp @@ -79,7 +79,9 @@ static Cvar::Cvar workaround_naclSystem_freebsd_disableQualification( // Many BSDs have a Linuxulator, for now we only tested one. #if defined(__linux__) || defined(__FreeBSD__) #define DAEMON_NACL_RUNTIME_LINUX +#if YOKAI_ARCH_I686 || YOKAI_ARCH_ARM64 || YOKAI_ARCH_ARMHF #define DAEMON_NACL_BOOSTRAP_ENABLED +#endif // !(YOKAI_ARCH_I686 || YOKAI_ARCH_ARM64 || YOKAI_ARCH_ARMHF) #endif // defined(__linux__) || defined(DAEMON_LINUXULATOR) #endif // defined(DAEMON_NACL_RUNTIME_ENABLED) @@ -90,11 +92,6 @@ static Cvar::Cvar workaround_box64_disableQualification( "Disable platform qualification when running amd64 NaCl loader under Box64 emulation", Cvar::NONE, true); -static Cvar::Cvar workaround_box64_disableBootstrap( - "workaround.box64.disableBootstrap", - "Disable NaCl bootstrap helper when using Box64 emulation", - Cvar::NONE, true); - static Cvar::Cvar vm_box64_path( "vm.box64.path", "Path to the box64 binary for NaCl emulation (empty = use provided one or search PATH if missing)", @@ -183,13 +180,6 @@ static Cvar::Cvar vm_nacl_qualification( Cvar::INIT, true); #endif // defined(DAEMON_NACL_RUNTIME_ENABLED) -#if defined(DAEMON_NACL_BOOSTRAP_ENABLED) -static Cvar::Cvar vm_nacl_bootstrap( - "vm.nacl.bootstrap", - "Use NaCl bootstrap helper", - Cvar::INIT, true); -#endif // defined(DAEMON_NACL_BOOSTRAP_ENABLED) - namespace VM { // https://github.com/Unvanquished/Unvanquished/issues/944#issuecomment-744454772 @@ -479,7 +469,7 @@ static std::pair CreateNaClVM(std::pair CreateNaClVM(std::pair Date: Mon, 7 Sep 2026 03:10:10 -0500 Subject: [PATCH 11/15] Windows: block NaCl process from inheriting environment When creating a NaCl (or native exe) VM on Windows, block evironment variables from being passed through to the subprocess as is done on *nix. Probably we do this since there are NACL* variables that can disable secure sandboxing. inheritEnvironment is always false on Windows, but I implemented the true case anyway since it's less code than having the Q_UNUSED and asserting it's false. --- src/engine/framework/VirtualMachine.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/engine/framework/VirtualMachine.cpp b/src/engine/framework/VirtualMachine.cpp index 456e492401..c416c2647d 100644 --- a/src/engine/framework/VirtualMachine.cpp +++ b/src/engine/framework/VirtualMachine.cpp @@ -288,8 +288,12 @@ static std::pair InternalLoadModule(std::pair InternalLoadModule(std::pair Date: Tue, 15 Sep 2026 06:45:37 -0500 Subject: [PATCH 12/15] Check mmap_min_addr only if using NaCl bootstrap Check the Linux sysctl vm.mmap_min_addr only when using the NaCl bootstrap (rather than always when using NaCl). Or equivalently, check it only with 32-bit NaCl runtimes. The bootstrap fails to start when the value is too high to due low fixed address mappings. On ARM at least, sel_ldr proper would also fail with a too-high min address since that disturbs the address space layout. On 64-bit there is neither the bootstrap nor 0-based address space layout so it always works. Co-authored-by: Thomas Debesse --- src/engine/framework/VirtualMachine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/framework/VirtualMachine.cpp b/src/engine/framework/VirtualMachine.cpp index c416c2647d..ee0a47e053 100644 --- a/src/engine/framework/VirtualMachine.cpp +++ b/src/engine/framework/VirtualMachine.cpp @@ -440,7 +440,6 @@ static ExeSupport CheckExeSupport(Str::StringRef probe) #if defined(DAEMON_NACL_RUNTIME_ENABLED) static std::pair CreateNaClVM(std::pair pair, Str::StringRef name, bool debug, bool extract, int debugLoader) { - CheckMinAddressSysctlTooLarge(); const std::string& libPath = FS::GetLibPath(); std::vector args; char rootSocketRedir[32]; @@ -572,6 +571,8 @@ static std::pair CreateNaClVM(std::pair Date: Sun, 11 Oct 2026 21:09:44 -0500 Subject: [PATCH 13/15] cmake: raise an error when the SDK prefix is not a directory Co-authored-by: Thomas Debesse --- cmake/DaemonGame.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/DaemonGame.cmake b/cmake/DaemonGame.cmake index 8a4cc2e4ff..3e79b0b96f 100644 --- a/cmake/DaemonGame.cmake +++ b/cmake/DaemonGame.cmake @@ -227,6 +227,10 @@ function(GAMEMODULE) if (BUILD_GAME_NACL AND NOT YOKAI_TARGET_SYSTEM_NACL) if (USE_NACL_SAIGO) + if (NOT IS_DIRECTORY "${SAIGOSDK_PREFIX}") + message(FATAL_ERROR "SAIGOSDK_PREFIX configured as '${SAIGOSDK_PREFIX}' which is not an existing directory") + endif() + add_custom_target(nacl-vms ALL) unset(NACL_VMS_PROJECTS) @@ -251,6 +255,10 @@ function(GAMEMODULE) ) endforeach() else() + if (NOT IS_DIRECTORY "${PNACL_SDK_PREFIX}") + message(FATAL_ERROR "PNACL_SDK_PREFIX configured as '${SAIGOSDK_PREFIX}' which is not an existing directory") + endif() + set(NACL_VMS_PROJECT nacl-vms) set(NACL_VMS_PROJECTS ${NACL_VMS_PROJECT}) From 7d85e4e25671c071ba6a5933a293652ff12a6032 Mon Sep 17 00:00:00 2001 From: slipher Date: Mon, 12 Oct 2026 02:29:55 -0500 Subject: [PATCH 14/15] Auto-download Saigo SDK for any supported host The old PNaCl toolchain has been being shipped as part of the deps package, with the host platform for the compilers assumed to be the same as the target platform of the deps package. Experimental Saigo support has thus far required manually downloading the SDK. Now, make the Saigo toolchain auto-downloadable (if USE_NACL_SAIGO=1) independently from the target platform dependencies. This has several advantages: - No need to download the NaCl toolchain if you are not building NaCl. - No need to download a useless NaCl toolchain when cross-compiling. - Toolchain can be downloaded for host systems that don't have a deps package, or where the deps package being used doesn't match the real host system. (The SDK is available for more systems than the deps package.) The toolchain is downloaded from Github and then, like the deps package, extracted into external_deps/. --- CMakeLists.txt | 17 +++--- cmake/DaemonDependenciesDownload.cmake | 72 ++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 cmake/DaemonDependenciesDownload.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 62996c75a7..6969189ab5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,8 +197,9 @@ else() set(FULL_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}) endif() -# Dependencies version, this must match the number in external_deps/build.sh -set(DEPS_VERSION 11) +# Dependencies versions +set(DEPS_VERSION 11) # This must match the number in external_deps/build.sh +set(SAIGOSDK_VERSION 20260925) option(USE_EXTERNAL_DEPS "Download or reuse dependencies from EXTERNAL_DEPS_DIR (mandatory for building and running NaCl .nexe binaries)." ON) @@ -273,11 +274,8 @@ endif() option(USE_EXTERNAL_DEPS_LIBS "Build and link against libraries from the EXTERNAL_DEPS_DIR" ${DEFAULT_USE_EXTERNAL_DEPS_LIBS}) -set(PNACLSDK_PREFIX "${DEPS_DIR}/pnacl" CACHE PATH "PNaCl SDK path") -mark_as_advanced(PNACLSDK_PREFIX) - -set(SAIGOSDK_PREFIX "${DEPS_DIR}/saigo_newlib" CACHE PATH "Saigo NaCl SDK path") -mark_as_advanced(SAIGOSDK_PREFIX) +set(PNACL_SDK_PREFIX "${DEPS_DIR}/pnacl" CACHE PATH "PNaCl SDK path") +mark_as_advanced(PNACL_SDK_PREFIX) if (USE_EXTERNAL_DEPS AND NOT YOKAI_TARGET_SYSTEM_NACL) if (DEPS_DIR) @@ -457,6 +455,11 @@ if (DEPS_DIR) endif() endif() + if (BUILD_GAME_NACL AND USE_NACL_SAIGO AND NOT SAIGOSDK_PREFIX) + include(DaemonDependenciesDownload) + download_saigosdk() + endif() + if (USE_EXTERNAL_DEPS_LIBS) # Add to paths set(CMAKE_FIND_ROOT_PATH ${DEPS_DIR} ${CMAKE_FIND_ROOT_PATH}) diff --git a/cmake/DaemonDependenciesDownload.cmake b/cmake/DaemonDependenciesDownload.cmake new file mode 100644 index 0000000000..a4bc08a4c4 --- /dev/null +++ b/cmake/DaemonDependenciesDownload.cmake @@ -0,0 +1,72 @@ +# Daemon BSD Source Code +# Copyright (c) 2013-2026, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Daemon developers nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# TODO: Move other deps downloading code in here. + +set(SAIGOSDK_BASENAME "saigosdk-${DEPS_SYSTEM}-${DEPS_ARCH}_${SAIGOSDK_VERSION}") + +# Warning: changing SAIGOSDK_PREFIX/SAIGOSDK_VERSION after subprojects have been configured WILL +# change the compiler, but it is a bad idea since flag tests and such (not to mention the actual +# compiled artifacts) will be out of date. +set(SAIGOSDK_PREFIX "${EXTERNAL_DEPS_DIR}/${SAIGOSDK_BASENAME}" CACHE PATH "PNaCl SDK path") +mark_as_advanced(SAIGOSDK_PREFIX) + +function(download_saigosdk) + if (NOT EXISTS "${SAIGOSDK_PREFIX}") + set(DEPS_FILENAME "${SAIGOSDK_BASENAME}.tar.xz") + set(REMOTE "https://github.com/DaemonEngine/saigo-nacl-sdk/releases/download/v${SAIGOSDK_VERSION}/${DEPS_FILENAME}") + message(STATUS "Downloading NaCl SDK from '${REMOTE}'") + + file(DOWNLOAD "${REMOTE}" "${OBJ_DIR}/${DEPS_FILENAME}" + SHOW_PROGRESS + STATUS DOWNLOAD_RESULT + LOG DOWNLOAD_LOG + ) + + list(GET DOWNLOAD_RESULT 0 DOWNLOAD_STATUS) + list(GET DOWNLOAD_RESULT 1 DOWNLOAD_STRING) + + if (NOT DOWNLOAD_STATUS EQUAL 0) + message(FATAL_ERROR "Failed to download '${REMOTE}': This may be a network error, or your system may be an unsupported host platform. + Status code: ${DOWNLOAD_STATUS} + Error string: ${DOWNLOAD_STRING} + Download log: ${DOWNLOAD_LOG}" + ) + endif() + + message(STATUS "SDK download completed successfully") + + # Extract the downloaded archive + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xJf ${OBJ_DIR}/${DEPS_FILENAME} + WORKING_DIRECTORY ${EXTERNAL_DEPS_DIR} + RESULT_VARIABLE EXTRACT_RESULT + ) + if (NOT EXTRACT_RESULT EQUAL 0) + message(FATAL_ERROR "Could not extract ${DEPS_FILENAME}") + endif() + endif() +endfunction() From 5027c53d07727102a50d18cf5e603133c518eae5 Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 13 Oct 2026 02:56:50 -0500 Subject: [PATCH 15/15] Add build script for Saigo SDK (host-mode deps) Add external_deps/sdk-build.sh which can be used as an alternative to auto-downloading Saigo. Like external_deps/build.sh, it builds the dependency package and installs it to the expected location. It is a thin wrapper around the saigo-nacl-sdk CMake build; if you need more control it is better to use CMake directly. --- .gitignore | 1 + CMakeLists.txt | 2 +- cmake/DaemonDependenciesDownload.cmake | 2 + external_deps/sdk-build.sh | 88 ++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100755 external_deps/sdk-build.sh diff --git a/.gitignore b/.gitignore index 00e20db8da..b753d1cf66 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ build #ignore external deps external_deps/* !external_deps/build.sh +!external_deps/sdk-build.sh !external_deps/cygtar.py !external_deps/*.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 6969189ab5..47797591c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ endif() # Dependencies versions set(DEPS_VERSION 11) # This must match the number in external_deps/build.sh -set(SAIGOSDK_VERSION 20260925) +set(SAIGOSDK_VERSION 20260925) # This must match the number in external_deps/sdk-build.sh option(USE_EXTERNAL_DEPS "Download or reuse dependencies from EXTERNAL_DEPS_DIR (mandatory for building and running NaCl .nexe binaries)." ON) diff --git a/cmake/DaemonDependenciesDownload.cmake b/cmake/DaemonDependenciesDownload.cmake index a4bc08a4c4..2313300d3e 100644 --- a/cmake/DaemonDependenciesDownload.cmake +++ b/cmake/DaemonDependenciesDownload.cmake @@ -34,6 +34,8 @@ set(SAIGOSDK_BASENAME "saigosdk-${DEPS_SYSTEM}-${DEPS_ARCH}_${SAIGOSDK_VERSION}" set(SAIGOSDK_PREFIX "${EXTERNAL_DEPS_DIR}/${SAIGOSDK_BASENAME}" CACHE PATH "PNaCl SDK path") mark_as_advanced(SAIGOSDK_PREFIX) +# As an alternative to downloading, external_deps/sdk-build.sh can be used, to build the host-mode +# dependencies and install them in the expected path. function(download_saigosdk) if (NOT EXISTS "${SAIGOSDK_PREFIX}") set(DEPS_FILENAME "${SAIGOSDK_BASENAME}.tar.xz") diff --git a/external_deps/sdk-build.sh b/external_deps/sdk-build.sh new file mode 100755 index 0000000000..e90e0ace1f --- /dev/null +++ b/external_deps/sdk-build.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +# Exit on undefined variable and error. +set -u -e -o pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +WORK_DIR="${PWD}" +DOWNLOAD_DIR="${WORK_DIR}/download_cache" + +# This should match the SAIGOSDK_VERSION in CMakeLists.txt. +# This is mostly to ensure the path the files end up at if you build deps yourself +# are the same as the ones when extracting from the downloaded packages. +SAIGOSDK_VERSION=20261013 +# Can be a tag like v${SAIGOSDK_VERSION}, or a full commit hash +SAIGOSDK_REF="v${SAIGOSDK_VERSION}" + +REPO_BASENAME=saigo-nacl-sdk +REPO_URL="https://github.com/DaemonEngine/${REPO_BASENAME}" +ARCHIVE_PATH="${DOWNLOAD_DIR}/saigosdk-${SAIGOSDK_REF}.tar.gz" + +usage() { + echo "Usage: $0 - (build | install | package | wipe)..." + echo "- should normally be your current native platform." + echo "For a list of supported platforms see ${REPO_URL}/tree/master/tools/release/conf" + echo "Actions:" + echo " build - build all tools and libraries in the SDK" + echo " install - install final build products to ${WORK_DIR}/saigosdk--_${SAIGOSDK_VERSION}/" + echo " wipe - delete build products (except download cache) AND install directory" + echo "If you want to build only a subset of packages, prefer using the" + echo "${REPO_URL} CMake build directly." + echo "Some global configuration options are available via environment" + echo "variables; see ${REPO_URL}/tree/master/tools/release/build" +} + +download() { + test -f "${ARCHIVE_PATH}" && return + mkdir -p "${DOWNLOAD_DIR}" + curl --fail -L "${DOWNLOAD_URL}" -o "${ARCHIVE_PATH}" +} + +if [ "$#" -lt 2 ] +then + usage + exit 1 +fi + +PLATFORM="$1" +shift + +if grep -q -E '^[0-9a-f]{40}$' <<< "${SAIGOSDK_REF}" +then + DOWNLOAD_URL="https://github.com/DaemonEngine/saigo-nacl-sdk/archive/${SAIGOSDK_REF}.tar.gz" + TARBALL_OUTER_DIR="${REPO_BASENAME}-${SAIGOSDK_REF}" +elif grep -q -E '^v[0-9]' <<< "${SAIGOSDK_REF}" +then + # The 'v' from the tag name is mysteriously removed??? + TARBALL_OUTER_DIR="${REPO_BASENAME}-${SAIGOSDK_REF:1}" + DOWNLOAD_URL="https://github.com/DaemonEngine/saigo-nacl-sdk/archive/refs/tags/${SAIGOSDK_REF}.tar.gz" +fi + +INSTALL_DIR="${WORK_DIR}/saigosdk-${PLATFORM}_${SAIGOSDK_VERSION}" +BUILD_DIR="${WORK_DIR}/build-saigosdk_${SAIGOSDK_VERSION}" +REPO_DIR="${BUILD_DIR}/${TARBALL_OUTER_DIR}" + +for target in "$@" +do + case "${target}" in + build) + download + mkdir -p "${BUILD_DIR}" + tar xzf "${ARCHIVE_PATH}" -C "${BUILD_DIR}" + ( + cd "${REPO_DIR}" + tools/release/build "${PLATFORM}" + ) + ;; + install) + cp -R "${REPO_DIR}/build/${PLATFORM}/install/." "${INSTALL_DIR}/" + ;; + wipe) + rm -rf "${BUILD_DIR}" "${INSTALL_DIR}" + ;; + *) + usage + exit 1 + ;; + esac +done