diff options
-rw-r--r-- | backend/ninja/Ninja.cpp | 356 | ||||
-rw-r--r-- | src/main.cpp | 2 |
2 files changed, 230 insertions, 128 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index 2c76fd4..0b7dbe5 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -498,7 +498,7 @@ namespace backend string resultStr; for(ninja::NinjaArg &include : result) { - resultStr += "-isystem \"" + include.arg + "\""; + resultStr += " -isystem \"" + include.arg + "\""; } return resultStr; } @@ -592,6 +592,16 @@ namespace backend return filepath.size(); } + static string combineObjectFilesAsZigArgs(const vector<string> &objectFiles) + { + string result; + for(const string &objectFile : objectFiles) + { + result += " --object \"" + objectFile + "\""; + } + return result; + } + Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { Result<bool> createBuildDirResult = createDirectoryRecursive(savePath); @@ -888,58 +898,59 @@ namespace backend // TODO: Remove --library c if project does not depend on c libraries or project only has .zig files + vector<ninja::NinjaArg> commonZigArgs = { + ninja::NinjaArg::createRaw("-isystem ../../"), + ninja::NinjaArg::createRaw("--color on"), + ninja::NinjaArg::createRaw("--library c"), // TODO: Remove this if project does not depend on c libraries or project only has .zig files + ninja::NinjaArg::createRaw("$globalIncDirZig") + }; + ninja::NinjaVariable zigHeaderFile("headerFile"); vector<ninja::NinjaArg> zigTestArgs = { - ninja::NinjaArg::createRaw("zig test $in --output $out --output-h $headerFile -isystem ../../ --color on --library c $globalIncDirZig") + ninja::NinjaArg::createRaw("zig test $in --output $out --output-h $headerFile") }; - // TODO: Find a way to do this more efficiently - vector<ninja::NinjaArg> cflagsIncludes = convertCFlagsIncludesToZigIncludes(config.getCompiler(), cflags); vector<ninja::NinjaArg> compileZigArgs = { ninja::NinjaArg::createRaw("zig build-obj"), ninja::NinjaArg::createRaw("$in"), - ninja::NinjaArg::createRaw("--output $out"), ninja::NinjaArg::createRaw("--output-h $headerFile"), - ninja::NinjaArg::createRaw("-isystem ../../"), - ninja::NinjaArg::createRaw("--color on"), - ninja::NinjaArg::createRaw("--library c"), // TODO: Remove this if project does not depend on c libraries or project only has .zig files - ninja::NinjaArg::createRaw("$globalIncDirZig") + ninja::NinjaArg::createRaw("--output $out") }; - compileZigArgs.insert(compileZigArgs.end(), cflagsIncludes.begin(), cflagsIncludes.end()); - zigTestArgs.insert(zigTestArgs.end(), cflagsIncludes.begin(), cflagsIncludes.end()); - - if(zigTest) - { - // TODO: Verify if we really need to add all libraries for every object file - vector<ninja::NinjaArg> zigLibraryFlags = convertCLibrariesToZigLibraries(config.getCompiler(), allLinkerFlags); - zigTestArgs.insert(zigTestArgs.end(), zigLibraryFlags.begin(), zigLibraryFlags.end()); - } + // TODO: Find a way to do this more efficiently + vector<ninja::NinjaArg> cflagsIncludes = convertCFlagsIncludesToZigIncludes(config.getCompiler(), cflags); + commonZigArgs.insert(commonZigArgs.end(), cflagsIncludes.begin(), cflagsIncludes.end()); if(config.getOptimizationLevel() == sibs::OPT_LEV_RELEASE) { // TODO: Specify a way to change these options, either in project.conf or argument to sibs build - compileZigArgs.insert(compileZigArgs.end(), { - ninja::NinjaArg::createRaw("--release-safe"), - ninja::NinjaArg::createRaw("--strip") - }); - - zigTestArgs.insert(zigTestArgs.end(), { + commonZigArgs.insert(commonZigArgs.end(), { ninja::NinjaArg::createRaw("--release-safe"), ninja::NinjaArg::createRaw("--strip") }); } + zigTestArgs.insert(zigTestArgs.end(), commonZigArgs.begin(), commonZigArgs.end()); + compileZigArgs.insert(compileZigArgs.end(), commonZigArgs.begin(), commonZigArgs.end()); + if(libraryType == LibraryType::STATIC) compileZigArgs.push_back(ninja::NinjaArg::createRaw("--static")); else if(libraryType == LibraryType::DYNAMIC) // TODO: Verify if this is the correct way to handle dynamic libraries in zig compileZigArgs.push_back(ninja::NinjaArg::createRaw("-rdynamic")); + if(zigTest) + { + // TODO: Verify if we really need to add all libraries for every object file + vector<ninja::NinjaArg> zigLibraryFlags = convertCLibrariesToZigLibraries(config.getCompiler(), allLinkerFlags); + zigTestArgs.insert(zigTestArgs.end(), zigLibraryFlags.begin(), zigLibraryFlags.end()); + } + ninja::NinjaRule *compileZigRule = ninjaBuildFile.createRule("compile_zig", compileZigArgs); ninja::NinjaRule *testZigRule = ninjaBuildFile.createRule("zig_test", zigTestArgs); bool usesCFiles = false; bool usesCppFiles = false; + bool onlyZigFiles = true; vector<string> objectNames; objectNames.reserve(sourceFiles.size()); @@ -973,6 +984,8 @@ namespace backend ninjaBuild = compileZigRule->build("../../" + sourceFile.filepath, objectName, { zigHeaderFileValue }); zigBuilds.push_back(ninjaBuild); } + else + onlyZigFiles = false; } for(const sibs::SourceFile &sourceFile : sourceFiles) @@ -982,6 +995,7 @@ namespace backend { case sibs::Language::C: { + // TODO: Verify what happens if object name contains colon or space objectName += config.getPackageName() + "@exe/" + sourceFile.filepath; objectName += getObjectFileExtension(config.getCompiler()); compileCRule->build("../../" + sourceFile.filepath, objectName, {}, zigBuilds); @@ -1017,72 +1031,98 @@ namespace backend string projectGeneratedBinary = "\""; projectGeneratedBinary += savePathUtf8; projectGeneratedBinary += "/"; + + ninja::NinjaVariable zigObjectArgs("object_args"); + string objectZigArgs; + if(onlyZigFiles) + objectZigArgs = combineObjectFilesAsZigArgs(objectNames); + ninja::NinjaArgValue zigObjectArgsValue = { zigObjectArgs, move(objectZigArgs) }; switch (libraryType) { case LibraryType::EXECUTABLE: { vector<ninja::NinjaArg> buildExeArgs; - switch (config.getCompiler()) + if(onlyZigFiles) { - case Compiler::GCC: + buildExeArgs.insert(buildExeArgs.end(), { + ninja::NinjaArg::createRaw("zig build-exe"), + ninja::NinjaArg::createRaw("--name __tmp_zig"), + ninja::NinjaArg::createRaw("--output $out"), + ninja::NinjaArg::createRaw("$object_args"), + }); + buildExeArgs.insert(buildExeArgs.end(), commonZigArgs.begin(), commonZigArgs.end()); + + vector<ninja::NinjaArg> zigLibraryFlags = convertCLibrariesToZigLibraries(config.getCompiler(), allLinkerFlags); + buildExeArgs.insert(buildExeArgs.end(), zigLibraryFlags.begin(), zigLibraryFlags.end()); + + ninja::NinjaRule *buildExeRule = ninjaBuildFile.createRule("build_exec", buildExeArgs); + buildExeRule->build(join(objectNames, " "), config.getPackageName(), { zigObjectArgsValue }); + } + else + { + switch (config.getCompiler()) { - buildExeArgs.insert(buildExeArgs.end(), { - ninja::NinjaArg("ccache"), - ninja::NinjaArg(usesCppFiles ? "c++" : "cc"), - ninja::NinjaArg("-o"), - ninja::NinjaArg("$out"), - ninja::NinjaArg("$in"), - ninja::NinjaArg("-Wl,--no-undefined,--as-needed") - }); - - if(config.getSanitize()) + case Compiler::GCC: { buildExeArgs.insert(buildExeArgs.end(), { - ninja::NinjaArg("-lasan"), - ninja::NinjaArg("-lubsan") + ninja::NinjaArg::createRaw("ccache"), + ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"), + ninja::NinjaArg::createRaw("-o"), + ninja::NinjaArg::createRaw("$out"), + ninja::NinjaArg::createRaw("$in"), + ninja::NinjaArg::createRaw("-Wl,--no-undefined,--as-needed") }); - } - // TODO: Add flag to disable -ldl and -lm (dlopen, dlclose, floor, max, ...) - buildExeArgs.insert(buildExeArgs.end(), { - ninja::NinjaArg("-ldl"), - ninja::NinjaArg("-lm") - }); - break; - } - case Compiler::MSVC: - { - // TODO: Do not link all of these. Find a way to only link the ones that are needed - buildExeArgs.insert(buildExeArgs.end(), { - ninja::NinjaArg("cl.exe"), - ninja::NinjaArg("$in"), - ninja::NinjaArg("/Fe$out"), - ninja::NinjaArg("Ws2_32.lib"), - ninja::NinjaArg("Wldap32.lib"), - ninja::NinjaArg("Crypt32.lib"), - ninja::NinjaArg("Advapi32.lib"), - ninja::NinjaArg("Gdi32.lib"), - ninja::NinjaArg("User32.lib"), - ninja::NinjaArg("Userenv.lib"), - ninja::NinjaArg("OpenGL32.lib"), - ninja::NinjaArg("GlU32.lib"), - ninja::NinjaArg("Shell32.lib") - }); - break; + if(config.getSanitize()) + { + buildExeArgs.insert(buildExeArgs.end(), { + ninja::NinjaArg::createRaw("-lasan"), + ninja::NinjaArg::createRaw("-lubsan") + }); + } + + // TODO: Add flag to disable -ldl and -lm (dlopen, dlclose, floor, max, ...) + buildExeArgs.insert(buildExeArgs.end(), { + ninja::NinjaArg::createRaw("-ldl"), + ninja::NinjaArg::createRaw("-lm") + }); + break; + } + case Compiler::MSVC: + { + // 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("$in"), + ninja::NinjaArg::createRaw("/Fe$out"), + ninja::NinjaArg::createRaw("Ws2_32.lib"), + ninja::NinjaArg::createRaw("Wldap32.lib"), + ninja::NinjaArg::createRaw("Crypt32.lib"), + ninja::NinjaArg::createRaw("Advapi32.lib"), + ninja::NinjaArg::createRaw("Gdi32.lib"), + ninja::NinjaArg::createRaw("User32.lib"), + ninja::NinjaArg::createRaw("Userenv.lib"), + ninja::NinjaArg::createRaw("OpenGL32.lib"), + ninja::NinjaArg::createRaw("GlU32.lib"), + ninja::NinjaArg::createRaw("Shell32.lib") + }); + break; + } } - } - if (!allLinkerFlags.empty()) - buildExeArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags)); + if (!allLinkerFlags.empty()) + buildExeArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags)); - ninja::NinjaRule *buildExeRule = ninjaBuildFile.createRule("build_exec", buildExeArgs); - buildExeRule->build(join(objectNames, " "), config.getPackageName(), {}); + ninja::NinjaRule *buildExeRule = ninjaBuildFile.createRule("build_exec", buildExeArgs); + buildExeRule->build(join(objectNames, " "), config.getPackageName(), {}); + } projectGeneratedBinary += config.getPackageName(); #if OS_FAMILY == OS_FAMILY_WINDOWS projectGeneratedBinary += ".exe"; #endif + projectGeneratedBinary += "\""; break; } case LibraryType::STATIC: @@ -1094,28 +1134,60 @@ namespace backend case Compiler::GCC: { generatedFile = "lib" + config.getPackageName() + ".a"; - buildStaticArgs.insert(buildStaticArgs.end(), { - ninja::NinjaArg::createRaw("ar"), - ninja::NinjaArg::createRaw("rcs"), - ninja::NinjaArg::createRaw("$out"), - ninja::NinjaArg::createRaw("$in") - }); break; } case Compiler::MSVC: { generatedFile = config.getPackageName() + ".lib"; - buildStaticArgs.insert(buildStaticArgs.end(), { - ninja::NinjaArg::createRaw("lib.exe"), - ninja::NinjaArg::createRaw("/OUT:$out"), - ninja::NinjaArg::createRaw("$in") - }); break; } } - ninja::NinjaRule *buildStaticRule = ninjaBuildFile.createRule("build_static", buildStaticArgs); - buildStaticRule->build(join(objectNames, " "), generatedFile, {}); + if(onlyZigFiles) + { + buildStaticArgs.insert(buildStaticArgs.end(), { + ninja::NinjaArg::createRaw("zig build-lib --static"), + ninja::NinjaArg::createRaw("--name __tmp_zig"), + ninja::NinjaArg::createRaw("--output $out"), + ninja::NinjaArg::createRaw("$object_args") + }); + buildStaticArgs.insert(buildStaticArgs.end(), commonZigArgs.begin(), commonZigArgs.end()); + + // TODO: Verify if this is needed. It's not needed for c/c++ files... + //vector<ninja::NinjaArg> zigLibraryFlags = convertCLibrariesToZigLibraries(config.getCompiler(), allLinkerFlags); + //buildStaticArgs.insert(buildStaticArgs.end(), zigLibraryFlags.begin(), zigLibraryFlags.end()); + + ninja::NinjaRule *buildStaticRule = ninjaBuildFile.createRule("build_static", buildStaticArgs); + buildStaticRule->build(join(objectNames, " "), generatedFile, { zigObjectArgsValue }); + } + else + { + switch (config.getCompiler()) + { + case Compiler::GCC: + { + buildStaticArgs.insert(buildStaticArgs.end(), { + ninja::NinjaArg::createRaw("ar"), + ninja::NinjaArg::createRaw("rcs"), + ninja::NinjaArg::createRaw("$out"), + ninja::NinjaArg::createRaw("$in") + }); + break; + } + case Compiler::MSVC: + { + buildStaticArgs.insert(buildStaticArgs.end(), { + ninja::NinjaArg::createRaw("lib.exe"), + ninja::NinjaArg::createRaw("/OUT:$out"), + ninja::NinjaArg::createRaw("$in") + }); + break; + } + } + + ninja::NinjaRule *buildStaticRule = ninjaBuildFile.createRule("build_static", buildStaticArgs); + buildStaticRule->build(join(objectNames, " "), generatedFile, {}); + } projectGeneratedBinary += generatedFile; projectGeneratedBinary += "\""; @@ -1133,59 +1205,89 @@ namespace backend case Compiler::GCC: { generatedFile = "lib" + config.getPackageName() + ".so"; - - buildDynamicArgs.insert(buildDynamicArgs.end(), { - ninja::NinjaArg("ccache"), - ninja::NinjaArg(usesCppFiles ? "c++" : "cc"), - ninja::NinjaArg("$in"), - ninja::NinjaArg("-shared"), - ninja::NinjaArg("-o"), - ninja::NinjaArg("$out"), - ninja::NinjaArg("-Wl,--no-undefined,--as-needed") - }); - - if(config.getSanitize()) - { - buildDynamicArgs.insert(buildDynamicArgs.end(), { - ninja::NinjaArg("-lasan"), - ninja::NinjaArg("-lubsan") - }); - } - - // TODO: Add flag to disable -ldl and -lm (dlopen, dlclose, floor, max, ...) - buildDynamicArgs.insert(buildDynamicArgs.end(), { - ninja::NinjaArg("-ldl"), - ninja::NinjaArg("-lm") - }); break; } case Compiler::MSVC: { generatedFile = config.getPackageName() + ".dll"; - buildDynamicArgs.insert(buildDynamicArgs.end(), { - ninja::NinjaArg::createRaw("lib.exe"), - ninja::NinjaArg::createRaw("/OUT:$out"), - ninja::NinjaArg::createRaw("$in"), - ninja::NinjaArg("Ws2_32.lib"), - ninja::NinjaArg("Wldap32.lib"), - ninja::NinjaArg("Crypt32.lib"), - ninja::NinjaArg("Advapi32.lib"), - ninja::NinjaArg("Gdi32.lib"), - ninja::NinjaArg("User32.lib"), - ninja::NinjaArg("Userenv.lib"), - ninja::NinjaArg("OpenGL32.lib"), - ninja::NinjaArg("GlU32.lib"), - ninja::NinjaArg("Shell32.lib") - }); break; } } - if (!allLinkerFlags.empty()) - buildDynamicArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags)); + if(onlyZigFiles) + { + buildDynamicArgs.insert(buildDynamicArgs.end(), { + ninja::NinjaArg::createRaw("zig build-lib --rdynamic"), + ninja::NinjaArg::createRaw("--name __tmp_zig"), + ninja::NinjaArg::createRaw("--output $out"), + ninja::NinjaArg::createRaw("$object_args") + }); + buildDynamicArgs.insert(buildDynamicArgs.end(), commonZigArgs.begin(), commonZigArgs.end()); + + vector<ninja::NinjaArg> zigLibraryFlags = convertCLibrariesToZigLibraries(config.getCompiler(), allLinkerFlags); + buildDynamicArgs.insert(buildDynamicArgs.end(), zigLibraryFlags.begin(), zigLibraryFlags.end()); + + ninja::NinjaRule *buildDynamicRule = ninjaBuildFile.createRule("build_dynamic", buildDynamicArgs); + buildDynamicRule->build(join(objectNames, " "), generatedFile, { zigObjectArgsValue }); + } + else + { + switch (config.getCompiler()) + { + case Compiler::GCC: + { + buildDynamicArgs.insert(buildDynamicArgs.end(), { + ninja::NinjaArg::createRaw("ccache"), + ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"), + ninja::NinjaArg::createRaw("$in"), + ninja::NinjaArg::createRaw("-shared"), + ninja::NinjaArg::createRaw("-o"), + ninja::NinjaArg::createRaw("$out"), + ninja::NinjaArg::createRaw("-Wl,--no-undefined,--as-needed") + }); + + if(config.getSanitize()) + { + buildDynamicArgs.insert(buildDynamicArgs.end(), { + ninja::NinjaArg::createRaw("-lasan"), + ninja::NinjaArg::createRaw("-lubsan") + }); + } + + // TODO: Add flag to disable -ldl and -lm (dlopen, dlclose, floor, max, ...) + buildDynamicArgs.insert(buildDynamicArgs.end(), { + ninja::NinjaArg::createRaw("-ldl"), + ninja::NinjaArg::createRaw("-lm") + }); + break; + } + case Compiler::MSVC: + { + buildDynamicArgs.insert(buildDynamicArgs.end(), { + ninja::NinjaArg::createRaw("lib.exe"), + ninja::NinjaArg::createRaw("/OUT:$out"), + ninja::NinjaArg::createRaw("$in"), + ninja::NinjaArg::createRaw("Ws2_32.lib"), + ninja::NinjaArg::createRaw("Wldap32.lib"), + ninja::NinjaArg::createRaw("Crypt32.lib"), + ninja::NinjaArg::createRaw("Advapi32.lib"), + ninja::NinjaArg::createRaw("Gdi32.lib"), + ninja::NinjaArg::createRaw("User32.lib"), + ninja::NinjaArg::createRaw("Userenv.lib"), + ninja::NinjaArg::createRaw("OpenGL32.lib"), + ninja::NinjaArg::createRaw("GlU32.lib"), + ninja::NinjaArg::createRaw("Shell32.lib") + }); + break; + } + } + + if (!allLinkerFlags.empty()) + buildDynamicArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags)); - ninja::NinjaRule *buildDynamicRule = ninjaBuildFile.createRule("build_dynamic", buildDynamicArgs); - buildDynamicRule->build(join(objectNames, " "), generatedFile, {}); + ninja::NinjaRule *buildDynamicRule = ninjaBuildFile.createRule("build_dynamic", buildDynamicArgs); + buildDynamicRule->build(join(objectNames, " "), generatedFile, {}); + } projectGeneratedBinary += generatedFile; projectGeneratedBinary += "\""; @@ -1209,8 +1311,6 @@ namespace backend if (fileOverwriteResult.isErr()) return fileOverwriteResult; - //nprintf(TINYDIR_STRING("Created ninja build file: %s\n"), ninjaBuildFilePath.c_str()); - Result<bool> buildResult = compile(savePath); if (!buildResult) return buildResult; diff --git a/src/main.cpp b/src/main.cpp index 0d29a75..12d3bc4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,8 @@ using namespace std; using namespace sibs; using namespace std::chrono; +// TODO: Use XDG (XDG_CACHE_HOME) for cache directory + // TODO: Fail if multiple versions of the same dependency is used // as linking will fail because of multiple definitions of the same thing |