aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/ninja/Ninja.cpp116
-rw-r--r--backend/ninja/Ninja.hpp6
-rw-r--r--include/GlobalLib.hpp2
-rw-r--r--include/Result.hpp2
-rw-r--r--src/GlobalLib.cpp52
-rw-r--r--src/PkgConfig.cpp4
6 files changed, 132 insertions, 50 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index ede150c..d8345a4 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -81,7 +81,7 @@ namespace backend
// 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 vector<Dependency> &dependencies, LinkerFlagCallbackFunc linkerFlagCallbackFunc) const
+ Result<bool> Ninja::getLinkerFlags(const vector<Dependency> &dependencies, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback) const
{
if(dependencies.empty()) return Result<bool>::Ok(true);
@@ -120,13 +120,13 @@ namespace backend
else
{
if(!pkgConfigLinkerFlagsResult.unwrap().empty())
- linkerFlagCallbackFunc(pkgConfigLinkerFlagsResult.unwrap());
+ dynamicLinkerFlagCallback(pkgConfigLinkerFlagsResult.unwrap());
}
for(const Dependency &globalLibDependency : globalLibDependencies)
{
printf("Dependency %s is missing from pkg-config, trying global lib\n", globalLibDependency.name.c_str());
- Result<string> globalLibLinkerFlagsResult = GlobalLib::getStaticLibsLinkerFlags(globalLibDir, globalLibDependency.name, globalLibDependency.version, linkerFlagCallbackFunc);
+ Result<string> globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(globalLibDir, globalLibDependency.name, globalLibDependency.version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback);
if(globalLibLinkerFlagsResult.isErr())
{
if(globalLibLinkerFlagsResult.getErrorCode() == GlobalLib::DependencyError::DEPENDENCY_NOT_FOUND || globalLibLinkerFlagsResult.getErrorCode() == GlobalLib::DependencyError::DEPENDENCY_VERSION_NO_MATCH)
@@ -142,7 +142,7 @@ namespace backend
if(downloadDependencyResult.isErr())
return downloadDependencyResult;
- globalLibLinkerFlagsResult = GlobalLib::getStaticLibsLinkerFlags(globalLibDir, globalLibDependency.name, globalLibDependency.version, linkerFlagCallbackFunc);
+ globalLibLinkerFlagsResult = GlobalLib::getLibsLinkerFlags(globalLibDir, globalLibDependency.name, globalLibDependency.version, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback);
if(globalLibLinkerFlagsResult.isErr())
return Result<bool>::Err(globalLibLinkerFlagsResult);
}
@@ -156,8 +156,9 @@ namespace backend
return Result<bool>::Ok(true);
}
- Result<bool> Ninja::createBuildFile(const std::string &packageName, const vector<Dependency> &dependencies, const char *savePath, LinkerFlagCallbackFunc linkerFlagCallbackFunc)
+ Result<bool> Ninja::createBuildFile(const std::string &packageName, const vector<Dependency> &dependencies, const char *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())
return Result<bool>::Err("No source files provided");
@@ -178,35 +179,50 @@ namespace backend
result += globalLibDir;
result += "'\n\n";
- result += "rule cpp_COMPILER\n";
- result += " command = ccache c++ $ARGS -c $in -o $out\n\n";
-
- string linkerJob;
+ string buildJob;
switch(libraryType)
{
case LibraryType::EXECUTABLE:
{
- result += "rule cpp_EXEC_LINKER\n";
+ 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";
- linkerJob = "cpp_EXEC_LINKER";
+ buildJob = "cpp_BUILD_EXEC";
break;
}
case LibraryType::STATIC:
{
- result += "rule cpp_STATIC_LINKER\n";
+ result += "rule cpp_COMPILER\n";
+ result += " command = ccache c++ $ARGS -c -fPIC $in -o $out\n\n";
+
+ result += "rule cpp_BUILD_STATIC\n";
result += " command = ar rcs lib";
result += packageName;
result += ".a";
result += " $in\n\n";
- linkerJob = "cpp_STATIC_LINKER";
+ buildJob = "cpp_BUILD_STATIC";
+ break;
+ }
+ case LibraryType::DYNAMIC:
+ {
+ 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";
+ buildJob = "cpp_BUILD_DYNAMIC";
break;
}
default:
assert(false);
- return Result<bool>::Err("Building a dynamic library is not supported yet");
+ return Result<bool>::Err("Unexpected error");
}
vector<string> objectNames;
+ objectNames.reserve(sourceFiles.size());
for(const string &sourceFile : sourceFiles)
{
// TODO: Handle tests differently.
@@ -227,46 +243,80 @@ namespace backend
objectNames.emplace_back(objectName);
}
+ string allLinkerFlags;
+ if(!staticLinkerFlagCallbackFunc || libraryType == LibraryType::DYNAMIC)
+ {
+ staticLinkerFlagCallbackFunc = [&allLinkerFlags](const string &linkerFlag)
+ {
+ allLinkerFlags += " ";
+ allLinkerFlags += linkerFlag;
+ };
+ }
+
+ // TODO: If project contains no source files, then we shouldn't override this function
+ dynamicLinkerFlagCallback = [&allLinkerFlags](const string &linkerFlag)
+ {
+ allLinkerFlags += " ";
+ allLinkerFlags += linkerFlag;
+ };
+
switch(libraryType)
{
case LibraryType::EXECUTABLE:
{
- string allLinkerFlags;
- Result<bool> linkerFlags = getLinkerFlags(dependencies, [&allLinkerFlags](const string &linkerFlag)
- {
- allLinkerFlags += " ";
- allLinkerFlags += linkerFlag;
- });
+ Result<bool> linkerFlags = getLinkerFlags(dependencies, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback);
if(linkerFlags.isErr())
return Result<bool>::Err(linkerFlags.getErrMsg());
result += "build ";
result += packageName;
- result += ": " + linkerJob + " ";
+ result += ": " + buildJob + " ";
result += join(objectNames, " ");
result += "\n";
- result += " LINK_ARGS = '-Wl,--no-undefined' '-Wl,--as-needed' ";
- result += allLinkerFlags;
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ if(!allLinkerFlags.empty())
+ {
+ result += allLinkerFlags;
+ }
result += "\n\n";
break;
}
case LibraryType::STATIC:
{
- string allLinkerFlags;
- Result<bool> linkerFlags = getLinkerFlags(dependencies, linkerFlagCallbackFunc);
+ Result<bool> linkerFlags = getLinkerFlags(dependencies, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback);
if(linkerFlags.isErr())
return linkerFlags;
result += "build ";
result += packageName;
- result += ": " + linkerJob + " ";
+ result += ": " + buildJob + " ";
result += join(objectNames, " ");
result += "\n\n";
break;
}
+ case LibraryType::DYNAMIC:
+ {
+ Result<bool> linkerFlags = getLinkerFlags(dependencies, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback);
+ if(linkerFlags.isErr())
+ return Result<bool>::Err(linkerFlags.getErrMsg());
+
+ result += "build lib";
+ result += packageName;
+ result += ".so: " + buildJob + " ";
+ result += join(objectNames, " ");
+ result += "\n";
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ if(!allLinkerFlags.empty())
+ {
+ result += allLinkerFlags;
+ //result += " '-Wl,--no-whole-archive'";
+ }
+ result += "\n\n";
+ break;
+ }
default:
assert(false);
- return Result<bool>::Err("Building a dynamic library is not supported yet");
+ return Result<bool>::Err("Unexpected error");
}
Result<bool> fileOverwriteResult = sibs::fileOverwrite(ninjaBuildFilePath.c_str(), sibs::StringView(result.data(), result.size()));
@@ -282,9 +332,17 @@ namespace backend
string command = "ninja -C '";
command += buildFilePath;
command += "'";
- Result<ExecResult> execResult = exec(command.c_str(), true);
+ Result<ExecResult> execResult = exec(command.c_str());
if(execResult.isOk())
- return Result<bool>::Ok(true);
+ {
+ if(execResult.unwrap().exitCode == 0)
+ {
+ printf("%s", execResult.unwrap().execStdout.c_str());
+ return Result<bool>::Ok(true);
+ }
+ else
+ return Result<bool>::Err(execResult.unwrap().execStdout);
+ }
else
return Result<bool>::Err(execResult.getErrMsg());
}
diff --git a/backend/ninja/Ninja.hpp b/backend/ninja/Ninja.hpp
index b82139c..a0239d2 100644
--- a/backend/ninja/Ninja.hpp
+++ b/backend/ninja/Ninja.hpp
@@ -17,19 +17,19 @@ namespace backend
enum class LibraryType
{
EXECUTABLE,
+ STATIC,
DYNAMIC,
- STATIC
};
Ninja(LibraryType libraryType = LibraryType::EXECUTABLE);
void addSourceFile(const char *filepath);
const std::vector<std::string>& getSourceFiles() const;
- sibs::Result<bool> createBuildFile(const std::string &packageName, const std::vector<sibs::Dependency> &dependencies, const char *savePath, sibs::LinkerFlagCallbackFunc linkerFlagCallbackFunc = nullptr);
+ sibs::Result<bool> createBuildFile(const std::string &packageName, const std::vector<sibs::Dependency> &dependencies, const char *savePath, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc = nullptr, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback = nullptr);
sibs::Result<bool> build(const char *buildFilePath);
private:
bool containsSourceFile(const char *filepath) const;
- sibs::Result<bool> getLinkerFlags(const std::vector<sibs::Dependency> &dependencies, sibs::LinkerFlagCallbackFunc linkerFlagCallbackFunc) const;
+ sibs::Result<bool> getLinkerFlags(const std::vector<sibs::Dependency> &dependencies, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback) const;
private:
std::vector<std::string> sourceFiles;
LibraryType libraryType;
diff --git a/include/GlobalLib.hpp b/include/GlobalLib.hpp
index ca542f9..78511c3 100644
--- a/include/GlobalLib.hpp
+++ b/include/GlobalLib.hpp
@@ -17,7 +17,7 @@ namespace sibs
};
static Result<bool> validatePackageExists(const std::string &globalLibRootDir, const std::string &name);
- static Result<std::string> getStaticLibsLinkerFlags(const std::string &globalLibRootDir, const std::string &name, const std::string &version, LinkerFlagCallbackFunc linkerFlagCallbackFunc);
+ static Result<std::string> getLibsLinkerFlags(const std::string &globalLibRootDir, const std::string &name, const std::string &version, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc);
static Result<bool> downloadDependency(const Dependency &dependency);
};
}
diff --git a/include/Result.hpp b/include/Result.hpp
index eb0aa01..e8f4d12 100644
--- a/include/Result.hpp
+++ b/include/Result.hpp
@@ -53,6 +53,8 @@ namespace sibs
{
return errorCode;
}
+
+ operator bool () { return isOk(); }
private:
Result(const T &_value = T()) : value(_value) {}
private:
diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp
index 617f993..a07e23d 100644
--- a/src/GlobalLib.cpp
+++ b/src/GlobalLib.cpp
@@ -55,7 +55,7 @@ namespace sibs
return false;
}
- Result<string> GlobalLib::getStaticLibsLinkerFlags(const string &globalLibRootDir, const string &name, const string &version, LinkerFlagCallbackFunc linkerFlagCallbackFunc)
+ Result<string> GlobalLib::getLibsLinkerFlags(const string &globalLibRootDir, const string &name, const string &version, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc)
{
Result<bool> packageExistsResult = validatePackageExists(globalLibRootDir, name);
if(packageExistsResult.isErr())
@@ -121,7 +121,22 @@ namespace sibs
return Result<string>::Err(errMsg);
}
- backend::Ninja ninja(backend::Ninja::LibraryType::STATIC);
+ backend::Ninja::LibraryType libraryType;
+ switch(sibsConfig.getPackageType())
+ {
+ case PackageType::STATIC:
+ libraryType = backend::Ninja::LibraryType::STATIC;
+ break;
+ case PackageType::DYNAMIC:
+ case PackageType::LIBRARY:
+ libraryType = backend::Ninja::LibraryType::DYNAMIC;
+ break;
+ default:
+ assert(false);
+ return Result<string>::Err("Unexpected error");
+ }
+
+ backend::Ninja ninja(libraryType);
walkDirFilesRecursive(packageDir.c_str(), [&ninja, &packageDir](tinydir_file *file)
{
if (isSourceFile(file))
@@ -141,15 +156,26 @@ namespace sibs
else
{
string debugBuildPath = packageDir + "/sibs-build/debug";
- string staticLibPath = debugBuildPath;
- staticLibPath += "/lib";
- staticLibPath += name;
- staticLibPath += ".a";
-
- string staticLibPathCmd = "'";
- staticLibPathCmd += staticLibPath;
- staticLibPathCmd += "'";
- linkerFlagCallbackFunc(staticLibPathCmd);
+ string libPath = debugBuildPath;
+ libPath += "/lib";
+ libPath += name;
+ if(libraryType == backend::Ninja::LibraryType::STATIC)
+ {
+ libPath += ".a";
+ string libPathCmd = "'";
+ libPathCmd += libPath;
+ libPathCmd += "'";
+ staticLinkerFlagCallbackFunc(libPathCmd);
+ libPath += ".a";
+ }
+ else
+ {
+ libPath += ".so";
+ string libPathCmd = "'";
+ libPathCmd += libPath;
+ libPathCmd += "'";
+ dynamicLinkerFlagCallbackFunc(libPathCmd);
+ }
// TODO: Use different directories depending on the project type, but .o build files should be in the same directory
// no matter what project type, since they are used for executables, static/dynamic libraries
@@ -157,7 +183,7 @@ namespace sibs
if(createBuildDirResult.isErr())
return Result<string>::Err(createBuildDirResult);
- Result<bool> buildFileResult = ninja.createBuildFile(sibsConfig.getPackageName(), sibsConfig.getDependencies(), debugBuildPath.c_str(), linkerFlagCallbackFunc);
+ Result<bool> buildFileResult = ninja.createBuildFile(sibsConfig.getPackageName(), sibsConfig.getDependencies(), debugBuildPath.c_str(), staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallbackFunc);
if (buildFileResult.isErr())
return Result<string>::Err(buildFileResult.getErrMsg());
@@ -165,7 +191,7 @@ namespace sibs
if (buildResult.isErr())
return Result<string>::Err(buildResult.getErrMsg());
- return Result<string>::Ok(staticLibPath);
+ return Result<string>::Ok(libPath);
}
}
diff --git a/src/PkgConfig.cpp b/src/PkgConfig.cpp
index 5f85549..620b1a7 100644
--- a/src/PkgConfig.cpp
+++ b/src/PkgConfig.cpp
@@ -25,9 +25,7 @@ namespace sibs
command += "'";
Result<ExecResult> execResult = exec(command.c_str());
if(execResult.isErr())
- {
return Result<bool>::Err(execResult.getErrMsg());
- }
if(execResult.unwrap().exitCode == 1)
{
@@ -63,9 +61,7 @@ namespace sibs
command += "'";
Result<ExecResult> execResult = exec(command.c_str());
if(execResult.isErr())
- {
return Result<bool>::Err(execResult.getErrMsg());
- }
if(execResult.unwrap().exitCode == 1)
{