From cd98e64f462e650c9ec4cb673c2b77831396113b Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 2 Oct 2018 18:47:24 +0200 Subject: Add bundle command to sibs package Bundle command copies all dynamic library dependencies to one location and creates an archive that can be distributed. Currently only for linux. In testing phase... --- src/main.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 134 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index eae90d0..6f54ba5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -174,19 +174,21 @@ static void usageInit() printf(" --lang\t\t\tProject template language - Optional (default: c++)\n"); printf("Examples:\n"); printf(" sibs init . --exec\n"); - printf(" sibs init dirA/dirB --dynamic"); + printf(" sibs init dirA/dirB --dynamic\n"); exit(1); } static void usagePackage() { - printf("Usage: sibs package [project_path]\n\n"); - printf("Create a redistributable package from a sibs project. Note: Redistributable packages can't use system packages to build\n\n"); + printf("Usage: sibs package [project_path] <--static|--bundle>\n\n"); + printf("Create a redistributable package from a sibs project. Note: Redistributable packages can't use system packages to build if packaging using --static\n\n"); printf("Options:\n"); printf(" project_path\t\tThe directory containiung a project.conf file - Optional (default: current directory)\n"); + printf(" --static\t\tPackage project by building everything statically. Note: can't use system packages when using this option (meaning no pkg-config support)\n\n"); + printf(" --bundle\t\tPackage project by copying all dynamic libraries into one location and creating an archive of all files. The executable is patched to use the dynamic libraries in the same directory. Note: if your project loads dynamic libraries at runtime (for example using dlopen) then you need to manually copy those libraries to the archive\n\n"); printf("Examples:\n"); - printf(" sibs package\n"); - printf(" sibs package dirA/dirB"); + printf(" sibs package --static\n"); + printf(" sibs package dirA/dirB --bundle\n"); exit(1); } @@ -927,14 +929,114 @@ static int initProject(int argc, const _tinydir_char_t **argv) return 0; } +enum class PackagingType +{ + NONE, + STATIC, + BUNDLE +}; + +static const char* asString(PackagingType packagingType) +{ + switch(packagingType) + { + case PackagingType::STATIC: return "--static"; + case PackagingType::BUNDLE: return "--bundle"; + default: return "none"; + } +} + +static void validateSibsScriptDir(const FileString &sibsScriptDir) +{ + FileType projectPathFileType = getFileType(sibsScriptDir.c_str()); + if(projectPathFileType == FileType::FILE_NOT_FOUND) + { + string errMsg = "Error: invalid SIBS_SCRIPT_DIR: "; + errMsg += toUtf8(sibsScriptDir); + perror(errMsg.c_str()); + exit(2); + } + else if(projectPathFileType == FileType::REGULAR) + { + ferr <<"Error: Expected SIBS_SCRIPT_DIR path (" << sibsScriptDir << ") to be a directory, was a file" << endl; + exit(3); + } +} + +static void validateSibsScriptPath(const FileString &sibsScriptFilepath) +{ + FileType projectPathFileType = getFileType(sibsScriptFilepath.c_str()); + if(projectPathFileType == FileType::FILE_NOT_FOUND) + { + string errMsg = "Error: invalid sibs script: "; + errMsg += toUtf8(sibsScriptFilepath); + perror(errMsg.c_str()); + exit(2); + } + else if(projectPathFileType == FileType::DIRECTORY) + { + ferr <<"Error: Expected sibs script at location (" << sibsScriptFilepath << ") to be a file, was a directory" << endl; + exit(3); + } +} + static int packageProject(int argc, const _tinydir_char_t **argv) { - if(argc > 1) - usagePackage(); +#if OS_TYPE != OS_TYPE_LINUX + fprintf(stderr, "Error: sibs package command is currently only available on linux\n"); + exit(66); +#endif + char *sibsScriptDirRaw = getenv("SIBS_SCRIPT_DIR"); + if(!sibsScriptDirRaw) + { + fprintf(stderr, "Error: SIBS_SCRIPT_DIR needs to be defined. SIBS_SCRIPT_DIR should be the location to sibs scripts\n"); + exit(67); + } + FileString sibsScriptDir = toFileString(string(sibsScriptDirRaw)); + validateSibsScriptDir(sibsScriptDir); + FileString packageScriptPath = sibsScriptDir + TINYDIR_STRING("/package.py"); + validateSibsScriptPath(packageScriptPath); FileString projectPath; - if(argc == 1) - projectPath = argv[0]; + PackagingType packagingType = PackagingType::NONE; + + for(int i = 0; i < argc; ++i) + { + const _tinydir_char_t *arg = argv[i]; + if(_tinydir_strcmp(arg, TINYDIR_STRING("--static")) == 0) + { + if(packagingType != PackagingType::NONE) + { + ferr << "Error: Project packaging type was defined more than once. First as " << asString(packagingType) << " then as " << "static" << endl; + usagePackage(); + } + packagingType = PackagingType::STATIC; + } + else if(_tinydir_strcmp(arg, TINYDIR_STRING("--bundle")) == 0) + { + if(packagingType != PackagingType::NONE) + { + ferr << "Error: Project packaging type was defined more than once. First as " << asString(packagingType) << " then as " << "bundle" << endl; + usagePackage(); + } + packagingType = PackagingType::BUNDLE; + } + else + { + if(!projectPath.empty()) + { + ferr << "Error: Project path was defined more than once. First defined as " << projectPath << " then as " << arg << endl; + usagePackage(); + } + projectPath = arg; + } + } + + if(packagingType == PackagingType::NONE) + { + ferr << "Error: Project packaging type is not defined, expected to be either --static or --bundle" << endl; + usagePackage(); + } // TODO: If projectPath is not defined and working directory does not contain project.conf, then search every parent directory until one is found if(projectPath.empty()) @@ -966,13 +1068,33 @@ static int packageProject(int argc, const _tinydir_char_t **argv) SibsConfig sibsConfig(compiler, projectPath, OPT_LEV_RELEASE, false); sibsConfig.showWarnings = true; - sibsConfig.packaging = true; + sibsConfig.packaging = packagingType == PackagingType::STATIC; int result = buildProject(projectPath, projectConfFilePath, sibsConfig); if(result != 0) return result; - string packagePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/package")); - printf("Project %s was successfully packaged and can be found at %s\n", sibsConfig.getPackageName().c_str(), packagePath.c_str()); + switch(packagingType) + { + case PackagingType::STATIC: + { + string packagePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/package")); + printf("Project %s was successfully packaged and can be found at %s\n", sibsConfig.getPackageName().c_str(), packagePath.c_str()); + break; + } + case PackagingType::BUNDLE: + { + string packagePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/package")); + string executablePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/release/") + sibsConfig.getPackageName()); + FileString cmd = "python3 \"" + packageScriptPath + "\" \"" + executablePath + "\" \"" + packagePath + "\""; + Result bundleResult = exec(cmd.c_str()); + if(!bundleResult) + { + fprintf(stderr, "Error: failed to package project as a bundle, reason: %s\n", bundleResult.getErrMsg().c_str()); + exit(77); + } + break; + } + } return 0; } -- cgit v1.2.3