From 61d9e8699687342c2e32c32c8d4eb71760d5d290 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 26 Jun 2021 17:33:24 +0200 Subject: Use fork/exec instead of popen. Add Path class --- backend/ninja/Ninja.cpp | 223 +++++++++++++++++------------------------------- 1 file changed, 79 insertions(+), 144 deletions(-) (limited to 'backend/ninja/Ninja.cpp') diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index ea3d96f..be78ba1 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -40,43 +40,6 @@ namespace backend return result; } - static string join(const vector &list, const char *joinStr) - { - if(list.empty()) return ""; - string result; - long stringSize = 0; - long joinStrLen = strlen(joinStr); - int i = 0; - for(const string &str : list) - { - stringSize += str.size(); - if(!str.empty() && i > 0) - stringSize += joinStrLen; - ++i; - } - - result.reserve(stringSize); - - i = 0; - for(const string &str : list) - { - if(i > 0) - result += joinStr; - result += str; - ++i; - } - - return result; - } - - static bool endsWith(const string &str, const string &endWithStr) - { - if(endWithStr.size() > str.size()) - return false; - else - return strncmp(&str[str.size() - endWithStr.size()], &endWithStr[0], endWithStr.size()) == 0; - } - static Ninja::LibraryType getNinjaLibraryType(PackageType packageType) { switch(packageType) @@ -147,31 +110,6 @@ namespace backend return ""; } - static string getObjectFileNameFlag(Compiler compiler, const string &objectFileName) - { - string result; - switch (compiler) - { - case Compiler::MINGW_W64: - case Compiler::GCC: - { - result = "-o "; - result += objectFileName; - break; - } - case Compiler::MSVC: - { - result = "/Fo"; - result += objectFileName; - break; - } - default: - assert(false); - break; - } - return result; - } - static vector getLanguageVersionFlag(Compiler compiler, CVersion cVersion) { switch (compiler) @@ -320,22 +258,20 @@ namespace backend Result Ninja::getLinkerFlags(const SibsConfig &config, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback, CflagsCallbackFunc cflagsCallbackFunc) const { - const vector &packageListDependencies = config.getPackageListDependencies(); + const vector &packageListDependencies = config.getPackageListDependencies(); Result globalLibDirResult = getHomeDir(); if (!globalLibDirResult) return Result::Err(globalLibDirResult); - FileString globalLibDir = globalLibDirResult.unwrap(); - globalLibDir += TINYDIR_STRING("/.cache/sibs/lib/"); - globalLibDir += toFileString(asString(config.platform)); - Result createGlobalLibDirResult = createDirectoryRecursive(globalLibDir.c_str()); + Path globalLibDir = Path(globalLibDirResult.unwrap()).join(".cache/sibs/lib").join(toFileString(asString(config.platform))); + Result createGlobalLibDirResult = createDirectoryRecursive(globalLibDir.data.c_str()); if(createGlobalLibDirResult.isErr()) return createGlobalLibDirResult; // If pkg-config is not available then it will be ignored and we check if package instead exists as a global lib (on github etc) - vector globalLibDependencies; - vector pkgConfigDependencies; - for(PackageListDependency *dependency : packageListDependencies) + vector globalLibDependencies; + vector pkgConfigDependencies; + for(const PackageListDependency &dependency : packageListDependencies) { // PkgConfig libraries, even the static ones are most likely not built statically against libgcc/libc++, so we don't use them if(!config.packaging && PkgConfig::validatePkgConfigPackageVersionExists(dependency)) @@ -353,7 +289,7 @@ namespace backend { printf("%s, using global lib...\n", pkgConfigFlagsResult.getErrMsg().c_str()); globalLibDependencies.reserve(globalLibDependencies.size() + pkgConfigDependencies.size()); - for (PackageListDependency *pkgConfigDependency : pkgConfigDependencies) + for (const PackageListDependency &pkgConfigDependency : pkgConfigDependencies) { globalLibDependencies.push_back(pkgConfigDependency); } @@ -368,7 +304,7 @@ namespace backend cflagsCallbackFunc(pkgConfigFlag.cflags); } - return GlobalLib::getLibs(globalLibDependencies, config, globalLibDir, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback, globalIncludeDirCallback); + return GlobalLib::getLibs(globalLibDependencies, config, globalLibDir.data, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback, globalIncludeDirCallback); } Result Ninja::buildSubProjects(LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) @@ -764,9 +700,9 @@ namespace backend Result Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { - string cCompilerName = BackendUtils::getCompilerCExecutable(config.getCompiler()); - string cppCompilerName = BackendUtils::getCompilerCppExecutable(config.getCompiler()); - string compilerLinker = BackendUtils::getCompilerLinker(config.getCompiler()); + std::vector cCompilerName = BackendUtils::getCompilerCExecutable(config.getCompiler()); + std::vector cppCompilerName = BackendUtils::getCompilerCppExecutable(config.getCompiler()); + std::vector compilerLinker = BackendUtils::getCompilerLinker(config.getCompiler()); RuntimeCompilerType cCompilerType = BackendUtils::getCCompilerType(config.getCompiler()); RuntimeCompilerType cppCompilerType = BackendUtils::getCppCompilerType(config.getCompiler()); @@ -786,19 +722,17 @@ namespace backend if (!createBuildDirResult) return createBuildDirResult; - FileString generatedHeadersDir = config.getProjectPath() + TINYDIR_STRING("/sibs-build/"); - generatedHeadersDir += toFileString(asString(config.platform)) + TINYDIR_STRING("/"); - generatedHeadersDir += TINYDIR_STRING("generated-headers"); - Result createGeneratedHeadersDirResult = createDirectoryRecursive(generatedHeadersDir.c_str()); + Path generatedHeadersDir = Path(config.getProjectPath()).join(TINYDIR_STRING("sibs-build")).join(toFileString(asString(config.platform))).join(TINYDIR_STRING("generated-headers")); + Result createGeneratedHeadersDirResult = createDirectoryRecursive(generatedHeadersDir.data.c_str()); if (!createGeneratedHeadersDirResult) return createGeneratedHeadersDirResult; - FileString generatedZigHeadersDir = generatedHeadersDir + TINYDIR_STRING("/zig"); - Result createGeneratedZigHeadersDirResult = createDirectory(generatedZigHeadersDir.c_str()); + Path generatedZigHeadersDir = Path(generatedHeadersDir).join(TINYDIR_STRING("zig")); + Result createGeneratedZigHeadersDirResult = createDirectory(generatedZigHeadersDir.data.c_str()); if (!createGeneratedZigHeadersDirResult) return createGeneratedZigHeadersDirResult; - string generatedZigHeaderDirUtf8 = toUtf8(generatedZigHeadersDir); + string generatedZigHeaderDirUtf8 = toUtf8(generatedZigHeadersDir.data); LibraryType libraryType = getNinjaLibraryType(config.getPackageType()); // TODO: Instead of statically linking everything, maybe we should build everything as they prefer to be built @@ -814,8 +748,7 @@ namespace backend string savePathUtf8 = toUtf8(savePath); string projectPathUtf8 = toUtf8(config.getProjectPath()); - FileString ninjaBuildFilePath = savePath; - ninjaBuildFilePath += TINYDIR_STRING("/build.ninja"); + Path ninjaBuildFilePath = Path(savePath).join(TINYDIR_STRING("build.ninja")); ninja::NinjaBuildFile ninjaBuildFile; @@ -929,7 +862,7 @@ namespace backend } globalIncDir += dependencyExportIncludeDirs; - globalIncDir += " " + getIncludeOptionFlag(config.getCompiler(), toUtf8(generatedHeadersDir)); + globalIncDir += " " + getIncludeOptionFlag(config.getCompiler(), toUtf8(generatedHeadersDir.data)); ninjaBuildFile.defineGlobalVariable("globalIncDir", globalIncDir); // TODO: Find a better way to convert includes, this could be slow... ninjaBuildFile.defineGlobalVariable("globalIncDirZig", convertCIncludeSyntaxToZigInclude(config.getCompiler(), globalIncDir)); @@ -992,7 +925,6 @@ namespace backend case LibraryType::EXECUTABLE: { baseCompileCArgs.insert(baseCompileCArgs.end(), { - ninja::NinjaArg::createRaw(cCompilerName), ninja::NinjaArg("-c"), ninja::NinjaArg::createRaw("-fPIE -fPIC"), ninja::NinjaArg("$in"), @@ -1005,7 +937,6 @@ namespace backend case LibraryType::DYNAMIC: { baseCompileCArgs.insert(baseCompileCArgs.end(), { - ninja::NinjaArg::createRaw(cCompilerName), ninja::NinjaArg("-c"), ninja::NinjaArg("-fPIC"), ninja::NinjaArg("$in"), @@ -1064,11 +995,18 @@ namespace backend compileCCommand.push_back(std::move(sanitizerFlag)); compileCppCommand = compileCCommand; - compileCppCommand[0] = ninja::NinjaArg::createRaw(cppCompilerName); compileCppCommand.insert(compileCppCommand.end(), { ninja::NinjaArg("-fexceptions"), ninja::NinjaArg("-Wnon-virtual-dtor") }); + + for(auto it = cCompilerName.rbegin(), end = cCompilerName.rend(); it != end; ++it) { + compileCCommand.insert(compileCCommand.begin(), ninja::NinjaArg(*it)); + } + + for(auto it = cppCompilerName.rbegin(), end = cppCompilerName.rend(); it != end; ++it) { + compileCppCommand.insert(compileCppCommand.begin(), ninja::NinjaArg(*it)); + } break; } case Compiler::MSVC: @@ -1388,9 +1326,17 @@ namespace backend case Compiler::MINGW_W64: case Compiler::GCC: { + if(usesCppFiles) { + for(const FileString &arg : cppCompilerName) { + buildExeArgs.push_back(ninja::NinjaArg(arg)); + } + } else { + for(const FileString &arg : cCompilerName) { + buildExeArgs.push_back(ninja::NinjaArg(arg)); + } + } string rpath = extractDynamicLibDirsFromLinkerFlags(dynamicLinkerFlags); buildExeArgs.insert(buildExeArgs.end(), { - ninja::NinjaArg::createRaw(usesCppFiles ? cppCompilerName : cCompilerName), ninja::NinjaArg::createRaw("-o"), ninja::NinjaArg::createRaw("$out"), ninja::NinjaArg::createRaw("$in"), @@ -1437,9 +1383,11 @@ namespace backend } case Compiler::MSVC: { + for(const FileString &arg : cppCompilerName) { + buildExeArgs.push_back(ninja::NinjaArg(arg)); + } // 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(cppCompilerName), ninja::NinjaArg::createRaw("$in"), ninja::NinjaArg::createRaw("/Fe$out"), ninja::NinjaArg::createRaw("Ws2_32.lib"), @@ -1535,8 +1483,10 @@ namespace backend case Compiler::MINGW_W64: case Compiler::GCC: { + for(const FileString &arg : compilerLinker) { + buildStaticArgs.push_back(ninja::NinjaArg(arg)); + } buildStaticArgs.insert(buildStaticArgs.end(), { - ninja::NinjaArg::createRaw(compilerLinker), ninja::NinjaArg::createRaw("rcs"), ninja::NinjaArg::createRaw("$out"), ninja::NinjaArg::createRaw("$in") @@ -1545,8 +1495,10 @@ namespace backend } case Compiler::MSVC: { + for(const FileString &arg : compilerLinker) { + buildStaticArgs.push_back(ninja::NinjaArg(arg)); + } buildStaticArgs.insert(buildStaticArgs.end(), { - ninja::NinjaArg::createRaw(compilerLinker), ninja::NinjaArg::createRaw("/OUT:$out"), ninja::NinjaArg::createRaw("$in") }); @@ -1623,8 +1575,16 @@ namespace backend case Compiler::MINGW_W64: case Compiler::GCC: { + if(usesCppFiles) { + for(const FileString &arg : cppCompilerName) { + buildDynamicArgs.push_back(ninja::NinjaArg(arg)); + } + } else { + for(const FileString &arg : cCompilerName) { + buildDynamicArgs.push_back(ninja::NinjaArg(arg)); + } + } buildDynamicArgs.insert(buildDynamicArgs.end(), { - ninja::NinjaArg::createRaw(usesCppFiles ? cppCompilerName : cCompilerName), ninja::NinjaArg::createRaw("$in"), ninja::NinjaArg::createRaw("-shared"), ninja::NinjaArg("-Wl,-soname," + generatedFile), @@ -1665,8 +1625,10 @@ namespace backend } case Compiler::MSVC: { + for(const FileString &arg : compilerLinker) { + buildDynamicArgs.push_back(ninja::NinjaArg(arg)); + } buildDynamicArgs.insert(buildDynamicArgs.end(), { - ninja::NinjaArg::createRaw(compilerLinker), ninja::NinjaArg::createRaw("/OUT:$out"), ninja::NinjaArg::createRaw("$in"), ninja::NinjaArg::createRaw("Ws2_32.lib"), @@ -1735,7 +1697,7 @@ namespace backend if(!sourceFiles.empty()) { string result = ninjaBuildFile.generate(); - Result fileOverwriteResult = sibs::fileOverwrite(ninjaBuildFilePath.c_str(), sibs::StringView(result.data(), result.size())); + Result fileOverwriteResult = sibs::fileOverwrite(ninjaBuildFilePath.data.c_str(), sibs::StringView(result.data(), result.size())); if (fileOverwriteResult.isErr()) return fileOverwriteResult; @@ -1777,24 +1739,18 @@ namespace backend parentExportIncludeDirs += getIncludeOptionFlag(config.getCompiler(), parentExportIncludeDir); } -#if OS_FAMILY == OS_FAMILY_POSIX - FileString testSourceDirNative = testSourceDir; - FileString projectConfFilePath = testSourceDir; -#else - FileString testSourceDirNative = utf8To16(testSourceDir); - FileString projectConfFilePath = testSourceDirNative; -#endif - projectConfFilePath += TINYDIR_STRING("/project.conf"); + Path testSourceDirNative = toFileString(testSourceDir); + Path projectConfFilePath = Path(testSourceDirNative).join("project.conf"); - FileType projectConfFileType = getFileType(projectConfFilePath.c_str()); - SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative, config.getOptimizationLevel()); + FileType projectConfFileType = getFileType(projectConfFilePath.data.c_str()); + SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative.data, config.getOptimizationLevel()); sibsTestConfig.platform = config.platform; sibsTestConfig.setSanitize(config.getSanitize()); sibsTestConfig.zigTestFiles = move(config.zigTestFiles); sibsTestConfig.zigTestAllFiles = config.zigTestAllFiles; if(projectConfFileType == FileType::REGULAR) { - Result result = Config::readFromFile(projectConfFilePath.c_str(), sibsTestConfig); + Result result = Config::readFromFile(projectConfFilePath.data.c_str(), sibsTestConfig); if(!result) return result; } @@ -1826,7 +1782,7 @@ namespace backend bool zigTest = false; if(config.zigTestAllFiles) { - backend::BackendUtils::collectSourceFiles(testSourceDirNative.c_str(), &ninja, sibsTestConfig); + backend::BackendUtils::collectSourceFiles(testSourceDirNative.data.c_str(), &ninja, sibsTestConfig); // TODO: This can be optimized as well. No need to insert non-zig files if we are going to remove them. // Maybe pass a filter callback function to @collectSourceFiles. for(auto it = ninja.sourceFiles.begin(); it != ninja.sourceFiles.end(); ) @@ -1853,33 +1809,29 @@ namespace backend } else { - backend::BackendUtils::collectSourceFiles(testSourceDirNative.c_str(), &ninja, sibsTestConfig); + backend::BackendUtils::collectSourceFiles(testSourceDirNative.data.c_str(), &ninja, sibsTestConfig); } if(!ninja.getSourceFiles().empty()) { - FileString buildPath = testSourceDirNative; - buildPath += TINYDIR_STRING("/sibs-build/") + toFileString(asString(config.platform)); + Path buildPath = Path(testSourceDirNative).join(TINYDIR_STRING("sibs-build")).join(toFileString(asString(config.platform))); switch(sibsTestConfig.getOptimizationLevel()) { case OPT_LEV_DEBUG: - buildPath += TINYDIR_STRING("/debug"); + buildPath.join(TINYDIR_STRING("debug")); break; case OPT_LEV_RELEASE: - buildPath += TINYDIR_STRING("/release"); + buildPath.join(TINYDIR_STRING("release")); break; } - Result buildFileResult = ninja.build(sibsTestConfig, buildPath.c_str()); + Result buildFileResult = ninja.build(sibsTestConfig, buildPath.data.c_str()); if (!buildFileResult) return buildFileResult; if(!zigTest) { - FileString testExecutableName = buildPath; - testExecutableName += TINYDIR_STRING("/"); - testExecutableName += toFileString(sibsTestConfig.getPackageName()); - Result runTestResult = exec(testExecutableName.c_str(), true); + Result runTestResult = exec({ Path(buildPath).join(toFileString(sibsTestConfig.getPackageName())).data }, true); if(!runTestResult) return Result::Err(runTestResult); @@ -1893,26 +1845,7 @@ namespace backend Result Ninja::compile(const _tinydir_char_t *buildFilePath) { -#if OS_TYPE == OS_TYPE_LINUX - FileString command; - if(isatty(STDOUT_FILENO) == 1) - { - command = TINYDIR_STRING("script -eqc 'ninja -C \""); - command += buildFilePath; - command += TINYDIR_STRING("\"' /dev/null"); - } - else - { - command = TINYDIR_STRING("ninja -C \""); - command += buildFilePath; - command += TINYDIR_STRING("\""); - } -#else - FileString command = TINYDIR_STRING("ninja -C \""); - command += buildFilePath; - command += TINYDIR_STRING("\""); -#endif - Result execResult = exec(command.c_str(), true); + Result execResult = exec({ TINYDIR_STRING("ninja"), TINYDIR_STRING("-C"), buildFilePath }, true); if(execResult.isOk()) { if(execResult.unwrap().exitCode == 0) @@ -1929,15 +1862,17 @@ namespace backend Result Ninja::buildCompilationDatabase(const _tinydir_char_t *buildFilePath, const FileString &saveDir) { - FileString command = TINYDIR_STRING("ninja -C \""); - command += buildFilePath; - command += TINYDIR_STRING("\" -t compdb compile_c compile_cpp > \""); - command += saveDir; - command += TINYDIR_STRING("/compile_commands.json\""); - Result execResult = exec(command.c_str(), false); + Result execResult = exec({ + TINYDIR_STRING("ninja"), TINYDIR_STRING("-C"), buildFilePath, TINYDIR_STRING("-t"), + TINYDIR_STRING("compdb"), TINYDIR_STRING("compile_c"), TINYDIR_STRING("compile_cpp") + }, false); if(execResult) { - if(execResult.unwrap().exitCode != 0) + if(execResult.unwrap().exitCode == 0) + { + fileOverwrite(Path(saveDir).join("compile_commands.json").data.c_str(), { execResult.unwrap().execStdout.data(), execResult.unwrap().execStdout.size() }); + } + else { string errMsg = "Failed to build compilation database, reason: "; errMsg += execResult.unwrap().execStdout; -- cgit v1.2.3