aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2017-12-30 05:33:25 +0100
committerdec05eba <dec05eba@protonmail.com>2017-12-30 05:33:25 +0100
commit7c215c39d530f01235043a131d64d4c7f766e9ab (patch)
treed72effe043a46566e34276525081637cad1bb7a0 /backend
parentabab2184ade33097f3441f8cdd95dd27c5653930 (diff)
parent98ad7dd049a366e21d60a34548736a3c8ef72877 (diff)
Merge release_0.1.0 to master
Add support for windows
Diffstat (limited to 'backend')
-rw-r--r--backend/ninja/Ninja.cpp317
-rw-r--r--backend/ninja/Ninja.hpp4
2 files changed, 262 insertions, 59 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index d9b4eed..49bda4f 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -8,6 +8,12 @@
using namespace std;
using namespace sibs;
+#if OS_FAMILY == OS_FAMILY_POSIX
+#define nprintf printf
+#else
+#define nprintf wprintf
+#endif
+
namespace backend
{
string join(const vector<string> &list, const char *joinStr)
@@ -38,7 +44,7 @@ namespace backend
return result;
}
-
+
bool endsWith(const string &str, const string &endWithStr)
{
if(endWithStr.size() > str.size())
@@ -46,7 +52,7 @@ namespace backend
else
return strncmp(&str[str.size() - endWithStr.size()], &endWithStr[0], endWithStr.size()) == 0;
}
-
+
Ninja::LibraryType getNinjaLibraryType(PackageType packageType)
{
switch(packageType)
@@ -61,6 +67,78 @@ namespace backend
}
}
+ string getIncludeOptionFlag(Compiler compiler, const string &filepath)
+ {
+ string result;
+ switch (compiler)
+ {
+ case Compiler::GCC:
+ {
+ result = "'-I";
+ result += filepath;
+ result += "'";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result = "/I \"";
+ result += filepath;
+ result += "\"";
+ break;
+ }
+ }
+ return result;
+ }
+
+ string getCompileWithoutLinkingFlag(Compiler compiler)
+ {
+ string result;
+ switch (compiler)
+ {
+ case Compiler::GCC:
+ {
+ result = "-c";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result = "/c";
+ break;
+ }
+ }
+ return result;
+ }
+
+ string getObjectFileNameFlag(Compiler compiler, const string &objectFileName)
+ {
+ string result;
+ switch (compiler)
+ {
+ case Compiler::GCC:
+ {
+ result = "-o ";
+ result += objectFileName;
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result = "/Fo";
+ result += objectFileName;
+ break;
+ }
+ }
+ return result;
+ }
+
+ const char* getObjectFileExtension(Compiler compiler)
+ {
+ switch (compiler)
+ {
+ case Compiler::GCC: return ".o";
+ case Compiler::MSVC: return ".obj";
+ }
+ }
+
Ninja::Ninja()
{
@@ -127,6 +205,7 @@ namespace backend
return false;
}
+#if OS_FAMILY == OS_FAMILY_POSIX
Result<bool> validatePkgConfigPackageVersionExists(const Dependency &dependency)
{
Result<bool> dependencyValidationResult = PkgConfig::validatePackageExists(dependency.name);
@@ -139,7 +218,7 @@ namespace backend
return Result<bool>::Ok(true);
}
-
+#endif
// 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) const
@@ -147,14 +226,18 @@ namespace backend
const vector<Dependency> &dependencies = config.getDependencies();
if(dependencies.empty()) return Result<bool>::Ok(true);
- string globalLibDir = getHomeDir();
- globalLibDir += "/.sibs/lib";
+ Result<FileString> globalLibDirResult = getHomeDir();
+ if (!globalLibDirResult)
+ return Result<bool>::Err(globalLibDirResult);
+ FileString globalLibDir = globalLibDirResult.unwrap();
+ globalLibDir += TINYDIR_STRING("/.sibs/lib");
Result<bool> createGlobalLibDirResult = createDirectoryRecursive(globalLibDir.c_str());
if(createGlobalLibDirResult.isErr())
return createGlobalLibDirResult;
- vector<Dependency> pkgConfigDependencies;
vector<Dependency> globalLibDependencies;
+#if OS_FAMILY == OS_FAMILY_POSIX
+ vector<Dependency> pkgConfigDependencies;
for(const Dependency &dependency : dependencies)
{
Result<bool> pkgConfigDependencyValidation = validatePkgConfigPackageVersionExists(dependency);
@@ -169,11 +252,11 @@ namespace backend
}
Result<string> pkgConfigLinkerFlagsResult = PkgConfig::getDynamicLibsLinkerFlags(pkgConfigDependencies);
- if(pkgConfigLinkerFlagsResult.isErr())
+ if (pkgConfigLinkerFlagsResult.isErr())
{
printf("%s, using global lib...\n", pkgConfigLinkerFlagsResult.getErrMsg().c_str());
globalLibDependencies.reserve(globalLibDependencies.size() + pkgConfigDependencies.size());
- for(const Dependency &pkgConfigDependency : pkgConfigDependencies)
+ for (const Dependency &pkgConfigDependency : pkgConfigDependencies)
{
globalLibDependencies.push_back(pkgConfigDependency);
}
@@ -181,9 +264,15 @@ namespace backend
}
else
{
- if(!pkgConfigLinkerFlagsResult.unwrap().empty())
+ if (!pkgConfigLinkerFlagsResult.unwrap().empty())
dynamicLinkerFlagCallback(pkgConfigLinkerFlagsResult.unwrap());
}
+#else
+ for (const Dependency &dependency : dependencies)
+ {
+ globalLibDependencies.push_back(dependency);
+ }
+#endif
for(const Dependency &globalLibDependency : globalLibDependencies)
{
@@ -221,7 +310,7 @@ namespace backend
return Result<bool>::Ok(true);
}
- Result<bool> Ninja::build(const SibsConfig &config, const char *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback)
+ Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback)
{
// TODO: Do not quit here if no source files are provided. The source-less project could have dependencies
if(sourceFiles.empty())
@@ -230,29 +319,35 @@ namespace backend
Result<bool> createBuildDirResult = createDirectoryRecursive(savePath);
if(createBuildDirResult.isErr())
return createBuildDirResult;
-
+
LibraryType libraryType = getNinjaLibraryType(config.getPackageType());
- string ninjaBuildFilePath = savePath;
- ninjaBuildFilePath += "/build.ninja";
+ string savePathUtf8 = toUtf8(savePath);
+
+ FileString ninjaBuildFilePath = savePath;
+ ninjaBuildFilePath += TINYDIR_STRING("/build.ninja");
string result;
result.reserve(16384);
- string globalIncDir = getHomeDir();
- globalIncDir += "/.sibs/lib";
+ Result<FileString> globalIncDirResult = getHomeDir();
+ if (!globalIncDirResult)
+ return Result<bool>::Err(globalIncDirResult);
- result += "globalIncDir = '-I";
- result += globalIncDir;
- result += "'";
+ FileString globalIncDir = globalIncDirResult.unwrap();
+ globalIncDir += TINYDIR_STRING("/.sibs/lib");
+
+ result += "globalIncDir = ";
+ result += getIncludeOptionFlag(config.getCompiler(), toUtf8(globalIncDir));
for(const auto &includeDir : config.getIncludeDirs())
{
- result += " '-I../../";
- result += includeDir;
- result += "'";
+ string includeDirRelative = "../../";
+ includeDirRelative += includeDir;
+ result += " ";
+ result += getIncludeOptionFlag(config.getCompiler(), includeDirRelative);
}
result += "\n\n";
-
+
string defines;
for(const auto &definePair : config.getDefines())
{
@@ -262,25 +357,54 @@ namespace backend
defines += definePair.second;
defines += "'";
}
-
+
if(!defines.empty())
printf("Custom define: %s\n", defines.c_str());
+ string compilerName;
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ compilerName = "ccache c++";
+ break;
+ case Compiler::MSVC:
+ compilerName = "cl.exe";
+ break;
+ }
+
string buildJob;
switch(libraryType)
{
case LibraryType::EXECUTABLE:
{
- result += "rule cpp_COMPILER\n";
- result += " command = ccache c++ $ARGS -c $in -o $out\n\n";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = ccache c++ $ARGS -c $in -o $out\n\n";
+
+ result += "rule cpp_BUILD_EXEC\n";
+ result += " command = ccache c++ $ARGS -o $out $in $LINK_ARGS $aliasing\n\n";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = cl.exe $ARGS /c $in /Fo$out\n\n";
+
+ result += "rule cpp_BUILD_EXEC\n";
+ result += " command = cl.exe $ARGS $in /Fe$out $LINK_ARGS\n\n";
+ break;
+ }
+ }
- result += "rule cpp_BUILD_EXEC\n";
- result += " command = ccache c++ $ARGS -o $out $in $LINK_ARGS $aliasing\n\n";
buildJob = "cpp_BUILD_EXEC";
break;
}
case LibraryType::STATIC:
{
+ // TODO: Write equivalent code for msvc
result += "rule cpp_COMPILER\n";
result += " command = ccache c++ $ARGS -c -fPIC $in -o $out\n\n";
@@ -294,12 +418,32 @@ namespace backend
}
case LibraryType::DYNAMIC:
{
- result += "rule cpp_COMPILER\n";
- result += " command = ccache c++ $ARGS -c -fPIC $in -o $out\n\n";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = ccache c++ $ARGS -c -fPIC $in -o $out\n\n";
+
+ // --whole-archive
+ result += "rule cpp_BUILD_DYNAMIC\n";
+ result += " command = ccache c++ $in -shared -o $out $LINK_ARGS $aliasing\n\n";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = cl.exe $ARGS /c $in /Fo$out\n\n";
+
+ //result += "rule cpp_BUILD_DYNAMIC\n";
+ //result += " command = cl.exe /LD $in /Fe$out $LINK_ARGS\n\n";
+
+ result += "rule cpp_BUILD_DYNAMIC\n";
+ result += " command = lib.exe /OUT:$out $in\n\n";
+ break;
+ }
+ }
- // --whole-archive
- result += "rule cpp_BUILD_DYNAMIC\n";
- result += " command = ccache c++ $in -shared -o $out $LINK_ARGS $aliasing\n\n";
buildJob = "cpp_BUILD_DYNAMIC";
break;
}
@@ -328,21 +472,28 @@ namespace backend
sourceFileLanguage = "c";
//string sourceFileEncoded = sourceFile;
//replace(sourceFileEncoded, '/', '@');
- string objectName = config.getPackageName() + "@exe/" + sourceFile + ".o";
+ string objectName = config.getPackageName() + "@exe/" + sourceFile;
+ objectName += getObjectFileExtension(config.getCompiler());
result += "build ";
result += objectName;
result += ": cpp_COMPILER ../../";
result += sourceFile;
result += "\n";
- result += " ARGS = $globalIncDir '-I" + config.getPackageName() + "@exe' '-I..' ";
+ result += " ARGS = $globalIncDir ";
if(!defines.empty())
result += defines;
- result += " '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags + " '-g'\n\n";
+ if(config.getCompiler() != Compiler::MSVC)
+ result += " '-I" + config.getPackageName() + "@exe' '-I..' '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags + " '-g'";
+ result += "\n\n";
objectNames.emplace_back(objectName);
}
+#if OS_TYPE == OS_TYPE_LINUX
// TODO: Allow configuring default linking flags. Maybe have `package.useThreads = false` to disable this flag
string allLinkerFlags = "-pthread";
+#else
+ string allLinkerFlags = "";
+#endif
// TODO: Somehow check loading order, because it has to be correct to work.. Or does it for dynamic libraries?
// Anyways it's required for static libraries (especially on Windows)
@@ -374,7 +525,7 @@ namespace backend
string projectGeneratedBinary = allLinkerFlags;
projectGeneratedBinary += " '";
- projectGeneratedBinary += savePath;
+ projectGeneratedBinary += savePathUtf8;
projectGeneratedBinary += "/";
switch(libraryType)
{
@@ -385,7 +536,20 @@ namespace backend
result += ": " + buildJob + " ";
result += join(objectNames, " ");
result += "\n";
- result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += " LINK_ARGS = ";
+ break;
+ }
+ }
+
if(!allLinkerFlags.empty())
{
result += allLinkerFlags;
@@ -401,24 +565,56 @@ namespace backend
result += ": " + buildJob + " ";
result += join(objectNames, " ");
result += "\n\n";
- projectGeneratedBinary += config.getPackageName() + ".a";
+
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ projectGeneratedBinary += config.getPackageName() + ".a";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ projectGeneratedBinary += config.getPackageName() + ".lib";
+ break;
+ }
+ }
break;
}
case LibraryType::DYNAMIC:
{
- result += "build lib";
- result += config.getPackageName();
- result += ".so: " + buildJob + " ";
- result += join(objectNames, " ");
- result += "\n";
- result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += "build lib";
+ result += config.getPackageName();
+ result += ".so: " + buildJob + " ";
+ result += join(objectNames, " ");
+ result += "\n";
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ projectGeneratedBinary += "lib" + config.getPackageName() + ".so";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += "build ";
+ result += config.getPackageName();
+ result += ".lib: " + buildJob + " ";
+ result += join(objectNames, " ");
+ result += "\n";
+ result += " LINK_ARGS = ";
+ projectGeneratedBinary += config.getPackageName() + ".lib";
+ break;
+ }
+ }
+
if(!allLinkerFlags.empty())
{
result += allLinkerFlags;
//result += " '-Wl,--no-whole-archive'";
}
result += "\n\n";
- projectGeneratedBinary += "lib" + config.getPackageName() + ".so";
break;
}
default:
@@ -431,7 +627,7 @@ namespace backend
if(fileOverwriteResult.isErr())
return fileOverwriteResult;
- printf("Created ninja build file: %s\n", ninjaBuildFilePath.c_str());
+ nprintf(TINYDIR_STRING("Created ninja build file: %s\n"), ninjaBuildFilePath.c_str());
Result<bool> buildResult = build(savePath);
if(!buildResult)
@@ -444,13 +640,13 @@ namespace backend
return Result<bool>::Ok(true);
}
- const char *sourceFileExtensions[] = { "c", "cc", "cpp", "cxx" };
+ const _tinydir_char_t *sourceFileExtensions[] = { TINYDIR_STRING("c"), TINYDIR_STRING("cc"), TINYDIR_STRING("cpp"), TINYDIR_STRING("cxx") };
bool isSourceFile(tinydir_file *file)
{
if(!file->is_reg)
return false;
- for(const char *sourceFileExtension : sourceFileExtensions)
+ for(const _tinydir_char_t *sourceFileExtension : sourceFileExtensions)
{
if(_tinydir_strcmp(sourceFileExtension, file->extension) == 0)
return true;
@@ -480,11 +676,17 @@ namespace backend
for(const string &testSourceDir : testSourceDirs)
{
- string projectConfFilePath = testSourceDir;
- projectConfFilePath += "/project.conf";
+#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");
FileType projectConfFileType = getFileType(projectConfFilePath.c_str());
- SibsTestConfig sibsTestConfig(testSourceDir);
+ SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative);
if(projectConfFileType == FileType::REGULAR)
{
Result<bool> result = Config::readFromFile(projectConfFilePath.c_str(), sibsTestConfig);
@@ -494,11 +696,12 @@ namespace backend
backend::Ninja ninja;
ninja.addDependency(projectGeneratedBinary);
- walkDirFilesRecursive(testSourceDir.c_str(), [&ninja, &sibsTestConfig](tinydir_file *file)
+ walkDirFilesRecursive(testSourceDirNative.c_str(), [&ninja, &sibsTestConfig](tinydir_file *file)
{
if (isSourceFile(file))
{
- ninja.addSourceFile(file->path + sibsTestConfig.getProjectPath().size() + 1);
+ string filePathUtf8 = toUtf8(file->path + sibsTestConfig.getProjectPath().size() + 1);
+ ninja.addSourceFile(filePathUtf8.c_str());
}
else
{
@@ -508,7 +711,7 @@ namespace backend
if(!ninja.getSourceFiles().empty())
{
- string debugBuildPath = testSourceDir + "/sibs-build/debug";
+ FileString debugBuildPath = testSourceDirNative + TINYDIR_STRING("/sibs-build/debug");
Result<bool> buildFileResult = ninja.build(sibsTestConfig, debugBuildPath.c_str());
if (!buildFileResult)
return buildFileResult;
@@ -522,11 +725,11 @@ namespace backend
return Result<bool>::Ok(true);
}
- Result<bool> Ninja::build(const char *buildFilePath)
+ Result<bool> Ninja::build(const _tinydir_char_t *buildFilePath)
{
- string command = "ninja -C '";
+ FileString command = TINYDIR_STRING("ninja -C \"");
command += buildFilePath;
- command += "'";
+ command += TINYDIR_STRING("\"");
Result<ExecResult> execResult = exec(command.c_str(), true);
if(execResult.isOk())
{
diff --git a/backend/ninja/Ninja.hpp b/backend/ninja/Ninja.hpp
index 17649aa..36a57ff 100644
--- a/backend/ninja/Ninja.hpp
+++ b/backend/ninja/Ninja.hpp
@@ -28,14 +28,14 @@ namespace backend
void addTestSourceDir(const char *dir);
void addDependency(const std::string &binaryFile);
const std::vector<std::string>& getSourceFiles() const;
- sibs::Result<bool> build(const sibs::SibsConfig &config, const char *savePath, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc = nullptr, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback = nullptr);
+ sibs::Result<bool> build(const sibs::SibsConfig &config, const _tinydir_char_t *savePath, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc = nullptr, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback = nullptr);
private:
sibs::Result<bool> buildTests(const std::string &projectGeneratedBinary, const sibs::SibsConfig &config, const char *savePath);
bool containsSourceFile(const std::string &filepath) const;
bool containsTestSourceDir(const std::string &dir) const;
bool containsDependency(const std::string &dependency) const;
sibs::Result<bool> getLinkerFlags(const sibs::SibsConfig &config, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback) const;
- sibs::Result<bool> build(const char *buildFilePath);
+ sibs::Result<bool> build(const _tinydir_char_t *buildFilePath);
private:
std::vector<std::string> sourceFiles;
std::vector<std::string> testSourceDirs;