From d22001283a49ad723da0023039c904dc6db7c5a0 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 2 Oct 2018 21:14:45 +0200 Subject: Fix bundle for non system libraries --- CMakeLists.txt | 24 +-------------- backend/ninja/Ninja.cpp | 68 ++++++++++++++++++++++++++++++++++++++++-- include/Conf.hpp | 4 ++- scripts/package.py | 40 ++++++++++++++++++++----- src/Conf.cpp | 5 +++- src/FileUtil.cpp | 2 +- src/main.cpp | 2 ++ static/linux/libarchive.a | Bin 1621578 -> 0 bytes static/linux/libbz2.a | Bin 117762 -> 0 bytes static/linux/libcrypto.a | Bin 4374008 -> 0 bytes static/linux/libcurl.a | Bin 1378480 -> 0 bytes static/linux/libgit2.a | Bin 2481536 -> 0 bytes static/linux/libhttp_parser.a | Bin 46096 -> 0 bytes static/linux/liblz4.a | Bin 301294 -> 0 bytes static/linux/liblzma.a | Bin 409792 -> 0 bytes static/linux/libssh2.a | Bin 354480 -> 0 bytes static/linux/libssl.a | Bin 765298 -> 0 bytes static/linux/libxml2.a | Bin 2804996 -> 0 bytes static/linux/libz.a | Bin 154898 -> 0 bytes 19 files changed, 109 insertions(+), 36 deletions(-) delete mode 100644 static/linux/libarchive.a delete mode 100644 static/linux/libbz2.a delete mode 100644 static/linux/libcrypto.a delete mode 100644 static/linux/libcurl.a delete mode 100644 static/linux/libgit2.a delete mode 100644 static/linux/libhttp_parser.a delete mode 100644 static/linux/liblz4.a delete mode 100644 static/linux/liblzma.a delete mode 100644 static/linux/libssh2.a delete mode 100644 static/linux/libssl.a delete mode 100644 static/linux/libxml2.a delete mode 100644 static/linux/libz.a diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b4c3ae..285f69d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,6 @@ project(sibs) set(CMAKE_CXX_STANDARD 14) -option(BUILD_STATIC "Build sibs statically on linux" OFF) - set(SOURCE_FILES external/xxhash.c backend/ninja/Ninja.cpp @@ -40,26 +38,6 @@ if(WIN32) target_link_libraries(sibs ${CURL_LIBRARIES} ${LibArchive_LIBRARIES} "${CMAKE_CURRENT_SOURCE_DIR}/static/windows/git2.lib") target_compile_options(sibs PRIVATE /Wall) else() - if(BUILD_STATIC AND UNIX AND NOT APPLE AND CMAKE_SIZEOF_VOID_P EQUAL 8) - target_link_libraries(sibs - -static - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libarchive.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libbz2.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libxml2.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/liblzma.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/liblz4.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libgit2.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libcurl.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libz.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libssh2.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libhttp_parser.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libssl.a" - "${CMAKE_CURRENT_SOURCE_DIR}/static/linux/libcrypto.a" - -pthread - -ldl - -lm) - else() - target_link_libraries(sibs ${CURL_LIBRARIES} ${LibArchive_LIBRARIES} -lgit2) - endif() + target_link_libraries(sibs ${CURL_LIBRARIES} ${LibArchive_LIBRARIES} -lgit2) target_compile_options(sibs PRIVATE -Wall -Wextra -Werror=return-type -fdiagnostics-show-option -fexceptions) endif() diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index 8b92af1..4495bd4 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -6,6 +6,7 @@ #include "../../include/PkgConfig.hpp" #include "../../include/GlobalLib.hpp" #include +#include using namespace std; using namespace sibs; @@ -636,6 +637,62 @@ namespace backend return result; } +#if OS_FAMILY == OS_FAMILY_WINDOWS + struct PathSeperatorMatcher + { + bool operator()(char c) const + { + return c == '/' || c == '\\'; + } + }; +#else + struct PathSeperatorMatcher + { + bool operator()(char c) const + { + return c == '/'; + } + }; +#endif + + static FileString getFileParentDirectory(const FileString &filepath) + { + auto it = find_if(filepath.rbegin(), filepath.rend(), PathSeperatorMatcher()); + if(it == filepath.rend()) + return TINYDIR_STRING(""); + else + return filepath.substr(0, it.base().base() - &filepath[0]); + } + + static string extractDynamicLibDirsFromLinkerFlags(const vector &linkerFlags) + { + string result; + for(const string &flag : linkerFlags) + { + FileString flagNative; + if(flag.size() >= 2 && (flag[0] == '\'' || flag[0] == '"') && (flag.back() == '\'' || flag.back() == '"')) + flagNative = toFileString(StringView(&flag[1], flag.size() - 2)); + else + flagNative = toFileString(flag); + + if(getFileType(flagNative.c_str()) == FileType::REGULAR) + { + Result libFullPath = getRealPath(flagNative.c_str()); + if(libFullPath) + { + FileString libDir = getFileParentDirectory(libFullPath.unwrap()); + if(!libDir.empty()) + { + if(!result.empty()); + result += ":"; + result += toUtf8(libDir); + } + } + } + } + return result; + } + Result Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { bool isCCompilerClang = false; @@ -723,6 +780,7 @@ namespace backend } vector linkerFlags; + vector dynamicLinkerFlags; auto parentProjStaticLinkerFlagCallbackFunc = staticLinkerFlagCallbackFunc; if (!staticLinkerFlagCallbackFunc || libraryType == LibraryType::DYNAMIC) @@ -736,11 +794,12 @@ namespace backend auto parentProjDynamicLinkerFlagCallbackFunc = dynamicLinkerFlagCallback; if(!dynamicLinkerFlagCallback || libraryType != LibraryType::STATIC) { - dynamicLinkerFlagCallback = [&linkerFlags, &parentProjDynamicLinkerFlagCallbackFunc](const string &linkerFlag) + dynamicLinkerFlagCallback = [&linkerFlags, &dynamicLinkerFlags, &parentProjDynamicLinkerFlagCallbackFunc](const string &linkerFlag) { if(parentProjDynamicLinkerFlagCallbackFunc) parentProjDynamicLinkerFlagCallbackFunc(linkerFlag); linkerFlags.push_back(linkerFlag); + dynamicLinkerFlags.push_back(linkerFlag); }; } @@ -1161,6 +1220,7 @@ namespace backend { case Compiler::GCC: { + string rpath = extractDynamicLibDirsFromLinkerFlags(dynamicLinkerFlags); buildExeArgs.insert(buildExeArgs.end(), { ninja::NinjaArg::createRaw("ccache"), ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"), @@ -1170,6 +1230,9 @@ namespace backend ninja::NinjaArg::createRaw(noUndefinedFlag) }); + if(!rpath.empty()) + buildExeArgs.push_back(ninja::NinjaArg("-Wl,-rpath," + rpath)); + if(config.getSanitize()) { buildExeArgs.insert(buildExeArgs.end(), { @@ -1364,7 +1427,8 @@ namespace backend ninja::NinjaArg::createRaw("ccache"), ninja::NinjaArg::createRaw(usesCppFiles ? "c++" : "cc"), ninja::NinjaArg::createRaw("$in"), - ninja::NinjaArg::createRaw("-shared"), + ninja::NinjaArg::createRaw("-shared"), + ninja::NinjaArg("-Wl,-soname," + generatedFile), ninja::NinjaArg::createRaw("-o"), ninja::NinjaArg::createRaw("$out"), ninja::NinjaArg::createRaw(noUndefinedFlag) diff --git a/include/Conf.hpp b/include/Conf.hpp index 7a29624..d23c655 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -302,7 +302,8 @@ namespace sibs sanitize(false), showWarnings(false), zigTestAllFiles(false), - packaging(false) + packaging(false), + bundling(false) { cmakeDirGlobal = projectPath; cmakeDirStatic = cmakeDirGlobal; @@ -501,6 +502,7 @@ namespace sibs bool showWarnings; bool zigTestAllFiles; bool packaging; + bool bundling; protected: virtual void processObject(StringView name) override; virtual void processField(StringView name, const ConfigValue &value) override; diff --git a/scripts/package.py b/scripts/package.py index 3de3448..47fc45d 100755 --- a/scripts/package.py +++ b/scripts/package.py @@ -8,6 +8,17 @@ import re import stat import tarfile +run_script_linux = """ +#!/bin/sh + +set -e + +script_path=`realpath $0` +script_dir=`dirname $script_path` +cd "$script_dir" +"./$PROGRAM_NAME" +""" + def get_executable_dynamic_libraries(filepath): libs = [] process = subprocess.Popen(["ldd", filepath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -17,9 +28,10 @@ def get_executable_dynamic_libraries(filepath): lines = stdout.splitlines() for line in lines: s = line.split() - if b"=>" in s: - if len(s) >= 3: - libs.append(os.path.realpath(s[2].decode("UTF-8"))) + if len(s) >= 3 and b"=>" in s: + lib_path = " ".join(x.decode("UTF-8") for x in s[2:-1]) + if os.path.exists(lib_path): + libs.append(os.path.realpath(lib_path)) return libs def make_executable(filepath): @@ -43,6 +55,10 @@ def main(): print("Unexpected error: found multiple so loaders, unable to recover") exit(2) so_loader = lib_filename + + if not so_loader: + print("Unexpected error: no so loader found, unable to recover") + exit(5) executable_filename = os.path.basename(sys.argv[1]) new_executable_path = os.path.join(sys.argv[2], executable_filename) @@ -62,17 +78,25 @@ def main(): print("Failed to execute patchelf --set-rpath on executable %s, error: %s" % (new_executable_path, stderr)) exit(4) + run_script_path = os.path.join(sys.argv[2], "run.sh") + with open(run_script_path, "wb") as run_script: + run_script.write(run_script_linux.replace("$PROGRAM_NAME", executable_filename).encode("UTF-8")) + make_executable(run_script_path) + package_name = new_executable_path + ".tar.gz" - print("Creating package %s" % os.path.basename(package_name)) + print("Creating archive %s" % os.path.basename(package_name)) with tarfile.open(package_name, "w:gz") as tar: for lib in libs: - print("Adding shared library %s to tar" % lib) + print("Adding shared library %s to package" % lib) tar.add(lib, arcname=os.path.basename(lib)) - print("Adding executable %s to tar" % sys.argv[1]) - tar.add(new_executable_path, arcname=os.path.basename(new_executable_path)) + print("Adding executable %s to package" % sys.argv[1]) + tar.add(new_executable_path, arcname=executable_filename) + print("Adding run script %s to package" % run_script_path) + tar.add(run_script_path, arcname="run.sh") - print("Removing temporary file %s" % new_executable_path) + print("Removing temporary files") os.remove(new_executable_path) + os.remove(run_script_path) print("Package has been created at %s" % package_name) if __name__ == "__main__": diff --git a/src/Conf.cpp b/src/Conf.cpp index 365cf38..fa92bf5 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -487,6 +487,9 @@ namespace sibs else fprintf(stderr, "Warning: Project contains tests directory but we got an error while retrieving the full path to it\n"); } + + if(config.isMainProject() && (config.packaging || config.bundling) && config.getPackageType() != PackageType::EXECUTABLE) + return Result::Err("Packaging is only supported for projects that are of type executable"); } return parseResult; @@ -1235,7 +1238,7 @@ namespace sibs if(prependSpace) cmakeArgs += TINYDIR_STRING(" "); cmakeArgs += TINYDIR_STRING("\"-D"); - cmakeArgs += toFileString(string(arg.data, arg.size)); + cmakeArgs += toFileString(arg); cmakeArgs += TINYDIR_STRING("\""); } } diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp index f52dd1f..498f638 100644 --- a/src/FileUtil.cpp +++ b/src/FileUtil.cpp @@ -52,7 +52,7 @@ namespace sibs FileString toFileString(const StringView &utf8Str) { - return FileString(utf8Str.data, utf8Str.size); + return FileString(utf8Str.data, utf8Str.data + utf8Str.size); } #else std::string toUtf8(const sibs::FileString &input) diff --git a/src/main.cpp b/src/main.cpp index f33b1f6..119aafb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1071,6 +1071,7 @@ static int packageProject(int argc, const _tinydir_char_t **argv) SibsConfig sibsConfig(compiler, projectPath, OPT_LEV_RELEASE, false); sibsConfig.showWarnings = true; sibsConfig.packaging = packagingType == PackagingType::STATIC; + sibsConfig.bundling = packagingType == PackagingType::BUNDLE; int result = buildProject(projectPath, projectConfFilePath, sibsConfig); if(result != 0) return result; @@ -1087,6 +1088,7 @@ static int packageProject(int argc, const _tinydir_char_t **argv) { string packagePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/package")); string executablePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/release/") + sibsConfig.getPackageName()); + printf("Creating a package from project and dependencies...\n"); FileString cmd = "python3 \"" + packageScriptPath + "\" \"" + executablePath + "\" \"" + packagePath + "\""; Result bundleResult = exec(cmd.c_str(), true); if(!bundleResult) diff --git a/static/linux/libarchive.a b/static/linux/libarchive.a deleted file mode 100644 index 09f2986..0000000 Binary files a/static/linux/libarchive.a and /dev/null differ diff --git a/static/linux/libbz2.a b/static/linux/libbz2.a deleted file mode 100644 index 58652ca..0000000 Binary files a/static/linux/libbz2.a and /dev/null differ diff --git a/static/linux/libcrypto.a b/static/linux/libcrypto.a deleted file mode 100644 index 518e29b..0000000 Binary files a/static/linux/libcrypto.a and /dev/null differ diff --git a/static/linux/libcurl.a b/static/linux/libcurl.a deleted file mode 100644 index 8d208c1..0000000 Binary files a/static/linux/libcurl.a and /dev/null differ diff --git a/static/linux/libgit2.a b/static/linux/libgit2.a deleted file mode 100644 index 47f6c26..0000000 Binary files a/static/linux/libgit2.a and /dev/null differ diff --git a/static/linux/libhttp_parser.a b/static/linux/libhttp_parser.a deleted file mode 100644 index f8db936..0000000 Binary files a/static/linux/libhttp_parser.a and /dev/null differ diff --git a/static/linux/liblz4.a b/static/linux/liblz4.a deleted file mode 100644 index ab07dd9..0000000 Binary files a/static/linux/liblz4.a and /dev/null differ diff --git a/static/linux/liblzma.a b/static/linux/liblzma.a deleted file mode 100644 index 553ac4c..0000000 Binary files a/static/linux/liblzma.a and /dev/null differ diff --git a/static/linux/libssh2.a b/static/linux/libssh2.a deleted file mode 100644 index ed5e0c5..0000000 Binary files a/static/linux/libssh2.a and /dev/null differ diff --git a/static/linux/libssl.a b/static/linux/libssl.a deleted file mode 100644 index 6876ce9..0000000 Binary files a/static/linux/libssl.a and /dev/null differ diff --git a/static/linux/libxml2.a b/static/linux/libxml2.a deleted file mode 100644 index c244b71..0000000 Binary files a/static/linux/libxml2.a and /dev/null differ diff --git a/static/linux/libz.a b/static/linux/libz.a deleted file mode 100644 index fa2b2ab..0000000 Binary files a/static/linux/libz.a and /dev/null differ -- cgit v1.2.3