diff options
-rwxr-xr-x | .circleci/init.sh | 2 | ||||
-rw-r--r-- | README.md | 12 | ||||
-rw-r--r-- | images/spmbuild/Dockerfile | 19 | ||||
-rw-r--r-- | include/rpath.h | 6 | ||||
-rw-r--r-- | lib/config_global.c | 2 | ||||
-rw-r--r-- | lib/internal_cmd.c | 7 | ||||
-rw-r--r-- | lib/relocation.c | 2 | ||||
-rw-r--r-- | lib/rpath.c | 49 | ||||
-rwxr-xr-x | scripts/spmbuild | 25 |
9 files changed, 89 insertions, 35 deletions
diff --git a/.circleci/init.sh b/.circleci/init.sh index 6a25d16..5c130f4 100755 --- a/.circleci/init.sh +++ b/.circleci/init.sh @@ -9,6 +9,8 @@ if [[ $(uname -s) == Linux ]]; then file \ which \ rsync \ + bsdtar \ + libarchive-devel \ tar \ cmake3 \ gcc \ @@ -16,7 +16,7 @@ A basic userland package management system with a few humble goals: - gcc (https://gcc.gnu.org) - make (https://www.gnu.org/software/make) - openssl (https://www.openssl.org) -- tar (https://www.gnu.org/software/tar) +- bsdtar (https://www.libarchive.org) - which (https://carlowood.github.io/which) ## Runtime Requirements @@ -26,7 +26,7 @@ A basic userland package management system with a few humble goals: - objdump (https://www.gnu.org/software/binutils) - reloc (https://github.com/jhunkeler/reloc) - rsync (https://rsync.samba.org) -- tar (https://www.gnu.org/software/tar) +- bsdtar (https://www.libarchive.org) - which (https://carlowood.github.io/which) ## Installation @@ -38,14 +38,14 @@ A basic userland package management system with a few humble goals: ```bash $ yum install epel-release $ yum install -y binutils cmake3 curl-devel file gcc gcc-c++ gcc-gfortran glibc-devel \ - make openssl-devel patchelf rsync tar which + make openssl-devel patchelf rsync bsdtar which ``` #### Arch ```bash $ pacman -S binutils cmake curl file gcc gcc-c++ gcc-gfortran openssl make patchelf \ - rsync tar which + rsync libarchive which ``` ### Install reloc @@ -132,8 +132,8 @@ $ spm --root ~/spmenv123 --install "python" # [...] #### Export environment variables ```bash -$ source <(spm --mkruntime ~/spmenv123) -$ hash -r # or "rehash" if your shell supports it +$ spm --mkruntime ~/spmenv123 > ~/spmenv123/bin/activate +$ source ~/spmenv123/bin/activate ``` #### Use package diff --git a/images/spmbuild/Dockerfile b/images/spmbuild/Dockerfile new file mode 100644 index 0000000..1a939f8 --- /dev/null +++ b/images/spmbuild/Dockerfile @@ -0,0 +1,19 @@ +FROM jhunkeler/spm_ci_centos7:latest +ARG RELOC_COMMIT=${RELOC_COMMIT:-} +ARG SPM_COMMIT=${SPM_COMMIT:-} +ENV PATH /opt/spm/bin:/usr/bin:/usr/sbin:/bin:/sbin +ENV SHELL /bin/bash + +RUN yum install -y \ + perl-Data-Dumper \ + perl-Thread-Queue \ + perl-ExtUtils-ParseXS + +RUN ln -s cmake3 /usr/bin/cmake \ + && git clone https://github.com/jhunkeler/spmc \ + && git clone https://github.com/jhunkeler/reloc \ + && pushd reloc && mkdir build && cd build && git checkout ${RELOC_COMMIT} && cmake .. -DCMAKE_INSTALL_PREFIX=/opt/spm && make install && popd \ + && pushd spmc && mkdir build && cd build && git checkout ${SPM_COMMIT} && cmake .. -DCMAKE_INSTALL_PREFIX=/opt/spm && make install && popd + +WORKDIR /spm_packages +CMD ["bash", "-l"] diff --git a/include/rpath.h b/include/rpath.h index 2a33bea..1703b76 100644 --- a/include/rpath.h +++ b/include/rpath.h @@ -7,11 +7,11 @@ Process *patchelf(const char *_filename, const char *_args); Process *install_name_tool(const char *_filename, const char *_args); FSTree *rpath_libraries_available(const char *root); -char *rpath_autodetect(const char *filename, FSTree *tree); +char *rpath_autodetect(const char *filename, FSTree *tree, const char *destroot); int has_rpath(const char *_filename); char *rpath_get(const char *_filename); -char *rpath_generate(const char *_filename, FSTree *tree); -int rpath_autoset(const char *filename, FSTree *tree); +char *rpath_generate(const char *_filename, FSTree *tree, const char *destroot); +int rpath_autoset(const char *filename, FSTree *tree, const char *destroot); int rpath_set(const char *filename, const char *rpath); #endif //SPM_RPATH_H diff --git a/lib/config_global.c b/lib/config_global.c index 95302c3..0d244fc 100644 --- a/lib/config_global.c +++ b/lib/config_global.c @@ -138,7 +138,7 @@ void check_runtime_environment(void) { #endif "objdump", "rsync", - "tar", + "bsdtar", "bash", "reloc", NULL, diff --git a/lib/internal_cmd.c b/lib/internal_cmd.c index a859b5b..6489986 100644 --- a/lib/internal_cmd.c +++ b/lib/internal_cmd.c @@ -323,7 +323,7 @@ int rpath_set_interface(int argc, char **argv) { * */ void rpath_autoset_interface_usage(void) { - printf("usage: rpath_autoset {file} {topdir}\n"); + printf("usage: rpath_autoset {file} {topdir} {destroot}\n"); } /** @@ -333,12 +333,13 @@ void rpath_autoset_interface_usage(void) { * @return return value of `rpath_autoset` */ int rpath_autoset_interface(int argc, char **argv) { - if (argc < 3) { + if (argc < 4) { rpath_autoset_interface_usage(); return -1; } char *filename = argv[1]; const char *topdir = argv[2]; + const char *destroot = argv[3]; if (exists(filename) != 0) { perror(filename); @@ -351,7 +352,7 @@ int rpath_autoset_interface(int argc, char **argv) { } FSTree *libs = rpath_libraries_available(topdir); - int result = rpath_autoset(filename, libs); + int result = rpath_autoset(filename, libs, destroot); if (result < 0) { fprintf(SYSERROR); diff --git a/lib/relocation.c b/lib/relocation.c index a0ba6a6..870d7cf 100644 --- a/lib/relocation.c +++ b/lib/relocation.c @@ -423,7 +423,7 @@ void relocate_root(const char *destroot, const char *baseroot) { if (SPM_GLOBAL.verbose) { printf("Relocate RPATH: %s\n", b_record[i]->path); } - rpath_autoset(b_record[i]->path, libs); + rpath_autoset(b_record[i]->path, libs, destroot); } if (SPM_GLOBAL.verbose) { printf("Relocate DATA : %s\n", b_record[i]->path); diff --git a/lib/rpath.c b/lib/rpath.c index 0044db8..f15de86 100644 --- a/lib/rpath.c +++ b/lib/rpath.c @@ -105,13 +105,13 @@ char *rpath_get(const char *_filename) { * @param _filename * @return */ -char *rpath_generate(const char *_filename, FSTree *tree) { +char *rpath_generate(const char *_filename, FSTree *tree, const char *destroot) { char *filename = realpath(_filename, NULL); if (!filename) { return NULL; } - char *result = rpath_autodetect(filename, tree); + char *result = rpath_autodetect(filename, tree, destroot); if (!result) { free(filename); return NULL; @@ -134,7 +134,7 @@ int rpath_set(const char *filename, const char *rpath) { memset(args, '\0', PATH_MAX); #if OS_LINUX - sprintf(args, "--set-rpath '%s'", rpath); + sprintf(args, "--force-rpath --set-rpath '%s'", rpath); pe = patchelf(filename, args); #elif OS_DARWIN sprintf(args, "-add-rpath '%s'", rpath); @@ -156,10 +156,10 @@ int rpath_set(const char *filename, const char *rpath) { * @param _rpath * @return */ -int rpath_autoset(const char *filename, FSTree *tree) { +int rpath_autoset(const char *filename, FSTree *tree, const char *destroot) { int returncode = 0; - char *rpath_new = rpath_generate(filename, tree); + char *rpath_new = rpath_generate(filename, tree, destroot); if (!rpath_new) { return -1; } @@ -192,7 +192,7 @@ FSTree *rpath_libraries_available(const char *root) { * @param filename path to file (or a directory) * @return success=relative path from `filename` to nearest lib directory, failure=NULL */ -char *rpath_autodetect(const char *filename, FSTree *tree) { +char *rpath_autodetect(const char *filename, FSTree *tree, const char *destroot) { const char *origin; char *rootdir = dirname(filename); char *start = realpath(rootdir, NULL); @@ -216,6 +216,7 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { // This function returns `$ORIGIN/../../../CORE` which is not what we want to see. // TODO: We WANT to see this: `$ORIGIN/../lib/perl5/xx.xx.xx/<arch>/CORE` not just the basename() + /* // Change directory to the requested root chdir(start); @@ -233,6 +234,7 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { // return to calling directory chdir(cwd); + */ StrList *libs = strlist_init(); if (libs == NULL) { @@ -249,6 +251,30 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { } for (size_t i = 0; i < strlist_count(libs_wanted); i++) { + char *shared_library = strlist_item(libs_wanted, i); + char *match = NULL; + char *repl = NULL; + + match = dirname(fstree_search(tree, shared_library)); + + if (match != NULL) { + char *libpath = match; + if (startswith(match, "./")) { + libpath = &match[2]; + } + repl = join((char *[]){destroot, libpath, NULL}, DIRSEPS); + } else { + repl = join((char *[]){destroot, "lib", NULL}, DIRSEPS); + } + + if (strstr_array(libs->data, repl) == NULL) { + strlist_append(libs, repl); + } + free(repl); + } + + /* + for (size_t i = 0; i < strlist_count(libs_wanted); i++) { // zero out relative path string memset(_relative, '\0', sizeof(_relative)); // Get the shared library name we are going to look for in the tree @@ -258,8 +284,8 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { char *match = NULL; if ((match = dirname(fstree_search(tree, shared_library))) != NULL) { // Begin generating the relative path string - strcat(relative, origin); - strcat(relative, DIRSEPS); + //strcat(relative, origin); + //strcat(relative, DIRSEPS); // Append the number of relative levels to the relative path string if (depth_to_root) { @@ -276,18 +302,23 @@ char *rpath_autodetect(const char *filename, FSTree *tree) { // Append relative path to array of libraries (if it isn't already in there) if (strstr_array(libs->data, relative) == NULL) { - strlist_append(libs, relative); + char *final = realpath(relative, NULL); + strlist_append(libs, final); + free(final); } } } + */ #if OS_LINUX // Some programs do not require local libraries provided by SPM (i.e. libc) // Inject "likely" defaults here + /* if (strlist_count(libs) == 0) { strlist_append(libs, "$ORIGIN/../lib"); strlist_append(libs, "$ORIGIN/../lib64"); } + */ #endif // Populate result string diff --git a/scripts/spmbuild b/scripts/spmbuild index 5bdcf3d..17f4e21 100755 --- a/scripts/spmbuild +++ b/scripts/spmbuild @@ -42,10 +42,7 @@ function msg_warn() { } function tar() { - local cmd=tar - if [[ $(uname -s) == Darwin ]]; then - cmd=gtar - fi + local cmd=bsdtar $cmd "$@" } @@ -348,15 +345,14 @@ summary=${summary:-*} function spm_build_mkfilelist() { local filename="${1}" + if [[ -z ${filename} ]]; then msg_error "spmbuild_mkfilelist requires an output filename" exit 1 fi - pushd "${pathname}" - echo "# SPM PACKAGE FILE LIST" > "${filename}" - find . -type f -not -name ".SPM_*" >> "${filename}" - popd + echo "# SPM PACKAGE FILE LIST" > "${filename}" + find . -type f -not -name ".SPM_*" >> "${filename}" } function prepare() { @@ -389,6 +385,14 @@ function spm_build_do_stage_package() { set +x } +function spm_build_tar() { + local archive="${1}" + bsdtar -c -z -f "${archive}" \ + --exclude '..' \ + --exclude '.' \ + .* * +} + function spm_build_do_stage_archive() { local archive="${1}" @@ -406,7 +410,7 @@ function spm_build_do_stage_archive() { msg2 "Recording paths..." spm_build_mkfilelist "${SPM_META_FILELIST}" msg2 "Archiving files..." - tar --hard-dereference --create --gzip --file "${archive}" --exclude '..' --exclude '.' .* * + spm_build_tar "${archive}" popd popd } @@ -437,9 +441,6 @@ msg "Initializing..." spm_build_initialize_stage1 spm_build_initialize_stage2 # post-runtime activation -#msg2 "Installing build toolchain..." -#spm_build_install binutils gcc - msg2 "Sourcing build script..." source "${SPM_BUILD_SCRIPT_ROOT}/${SPM_BUILD_SCRIPT}" |