aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-09-24 15:57:53 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-06 07:39:33 +0200
commit0bbb9be629ce35c11e4bf4a5180810ae2b16e5b4 (patch)
tree1a5904f36619385c99a4f88a76dc6db29694c0a2
parentf71886d54dddbf92c64f8c48978b7c4c60090194 (diff)
Fix TODOs, mainly escaping strings for ninja
-rw-r--r--backend/BackendUtils.cpp1
-rw-r--r--backend/ninja/Ninja.cpp121
m---------depends/libninja0
-rw-r--r--include/Conf.hpp1
-rw-r--r--src/PkgConfig.cpp2
-rw-r--r--src/main.cpp10
-rw-r--r--tests/src/confTest/confTest.cpp2
7 files changed, 88 insertions, 49 deletions
diff --git a/backend/BackendUtils.cpp b/backend/BackendUtils.cpp
index 3c9dd71..4e1a0e8 100644
--- a/backend/BackendUtils.cpp
+++ b/backend/BackendUtils.cpp
@@ -88,7 +88,6 @@ namespace backend
}
else
{
- // TODO: Verify what happens if test has test sub directory
if (!sibsConfig.getTestPath().empty() && isPathSubPathOf(pathNative.c_str(), sibsConfig.getTestPath()))
{
string filePathUtf8 = toUtf8(pathNative.c_str());
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index 0b7dbe5..64f8f53 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -18,6 +18,26 @@ using namespace sibs;
namespace backend
{
+ static std::string escape(const std::string &str)
+ {
+ std::string result;
+ result.reserve(str.size());
+ for(char c : str)
+ {
+ if(c == '\n')
+ result += "$\n";
+ else if(c == '$')
+ result += "$$";
+ else if(c == ' ')
+ result += "$ ";
+ else if(c == ':')
+ result += "$:";
+ else
+ result += c;
+ }
+ return result;
+ }
+
static string join(const vector<string> &list, const char *joinStr)
{
if(list.empty()) return "";
@@ -157,7 +177,10 @@ namespace backend
}
case Compiler::MSVC:
{
- // TODO: Is it possible to specify c version in msvc?
+ // It's not possible to specify C version in MSVC, programmer will have to instead be careful to not use features that are outside
+ // the desired version features...
+ // MSVC specific extensions can be disabled by /Za /Ze but we dont want to do that, code could have check if compiler is MSVC
+ // before using msvc extensions
return {};
}
}
@@ -183,7 +206,6 @@ namespace backend
{
switch(cppVersion)
{
- // Use /Za flag?
case CPPVersion::CPP11: return { ninja::NinjaArg("/std=c++11") };
case CPPVersion::CPP14: return { ninja::NinjaArg("/std=c++14") };
case CPPVersion::CPP17: return { ninja::NinjaArg("/std=c++17") };
@@ -275,8 +297,6 @@ namespace backend
return false;
}
- // TODO: First check if pkg-config is installed. If it's not, only check dependencies that exists in the dependencies sub directory.
- // If pkg-config is installed and dependency is not installed, check in dependencies sub directory.
Result<bool> Ninja::getLinkerFlags(const SibsConfig &config, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback, CflagsCallbackFunc cflagsCallbackFunc) const
{
const vector<PackageListDependency*> &packageListDependencies = config.getPackageListDependencies();
@@ -290,8 +310,8 @@ namespace backend
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<PackageListDependency*> globalLibDependencies;
-#if OS_FAMILY == OS_FAMILY_POSIX
vector<PackageListDependency*> pkgConfigDependencies;
for(PackageListDependency *dependency : packageListDependencies)
{
@@ -325,12 +345,6 @@ namespace backend
if(!pkgConfigFlag.cflags.empty())
cflagsCallbackFunc(pkgConfigFlag.cflags);
}
-#else
- for (PackageListDependency *pkgConfigDependency : packageListDependencies)
- {
- globalLibDependencies.push_back(pkgConfigDependency);
- }
-#endif
return GlobalLib::getLibs(globalLibDependencies, config, globalLibDir, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback, globalIncludeDirCallback);
}
@@ -523,16 +537,24 @@ namespace backend
char c = cLibraries[i];
if(c == '\'' || c == '"')
{
- // TODO: Handle quote escaping
+ bool escapeQuote = false;
char quoteSymbol = c;
++i;
size_t libraryIndexStart = i;
- while(i < cLibraries.size() && cLibraries[i] != quoteSymbol)
+ while(i < cLibraries.size())
{
+ if(cLibraries[i] == '\\')
+ escapeQuote = !escapeQuote;
+ else if(cLibraries[i] == quoteSymbol && !escapeQuote)
+ break;
++i;
}
size_t libraryIndexEnd = i;
++i;
+
+ // This actually means the library path is malformed, but we can fix it here
+ if(escapeQuote)
+ libraryIndexEnd--;
if(strncmp(&cLibraries[libraryIndexStart], "-l", 2) == 0)
libraryIndexStart += 2;
@@ -545,15 +567,23 @@ namespace backend
}
else if(c != ' ')
{
- // TODO: Handle space escaping
+ bool escapeSpace = false;
size_t libraryIndexStart = i;
- while(i < cLibraries.size() && cLibraries[i] != ' ')
+ while(i < cLibraries.size() && !escapeSpace && cLibraries[i] != ' ')
{
+ if(cLibraries[i] == '\\')
+ escapeSpace = !escapeSpace;
+ else if(cLibraries[i] == ' ' && !escapeSpace)
+ break;
++i;
}
size_t libraryIndexEnd = i;
++i;
+ // This actually means the library path is malformed, but we can fix it here
+ if(escapeSpace)
+ libraryIndexEnd--;
+
if(strncmp(&cLibraries[libraryIndexStart], "-l", 2) == 0)
libraryIndexStart += 2;
else if(strncmp(&cLibraries[libraryIndexStart], "-pthread", libraryIndexEnd - libraryIndexStart) == 0)
@@ -597,7 +627,7 @@ namespace backend
string result;
for(const string &objectFile : objectFiles)
{
- result += " --object \"" + objectFile + "\"";
+ result += " --object " + escape(objectFile);
}
return result;
}
@@ -751,11 +781,6 @@ namespace backend
}
}
- // TODO: Verify ccache is installed
- // -Werror
- // TODO: Find equivalent -MMD -MP for other compilers than gcc. MMD is used to create "dependency files" -> if headers are modified then source files will be recompiled
- // when compiling next time...
-
// TODO: Verify compilers for language are installed when attempting to build a project that has source files of those types
vector<ninja::NinjaArg> compileCCommand;
@@ -843,10 +868,10 @@ namespace backend
case Compiler::MSVC:
{
compileCCommand.insert(compileCCommand.end(), {
- ninja::NinjaArg("cl.exe"),
- ninja::NinjaArg("/c"),
- ninja::NinjaArg("$in"),
- ninja::NinjaArg("/Fo$out")
+ ninja::NinjaArg::createRaw("cl.exe /showIncludes"),
+ ninja::NinjaArg::createRaw("/c"),
+ ninja::NinjaArg::createRaw("$in"),
+ ninja::NinjaArg::createRaw("/Fo$out")
});
compileCCommand.insert(compileCCommand.end(), cflags.begin(), cflags.end());
@@ -888,10 +913,23 @@ namespace backend
compileCppCommand.insert(compileCppCommand.end(), cppLanguageVersionFlags.begin(), cppLanguageVersionFlags.end());
ninja::NinjaRule *compileCRule = ninjaBuildFile.createRule("compile_c", compileCCommand);
- compileCRule->depFile = "$out.d";
-
ninja::NinjaRule *compileCppRule = ninjaBuildFile.createRule("compile_cpp", compileCppCommand);
- compileCppRule->depFile = "$out.d";
+
+ switch(config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ compileCRule->depFile = "$out.d";
+ compileCppRule->depFile = "$out.d";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ compileCRule->deps = "msvc";
+ compileCppRule->deps = "msvc";
+ break;
+ }
+ }
// 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).
@@ -962,12 +1000,9 @@ namespace backend
{
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);
@@ -983,6 +1018,8 @@ namespace backend
else
ninjaBuild = compileZigRule->build("../../" + sourceFile.filepath, objectName, { zigHeaderFileValue });
zigBuilds.push_back(ninjaBuild);
+
+ objectNames.emplace_back(move(objectName));
}
else
onlyZigFiles = false;
@@ -995,7 +1032,6 @@ 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);
@@ -1019,7 +1055,9 @@ namespace backend
assert(false);
break;
}
- objectNames.emplace_back(objectName);
+
+ if(!objectName.empty())
+ objectNames.emplace_back(move(objectName));
}
// TODO: For now zig projects (zig object files) are built with c/c++ compiler,
@@ -1057,7 +1095,7 @@ namespace backend
buildExeArgs.insert(buildExeArgs.end(), zigLibraryFlags.begin(), zigLibraryFlags.end());
ninja::NinjaRule *buildExeRule = ninjaBuildFile.createRule("build_exec", buildExeArgs);
- buildExeRule->build(join(objectNames, " "), config.getPackageName(), { zigObjectArgsValue });
+ buildExeRule->build(objectNames, config.getPackageName(), { zigObjectArgsValue });
}
else
{
@@ -1115,7 +1153,7 @@ namespace backend
buildExeArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags));
ninja::NinjaRule *buildExeRule = ninjaBuildFile.createRule("build_exec", buildExeArgs);
- buildExeRule->build(join(objectNames, " "), config.getPackageName(), {});
+ buildExeRule->build(objectNames, config.getPackageName(), {});
}
projectGeneratedBinary += config.getPackageName();
@@ -1153,12 +1191,8 @@ namespace backend
});
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 });
+ buildStaticRule->build(objectNames, generatedFile, { zigObjectArgsValue });
}
else
{
@@ -1186,7 +1220,7 @@ namespace backend
}
ninja::NinjaRule *buildStaticRule = ninjaBuildFile.createRule("build_static", buildStaticArgs);
- buildStaticRule->build(join(objectNames, " "), generatedFile, {});
+ buildStaticRule->build(objectNames, generatedFile, {});
}
projectGeneratedBinary += generatedFile;
@@ -1228,7 +1262,7 @@ namespace backend
buildDynamicArgs.insert(buildDynamicArgs.end(), zigLibraryFlags.begin(), zigLibraryFlags.end());
ninja::NinjaRule *buildDynamicRule = ninjaBuildFile.createRule("build_dynamic", buildDynamicArgs);
- buildDynamicRule->build(join(objectNames, " "), generatedFile, { zigObjectArgsValue });
+ buildDynamicRule->build(objectNames, generatedFile, { zigObjectArgsValue });
}
else
{
@@ -1286,7 +1320,7 @@ namespace backend
buildDynamicArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags));
ninja::NinjaRule *buildDynamicRule = ninjaBuildFile.createRule("build_dynamic", buildDynamicArgs);
- buildDynamicRule->build(join(objectNames, " "), generatedFile, {});
+ buildDynamicRule->build(objectNames, generatedFile, {});
}
projectGeneratedBinary += generatedFile;
@@ -1455,7 +1489,6 @@ namespace backend
Result<bool> Ninja::compile(const _tinydir_char_t *buildFilePath)
{
- // TODO: Verify `script` is installed. We need `script` to get colored output
#if OS_FAMILY == OS_FAMILY_POSIX
FileString command = TINYDIR_STRING("script -eqc 'ninja -C \"");
command += buildFilePath;
diff --git a/depends/libninja b/depends/libninja
-Subproject 2698cbc14f8a2a108a3252f03e053cb47b8b510
+Subproject f414fe587cef52cb8ff2b73a320ee0ce481170b
diff --git a/include/Conf.hpp b/include/Conf.hpp
index 951def9..f1dded6 100644
--- a/include/Conf.hpp
+++ b/include/Conf.hpp
@@ -173,7 +173,6 @@ namespace sibs
};
const int NUM_CONFIGS = 12;
- // TODO: Detect this at runtime?
#if OS_TYPE == OS_TYPE_WINDOWS
#ifdef SIBS_ENV_32BIT
#define SYSTEM_PLATFORM Platform::PLATFORM_WIN32
diff --git a/src/PkgConfig.cpp b/src/PkgConfig.cpp
index 42d0d13..3a36f39 100644
--- a/src/PkgConfig.cpp
+++ b/src/PkgConfig.cpp
@@ -6,7 +6,7 @@
using namespace std;
// TODO: Do not use pkg-config program. The same functionality can easily be achieved
-// by reading files in /usr/bin/pkgconfig
+// by reading files in /usr/share/pkgconfig
// Or is there no downside to calling pkg-config program?
namespace sibs
{
diff --git a/src/main.cpp b/src/main.cpp
index 12d3bc4..38e68f0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -182,7 +182,7 @@ void usageInit()
printf(" --dynamic\t\t\tProject compiles to a dynamic library\n");
printf(" --lang\t\t\tProject template language - Optional (default: c++)\n");
printf("Examples:\n");
- printf(" sibs init --exec\n");
+ printf(" sibs init . --exec\n");
printf(" sibs init dirA/dirB --dynamic");
exit(1);
}
@@ -226,6 +226,14 @@ bool isPathSubPathOf(const FileString &path, const FileString &subPathOf)
return _tinydir_strncmp(path.c_str(), subPathOf.c_str(), subPathOf.size()) == 0;
}
+static bool doesProgramExist(const _tinydir_char_t *programName)
+{
+ FileString cmd = FileString(programName) + TINYDIR_STRING(" --version");
+ Result<sibs::ExecResult> result = exec(cmd.c_str());
+ bool programNotFound = !result && result.getErrorCode() == 127;
+ return !programNotFound;
+}
+
int buildProject(const FileString &projectPath, const FileString &projectConfFilePath, SibsConfig &sibsConfig)
{
FileString buildPath;
diff --git a/tests/src/confTest/confTest.cpp b/tests/src/confTest/confTest.cpp
index 5b0fd0f..100c7cf 100644
--- a/tests/src/confTest/confTest.cpp
+++ b/tests/src/confTest/confTest.cpp
@@ -1,4 +1,4 @@
-#include "catch.hpp"
+#include <catch.hpp>
#include "../../../include/Conf.hpp"
using namespace sibs;