From 31899d0a48108515d13508b660fb3bb82b869430 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 30 Oct 2018 13:35:36 +0100 Subject: Add support for emscripten, fix compdb for tests --- backend/ninja/Ninja.cpp | 125 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 36 deletions(-) (limited to 'backend/ninja/Ninja.cpp') diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index 6aad314..71e9c08 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -390,10 +390,9 @@ namespace backend static vector getCompilerSanitizerFlags(const SibsConfig &config) { - if(config.getCompiler() == Compiler::GCC && config.getSanitize()) + if(config.getCompiler() == Compiler::GCC || config.getCompiler() == Compiler::MINGW_W64) { return { - ninja::NinjaArg::createRaw("-fno-omit-frame-pointer"), ninja::NinjaArg::createRaw("-fsanitize=address"), ninja::NinjaArg::createRaw("-fsanitize=undefined") }; @@ -417,7 +416,8 @@ namespace backend ninja::NinjaArg::createRaw("-D_FORTIFY_SOURCE=2"), ninja::NinjaArg::createRaw("-D_GLIBCXX_ASSERTIONS"), ninja::NinjaArg::createRaw("-fasynchronous-unwind-tables"), - ninja::NinjaArg::createRaw("-D_DEBUG") + ninja::NinjaArg::createRaw("-D_DEBUG"), + ninja::NinjaArg::createRaw("-fno-omit-frame-pointer"), }; } case OPT_LEV_RELEASE: @@ -767,6 +767,10 @@ namespace backend static string getCompilerLinker(Compiler compiler) { + char *ar = std::getenv("AR"); + if(ar) + return ar; + string result; switch(compiler) { @@ -783,17 +787,54 @@ namespace backend return result; } + enum class RuntimeCompilerType + { + NONE, + OTHER, + CLANG, + EMSCRIPTEN + }; + Result Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { - bool isCCompilerClang = false; - Result cCompilerVersion = exec(TINYDIR_STRING("cc --version")); - if(cCompilerVersion && cCompilerVersion.unwrap().exitCode == 0 && cCompilerVersion.unwrap().execStdout.find("clang") != string::npos) - isCCompilerClang = true; + string cCompilerName = getCompilerCExecutable(config.getCompiler()); + string cppCompilerName = getCompilerCppExecutable(config.getCompiler()); + string compilerLinker = getCompilerLinker(config.getCompiler()); + + RuntimeCompilerType cCompilerType = RuntimeCompilerType::NONE; + Result cCompilerVersion = exec(toFileString(cCompilerName) + TINYDIR_STRING(" --version")); + if(cCompilerVersion && cCompilerVersion.unwrap().exitCode == 0) + { + if(cCompilerVersion.unwrap().execStdout.find("Emscripten") != string::npos) + cCompilerType = RuntimeCompilerType::EMSCRIPTEN; + else if(cCompilerVersion.unwrap().execStdout.find("clang") != string::npos) + cCompilerType = RuntimeCompilerType::CLANG; + else + cCompilerType = RuntimeCompilerType::OTHER; + } - bool isCppCompilerClang = false; - Result cppCompilerVersion = exec(TINYDIR_STRING("c++ --version")); - if(cppCompilerVersion && cppCompilerVersion.unwrap().exitCode == 0 && cppCompilerVersion.unwrap().execStdout.find("clang") != string::npos) - isCppCompilerClang = true; + RuntimeCompilerType cppCompilerType = RuntimeCompilerType::NONE; + Result cppCompilerVersion = exec(toFileString(cppCompilerName) + TINYDIR_STRING(" --version")); + if(cppCompilerVersion && cppCompilerVersion.unwrap().exitCode == 0) + { + if(cppCompilerVersion.unwrap().execStdout.find("Emscripten") != string::npos) + cppCompilerType = RuntimeCompilerType::EMSCRIPTEN; + else if(cppCompilerVersion.unwrap().execStdout.find("clang") != string::npos) + cppCompilerType = RuntimeCompilerType::CLANG; + else + cppCompilerType = RuntimeCompilerType::OTHER; + } + + if(cCompilerType != RuntimeCompilerType::NONE && cppCompilerType != RuntimeCompilerType::NONE && cCompilerType != cppCompilerType) + return Result::Err("The c and c++ compiler has to be of the same type"); + + RuntimeCompilerType compilerType = cCompilerType; + if(compilerType == RuntimeCompilerType::NONE) + compilerType = cppCompilerType; + + bool sanitize = config.getSanitize(); + if(compilerType == RuntimeCompilerType::EMSCRIPTEN) + sanitize = false; Result createBuildDirResult = createDirectoryRecursive(savePath); if (!createBuildDirResult) @@ -818,16 +859,16 @@ namespace backend if(config.packaging && !config.isMainProject()) libraryType = LibraryType::STATIC; + // TODO: Emscripten dynamic library support is not good at the moment, remove this once emscripten has been improved + if(libraryType == LibraryType::DYNAMIC && compilerType == RuntimeCompilerType::EMSCRIPTEN) + libraryType = LibraryType::STATIC; + string savePathUtf8 = toUtf8(savePath); string projectPathUtf8 = toUtf8(config.getProjectPath()); 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; @@ -1053,8 +1094,11 @@ namespace backend vector optimizationFlags = getCompilerOptimizationFlags(config); compileCCommand.insert(compileCCommand.end(), optimizationFlags.begin(), optimizationFlags.end()); - vector sanitizerFlags = getCompilerSanitizerFlags(config); - compileCCommand.insert(compileCCommand.end(), sanitizerFlags.begin(), sanitizerFlags.end()); + if(sanitize) + { + vector sanitizerFlags = getCompilerSanitizerFlags(config); + compileCCommand.insert(compileCCommand.end(), sanitizerFlags.begin(), sanitizerFlags.end()); + } compileCppCommand = compileCCommand; compileCppCommand[0] = ninja::NinjaArg::createRaw(cppCompilerName); @@ -1101,8 +1145,11 @@ namespace backend vector optimizationFlags = getCompilerOptimizationFlags(config); compileCCommand.insert(compileCCommand.end(), optimizationFlags.begin(), optimizationFlags.end()); - vector sanitizerFlags = getCompilerSanitizerFlags(config); - compileCCommand.insert(compileCCommand.end(), sanitizerFlags.begin(), sanitizerFlags.end()); + if(sanitize) + { + vector sanitizerFlags = getCompilerSanitizerFlags(config); + compileCCommand.insert(compileCCommand.end(), sanitizerFlags.begin(), sanitizerFlags.end()); + } compileCppCommand = compileCCommand; compileCppCommand.push_back(ninja::NinjaArg("/EHs")); @@ -1288,7 +1335,7 @@ namespace backend case Compiler::MINGW_W64: case Compiler::GCC: { - packagingFlags = "-static -static-libgcc -static-libstdc++"; + packagingFlags = "-static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic"; break; } case Compiler::MSVC: @@ -1319,10 +1366,11 @@ namespace backend string noUndefinedFlag; if(!onlyZigFiles) { + bool isCompilerClangLike = (compilerType == RuntimeCompilerType::CLANG) || (compilerType == RuntimeCompilerType::EMSCRIPTEN); if(usesCppFiles) - noUndefinedFlag = isCppCompilerClang ? "-Wl,-undefined,error" : "-Wl,--no-undefined,--as-needed"; + noUndefinedFlag = isCompilerClangLike ? "-Wl,-undefined,error" : "-Wl,--no-undefined,--as-needed"; else - noUndefinedFlag = isCCompilerClang ? "-Wl,-undefined,error" : "-Wl,--no-undefined,--as-needed"; + noUndefinedFlag = isCompilerClangLike ? "-Wl,-undefined,error" : "-Wl,--no-undefined,--as-needed"; } ninja::NinjaVariable zigObjectArgs("object_args"); @@ -1371,10 +1419,15 @@ namespace backend ninja::NinjaArg::createRaw(noUndefinedFlag) }); + if(compilerType == RuntimeCompilerType::EMSCRIPTEN) + { + buildExeArgs.push_back(ninja::NinjaArg::createRaw("-s MAIN_MODULE=1")); + } + if(!rpath.empty()) buildExeArgs.push_back(ninja::NinjaArg("-Wl,-rpath," + rpath)); - if(config.getSanitize()) + if(sanitize) { buildExeArgs.insert(buildExeArgs.end(), { ninja::NinjaArg::createRaw("-lasan"), @@ -1451,7 +1504,7 @@ namespace backend ninja::NinjaArg::createRaw("-luserenv"), ninja::NinjaArg::createRaw("-lopengl32"), ninja::NinjaArg::createRaw("-lglu32"), - ninja::NinjaArg::createRaw("-Wl,-Bstatic -lwinpthread"), + ninja::NinjaArg::createRaw("-Wl,-Bstatic -lwinpthread -Wl,-Bdynamic"), ninja::NinjaArg::createRaw("-lshell32") }); } @@ -1551,7 +1604,10 @@ namespace backend case Compiler::MINGW_W64: case Compiler::GCC: { - generatedFile = "lib" + config.getPackageName() + "." + CONFIG_DYNAMIC_LIB_FILE_EXTENSION; + const char *fileExtension = CONFIG_DYNAMIC_LIB_FILE_EXTENSION; + if(compilerType == RuntimeCompilerType::EMSCRIPTEN) + fileExtension = "wasm"; + generatedFile = "lib" + config.getPackageName() + "." + fileExtension; break; } case Compiler::MSVC: @@ -1594,7 +1650,12 @@ namespace backend ninja::NinjaArg::createRaw(noUndefinedFlag) }); - if(config.getSanitize()) + if(compilerType == RuntimeCompilerType::EMSCRIPTEN) + { + buildDynamicArgs.push_back(ninja::NinjaArg::createRaw("-s SIDE_MODULE=1")); + } + + if(sanitize) { buildDynamicArgs.insert(buildDynamicArgs.end(), { ninja::NinjaArg::createRaw("-lasan"), @@ -1665,7 +1726,7 @@ namespace backend ninja::NinjaArg::createRaw("-luserenv"), ninja::NinjaArg::createRaw("-lopengl32"), ninja::NinjaArg::createRaw("-lglu32"), - ninja::NinjaArg::createRaw("-Wl,-Bstatic -lwinpthread"), + ninja::NinjaArg::createRaw("-Wl,-Bstatic -lwinpthread -Wl,-Bdynamic"), ninja::NinjaArg::createRaw("-lshell32") }); } @@ -1697,7 +1758,7 @@ namespace backend if (!buildResult) return buildResult; - if(config.isMainProject()) + if((config.isMainProject() && !config.shouldBuildTests()) || config.isTest()) { buildResult = buildCompilationDatabase(savePath, config.getProjectPath()); if(!buildResult) @@ -1820,14 +1881,6 @@ namespace backend Result buildFileResult = ninja.build(sibsTestConfig, buildPath.c_str()); if (!buildFileResult) return buildFileResult; - - // Main projects test should also have compilation database, so we can use it inside IDE - if(config.isMainProject()) - { - buildFileResult = buildCompilationDatabase(buildPath.c_str(), testSourceDirNative); - if(!buildFileResult) - return buildFileResult; - } if(!zigTest) { -- cgit v1.2.3