From cf0c9479deedcbfc0592ac6d207b22ebf3655567 Mon Sep 17 00:00:00 2001
From: dec05eba <dec05eba@protonmail.com>
Date: Tue, 27 Jun 2023 02:27:44 +0200
Subject: Add --cpu=baseline|native option, propagate sanitize setting to sub
 projects

---
 src/CmakeModule.cpp | 13 +++++++++++++
 src/GlobalLib.cpp   |  1 +
 src/main.cpp        | 51 ++++++++++++++++++++++++++++++++++++++-------------
 3 files changed, 52 insertions(+), 13 deletions(-)

(limited to 'src')

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 <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=<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 <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 <filepath>...|--all-files]\n\n");
+    printf("Usage: sibs test [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--linker=lld|gold|mold] [--platform=<platform>] [--cpu=cpu] [--file <filepath>...|--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 <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-70-g09d2