From 5250cb90406693163763a214af95f670e0e3a4e0 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 5 Oct 2018 05:02:49 +0200 Subject: 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? --- src/FileUtil.cpp | 27 +++++++++++++++++++++++++++ src/GlobalLib.cpp | 2 ++ src/PkgConfig.cpp | 17 ++++++++++++----- src/Platform.cpp | 5 +++++ src/main.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 94 insertions(+), 10 deletions(-) (limited to 'src') 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 +#include #if OS_FAMILY == OS_FAMILY_POSIX #include @@ -497,4 +498,30 @@ namespace sibs return pathIndex == path.size() && otherPathIndex == otherPath.size(); } + + Result 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::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::Err(errMsg); + } + + dstFile << srcFile.rdbuf(); + return Result::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 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 PkgConfig::validatePkgConfigPackageVersionExists(PackageListDependency *dependency) { @@ -34,7 +41,7 @@ namespace sibs Result 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 = 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 = 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 = 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 ]\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 ...|--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); } -- cgit v1.2.3