aboutsummaryrefslogtreecommitdiff
path: root/backend/ninja/Ninja.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backend/ninja/Ninja.cpp')
-rw-r--r--backend/ninja/Ninja.cpp208
1 files changed, 71 insertions, 137 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index 73a6dc3..3df4e41 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -1,6 +1,9 @@
#include <cstring>
#include "Ninja.hpp"
#include "../../include/FileUtil.hpp"
+#include "../../include/Exec.hpp"
+#include "../../include/PkgConfig.hpp"
+#include "../../include/GlobalLib.hpp"
using namespace std;
using namespace sibs;
@@ -36,34 +39,10 @@ namespace backend
return move(result);
}
- struct ExecResult
+ Ninja::Ninja(LibraryType _libraryType) :
+ libraryType(_libraryType)
{
- string stdout;
- int exitCode;
- };
- Result<ExecResult> exec(const char *cmd, bool print = false)
- {
- char buffer[128];
- string result;
- FILE *pipe = popen(cmd, "r");
- if(!pipe)
- return Result<ExecResult>::Err("popen() failed");
-
- while(!feof(pipe))
- {
- if(fgets(buffer, 128, pipe))
- {
- result += buffer;
- if(print)
- printf("%s", buffer);
- }
- }
-
- ExecResult execResult;
- execResult.stdout = result;
- execResult.exitCode = WEXITSTATUS(pclose(pipe));
- return Result<ExecResult>::Ok(execResult);
}
void Ninja::addSourceFile(const char *filepath)
@@ -82,70 +61,15 @@ namespace backend
return false;
}
- Result<bool> Ninja::validatePkgConfigPackageExists(const string &name) const
+ Result<bool> validatePkgConfigPackageVersionExists(const Dependency &dependency)
{
- string command = "pkg-config --exists '";
- command += name;
- command += "'";
- Result<ExecResult> execResult = exec(command.c_str());
- if(execResult.isErr())
- {
- return Result<bool>::Err(execResult.getErrMsg());
- }
+ Result<bool> dependencyValidationResult = PkgConfig::validatePackageExists(dependency.name);
+ if(dependencyValidationResult.isErr())
+ return Result<bool>::Err(dependencyValidationResult.getErrMsg());
- if(execResult.unwrap().exitCode == 1)
- {
- string errMsg = "Dependency not found: ";
- errMsg += name;
- return Result<bool>::Err(errMsg);
- }
- else if(execResult.unwrap().exitCode == 127)
- {
- return Result<bool>::Err("pkg-config is not installed");
- }
- else if(execResult.unwrap().exitCode != 0)
- {
- string errMsg = "Failed to check if dependency exists, Unknown error, exit code: ";
- errMsg += to_string(execResult.unwrap().exitCode);
- return Result<bool>::Err(errMsg);
- }
-
- return Result<bool>::Ok(true);
- }
-
- Result<bool> Ninja::validatePkgConfigPackageVersionAtLeast(const string &name, const string &version) const
- {
- // Use --modversion instead and check if the version returned is newer or equal to dependency version.
- // This way we can output installed version vs expected dependency version
- string command = "pkg-config '--atleast-version=";
- command += version;
- command += "' '";
- command += name;
- command += "'";
- Result<ExecResult> execResult = exec(command.c_str());
- if(execResult.isErr())
- {
- return Result<bool>::Err(execResult.getErrMsg());
- }
-
- if(execResult.unwrap().exitCode == 1)
- {
- string errMsg = "Dependency ";
- errMsg += name;
- errMsg += " is installed but the version older than ";
- errMsg += version;
- return Result<bool>::Err(errMsg);
- }
- else if(execResult.unwrap().exitCode == 127)
- {
- return Result<bool>::Err("pkg-config is not installed");
- }
- else if(execResult.unwrap().exitCode != 0)
- {
- string errMsg = "Failed to check dependency version, Unknown error, exit code: ";
- errMsg += to_string(execResult.unwrap().exitCode);
- return Result<bool>::Err(errMsg);
- }
+ Result<bool> dependencyVersionValidationResult = PkgConfig::validatePackageVersionAtLeast(dependency.name, dependency.version);
+ if(dependencyVersionValidationResult.isErr())
+ return Result<bool>::Err(dependencyVersionValidationResult.getErrMsg());
return Result<bool>::Ok(true);
}
@@ -156,53 +80,39 @@ namespace backend
{
if(dependencies.empty()) return Result<string>::Ok("");
- for(const sibs::Dependency &dependency : dependencies)
- {
- Result<bool> dependencyValidationResult = validatePkgConfigPackageExists(dependency.name);
- if(dependencyValidationResult.isErr())
- return Result<string>::Err(dependencyValidationResult.getErrMsg());
-
- Result<bool> dependencyVersionValidationResult = validatePkgConfigPackageVersionAtLeast(dependency.name, dependency.version);
- if(dependencyVersionValidationResult.isErr())
- return Result<string>::Err(dependencyVersionValidationResult.getErrMsg());
- }
+ // TODO: Global library dir should be created during sibs installation
+ string globalLibDir = getHomeDir();
+ globalLibDir += "/.sibs/lib";
- string args;
+ string globalLibLinkerFlags;
+ vector<string> pkgConfigDependencies;
for(const sibs::Dependency &dependency : dependencies)
{
- args += " '";
- args += dependency.name;
- args += "'";
+ Result<bool> pkgConfigDependencyValidation = validatePkgConfigPackageVersionExists(dependency);
+ if(pkgConfigDependencyValidation.isOk())
+ {
+ pkgConfigDependencies.push_back(dependency.name);
+ }
+ else
+ {
+ printf("%s, trying global lib\n", pkgConfigDependencyValidation.getErrMsg().c_str());
+ Result<string> globalLibLinkerFlagsResult = GlobalLib::getDynamicLibsLinkerFlags(globalLibDir, dependency.name, dependency.version);
+ if(globalLibLinkerFlagsResult.isErr())
+ return globalLibLinkerFlagsResult;
+
+ globalLibLinkerFlags += " ";
+ globalLibLinkerFlags += globalLibLinkerFlagsResult.unwrap();
+ // TODO: If package doesn't exist, download it from github/server
+ }
}
- string command = "pkg-config --libs";
- command += args;
- Result<ExecResult> execResult = exec(command.c_str());
- if(execResult.isErr())
- return Result<string>::Err(execResult.getErrMsg());
+ Result<string> pkgConfigLinkerFlagsResult = PkgConfig::getDynamicLibsLinkerFlags(pkgConfigDependencies);
+ if(pkgConfigLinkerFlagsResult.isErr())
+ return pkgConfigLinkerFlagsResult;
- if(execResult.unwrap().exitCode == 0)
- {
- return Result<string>::Ok(execResult.unwrap().stdout);
- }
- else if(execResult.unwrap().exitCode == 1)
- {
- // TODO: This shouldn't happen because we check if each dependency is installed before this,
- // but maybe the package is uninstalled somewhere between here...
- // Would be better to recheck if each package is installed here again
- // to know which package was uninstalled
- return Result<string>::Err("Dependencies not found");
- }
- else if(execResult.unwrap().exitCode == 127)
- {
- return Result<string>::Err("pkg-config is not installed");
- }
- else
- {
- string errMsg = "Failed to get dependencies linking flags, Unknown error, exit code: ";
- errMsg += to_string(execResult.unwrap().exitCode);
- return Result<string>::Err(errMsg);
- }
+ string allLinkerFlags = pkgConfigLinkerFlagsResult.unwrap();
+ allLinkerFlags += globalLibLinkerFlags;
+ return Result<string>::Ok(allLinkerFlags);
}
Result<bool> Ninja::createBuildFile(const std::string &packageName, const vector<Dependency> &dependencies, const char *savePath)
@@ -210,7 +120,8 @@ namespace backend
if(sourceFiles.empty())
return Result<bool>::Err("No source files provided");
- printf("Package name: %s\n", packageName.c_str());
+ string ninjaBuildFilePath = savePath;
+ ninjaBuildFilePath += "/build.ninja";
string result;
result.reserve(16384);
@@ -220,8 +131,30 @@ namespace backend
result += "rule cpp_COMPILER\n";
result += " command = ccache c++ $ARGS -c $in -o $out\n\n";
- result += "rule cpp_LINKER\n";
- result += " command = ccache c++ $ARGS -o $out $in $LINK_ARGS $aliasing\n\n";
+ string linkerJob;
+ switch(libraryType)
+ {
+ case LibraryType::EXECUTABLE:
+ {
+ result += "rule cpp_EXEC_LINKER\n";
+ result += " command = ccache c++ $ARGS -o $out $in $LINK_ARGS $aliasing\n\n";
+ linkerJob = "cpp_EXEC_LINKER";
+ break;
+ }
+ case LibraryType::STATIC:
+ {
+ result += "rule cpp_STATIC_LINKER\n";
+ result += " command = ar rcs lib";
+ result += packageName;
+ result += ".a";
+ result += " $in\n\n";
+ linkerJob = "cpp_STATIC_LINKER";
+ break;
+ }
+ default:
+ assert(false);
+ return Result<bool>::Err("NOT IMPLEMENTED YET!");
+ }
vector<string> objectNames;
for(const string &sourceFile : sourceFiles)
@@ -234,7 +167,8 @@ namespace backend
result += ": cpp_COMPILER ../../";
result += sourceFile;
result += "\n";
- result += " ARGS = '-I" + packageName + "@exe' '-I.' '-I..' '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' '-O0' '-g'\n\n";
+ // TODO: Create .deps directory if it doesn't exist. Should be a symlink to homedir/.sibs/lib
+ result += " ARGS = '-I../../.deps' '-I" + packageName + "@exe' '-I.' '-I..' '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' '-O0' '-g'\n\n";
objectNames.emplace_back(objectName);
}
@@ -244,22 +178,22 @@ namespace backend
result += "build ";
result += packageName;
- result += ": cpp_LINKER ";
+ result += ": " + linkerJob + " ";
result += join(objectNames, " ");
result += "\n";
result += " LINK_ARGS = '-Wl,--no-undefined' '-Wl,--as-needed' ";
result += linkerFlags.unwrap();
result += "\n\n";
- bool fileOverwritten = sibs::fileOverwrite(savePath, sibs::StringView(result.data(), result.size()));
+ bool fileOverwritten = sibs::fileOverwrite(ninjaBuildFilePath.c_str(), sibs::StringView(result.data(), result.size()));
if(!fileOverwritten)
{
string errMsg = "Failed to overwrite ninja build file: ";
- errMsg += savePath;
+ errMsg += ninjaBuildFilePath;
return Result<bool>::Err(errMsg);
}
- printf("Created ninja build file: %s\n", savePath);
+ printf("Created ninja build file: %s\n", ninjaBuildFilePath.c_str());
return Result<bool>::Ok(true);
}