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? --- backend/ninja/Ninja.cpp | 148 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 121 insertions(+), 27 deletions(-) (limited to 'backend/ninja/Ninja.cpp') 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 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 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::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 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; -- cgit v1.2.3