From cf0c9479deedcbfc0592ac6d207b22ebf3655567 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 27 Jun 2023 02:27:44 +0200 Subject: Add --cpu=baseline|native option, propagate sanitize setting to sub projects --- backend/BackendUtils.cpp | 2 ++ backend/ninja/Ninja.cpp | 42 ++++++++++++++++++++++++++++++++++++++- include/Conf.hpp | 8 ++++++++ src/CmakeModule.cpp | 13 ++++++++++++ src/GlobalLib.cpp | 1 + src/main.cpp | 51 ++++++++++++++++++++++++++++++++++++------------ 6 files changed, 103 insertions(+), 14 deletions(-) diff --git a/backend/BackendUtils.cpp b/backend/BackendUtils.cpp index caeea3c..1109bf1 100644 --- a/backend/BackendUtils.cpp +++ b/backend/BackendUtils.cpp @@ -113,6 +113,8 @@ namespace backend backend::Ninja *subProject = new backend::Ninja(); SibsConfig *subProjectConfig = new SibsConfig(sibsConfig.getCompiler(), file->path, sibsConfig.getOptimizationLevel(), false); + subProjectConfig->setSanitize(sibsConfig.getSanitize()); + subProjectConfig->cpu = sibsConfig.cpu; subProjectConfig->packaging = sibsConfig.packaging; subProjectConfig->platform = sibsConfig.platform; subProjectConfig->bundling = sibsConfig.bundling; diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index c66907c..802ffd8 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -379,6 +379,37 @@ namespace backend return {}; } + static ninja::NinjaArg getCompilerCpuFlag(const SibsConfig &config) + { + // TODO: Also use -mcpu=native on non x86 systems + switch(config.getCompiler()) { + case Compiler::GCC: + case Compiler::MINGW_W64: { + switch(config.cpu) { + case sibs::CPU_INVALID: + case sibs::CPU_BASELINE: + return {}; + case sibs::CPU_NATIVE: + return ninja::NinjaArg::createRaw("-march=native"); + } + break; + } + case Compiler::MSVC: { + // msvc doesn't have any equivalent to gcc -march=native. + // TODO: Detect features at runtime here to manually add the cpu feature flags instead + switch(config.cpu) { + case sibs::CPU_INVALID: + case sibs::CPU_BASELINE: + return {}; + case sibs::CPU_NATIVE: + return ninja::NinjaArg::createRaw("-march=native"); + } + break; + } + } + return {}; + } + static vector getCompilerOptimizationFlags(const SibsConfig &config) { switch (config.getCompiler()) @@ -1017,6 +1048,10 @@ namespace backend allLinkerFlags += " " + optFlag.arg; } + ninja::NinjaArg cpuFlag = getCompilerCpuFlag(config); + if(cpuFlag.type != ninja::NinjaArg::Type::NONE) + compileCCommand.push_back(std::move(cpuFlag)); + ninja::NinjaArg sanitizerFlag = getCompilerSanitizerFlag(config); if(sanitizerFlag.type != ninja::NinjaArg::Type::NONE) compileCCommand.push_back(std::move(sanitizerFlag)); @@ -1075,6 +1110,10 @@ namespace backend allLinkerFlags += " " + optFlag.arg; } + ninja::NinjaArg cpuFlag = getCompilerCpuFlag(config); + if(cpuFlag.type != ninja::NinjaArg::Type::NONE) + compileCCommand.push_back(std::move(cpuFlag)); + ninja::NinjaArg sanitizerFlag = getCompilerSanitizerFlag(config); if(sanitizerFlag.type != ninja::NinjaArg::Type::NONE) compileCCommand.push_back(std::move(sanitizerFlag)); @@ -1764,7 +1803,8 @@ namespace backend SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative.data, config.getOptimizationLevel()); sibsTestConfig.platform = config.platform; sibsTestConfig.setSanitize(config.getSanitize()); - sibsTestConfig.zigTestFiles = move(config.zigTestFiles); + sibsTestConfig.cpu = config.cpu; + sibsTestConfig.zigTestFiles = config.zigTestFiles; sibsTestConfig.zigTestAllFiles = config.zigTestAllFiles; sibsTestConfig.cVersion = config.cVersion; sibsTestConfig.cppVersion = config.cppVersion; diff --git a/include/Conf.hpp b/include/Conf.hpp index 54c6b89..13fadcf 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -16,6 +16,13 @@ namespace sibs { + enum CPU + { + CPU_INVALID, + CPU_BASELINE, + CPU_NATIVE + }; + class ConfigValue { public: @@ -432,6 +439,7 @@ namespace sibs std::string versionStr; PackageVersion version; Platform platform; + CPU cpu = CPU_NATIVE; bool use_lto; bool include_debug_symbols_in_release; std::vector includeDirs; diff --git a/src/CmakeModule.cpp b/src/CmakeModule.cpp index 063cced..62aaf34 100644 --- a/src/CmakeModule.cpp +++ b/src/CmakeModule.cpp @@ -200,6 +200,19 @@ namespace sibs FileString cflags = TINYDIR_STRING("-fPIC"); FileString cxxflags; + // TODO: msvc + if(config.getCompiler() == Compiler::GCC || config.getCompiler() == Compiler::MINGW_W64) + { + switch(config.cpu) { + case sibs::CPU_INVALID: + case sibs::CPU_BASELINE: + break; + case sibs::CPU_NATIVE: + cflags += TINYDIR_STRING(" -march=native"); + break; + } + } + if(config.getCompiler() == Compiler::GCC || config.getCompiler() == Compiler::MINGW_W64) { cflags += TINYDIR_STRING(" -fno-omit-frame-pointer"); diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp index dc45e23..94145c1 100644 --- a/src/GlobalLib.cpp +++ b/src/GlobalLib.cpp @@ -157,6 +157,7 @@ namespace sibs sibsConfig.packaging = parentConfig.packaging; sibsConfig.bundling = parentConfig.bundling; sibsConfig.setSanitize(parentConfig.getSanitize()); + sibsConfig.cpu = parentConfig.cpu; sibsConfig.linker = parentConfig.linker; sibsConfig.use_lto = parentConfig.use_lto; sibsConfig.skipCompile = parentConfig.skipCompile; diff --git a/src/main.cpp b/src/main.cpp index aa06549..0e216b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,16 +129,17 @@ static void usage() static void usageBuild(bool run) { - printf("Usage: sibs %s [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--linker=lld|gold|mold] [--platform ]\n\n", run ? "run" : "build"); + printf("Usage: sibs %s [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--linker=lld|gold|mold] [--platform=] [--cpu=cpu]\n\n", run ? "run" : "build"); printf("%s a sibs project\n\n", run ? "Build and run" : "Build"); printf("Options:\n"); printf(" project_path The directory containing a project.conf file - Optional (default: current directory)\n"); printf(" --debug|--release Optimization level to build project and dependencies with (if not a system package) - Optional (default: --debug)\n"); printf(" --sanitize=option Add runtime address/undefined behavior sanitization. Program can be up to 3 times slower and use 10 times as much RAM. Ignored if compiler doesn't support sanitization - Optional (default: none)\n"); - printf(" --platform The platform to build for - Optional (default: the running platform)\n"); + printf(" --platform=platform The platform to build for. Run \"sibs platforms\" to see a list of supported platforms - Optional (default: the running platform)\n"); printf(" --lto Use link-time optimization. May increase compile times - Optional (default: not used)\n"); printf(" --debug-symbols Include debug symbols in release mode - Optional (default: not used)\n"); printf(" --linker=linker The linker to use. \"lld\", \"gold\" or \"mold\". \"gold\" - Optional (the compile automatically chooses best option)\n"); + printf(" --cpu=cpu The cpu to target. Should either be \"baseline\" or \"native\". \"baseline\" means to compile the binary to support a wide range of cpu's in the same architecture while \"native\" means to compile the binary specifically for your cpu, for better performance - Optional (default: native)\n"); if(run) { printf(" --args A list of arguments to run the program with\n"); } else { @@ -173,7 +174,7 @@ static void usageNew() static void usageTest() { - printf("Usage: sibs test [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--linker=lld|gold|mold] [--file ...|--all-files]\n\n"); + printf("Usage: sibs test [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--linker=lld|gold|mold] [--platform=] [--cpu=cpu] [--file ...|--all-files]\n\n"); printf("Build and run tests for a sibs project\n\n"); printf("Options:\n"); printf(" project_path The directory containing a project.conf file - Optional (default: current directory)\n"); @@ -182,7 +183,9 @@ static void usageTest() printf(" --sanitize=option Add runtime address/undefined behavior sanitization. Program can be up to 3 times slower and use 10 times as much RAM. Ignored if compiler doesn't support sanitization - Optional (default: none)\n"); printf(" --file Specify file to test, path to test file should be defined after this. Can be defined multiple times to test multiple files - Optional (default: not used), Only applicable for Zig\n"); printf(" --all-files Test all files - Optional (default: not used), Only applicable for Zig\n"); + printf(" --platform=platform The platform to build for. Run \"sibs platforms\" to see a list of supported platforms - Optional (default: the running platform)\n"); printf(" --linker=linker The linker to use. \"lld\", \"gold\" or \"mold\". \"gold\" - Optional (the compile automatically chooses best option)\n"); + printf(" --cpu=cpu The cpu to target. Should either be \"baseline\" or \"native\". \"baseline\" means to compile the binary to support a wide range of cpu's in the same architecture while \"native\" means to compile the binary specifically for your cpu, for better performance - Optional (default: native)\n"); printf(" --skip-compile Skip compilation. This can be used to generate a compile_commands.json file without compiling. Note that the compile_commands.json can miss files that are generated when this option is used. This option also skips running the tests\n"); printf(" --args A list of arguments to run the program with\n"); printf("Examples:\n"); @@ -503,6 +506,15 @@ static Sanitize sanitize_string_to_type(const _tinydir_char_t *str) { return SANITIZE_INVALID; } +static CPU getCpuByName(const std::string &cpuName) { + if(cpuName == "baseline") + return CPU_BASELINE; + else if(cpuName == "native") + return CPU_NATIVE; + else + return CPU_INVALID; +} + static int buildProject(int argc, const _tinydir_char_t **argv, bool run) { OptimizationLevel optimizationLevel = OPT_LEV_NONE; @@ -510,6 +522,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv, bool run) Sanitize sanitize = Sanitize::NONE; std::string linker; FileString platformName; + std::string cpuName; bool use_lto = false; bool include_debug_symbols_in_release = false; bool skipCompile = false; @@ -569,23 +582,23 @@ static int buildProject(int argc, const _tinydir_char_t **argv, bool run) { skipCompile = true; } - else if(_tinydir_strcmp(arg, TINYDIR_STRING("--platform")) == 0) + else if(_tinydir_strncmp(arg, TINYDIR_STRING("--platform="), 11) == 0) { - if(i == argc - 1) + if(!platformName.empty()) { - ferr << "Error: Expected platform to target after --platform" << endl; + ferr << "Error: Platform defined more than once" << endl; usageBuild(run); } - - ++i; - arg = argv[i]; - - if(!platformName.empty()) + platformName = arg + 11; + } + else if(_tinydir_strncmp(arg, TINYDIR_STRING("--cpu="), 6) == 0) + { + if(!cpuName.empty()) { - ferr << "Error: Platform defined twice. First as " << platformName << " then as " << arg << endl; + ferr << "Error: CPU defined more than once" << endl; usageBuild(run); } - platformName = arg; + cpuName = toUtf8(arg + 6); } else if(run && _tinydir_strcmp(arg, TINYDIR_STRING("--args")) == 0) { @@ -614,6 +627,9 @@ static int buildProject(int argc, const _tinydir_char_t **argv, bool run) if(platformName.empty()) platformName = toFileString(asString(SYSTEM_PLATFORM)); + if(cpuName.empty()) + cpuName = "native"; + string platformUtf8 = toUtf8(platformName); Platform platform = getPlatformByName(StringView(platformUtf8.data(), platformUtf8.size())); if(platform == PLATFORM_INVALID) @@ -623,6 +639,14 @@ static int buildProject(int argc, const _tinydir_char_t **argv, bool run) usageBuild(run); } + CPU cpu = getCpuByName(cpuName); + if(cpu == CPU_INVALID) + { + ferr << "Invalid cpu " << cpuName << endl; + ferr << "Expected one of: " << "baseline, cpu" << endl; + usageBuild(run); + } + bool crossCompileLinux64ToWin64 = (SYSTEM_PLATFORM == PLATFORM_LINUX_X86_64 && platform == PLATFORM_WIN64); if(platform != SYSTEM_PLATFORM && !crossCompileLinux64ToWin64) { @@ -685,6 +709,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv, bool run) SibsConfig sibsConfig(compiler, projectPath, optimizationLevel, false); sibsConfig.showWarnings = true; sibsConfig.platform = platform; + sibsConfig.cpu = cpu; sibsConfig.setSanitize(sanitize); sibsConfig.linker = std::move(linker); sibsConfig.use_lto = use_lto; -- cgit v1.2.3