aboutsummaryrefslogtreecommitdiff
path: root/backend/ninja
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-09-23 12:22:37 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-06 07:39:33 +0200
commit5006226e945fc645e6d9b21252c9eee53cc191cc (patch)
tree94371016233562351d70fb3b9ff312c6dacd9bb4 /backend/ninja
parent8fdc481d78a0426f6dbf235e872c3798ec57251e (diff)
Fix various things, add generated zig header files to global include
Fix compile_commands.json missing build steps. Fix c includes -> zig includes flags. Fix crash when running sibs new/init without defining lang. Add generated zig header files to global include so they can be used from c/c++. Add zig and zig/c (using zig and c in the same project) examples.
Diffstat (limited to 'backend/ninja')
-rw-r--r--backend/ninja/Ninja.cpp144
1 files changed, 90 insertions, 54 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index e71b22a..2c76fd4 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -219,20 +219,14 @@ namespace backend
{
string filePathStr = filepath ? filepath : "";
if(filepath && !containsSourceFile(filePathStr))
- {
sourceFiles.push_back({ language, filePathStr });
- //printf("Adding source file: %s\n", filepath);
- }
}
void Ninja::addTestSourceDir(const char *dir)
{
string dirStr = dir ? dir : "";
if(dir && !containsTestSourceDir(dirStr))
- {
testSourceDirs.emplace_back(dirStr);
- //printf("Using test source directory: %s\n", dir);
- }
}
void Ninja::addDependency(const std::string &binaryFile)
@@ -440,26 +434,7 @@ namespace backend
return result;
}
- static string convertCIncludeSyntaxToZigInclude(Compiler compiler, const string &cIncludes)
- {
- switch (compiler)
- {
- case Compiler::GCC:
- {
- return replaceAll(cIncludes, "-I", "-isystem ");
- }
- case Compiler::MSVC:
- {
- return replaceAll(cIncludes, "/I", "-isystem ");
- }
- default:
- assert(false);
- break;
- }
- return cIncludes;
- }
-
- static vector<ninja::NinjaArg> extractIncludesFromCFlag(Compiler compiler, const ninja::NinjaArg &cflag)
+ static vector<ninja::NinjaArg> extractIncludesFromCFlag(Compiler compiler, const string &cflag)
{
vector<ninja::NinjaArg> result;
string includeStartStr;
@@ -485,42 +460,52 @@ namespace backend
while(index != string::npos)
{
char endChar = ' ';
- size_t includeStartIndex = cflag.arg.find(includeStartStr, index);
+ size_t includeStartIndex = cflag.find(includeStartStr, index);
if(includeStartIndex == string::npos)
break;
else if(includeStartIndex > 0)
{
- if(cflag.arg[includeStartIndex - 1] == '"' || cflag.arg[includeStartIndex - 1] == '\'')
- endChar = cflag.arg[includeStartIndex - 1];
+ if(cflag[includeStartIndex - 1] == '"' || cflag[includeStartIndex - 1] == '\'')
+ endChar = cflag[includeStartIndex - 1];
}
includeStartIndex += includeStartStr.length();
- size_t includeEndIndex = cflag.arg.find(endChar, includeStartIndex);
+ size_t includeEndIndex = cflag.find(endChar, includeStartIndex);
index = includeEndIndex;
if(includeEndIndex == string::npos)
- includeEndIndex = cflag.arg.length();
+ includeEndIndex = cflag.length();
- result.push_back(ninja::NinjaArg::createRaw(cflag.arg.substr(includeStartIndex, includeEndIndex - includeStartIndex)));
+ result.push_back(ninja::NinjaArg::createRaw(cflag.substr(includeStartIndex, includeEndIndex - includeStartIndex)));
}
return result;
}
- static vector<ninja::NinjaArg> extractIncludesFromCFlags(Compiler compiler, const vector<ninja::NinjaArg> &cflags)
+ static vector<ninja::NinjaArg> extractIncludesFromCFlags(Compiler compiler, const vector<ninja::NinjaArg> &cflags)
{
vector<ninja::NinjaArg> result;
for(const ninja::NinjaArg &cflag : cflags)
{
- vector<ninja::NinjaArg> subCFlags = extractIncludesFromCFlag(compiler, cflag);
+ vector<ninja::NinjaArg> subCFlags = extractIncludesFromCFlag(compiler, cflag.arg);
result.insert(result.end(), subCFlags.begin(), subCFlags.end());
}
return result;
}
+ static string convertCIncludeSyntaxToZigInclude(Compiler compiler, const string &cIncludes)
+ {
+ vector<ninja::NinjaArg> result = extractIncludesFromCFlag(compiler, cIncludes);
+ string resultStr;
+ for(ninja::NinjaArg &include : result)
+ {
+ resultStr += "-isystem \"" + include.arg + "\"";
+ }
+ return resultStr;
+ }
+
static vector<ninja::NinjaArg> convertCFlagsIncludesToZigIncludes(Compiler compiler, const vector<ninja::NinjaArg> &cflags)
{
- vector<ninja::NinjaArg> result;
- result = extractIncludesFromCFlags(compiler, cflags);
+ vector<ninja::NinjaArg> result = extractIncludesFromCFlags(compiler, cflags);
for(ninja::NinjaArg &include : result)
{
include.arg = "-isystem \"" + include.arg + "\"";
@@ -596,14 +581,34 @@ namespace backend
return result;
}
- Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback)
+ static int getFilenameLength(const string &filepath)
{
- if (!sourceFiles.empty())
+ for(int i = filepath.size(); i >= 0; --i)
{
- Result<bool> createBuildDirResult = createDirectoryRecursive(savePath);
- if (createBuildDirResult.isErr())
- return createBuildDirResult;
+ char c = filepath[i];
+ if(c == '/' || c == '\\')
+ return filepath.size() - i;
}
+ return filepath.size();
+ }
+
+ Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback)
+ {
+ Result<bool> createBuildDirResult = createDirectoryRecursive(savePath);
+ if (!createBuildDirResult)
+ return createBuildDirResult;
+
+ FileString generatedHeadersDir = config.getProjectPath() + TINYDIR_STRING("/sibs-build/generated-headers");
+ Result<bool> createGeneratedHeadersDirResult = createDirectoryRecursive(generatedHeadersDir.c_str());
+ if (!createGeneratedHeadersDirResult)
+ return createGeneratedHeadersDirResult;
+
+ FileString generatedZigHeadersDir = generatedHeadersDir + TINYDIR_STRING("/zig");
+ Result<bool> createGeneratedZigHeadersDirResult = createDirectory(generatedZigHeadersDir.c_str());
+ if (!createGeneratedZigHeadersDirResult)
+ return createGeneratedZigHeadersDirResult;
+
+ string generatedZigHeaderDirUtf8 = toUtf8(generatedZigHeadersDir);
LibraryType libraryType = getNinjaLibraryType(config.getPackageType());
@@ -701,6 +706,7 @@ namespace backend
}
globalIncDir += dependencyExportIncludeDirs;
+ globalIncDir += TINYDIR_STRING(" ") + getIncludeOptionFlag(config.getCompiler(), toUtf8(generatedHeadersDir));
ninjaBuildFile.defineGlobalVariable("globalIncDir", globalIncDir);
// TODO: Find a better way to convert includes, this could be slow...
ninjaBuildFile.defineGlobalVariable("globalIncDirZig", convertCIncludeSyntaxToZigInclude(config.getCompiler(), globalIncDir));
@@ -881,8 +887,10 @@ namespace backend
// TODO: Convert sibs defines to const variables in a zig file that other zig files can include (like a config file).
// TODO: Remove --library c if project does not depend on c libraries or project only has .zig files
+
+ ninja::NinjaVariable zigHeaderFile("headerFile");
vector<ninja::NinjaArg> zigTestArgs = {
- ninja::NinjaArg::createRaw("zig test $in --output $out -isystem ../../ --color on --library c $globalIncDirZig")
+ ninja::NinjaArg::createRaw("zig test $in --output $out --output-h $headerFile -isystem ../../ --color on --library c $globalIncDirZig")
};
// TODO: Find a way to do this more efficiently
@@ -891,6 +899,7 @@ namespace backend
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
@@ -934,6 +943,38 @@ namespace backend
vector<string> objectNames;
objectNames.reserve(sourceFiles.size());
+ vector<ninja::NinjaBuild*> zigBuilds;
+ // TODO(Urgent): Instead of adding zig builds as dependencies for all c/c++ builds, generate two ninja files; one for zig and one for c/c++.
+ // Then build run zig ninja file first and then c/c++ ninja file.
+ // That would be more efficient as you dont need to add every single zig build as dependency for all c/c++ builds...
+ for(const sibs::SourceFile &sourceFile : sourceFiles)
+ {
+ if(sourceFile.language == sibs::Language::ZIG)
+ {
+ // TODO: Remove this and use NinjaBuilds to get object names
+ string objectName = config.getPackageName() + "@exe/" + sourceFile.filepath;
+ objectName += getObjectFileExtension(config.getCompiler());
+ objectNames.emplace_back(objectName);
+
+ // TODO: Optimize this by checking if directory has already been created with a hash map
+ int filenameLength = getFilenameLength(sourceFile.filepath);
+ string zigSourceDirRelative = sourceFile.filepath.substr(0, sourceFile.filepath.size() - filenameLength);
+ FileString zigHeaderFileDir = toFileString(generatedZigHeaderDirUtf8 + '/' + zigSourceDirRelative);
+ Result<bool> createZigHeaderFileDirResult = createDirectoryRecursive(zigHeaderFileDir.c_str());
+ if(!createZigHeaderFileDirResult)
+ return createZigHeaderFileDirResult;
+
+ string headerName = sourceFile.filepath.substr(sourceFile.filepath.size() - filenameLength, filenameLength - 4) + ".h";
+ ninja::NinjaArgValue zigHeaderFileValue = { zigHeaderFile, '"' + toUtf8(zigHeaderFileDir) + '/' + headerName + '"' };
+ ninja::NinjaBuild *ninjaBuild = nullptr;
+ if(zigTest)
+ ninjaBuild = testZigRule->build("../../" + sourceFile.filepath, objectName, { zigHeaderFileValue });
+ else
+ ninjaBuild = compileZigRule->build("../../" + sourceFile.filepath, objectName, { zigHeaderFileValue });
+ zigBuilds.push_back(ninjaBuild);
+ }
+ }
+
for(const sibs::SourceFile &sourceFile : sourceFiles)
{
string objectName;
@@ -943,7 +984,7 @@ namespace backend
{
objectName += config.getPackageName() + "@exe/" + sourceFile.filepath;
objectName += getObjectFileExtension(config.getCompiler());
- ninjaBuildFile.build(compileCRule, "../../" + sourceFile.filepath, objectName, {});
+ compileCRule->build("../../" + sourceFile.filepath, objectName, {}, zigBuilds);
usesCFiles = true;
break;
}
@@ -951,18 +992,13 @@ namespace backend
{
objectName += config.getPackageName() + "@exe/" + sourceFile.filepath;
objectName += getObjectFileExtension(config.getCompiler());
- ninjaBuildFile.build(compileCppRule, "../../" + sourceFile.filepath, objectName, {});
+ compileCppRule->build("../../" + sourceFile.filepath, objectName, {}, zigBuilds);
usesCppFiles = true;
break;
}
case sibs::Language::ZIG:
{
- objectName += "zig-cache/" + sourceFile.filepath;
- objectName += getObjectFileExtension(config.getCompiler());
- if(zigTest)
- ninjaBuildFile.build(testZigRule, "../../" + sourceFile.filepath, objectName, {});
- else
- ninjaBuildFile.build(compileZigRule, "../../" + sourceFile.filepath, objectName, {});
+ // Already built above
break;
}
default:
@@ -1041,7 +1077,7 @@ namespace backend
buildExeArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags));
ninja::NinjaRule *buildExeRule = ninjaBuildFile.createRule("build_exec", buildExeArgs);
- ninjaBuildFile.build(buildExeRule, join(objectNames, " "), config.getPackageName(), {});
+ buildExeRule->build(join(objectNames, " "), config.getPackageName(), {});
projectGeneratedBinary += config.getPackageName();
#if OS_FAMILY == OS_FAMILY_WINDOWS
@@ -1079,7 +1115,7 @@ namespace backend
}
ninja::NinjaRule *buildStaticRule = ninjaBuildFile.createRule("build_static", buildStaticArgs);
- ninjaBuildFile.build(buildStaticRule, join(objectNames, " "), generatedFile, {});
+ buildStaticRule->build(join(objectNames, " "), generatedFile, {});
projectGeneratedBinary += generatedFile;
projectGeneratedBinary += "\"";
@@ -1149,7 +1185,7 @@ namespace backend
buildDynamicArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags));
ninja::NinjaRule *buildDynamicRule = ninjaBuildFile.createRule("build_dynamic", buildDynamicArgs);
- ninjaBuildFile.build(buildDynamicRule, join(objectNames, " "), generatedFile, {});
+ buildDynamicRule->build(join(objectNames, " "), generatedFile, {});
projectGeneratedBinary += generatedFile;
projectGeneratedBinary += "\"";
@@ -1348,7 +1384,7 @@ namespace backend
{
FileString command = TINYDIR_STRING("ninja -C \"");
command += buildFilePath;
- command += TINYDIR_STRING("\" -t compdb c_COMPILER cpp_COMPILER BUILD_EXEC BUILD_STATIC BUILD_DYNAMIC > \"");
+ command += TINYDIR_STRING("\" -t compdb compile_c compile_cpp compile_zig > \"");
command += saveDir;
command += TINYDIR_STRING("/compile_commands.json\"");
Result<ExecResult> execResult = exec(command.c_str(), false);