aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-10-05 05:02:49 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-06 07:39:33 +0200
commit5250cb90406693163763a214af95f670e0e3a4e0 (patch)
tree7025c762d4f53aebfdc140d615306f558fa9b69a
parent3059b1cb8d701cf23f3e04a8a8fdcfcaa6a397fb (diff)
Add cross compilation (mingw-w64 x86_64)
Currently only cross compiling from linux64 to win64 works. Need to test cross compilation more, currently the cross compilation uses same profile as GCC, is that correct?
-rw-r--r--README.md3
-rw-r--r--backend/BackendUtils.cpp3
-rw-r--r--backend/ninja/Ninja.cpp148
-rw-r--r--examples/hello_lua/.gitignore5
-rw-r--r--examples/hello_lua/hello.lua1
-rw-r--r--examples/hello_lua/project.conf8
-rw-r--r--examples/hello_lua/src/main.cpp31
-rw-r--r--examples/hello_lua_mingw_w64/.gitignore5
-rw-r--r--examples/hello_lua_mingw_w64/README.md1
-rw-r--r--examples/hello_lua_mingw_w64/hello.lua1
-rw-r--r--examples/hello_lua_mingw_w64/project.conf8
-rwxr-xr-xexamples/hello_lua_mingw_w64/run.sh8
-rw-r--r--examples/hello_lua_mingw_w64/src/main.cpp32
-rw-r--r--include/Conf.hpp7
-rw-r--r--include/FileUtil.hpp1
-rw-r--r--include/PkgConfig.hpp2
-rw-r--r--include/Platform.hpp1
-rw-r--r--src/FileUtil.cpp27
-rw-r--r--src/GlobalLib.cpp2
-rw-r--r--src/PkgConfig.cpp17
-rw-r--r--src/Platform.cpp5
-rw-r--r--src/main.cpp53
22 files changed, 330 insertions, 39 deletions
diff --git a/README.md b/README.md
index 1b24b35..6bee538 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,9 @@ The package command also comes with --bundle-install option which reduces the si
Users are required to manually install some libraries as they can't be included in a distributed package (install with their package manager). These libraries are commonly gpu driver libraries, which vary even if you have the same cpu architecture.
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
+Cross compilation currently only works from linux64 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.
# IDE support
Sibs generates a compile_commands.json in the project root directory when executing `sibs build` and tools that support clang completion can be used, such as YouCompleteMe.
There are several editors that support YouCompleteMe, including Vim, Emacs and Visual Studio Code. Visual studio code now also supports clang completion with C/C++ extension by Microsoft; the extension will ask you which compile_commands.json file you want to use and you can choose the compile_commands.json in the project root directory.
diff --git a/backend/BackendUtils.cpp b/backend/BackendUtils.cpp
index 92a73ef..d5fad04 100644
--- a/backend/BackendUtils.cpp
+++ b/backend/BackendUtils.cpp
@@ -109,6 +109,9 @@ namespace backend
backend::Ninja *subProject = new backend::Ninja();
SibsConfig *subProjectConfig = new SibsConfig(sibsConfig.getCompiler(), file->path, sibsConfig.getOptimizationLevel(), false);
+ subProjectConfig->packaging = sibsConfig.packaging;
+ subProjectConfig->platform = sibsConfig.platform;
+ subProjectConfig->bundling = sibsConfig.bundling;
FileString subProjectBuildPath;
readSibsConfig(file->path, projectConfPath, *subProjectConfig, subProjectBuildPath);
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index 4495bd4..27608cc 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -98,6 +98,7 @@ namespace backend
string result;
switch (compiler)
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
result = "'-I";
@@ -123,6 +124,7 @@ namespace backend
{
switch (compiler)
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
return "'-D" + name + "=" + value + "'";
@@ -143,6 +145,7 @@ namespace backend
string result;
switch (compiler)
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
result = "-o ";
@@ -166,6 +169,7 @@ namespace backend
{
switch (compiler)
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
switch(cVersion)
@@ -193,6 +197,7 @@ namespace backend
{
switch (compiler)
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
switch(cppVersion)
@@ -223,6 +228,7 @@ namespace backend
{
switch (compiler)
{
+ case Compiler::MINGW_W64:
case Compiler::GCC: return ".o";
case Compiler::MSVC: return ".obj";
default: return nullptr;
@@ -387,6 +393,7 @@ namespace backend
{
switch (config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
switch (config.getOptimizationLevel())
@@ -460,6 +467,7 @@ namespace backend
switch (compiler)
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
includeStartStr = "-I";
@@ -693,6 +701,60 @@ namespace backend
return result;
}
+ static string getCompilerCExecutable(Compiler compiler)
+ {
+ string result;
+ switch(compiler)
+ {
+ case Compiler::GCC:
+ result = "cc";
+ break;
+ case Compiler::MINGW_W64:
+ result = "x86_64-w64-mingw32-cc";
+ break;
+ case Compiler::MSVC:
+ result = "cl.exe";
+ break;
+ }
+ return result;
+ }
+
+ static string getCompilerCppExecutable(Compiler compiler)
+ {
+ string result;
+ switch(compiler)
+ {
+ case Compiler::GCC:
+ result = "c++";
+ break;
+ case Compiler::MINGW_W64:
+ result = "x86_64-w64-mingw32-c++";
+ break;
+ case Compiler::MSVC:
+ result = "cl.exe";
+ break;
+ }
+ return result;
+ }
+
+ static string getCompilerLinker(Compiler compiler)
+ {
+ string result;
+ switch(compiler)
+ {
+ case Compiler::GCC:
+ result = "ar";
+ break;
+ case Compiler::MINGW_W64:
+ result = "x86_64-w64-mingw32-ar";
+ break;
+ case Compiler::MSVC:
+ result = "lib.exe";
+ break;
+ }
+ return result;
+ }
+
Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback)
{
bool isCCompilerClang = false;
@@ -734,6 +796,10 @@ namespace backend
FileString ninjaBuildFilePath = savePath;
ninjaBuildFilePath += TINYDIR_STRING("/build.ninja");
+ string cCompilerName = getCompilerCExecutable(config.getCompiler());
+ string cppCompilerName = getCompilerCppExecutable(config.getCompiler());
+ string compilerLinker = getCompilerLinker(config.getCompiler());
+
ninja::NinjaBuildFile ninjaBuildFile;
string globalIncDir;
@@ -764,12 +830,10 @@ namespace backend
parentGlobalIncludeDirCallback(globalIncludeDir);
};
-#if OS_TYPE == OS_TYPE_LINUX
// TODO: Allow configuring default linking flags. Maybe have `package.useThreads = false` to disable this flag
- string allLinkerFlags = "-pthread";
-#else
- string allLinkerFlags = "";
-#endif
+ string allLinkerFlags;
+ if(isSamePlatformFamily(config.platform, PLATFORM_LINUX))
+ allLinkerFlags = "-pthread";
// TODO: Somehow check loading order, because it has to be correct to work.. Or does it for dynamic libraries?
// Anyways it's required for static libraries
@@ -866,6 +930,7 @@ namespace backend
switch(config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
vector<ninja::NinjaArg> baseCompileCArgs;
@@ -875,7 +940,7 @@ namespace backend
{
baseCompileCArgs.insert(baseCompileCArgs.end(), {
ninja::NinjaArg("ccache"),
- ninja::NinjaArg("cc"),
+ ninja::NinjaArg(cCompilerName),
ninja::NinjaArg("-c"),
ninja::NinjaArg("-fpie"),
ninja::NinjaArg("$in"),
@@ -889,7 +954,7 @@ namespace backend
{
baseCompileCArgs.insert(baseCompileCArgs.end(), {
ninja::NinjaArg("ccache"),
- ninja::NinjaArg("cc"),
+ ninja::NinjaArg(cCompilerName),
ninja::NinjaArg("-c"),
ninja::NinjaArg("-fpic"),
ninja::NinjaArg("$in"),
@@ -936,7 +1001,7 @@ namespace backend
compileCCommand.insert(compileCCommand.end(), sanitizerFlags.begin(), sanitizerFlags.end());
compileCppCommand = compileCCommand;
- compileCppCommand[1] = ninja::NinjaArg("c++");
+ compileCppCommand[1] = ninja::NinjaArg(cppCompilerName);
compileCppCommand.insert(compileCppCommand.end(), {
ninja::NinjaArg("-fexceptions"),
ninja::NinjaArg("-Wnon-virtual-dtor")
@@ -1001,6 +1066,7 @@ namespace backend
switch(config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
compileCRule->depFile = "$out.d";
@@ -1015,6 +1081,8 @@ namespace backend
}
}
+ bool crossOsCompiling = !isSamePlatformFamily(config.platform, SYSTEM_PLATFORM);
+
// TODO: Specify -mconsole or -mwindows for windows.
// TODO: Convert sibs defines to const variables in a zig file that other zig files can include (like a config file).
@@ -1026,6 +1094,9 @@ namespace backend
ninja::NinjaArg::createRaw("$globalIncDirZig")
};
+ if(isSamePlatformFamily(SYSTEM_PLATFORM, PLATFORM_LINUX) && isSamePlatformFamily(config.platform, PLATFORM_WIN))
+ commonZigArgs.push_back(ninja::NinjaArg::createRaw("--target-os windows --target-arch x86_64 --target-environ gnu --libc-lib-dir /usr/x86_64-w64-mingw32/lib --libc-static-lib-dir /usr/x86_64-w64-mingw32/lib"));
+
// TODO: Remove this if project does not depend on c libraries or project only has .zig files
if(!config.packaging)
commonZigArgs.push_back(ninja::NinjaArg::createRaw("--library c"));
@@ -1112,6 +1183,7 @@ namespace backend
onlyZigFiles = false;
}
+ bool containsZigFiles = false;
for(const sibs::SourceFile &sourceFile : sourceFiles)
{
string objectName;
@@ -1136,6 +1208,7 @@ namespace backend
case sibs::Language::ZIG:
{
// Already built above
+ containsZigFiles = true;
break;
}
default:
@@ -1147,11 +1220,15 @@ namespace backend
objectNames.emplace_back(move(objectName));
}
+ if(containsZigFiles && isSamePlatformFamily(config.platform, PLATFORM_WIN) && !isSamePlatformFamily(SYSTEM_PLATFORM, PLATFORM_WIN))
+ return Result<bool>::Err("Cross compiling a project with zig files from a non-windows platform to windows is currently not supported because zig doesn't support libc when cross compiling");
+
string packagingFlags;
if(config.packaging)
{
switch(config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
packagingFlags = "-static -static-libgcc -static-libstdc++";
@@ -1164,6 +1241,14 @@ namespace backend
}
}
}
+ else
+ {
+ // By statically compiling when using mingw w64, we dont have to bundle our application with several runtime dlls
+ if(config.getCompiler() == Compiler::MINGW_W64)
+ {
+ packagingFlags = "-static -static-libgcc -static-libstdc++";
+ }
+ }
// TODO: For now zig projects (zig object files) are built with c/c++ compiler,
// they should be built with zig if project only contains zig files.
@@ -1196,7 +1281,7 @@ namespace backend
{
vector<ninja::NinjaArg> buildExeArgs;
string executableName = config.getPackageName();
- if(OS_FAMILY == OS_FAMILY_WINDOWS)
+ if(isSamePlatformFamily(config.platform, PLATFORM_WIN))
executableName += ".exe";
if(onlyZigFiles)
{
@@ -1218,12 +1303,13 @@ namespace backend
{
switch (config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
string rpath = extractDynamicLibDirsFromLinkerFlags(dynamicLinkerFlags);
buildExeArgs.insert(buildExeArgs.end(), {
ninja::NinjaArg::createRaw("ccache"),
- ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"),
+ ninja::NinjaArg::createRaw(usesCppFiles ? cppCompilerName : cCompilerName),
ninja::NinjaArg::createRaw("-o"),
ninja::NinjaArg::createRaw("$out"),
ninja::NinjaArg::createRaw("$in"),
@@ -1252,10 +1338,13 @@ namespace backend
ninja::NinjaArg::createRaw("-lm")
});
#else
- buildExeArgs.insert(buildExeArgs.end(), {
- ninja::NinjaArg::createRaw("-ldl"),
- ninja::NinjaArg::createRaw("-lm")
- });
+ if(!isSamePlatformFamily(config.platform, PLATFORM_WIN))
+ {
+ buildExeArgs.insert(buildExeArgs.end(), {
+ ninja::NinjaArg::createRaw("-ldl"),
+ ninja::NinjaArg::createRaw("-lm")
+ });
+ }
#endif
break;
}
@@ -1263,7 +1352,7 @@ namespace backend
{
// TODO: Do not link all of these. Find a way to only link the ones that are needed
buildExeArgs.insert(buildExeArgs.end(), {
- ninja::NinjaArg::createRaw("cl.exe"),
+ ninja::NinjaArg::createRaw(cppCompilerName),
ninja::NinjaArg::createRaw("$in"),
ninja::NinjaArg::createRaw("/Fe$out"),
ninja::NinjaArg::createRaw("Ws2_32.lib"),
@@ -1299,10 +1388,7 @@ namespace backend
buildExeRule->build(objectNames, executableName, {});
}
- projectGeneratedBinary += config.getPackageName();
- #if OS_FAMILY == OS_FAMILY_WINDOWS
- projectGeneratedBinary += ".exe";
- #endif
+ projectGeneratedBinary += executableName;
projectGeneratedBinary += "\"";
break;
}
@@ -1312,6 +1398,7 @@ namespace backend
string generatedFile;
switch (config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
generatedFile = "lib" + config.getPackageName() + ".a";
@@ -1341,10 +1428,11 @@ namespace backend
{
switch (config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
buildStaticArgs.insert(buildStaticArgs.end(), {
- ninja::NinjaArg::createRaw("ar"),
+ ninja::NinjaArg::createRaw(compilerLinker),
ninja::NinjaArg::createRaw("rcs"),
ninja::NinjaArg::createRaw("$out"),
ninja::NinjaArg::createRaw("$in")
@@ -1354,7 +1442,7 @@ namespace backend
case Compiler::MSVC:
{
buildStaticArgs.insert(buildStaticArgs.end(), {
- ninja::NinjaArg::createRaw("lib.exe"),
+ ninja::NinjaArg::createRaw(compilerLinker),
ninja::NinjaArg::createRaw("/OUT:$out"),
ninja::NinjaArg::createRaw("$in")
});
@@ -1389,6 +1477,7 @@ namespace backend
string generatedFile;
switch (config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
generatedFile = "lib" + config.getPackageName() + ".so";
@@ -1421,11 +1510,12 @@ namespace backend
{
switch (config.getCompiler())
{
+ case Compiler::MINGW_W64:
case Compiler::GCC:
{
buildDynamicArgs.insert(buildDynamicArgs.end(), {
ninja::NinjaArg::createRaw("ccache"),
- ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"),
+ ninja::NinjaArg::createRaw(usesCppFiles ? cppCompilerName : cCompilerName),
ninja::NinjaArg::createRaw("$in"),
ninja::NinjaArg::createRaw("-shared"),
ninja::NinjaArg("-Wl,-soname," + generatedFile),
@@ -1448,17 +1538,20 @@ namespace backend
ninja::NinjaArg::createRaw("-lm")
});
#else
- buildDynamicArgs.insert(buildDynamicArgs.end(), {
- ninja::NinjaArg::createRaw("-ldl"),
- ninja::NinjaArg::createRaw("-lm")
- });
+ if(!isSamePlatformFamily(config.platform, PLATFORM_WIN))
+ {
+ buildDynamicArgs.insert(buildDynamicArgs.end(), {
+ ninja::NinjaArg::createRaw("-ldl"),
+ ninja::NinjaArg::createRaw("-lm")
+ });
+ }
#endif
break;
}
case Compiler::MSVC:
{
buildDynamicArgs.insert(buildDynamicArgs.end(), {
- ninja::NinjaArg::createRaw("lib.exe"),
+ ninja::NinjaArg::createRaw(compilerLinker),
ninja::NinjaArg::createRaw("/OUT:$out"),
ninja::NinjaArg::createRaw("$in"),
ninja::NinjaArg::createRaw("Ws2_32.lib"),
@@ -1567,6 +1660,7 @@ namespace backend
FileType projectConfFileType = getFileType(projectConfFilePath.c_str());
SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative, config.getOptimizationLevel());
+ sibsTestConfig.platform = config.platform;
sibsTestConfig.setSanitize(config.getSanitize());
sibsTestConfig.zigTestFiles = move(config.zigTestFiles);
sibsTestConfig.zigTestAllFiles = config.zigTestAllFiles;
diff --git a/examples/hello_lua/.gitignore b/examples/hello_lua/.gitignore
new file mode 100644
index 0000000..636c6b9
--- /dev/null
+++ b/examples/hello_lua/.gitignore
@@ -0,0 +1,5 @@
+# Compiled sibs files
+sibs-build/
+compile_commands.json
+tests/sibs-build/
+tests/compile_commands.json
diff --git a/examples/hello_lua/hello.lua b/examples/hello_lua/hello.lua
new file mode 100644
index 0000000..4601856
--- /dev/null
+++ b/examples/hello_lua/hello.lua
@@ -0,0 +1 @@
+print("inside lua!")
diff --git a/examples/hello_lua/project.conf b/examples/hello_lua/project.conf
new file mode 100644
index 0000000..e416497
--- /dev/null
+++ b/examples/hello_lua/project.conf
@@ -0,0 +1,8 @@
+[package]
+name = "hello_lua"
+type = "executable"
+version = "0.1.0"
+platforms = ["any"]
+
+[dependencies]
+lua51 = "5.1.5"
diff --git a/examples/hello_lua/src/main.cpp b/examples/hello_lua/src/main.cpp
new file mode 100644
index 0000000..57f9194
--- /dev/null
+++ b/examples/hello_lua/src/main.cpp
@@ -0,0 +1,31 @@
+#include <stdio.h>
+extern "C" {
+#include <lua5.1/lua.h>
+#include <lua5.1/lualib.h>
+#include <lua5.1/lauxlib.h>
+}
+int main(int argc, char *argv[]) {
+ // Open lua
+ lua_State *L = lua_open();
+
+ // Load the libraries
+ luaL_openlibs(L);
+
+ // Execution of a lua string
+ luaL_dostring(L, "print \"Yo dude\"");
+
+ // Load a string and then execute it.
+ luaL_loadstring(L, "io.write(\"I'm here too\\n\")");
+ lua_pcall(L, 0, LUA_MULTRET, 0);
+
+ // Load from a file and then execute
+ if (luaL_loadfile(L, "hello.lua") == 0) {
+ // File loaded call it
+ lua_pcall(L, 0, LUA_MULTRET, 0);
+ }
+
+ // Close lua
+ lua_close (L);
+
+ return 0;
+}
diff --git a/examples/hello_lua_mingw_w64/.gitignore b/examples/hello_lua_mingw_w64/.gitignore
new file mode 100644
index 0000000..636c6b9
--- /dev/null
+++ b/examples/hello_lua_mingw_w64/.gitignore
@@ -0,0 +1,5 @@
+# Compiled sibs files
+sibs-build/
+compile_commands.json
+tests/sibs-build/
+tests/compile_commands.json
diff --git a/examples/hello_lua_mingw_w64/README.md b/examples/hello_lua_mingw_w64/README.md
new file mode 100644
index 0000000..524476d
--- /dev/null
+++ b/examples/hello_lua_mingw_w64/README.md
@@ -0,0 +1 @@
+This is an example of using system lua5.1 package (pkg-config).
diff --git a/examples/hello_lua_mingw_w64/hello.lua b/examples/hello_lua_mingw_w64/hello.lua
new file mode 100644
index 0000000..4601856
--- /dev/null
+++ b/examples/hello_lua_mingw_w64/hello.lua
@@ -0,0 +1 @@
+print("inside lua!")
diff --git a/examples/hello_lua_mingw_w64/project.conf b/examples/hello_lua_mingw_w64/project.conf
new file mode 100644
index 0000000..b568575
--- /dev/null
+++ b/examples/hello_lua_mingw_w64/project.conf
@@ -0,0 +1,8 @@
+[package]
+name = "hello_lua"
+type = "executable"
+version = "0.1.0"
+platforms = ["any"]
+
+[dependencies]
+lua5.1 = "5.1.5"
diff --git a/examples/hello_lua_mingw_w64/run.sh b/examples/hello_lua_mingw_w64/run.sh
new file mode 100755
index 0000000..0f23a37
--- /dev/null
+++ b/examples/hello_lua_mingw_w64/run.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+set -e
+
+script_path=`readlink -f $0`
+script_dir=`dirname $script_path`
+cd "$script_dir"
+sibs build --platform win64 && ./sibs-build/debug/hello_lua.exe
diff --git a/examples/hello_lua_mingw_w64/src/main.cpp b/examples/hello_lua_mingw_w64/src/main.cpp
new file mode 100644
index 0000000..1486b98
--- /dev/null
+++ b/examples/hello_lua_mingw_w64/src/main.cpp
@@ -0,0 +1,32 @@
+// Example taken from http://lua-users.org/lists/lua-l/2010-06/msg00153.html
+#include <stdio.h>
+extern "C" {
+#include <lua5.1/lua.h>
+#include <lua5.1/lualib.h>
+#include <lua5.1/lauxlib.h>
+}
+int main(int argc, char *argv[]) {
+ // Open lua
+ lua_State *L = lua_open();
+
+ // Load the libraries
+ luaL_openlibs(L);
+
+ // Execution of a lua string
+ luaL_dostring(L, "print \"Yo dude\"");
+
+ // Load a string and then execute it.
+ luaL_loadstring(L, "io.write(\"I'm here too\\n\")");
+ lua_pcall(L, 0, LUA_MULTRET, 0);
+
+ // Load from a file and then execute
+ if (luaL_loadfile(L, "hello.lua") == 0) {
+ // File loaded call it
+ lua_pcall(L, 0, LUA_MULTRET, 0);
+ }
+
+ // Close lua
+ lua_close (L);
+
+ return 0;
+}
diff --git a/include/Conf.hpp b/include/Conf.hpp
index 17ecc6b..15c8471 100644
--- a/include/Conf.hpp
+++ b/include/Conf.hpp
@@ -107,7 +107,8 @@ namespace sibs
enum class Compiler
{
GCC,
- MSVC
+ MSVC,
+ MINGW_W64
};
enum class CVersion
@@ -303,7 +304,8 @@ namespace sibs
showWarnings(false),
zigTestAllFiles(false),
packaging(false),
- bundling(false)
+ bundling(false),
+ platform(SYSTEM_PLATFORM)
{
cmakeDirGlobal = projectPath;
cmakeDirStatic = cmakeDirGlobal;
@@ -504,6 +506,7 @@ namespace sibs
bool packaging;
bool bundling;
std::string version;
+ Platform platform;
protected:
virtual void processObject(StringView name) override;
virtual void processField(StringView name, const ConfigValue &value) override;
diff --git a/include/FileUtil.hpp b/include/FileUtil.hpp
index 3e2e302..0106c19 100644
--- a/include/FileUtil.hpp
+++ b/include/FileUtil.hpp
@@ -60,6 +60,7 @@ namespace sibs
Result<FileString> getRealPath(const _tinydir_char_t *path);
bool pathEquals(const std::string &path, const std::string &otherPath);
Result<u64> getFileLastModifiedTime(const _tinydir_char_t *path);
+ Result<bool> copyFile(const FileString &src, const FileString &dst);
}
#endif //SIBS_FILEUTIL_HPP
diff --git a/include/PkgConfig.hpp b/include/PkgConfig.hpp
index 2a52f2b..9181a2f 100644
--- a/include/PkgConfig.hpp
+++ b/include/PkgConfig.hpp
@@ -5,6 +5,7 @@
#include "Result.hpp"
#include <string>
#include <vector>
+#include "FileUtil.hpp"
namespace sibs
{
@@ -19,6 +20,7 @@ namespace sibs
class PkgConfig
{
public:
+ static void setPkgConfigPath(const FileString &path);
static Result<bool> validatePkgConfigPackageVersionExists(PackageListDependency *dependency);
static Result<bool> validatePackageExists(const std::string &name);
static Result<bool> validatePackageVersionAtLeast(const std::string &name, const std::string &version);
diff --git a/include/Platform.hpp b/include/Platform.hpp
index 995d307..74b3a3d 100644
--- a/include/Platform.hpp
+++ b/include/Platform.hpp
@@ -50,4 +50,5 @@ namespace sibs
bool containsPlatform(const std::vector<Platform> &platforms, Platform platform);
const char* asString(Platform platform);
Platform getPlatformByName(StringView name);
+ bool isSamePlatformFamily(Platform a, Platform b);
} \ No newline at end of file
diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp
index 498f638..e317304 100644
--- a/src/FileUtil.cpp
+++ b/src/FileUtil.cpp
@@ -1,5 +1,6 @@
#include "../include/FileUtil.hpp"
#include <cstdio>
+#include <fstream>
#if OS_FAMILY == OS_FAMILY_POSIX
#include <unistd.h>
@@ -497,4 +498,30 @@ namespace sibs
return pathIndex == path.size() && otherPathIndex == otherPath.size();
}
+
+ Result<bool> copyFile(const FileString &src, const FileString &dst)
+ {
+ ifstream srcFile(src.c_str(), ios::binary);
+ if(!srcFile)
+ {
+ string errMsg = "Failed to open file ";
+ errMsg += toUtf8(src);
+ errMsg += ", reason: ";
+ errMsg += strerror(errno);
+ return Result<bool>::Err(errMsg);
+ }
+
+ ofstream dstFile(dst.c_str(), ios::binary);
+ if(!dstFile)
+ {
+ string errMsg = "Failed to create/overwrite file ";
+ errMsg += toUtf8(dst);
+ errMsg += ", reason: ";
+ errMsg += strerror(errno);
+ return Result<bool>::Err(errMsg);
+ }
+
+ dstFile << srcFile.rdbuf();
+ return Result<bool>::Ok(true);
+ }
}
diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp
index a175e02..242e621 100644
--- a/src/GlobalLib.cpp
+++ b/src/GlobalLib.cpp
@@ -202,7 +202,9 @@ namespace sibs
}
SibsConfig sibsConfig(parentConfig.getCompiler(), packageDir, parentConfig.getOptimizationLevel(), false);
+ sibsConfig.platform = parentConfig.platform;
sibsConfig.packaging = parentConfig.packaging;
+ sibsConfig.bundling = parentConfig.bundling;
Result<bool> result = Config::readFromFile(projectConfFilePath.c_str(), sibsConfig);
if (result.isErr())
return result;
diff --git a/src/PkgConfig.cpp b/src/PkgConfig.cpp
index faed146..9efc238 100644
--- a/src/PkgConfig.cpp
+++ b/src/PkgConfig.cpp
@@ -4,12 +4,14 @@
using namespace std;
+static sibs::FileString pkgConfigPath = "pkg-config";
+
// TODO: Do not use pkg-config program. The same functionality can easily be achieved
// by reading files in /usr/share/pkgconfig
// Or is there no downside to calling pkg-config program?
namespace sibs
{
- string trimRight(const string &input)
+ static string trimRight(const string &input)
{
for(int i = input.size() - 1; i >= 0; --i)
{
@@ -18,6 +20,11 @@ namespace sibs
}
return "";
}
+
+ void PkgConfig::setPkgConfigPath(const FileString &path)
+ {
+ pkgConfigPath = path;
+ }
Result<bool> PkgConfig::validatePkgConfigPackageVersionExists(PackageListDependency *dependency)
{
@@ -34,7 +41,7 @@ namespace sibs
Result<bool> PkgConfig::validatePackageExists(const string &name)
{
- FileString command = TINYDIR_STRING("pkg-config --exists '");
+ FileString command = pkgConfigPath + TINYDIR_STRING(" --exists '");
command += toFileString(name);
command += TINYDIR_STRING("'");
Result<ExecResult> execResult = exec(command.c_str());
@@ -68,7 +75,7 @@ namespace sibs
// Use --modversion instead and check if the version returned is newer or equal to dependency version.
// This way we can output installed version vs expected dependency version
- FileString command = TINYDIR_STRING("pkg-config '--atleast-version=");
+ FileString command = pkgConfigPath + TINYDIR_STRING(" '--atleast-version=");
command += toFileString(version);
command += TINYDIR_STRING("' '");
command += toFileString(name);
@@ -111,7 +118,7 @@ namespace sibs
args += "'";
}
- FileString command = TINYDIR_STRING("pkg-config --libs");
+ FileString command = pkgConfigPath + TINYDIR_STRING(" --libs");
command += toFileString(args);
Result<ExecResult> execResult = exec(command.c_str());
if(execResult.isErr())
@@ -154,7 +161,7 @@ namespace sibs
args += "'";
}
- FileString command = TINYDIR_STRING("pkg-config --cflags");
+ FileString command = pkgConfigPath + TINYDIR_STRING(" --cflags");
command += toFileString(args);
Result<ExecResult> execResult = exec(command.c_str());
if(execResult.isErr())
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 44f42db..2df019c 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -41,4 +41,9 @@ namespace sibs
return it->second;
return PLATFORM_INVALID;
}
+
+ bool isSamePlatformFamily(Platform a, Platform b)
+ {
+ return a & b;
+ }
} \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index e55014e..3ffb264 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -9,6 +9,7 @@
#include "../include/CmakeModule.hpp"
#include "../backend/BackendUtils.hpp"
#include "../backend/ninja/Ninja.hpp"
+#include "../include/PkgConfig.hpp"
using namespace std;
using namespace sibs;
@@ -118,18 +119,20 @@ static void usage()
static void usageBuild()
{
- printf("Usage: sibs build [project_path] [--debug|--release] [--sanitize]\n\n");
+ printf("Usage: sibs build [project_path] [--debug|--release] [--sanitize] [--platform <platform>]\n\n");
printf("Build a sibs project\n\n");
printf("Options:\n");
printf(" project_path\t\tThe directory containing a project.conf file - Optional (default: current directory)\n");
printf(" --debug|--release\t\tOptimization level to build project and dependencies with (if not a system package) - Optional (default: --debug)\n");
printf(" --sanitize\t\tAdd 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: disabled)\n");
+ printf(" --platform\t\tThe platform to build for - Optional (default: the running platform). Platform can be either linux32, linux64, win32 or win64\n");
printf("Examples:\n");
printf(" sibs build\n");
printf(" sibs build dirA/dirB\n");
printf(" sibs build --release\n");
printf(" sibs build dirA --release\n");
printf(" sibs build --sanitize\n");
+ printf(" sibs build --release --platform win64\n");
exit(1);
}
@@ -150,7 +153,7 @@ static void usageNew()
static void usageTest()
{
- printf("Usage: sibs test [project_path] [--no-sanitize] [--file filepath...|--all-files]\n\n");
+ printf("Usage: sibs test [project_path] [--no-sanitize] [--file <filepath>...|--all-files]\n\n");
printf("Build and run tests for a sibs project\n\n");
printf("Options:\n");
printf(" project_path\t\tThe directory containing a project.conf file - Optional (default: current directory)\n");
@@ -428,12 +431,10 @@ static int buildProject(const FileString &projectPath, const FileString &project
static int buildProject(int argc, const _tinydir_char_t **argv)
{
- if(argc > 3)
- usageBuild();
-
OptimizationLevel optimizationLevel = OPT_LEV_NONE;
FileString projectPath;
bool sanitize = false;
+ const _tinydir_char_t *platformName = nullptr;
for(int i = 0; i < argc; ++i)
{
@@ -460,6 +461,24 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
{
sanitize = true;
}
+ else if(_tinydir_strcmp(arg, TINYDIR_STRING("--platform")) == 0)
+ {
+ if(i == argc - 1)
+ {
+ ferr << "Error: Expected platform to target after --platform" << endl;
+ usageBuild();
+ }
+
+ ++i;
+ arg = argv[i];
+
+ if(platformName)
+ {
+ ferr << "Error: Platform defined twice. First as " << platformName << " then as " << arg << endl;
+ usageBuild();
+ }
+ platformName = arg;
+ }
else if(_tinydir_strncmp(arg, TINYDIR_STRING("--"), 2) == 0)
{
ferr << "Error: Invalid argument " << arg << endl;
@@ -479,6 +498,24 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
if(optimizationLevel == OPT_LEV_NONE)
optimizationLevel = OPT_LEV_DEBUG;
+ if(!platformName)
+ platformName = SYSTEM_PLATFORM_NAME;
+
+ string platformUtf8 = toUtf8(platformName);
+ Platform platform = getPlatformByName(StringView(platformUtf8.data(), platformUtf8.size()));
+ if(platform == PLATFORM_INVALID)
+ {
+ ferr << "Invalid platform " << platformName << endl;
+ usageBuild();
+ }
+
+ bool crossCompileLinux64ToWin64 = (SYSTEM_PLATFORM == PLATFORM_LINUX64 && platform == PLATFORM_WIN64);
+ if(platform != SYSTEM_PLATFORM && !crossCompileLinux64ToWin64)
+ {
+ ferr << "Cross compilation is currently only supported from linux64 to win64" << endl;
+ exit(33);
+ }
+
// TODO: If projectPath is not defined and working directory does not contain project.conf, then search every parent directory until one is found
if(projectPath.empty())
projectPath = TINYDIR_STRING(".");
@@ -503,12 +540,18 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
// by passing argument to `sibs build`
#if OS_FAMILY == OS_FAMILY_POSIX
Compiler compiler = Compiler::GCC;
+ if(crossCompileLinux64ToWin64)
+ {
+ compiler = Compiler::MINGW_W64;
+ PkgConfig::setPkgConfigPath(TINYDIR_STRING("x86_64-w64-mingw32-pkg-config"));
+ }
#else
Compiler compiler = Compiler::MSVC;
#endif
SibsConfig sibsConfig(compiler, projectPath, optimizationLevel, false);
sibsConfig.showWarnings = true;
+ sibsConfig.platform = platform;
sibsConfig.setSanitize(sanitize);
return buildProject(projectPath, projectConfFilePath, sibsConfig);
}