aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md8
-rw-r--r--backend/BackendUtils.cpp2
-rw-r--r--backend/ninja/Ninja.cpp54
-rw-r--r--include/Conf.hpp8
-rw-r--r--include/FileUtil.hpp1
-rw-r--r--include/Linker.hpp1
-rw-r--r--src/CmakeModule.cpp17
-rw-r--r--src/FileUtil.cpp10
-rw-r--r--src/GlobalLib.cpp1
-rw-r--r--src/Linker.cpp8
-rw-r--r--src/main.cpp77
11 files changed, 158 insertions, 29 deletions
diff --git a/README.md b/README.md
index 56ee9b2..c2661c2 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ cd project-name
# Build the project in debug mode and run it
sibs run
# To compile with optimizations enabled, run:
-# sibs build --release
+sibs build --release
# and then the output binary is available in sibs-build/<platform-name>/release/project-name
```
@@ -71,6 +71,8 @@ After you have installed sibs, execute `sibs` without any arguments and you will
The current recommended way of using sibs is to add dependencies as git submodules and they will automatically be used. To use system dependencies use pkg-config.\
You can list all your system packages with `pkg-config --list-all` (if the packages provide pkg-config files). To search for a package in this list you can use grep, like so: `pkg-config --list-all | grep 'pkg-name'` (replace pkg-name with the name of the package you want to search for).\
To then show the version of the found package you can use `pkg-config --modversion pkg-name`.
+
+sibs will prefer mold linker in release mode if it's available and then the lld linker and then the gold linker. You can install mold/lld to improve compile times. Note that gdb debugging is a bit buggy when using mold/lld so use of mold/lld is only recommended in release mode.
# Quirks
Zig support has not been tested properly yet and currently always links to c library.
You can run zig tests with `sibs test --file filepath` or `sibs test --all-files`.
@@ -90,9 +92,9 @@ Users are required to manually install some libraries as they can't be included
This requirement might be removed later, if the gpu driver libraries required can somehow be detected and downloaded cross platform.
Libraries that are downloaded are available at: https://github.com/DEC05EBA/libraries
# Cross compilation
-Automatic cross compilation (`sibs build --platform <platform>`)currently only works from linux_x86_64 to win64 by using mingw-w64. You need to install `mingw-w64-gcc` and optionally `mingw-w64-pkg-config` if you want to use mingw-w64 system installed packages.
+Automatic cross compilation (`sibs build --platform <platform>`) currently only works from linux_x86_64 to win64 by using mingw-w64. You need to install `mingw-w64-gcc` and optionally `mingw-w64-pkg-config` if you want to use mingw-w64 system installed packages.
Cross compilation does currently not work if you have zig files as zig doesn't support libc when cross compiling at the moment.
-You can run `scripts/mingw_package.py` to automatically copy dynamic library dependencies of your executable to the same directory as the executable, so the library can be found when running the executable on windows; this also allows you to bundle your application and distribute it without external dependencies. To run `scripts/mingw_package.py` you need to install pefile python library `sudo pip install pefile`.
+You can run `scripts/mingw_package.py` to automatically copy dynamic library dependencies of your executable to the same directory as the executable, so the library can be found when running the executable on windows; this also allows you to bundle your application and distribute it without external dependencies. To run `scripts/mingw_package.py` you need to install pefile python library: `sudo pip install pefile`.
Manual cross compilation can be done by replacing c, c++ compilers and static library archiver (ar) using the environment variable CC, CXX and AR.
# IDE support
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 6c69d13..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<ninja::NinjaArg> getCompilerOptimizationFlags(const SibsConfig &config)
{
switch (config.getCompiler())
@@ -810,7 +841,9 @@ namespace backend
// TODO: Allow configuring default linking flags. Maybe have `package.useThreads = false` to disable this flag
string allLinkerFlags;
- if(!config.linker.empty())
+ if(config.linker == "mold")
+ allLinkerFlags += " -B/usr/lib/mold/";
+ else if(!config.linker.empty())
allLinkerFlags += " -fuse-ld=" + config.linker;
if(isSamePlatformFamily(config.platform, PLATFORM_POSIX))
@@ -1011,6 +1044,14 @@ namespace backend
vector<ninja::NinjaArg> optimizationFlags = getCompilerOptimizationFlags(config);
compileCCommand.insert(compileCCommand.end(), optimizationFlags.begin(), optimizationFlags.end());
+ for(auto &optFlag : optimizationFlags) {
+ 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));
@@ -1065,6 +1106,14 @@ namespace backend
vector<ninja::NinjaArg> optimizationFlags = getCompilerOptimizationFlags(config);
compileCCommand.insert(compileCCommand.end(), optimizationFlags.begin(), optimizationFlags.end());
+ for(auto &optFlag : optimizationFlags) {
+ 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));
@@ -1754,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<std::string> includeDirs;
diff --git a/include/FileUtil.hpp b/include/FileUtil.hpp
index 5bd4d33..2b4f3c5 100644
--- a/include/FileUtil.hpp
+++ b/include/FileUtil.hpp
@@ -81,6 +81,7 @@ namespace sibs
};
FileType getFileType(const _tinydir_char_t *path);
+ bool fileExists(const _tinydir_char_t *path);
void walkDir(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc);
void walkDirFiles(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc);
bool walkDirFilesRecursive(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc);
diff --git a/include/Linker.hpp b/include/Linker.hpp
index b2e64fe..59e39b3 100644
--- a/include/Linker.hpp
+++ b/include/Linker.hpp
@@ -12,6 +12,7 @@ namespace sibs
bool is_gold_linker_installed();
bool is_lld_linker_installed();
+ bool is_mold_linker_installed();
}
#endif //SIBS_LINKER_HPP
diff --git a/src/CmakeModule.cpp b/src/CmakeModule.cpp
index e3b3918..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");
@@ -239,7 +252,9 @@ namespace sibs
}
}
- if(!config.linker.empty())
+ if(config.linker == "mold")
+ cflags += TINYDIR_STRING(" -B/usr/lib/mold/");
+ else if(!config.linker.empty())
cflags += TINYDIR_STRING(" -fuse-ld=") + toFileString(config.linker);
cxxflags = cflags;
diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp
index e1142ec..02acfa4 100644
--- a/src/FileUtil.cpp
+++ b/src/FileUtil.cpp
@@ -141,6 +141,11 @@ namespace sibs
else
return FileType::FILE_NOT_FOUND;
}
+
+ bool fileExists(const _tinydir_char_t *path) {
+ struct stat64 fileStat;
+ return stat64(path, &fileStat) == 0;
+ }
Result<u64> getFileLastModifiedTime(const _tinydir_char_t *path)
{
@@ -163,6 +168,11 @@ namespace sibs
else
return FileType::FILE_NOT_FOUND;
}
+
+ bool fileExists(const _tinydir_char_t *path) {
+ struct _stat64i32 fileStat;
+ return _wstat(path, &fileStat) == 0;
+ }
Result<u64> getFileLastModifiedTime(const _tinydir_char_t *path)
{
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/Linker.cpp b/src/Linker.cpp
index 7d90d46..d03e3a4 100644
--- a/src/Linker.cpp
+++ b/src/Linker.cpp
@@ -4,9 +4,9 @@
static void split_string(const std::string &str, char delimiter, std::function<bool(const char*,size_t)> callback) {
size_t index = 0;
while(index < str.size()) {
- const size_t end_index = str.find(delimiter, index);
+ size_t end_index = str.find(delimiter, index);
if(end_index == std::string::npos)
- break;
+ end_index = str.size();
if(!callback(&str[index], end_index - index))
break;
@@ -46,4 +46,8 @@ namespace sibs
bool is_lld_linker_installed() {
return is_linker_installed("ld.lld");
}
+
+ bool is_mold_linker_installed() {
+ return is_linker_installed("ld.mold") && fileExists("/usr/lib/mold/ld");
+ }
} \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 3c2ad46..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=linker] [--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\" or \"gold\" is the default linker when using gcc\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,16 +174,18 @@ static void usageNew()
static void usageTest()
{
- printf("Usage: sibs test [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--linker=linker] [--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");
printf(" --debug|--release Optimization level to build project and dependencies with (if not a system package) - Optional (default: --debug)\n");
printf(" --build|-b Build tests but don't run them\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: address)\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(" --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(" --linker=linker The linker to use. \"lld\" or \"gold\" is the default linker when using gcc\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)
{
@@ -664,17 +688,28 @@ static int buildProject(int argc, const _tinydir_char_t **argv, bool run)
Compiler compiler = Compiler::MSVC;
#endif
- // TODO: Make mold the default linker if it's installed and the installed gcc version supports it with -fuse-ld= option
if(linker.empty()) {
- if(is_lld_linker_installed())
- linker = "lld";
- else if(is_gold_linker_installed())
+ // Static object files compiled with gcc are not compatible with lld (llvm linker)
+ // and we dont know which compiler was used to compile to code so we disable automatic
+ // use of lld by default. The user can still force lld with --linker=lld, if they are
+ // sure that they used clang to compile the code.
+ // TODO: Detect if linker has change and recompile everything (that was compiled with a different linker).
+ if(!use_lto && optimizationLevel != OPT_LEV_DEBUG && !include_debug_symbols_in_release) {
+ if(is_mold_linker_installed())
+ linker = "mold";
+ else if(is_lld_linker_installed())
+ linker = "lld";
+ else if(is_gold_linker_installed())
+ linker = "gold";
+ } else if(is_gold_linker_installed()) {
linker = "gold";
+ }
}
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;
@@ -689,7 +724,7 @@ static int testProject(int argc, const _tinydir_char_t **argv)
FileString projectPath;
vector<FileString> filesToTest;
bool testAllFiles = false;
- Sanitize sanitize = Sanitize::ADDRESS;
+ Sanitize sanitize = Sanitize::NONE;
bool sanitize_defined = false;
bool buildOnly = false;
bool skipCompile = false;