{"id":13453527,"url":"https://github.com/intoli/exodus","last_synced_at":"2025-05-14T12:10:16.986Z","repository":{"id":37663514,"uuid":"119092220","full_name":"intoli/exodus","owner":"intoli","description":"Painless relocation of Linux binaries–and all of their dependencies–without containers.","archived":false,"fork":false,"pushed_at":"2023-11-05T00:02:14.000Z","size":5613,"stargazers_count":2954,"open_issues_count":20,"forks_count":71,"subscribers_count":45,"default_branch":"master","last_synced_at":"2025-04-13T12:41:25.075Z","etag":null,"topics":["binary","elf","exodus","linker","linux","packaging","portable","python","relocation"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/intoli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-01-26T19:10:14.000Z","updated_at":"2025-04-10T08:18:01.000Z","dependencies_parsed_at":"2024-01-08T08:00:09.938Z","dependency_job_id":null,"html_url":"https://github.com/intoli/exodus","commit_stats":{"total_commits":482,"total_committers":6,"mean_commits":80.33333333333333,"dds":"0.010373443983402453","last_synced_commit":"ef3d5e92c1b604b09cf0a57baff0f4d0b421b8da"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intoli%2Fexodus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intoli%2Fexodus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intoli%2Fexodus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intoli%2Fexodus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/intoli","download_url":"https://codeload.github.com/intoli/exodus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254140756,"owners_count":22021219,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binary","elf","exodus","linker","linux","packaging","portable","python","relocation"],"created_at":"2024-07-31T08:00:42.231Z","updated_at":"2025-05-14T12:10:16.940Z","avatar_url":"https://github.com/intoli.png","language":"Python","readme":"\u003ch1 vertical-align=\"middle\"\u003eExodus\n    \u003ca targe=\"_blank\" href=\"https://twitter.com/home?status=Exodus%20%E2%80%93%20Painless%20relocation%20of%20Linux%20binaries%20without%20containers!%20%40IntoliNow%0A%0Ahttps%3A//github.com/intoli/exodus\"\u003e\n        \u003cimg height=\"26px\" src=\"https://simplesharebuttons.com/images/somacro/twitter.png\"\n            alt=\"Tweet\"\u003e\u003c/a\u003e\n    \u003ca target=\"_blank\" href=\"https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/intoli/exodus\"\u003e\n        \u003cimg height=\"26px\" src=\"https://simplesharebuttons.com/images/somacro/facebook.png\"\n            alt=\"Share on Facebook\"\u003e\u003c/a\u003e\n    \u003ca target=\"_blank\" href=\"http://reddit.com/submit?url=https%3A%2F%2Fgithub.com%2Fintoli%2Fexodus\u0026title=Exodus%20-%20Painless%20relocation%20of%20ELF%20binaries%20on%20Linux\"\u003e\n        \u003cimg height=\"26px\" src=\"https://simplesharebuttons.com/images/somacro/reddit.png\"\n            alt=\"Share on Reddit\"\u003e\u003c/a\u003e\n    \u003ca target=\"_blank\" href=\"https://news.ycombinator.com/submitlink?u=https://github.com/intoli/exodus\u0026t=Exodus%20%E2%80%93%20Painless%20relocation%20of%20Linux%20binaries%20without%20containers\"\u003e\n        \u003cimg height=\"26px\" src=\"media/ycombinator.png\"\n            alt=\"Share on Hacker News\"\u003e\u003c/a\u003e\n\u003c/h1\u003e\n\n\u003cp align=\"left\"\u003e\n    \u003ca href=\"https://circleci.com/gh/intoli/exodus/tree/master\"\u003e\n        \u003cimg src=\"https://img.shields.io/circleci/project/github/intoli/exodus/master.svg\"\n            alt=\"Build Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://circleci.intoli.com/artifacts/intoli/exodus/coverage-report/index.html\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/dynamic/json.svg?label=coverage\u0026colorB=ff69b4\u0026query=$.coverage\u0026uri=https://circleci.intoli.com/artifacts/intoli/exodus/coverage-report/total-coverage.json\"\n          alt=\"Coverage\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/intoli/exodus/blob/master/LICENSE.md\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/l/exodus-bundler.svg\"\n            alt=\"License\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://pypi.python.org/pypi/exodus-bundler/\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/v/exodus-bundler.svg\"\n            alt=\"PyPI Version\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\nExodus is a tool that makes it easy to successfully relocate Linux ELF binaries from one system to another.\nThis is useful in situations where you don't have root access on a machine or where a package simply isn't available for a given Linux distribution.\nFor example, CentOS 6.X and Amazon Linux don't have packages for [Google Chrome](https://www.google.com/chrome/browser/desktop/index.html) or [aria2](https://aria2.github.io/).\nServer-oriented distributions tend to have more limited and outdated packages than desktop distributions, so it's fairly common that one might have a piece of software installed on their laptop that they can't easily install on a remote machine.\n\nWith exodus, transferring a piece of software that's working on one computer to another is as simple as this.\n\n```bash\nexodus aria2c | ssh intoli.com\n```\n\nExodus handles bundling all of the binary's dependencies, compiling a statically linked wrapper for the executable that invokes the relocated linker directly, and installing the bundle in `~/.exodus/` on the remote machine.\nYou can see it in action here.\n\n![Demonstration of usage with htop](media/htop-demo.gif)\n\n\n## Table of Contents\n\n- [The Problem Being Solved](#the-problem-being-solved) - An overview of some of the challenges that arise when relocating binaries.\n- [Installation](#installation) - Instructions for installing exodus.\n- [Usage](#usage)\n    - [The Command-Line Interface](#command-line-interface) - The options supported by the command-line utility.\n    - [Usage Examples](#examples) - Common usage patterns, helpful for getting started quickly.\n- [How It Works](#how-it-works) - An overview of how exodus works.\n- [Known Limitations](#known-limitations) - Situations that are currently outside the scope of what exodus can handle.\n- [Development](#development) - Instructions for setting up the development environment.\n- [Contributing](#contributing) - Guidelines for contributing.\n- [License](#license) - License details for the project.\n\n\n## The Problem Being Solved\n\nIf you simply copy an executable file from one system to another, then you're very likely going to run into problems.\nMost binaries available on Linux are dynamically linked and depend on a number of external library files.\nYou'll get an error like this when running a relocated binary when it has a missing dependency.\n\n```\naria2c: error while loading shared libraries: libgnutls.so.30: cannot open shared object file: No such file or directory\n```\n\nYou can try to install these libraries manually, or to relocate them and set `LD_LIBRARY_PATH` to wherever you put them, but it turns out that the locations of the [ld-linux](https://linux.die.net/man/8/ld-linux) linker and the [glibc](https://www.gnu.org/software/libc/) libraries are hardcoded.\nThings can very quickly turn into a mess of relocation errors,\n\n```\naria2c: relocation error: /lib/libpthread.so.0: symbol __getrlimit, version\nGLIBC_PRIVATE not defined in file libc.so.6 with link time reference\n```\n\nsegmentation faults,\n\n```\nSegmentation fault (core dumped)\n```\n\nor, if you're really unlucky, this very confusing symptom of a missing linker.\n\n```\n$ ./aria2c\nbash: ./aria2c: No such file or directory\n$ ls -lha ./aria2c\n-rwxr-xr-x 1 sangaline sangaline 2.8M Jan 30 21:18 ./aria2c\n```\n\nExodus works around these issues by compiling a small statically linked launcher binary that invokes the relocated linker directly with any hardcoded `RPATH` library paths overridden.\nThe relocated binary will run with the exact same linker and libraries that it ran with on its origin machine.\n\n\n## Installation\n\nThe package can be installed from [the package on pypi](https://pypi.python.org/pypi/exodus_bundler).\nRunning the following will install `exodus` locally for your current user.\n\n```bash\npip install --user exodus-bundler\n```\n\nYou will then need to add `~/.local/bin/` to your `PATH` variable in order to run the `exodus` executable (if you haven't already done so).\nThis can be done by adding\n\n```\nexport PATH=\"~/.local/bin/:${PATH}\"\n```\n\nto your `~/.bashrc` file.\n\n\n### Optional/Recommended Dependencies\n\nIt is also highly recommended that you install [gcc](https://gcc.gnu.org/) and one of either [musl libc](https://www.musl-libc.org/) or [diet libc](https://www.fefe.de/dietlibc/) on the machine where you'll be packaging binaries.\nIf present, these small C libraries will be used to compile small statically linked launchers for the bundled applications.\nAn equivalent shell script will be used as a fallback, but it carries significant overhead compared to the compiled launchers.\n\n\n## Usage\n\n### Command-Line Interface\n\nThe command-line interface supports the following options.\n\n```\nusage: exodus [-h] [-c CHROOT_PATH] [-a DEPENDENCY] [-d] [--no-symlink FILE]\n              [-o OUTPUT_FILE] [-q] [-r [NEW_NAME]] [--shell-launchers] [-t]\n              [-v]\n              EXECUTABLE [EXECUTABLE ...]\n\nBundle ELF binary executables with all of their runtime dependencies so that\nthey can be relocated to other systems with incompatible system libraries.\n\npositional arguments:\n  EXECUTABLE            One or more ELF executables to include in the exodus\n                        bundle.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -c CHROOT_PATH, --chroot CHROOT_PATH\n                        A directory that will be treated as the root during\n                        linking. Useful for testing and bundling extracted\n                        packages that won't run without a chroot. (default:\n                        None)\n  -a DEPENDENCY, --add DEPENDENCY, --additional-file DEPENDENCY\n                        Specifies an additional file to include in the bundle,\n                        useful for adding programatically loaded libraries and\n                        other non-library dependencies. The argument can be\n                        used more than once to include multiple files, and\n                        directories will be included recursively. (default:\n                        [])\n  -d, --detect          Attempt to autodetect direct dependencies using the\n                        system package manager. Operating system support is\n                        limited. (default: False)\n  --no-symlink FILE     Signifies that a file must not be symlinked to the\n                        deduplicated data directory. This is useful if a file\n                        looks for other resources based on paths relative its\n                        own location. This is enabled by default for\n                        executables. (default: [])\n  -o OUTPUT_FILE, --output OUTPUT_FILE\n                        The file where the bundle will be written out to. The\n                        extension depends on the output type. The\n                        \"{{executables}}\" and \"{{extension}}\" template strings\n                        can be used in the provided filename. If omitted, the\n                        output will go to stdout when it is being piped, or to\n                        \"./exodus-{{executables}}-bundle.{{extension}}\"\n                        otherwise. (default: None)\n  -q, --quiet           Suppress warning messages. (default: False)\n  -r [NEW_NAME], --rename [NEW_NAME]\n                        Renames the binary executable(s) before packaging. The\n                        order of rename tags must match the order of\n                        positional executable arguments. (default: [])\n  --shell-launchers     Force the use of shell launchers instead of attempting\n                        to compile statically linked ones. (default: False)\n  -t, --tarball         Creates a tarball for manual extraction instead of an\n                        installation script. Note that this will change the\n                        output extension from \".sh\" to \".tgz\". (default:\n                        False)\n  -v, --verbose         Output additional informational messages. (default:\n                        False)\n```\n\n\n### Examples\n\n#### Piping Over SSH\n\nThe easiest way to install an executable bundle on a remote machine is to pipe the `exodus` command output over SSH.\nFor example, the following will install the `aria2c` command on the `intoli.com` server.\n\n```bash\nexodus aria2c | ssh intoli.com\n```\n\nThis requires that the default shell for the remote user be set to `bash` (or a compatible shell).\nIf you use `csh`, then you need to additionally run `bash` on the remote server like this.\n\n```bash\nexodus aria2c | ssh intoli.com bash\n```\n\n#### Explicitly Adding Extra Files\n\nAdditional files can be added to bundles in a number of different ways.\nIf there is a specific file or directory that you would like to include, then you can use the `--add` option.\nFor example, the following command will bundle `nmap` and include the contents of `/usr/share/nmap` in the bundle.\n\n```bash\nexodus --add /usr/share/nmap nmap\n```\n\nYou can also pipe a list of dependencies into `exodus`.\nThis allows you to use standard Linux utilities to find and filter dependencies as you see fit.\nThe following command sequence uses `find` to include all of the Lua scripts under `/usr/share/nmap`.\n\n```bash\nfind /usr/share/nmap/ -iname '*.lua' | exodus nmap\n```\n\nThese two approaches can be used together, and the `--add` flag can also be used multiple times in one command.\n\n\n#### Auto-Detecting Extra Files\n\nIf you're not sure which extra dependencies are necessary, you can use the `--detect` option to query your system's package manager and automatically include any files in the corresponding packages.\nRunning\n\n```bash\nexodus --detect nmap\n```\n\nwill include the contents of `/usr/share/nmap` as well as its man pages and the contents of `/usr/share/zenmap/`.\nIf you ever try to relocate a binary that doesn't work with the default configuration, the `--detect` option is a good first thing to try.\n\nYou can also pipe the output of `strace` into `exodus` and all of the files that are accessed will be automatically included.\nThis is particularly useful in situations where shared libraries are loaded programmatically, but it can also be used to determine which files are necessary to run a specific command.\nThe following command will determine all of the files that `nmap` accesses while running the set of default scripts.\n\n```bash\nstrace -f nmap --script default 127.0.0.1 2\u003e\u00261 | exodus nmap\n```\n\nThe output of `strace` is then parsed by `exodus` and all of the files are included.\nIt's generally more robust to use `--detect` to find the non-library dependencies, but the `strace` pattern can be indispensable when a program uses `dlopen()` to load libraries programmatically.\nAlso, note that *any* files that a program accesses will be included in a bundle when following this approach.\nNever distribute a bundle without being certain that you haven't accidentally included a file that you don't want to make public.\n\n\n#### Renaming Binaries\n\nMultiple binaries that have the same name can be installed in parallel through the use of the `--rename`/`-r` option.\nSay that you have two different versions of `grep` on your local machine: one at `/bin/grep` and one at `/usr/local/bin/grep`.\nIn that situation, using the `-r` flag allows you to assign aliases for each binary.\n\n```bash\nexodus -r grep-1 -r grep-2 /bin/grep /usr/local/bin/grep\n```\n\nThe above command would install the two `grep` versions in parallel with `/bin/grep` called `grep-1` and `/usr/local/bin/grep` called `grep-2`.\n\n\n#### Manual Extraction\n\nYou can create a compressed tarball directly instead of the default script by specifying the `--tarball` option.\nTo create a tarball, copy it to a remote server, and then extract it in `~/custom-location`, you could run the following.\n\n```bash\n# Create the tarball.\nexodus --tarball aria2c --output aria2c.tgz\n\n# Copy it to the remote server and remove it locally.\nscp aria2c.tgz intoli.com:/tmp/aria2c.tgz\nrm aria2c.tgz\n\n# Make sure that `~/custom-location` exists.\nssh intoli.com \"mkdir -p ~/custom-location\"\n\n# Extract the tarball remotely.\nssh intoli.com \"tar --strip 1 -C ~/custom-location -zxf /tmp/aria2c.tgz\"\n\n# Remove the remote tarball.\nssh intoli.com \"rm /tmp/aria2c.tgz\"\n```\n\nYou will additionally need to add `~/custom-location/bin` to your `PATH` variable on the remote server.\nThis can be done by adding the following to `~/.bashrc` on the remote server.\n\n```bash\nexport PATH=\"~/custom-location/bin:${PATH}\"\n```\n\n\n#### Adding to a Docker Image\n\nTarball formatted exodus bundles can easily be included in Docker images by using the [ADD](https://docs.docker.com/engine/reference/builder/#add) instruction.\nYou must first create a bundle using the `--tarball` option\n\n```bash\n# Create and enter a directory for the Docker image.\nmkdir jq\ncd jq\n\n# Generate the `exodus-jq-bundle.tgz` bundle.\nexodus --tarball jq\n```\n\nand then create a `Dockerfile` file inside of the `jq` directory with the following contents.\n\n```\nFROM scratch\nADD exodus-jq-bundle.tgz /opt/\nENTRYPOINT [\"/opt/exodus/bin/jq\"]\n```\n\nThe Docker image can then be built by running\n\n```bash\ndocker build -t jq .\n```\n\nand `jq` can be run inside of the container.\n\n```bash\ndocker run jq\n```\n\nThis simple image will include only the `jq` binary and dependencies, but the bundles can be included in existing docker images in the same way.\nFor example, adding\n\n```bash\nENV PATH=\"/opt/exodus/bin:${PATH}\"\nADD exodus-jq-bundle.tgz /opt/\n```\n\nto an existing `Dockerfile` will make the `jq` binary available for use inside the container.\n\n\n## How It Works\n\nThere are two main components to how exodus works:\n\n1. Finding and bundling all of a binary's dependencies.\n\n2. Launching the binary in such a way that the proper dependencies are used without any potential interaction from system libraries on the destination machine.\n\nThe first component is actually fairly simple.\nYou can invoke [ld-linux](https://linux.die.net/man/8/ld-linux) with the `LD_TRACE_LOADED_OBJECTS` environment variable set to `1` and it will list all of the resolved library dependencies for a binary.\nFor example, running\n\n```bash\nLD_TRACE_LOADED_OBJECTS=1 /lib64/ld-linux-x86-64.so.2 /bin/grep\n```\n\nwill output the following.\n\n```\n    linux-vdso.so.1 =\u003e  (0x00007ffc7495c000)\n    libpcre.so.0 =\u003e /lib64/libpcre.so.0 (0x00007f89b2f3e000)\n    libc.so.6 =\u003e /lib64/libc.so.6 (0x00007f89b2b7a000)\n    libpthread.so.0 =\u003e /usr/lib/libpthread.so.0 (0x00007f0e95e8c000)\n    /lib64/ld-linux-x86-64.so.2 (0x00007f89b3196000)\n```\n\nThe `linus-vdso.so.1` dependency refers to kernel space routines that are exported to user space, but the other four are shared library files on disk that are required in order to run `grep`.\nNotably, one of these dependencies is the `/lib64/ld-linux-x86-64.so.2` linker itself.\nThe location of this file is typically hardcoded into an ELF binary's `INTERP` header and the linker is invoked by the kernel when you run the program.\nWe'll come back to that in a minute, but for now the main point is that we can find a binary's direct dependencies using the linker.\n\nOf course, these direct dependencies might have additional dependencies of their own.\nWe can iteratively find all of the necessary dependencies by following the same approach of invoking the linker again for each of the library dependencies.\nThis isn't actually necessary for `grep`, but exodus does handle finding the full set of dependencies for you.\n\nAfter all of the dependencies are found, exodus puts them together with the binary in a tarball that can be extracted (typically into either `/opt/exodus/` or `~/.exodus`).\nWe can explore the structure of the `grep` bundle by using [tree](https://linux.die.net/man/1/tree) combined with a `sed` one-liner to truncate long SHA-256 hashes to 8 digits.\nRunning\n\n```bash\nalias truncate-hashes=\"sed -r 's/([a-f0-9]{8})[a-f0-9]{56}/\\1.../g'\"\ntree ~/.exodus/ | truncate-hashes\n```\n\nwill show us all of the files and folders included in the `grep` bundle.\n\n```\n/home/sangaline/.exodus/\n├── bin\n│   └── grep -\u003e ../bundles/3124cd96.../usr/bin/grep\n├── bundles\n│   └── 3124cd96...\n│       ├── lib64\n│       │   └── ld-linux-x86-64.so.2 -\u003e ../../../data/dfd5de26...\n│       └── usr\n│           ├── bin\n│           │   ├── grep\n│           │   ├── grep-x -\u003e ../../../../data/7477c1a7...\n│           │   └── linker-dfd5de26...\n│           └── lib\n│               ├── libc.so.6 -\u003e ../../../../data/6d0e1d45...\n│               ├── libpcre.so.1 -\u003e ../../../../data/a0862ebc...\n│               └── libpthread.so.0 -\u003e ../../../../data/85cb56a5...\n└── data\n    ├── 6d0e1d45...\n    ├── 7477c1a7...\n    ├── 85cb56a5...\n    ├── a0862ebc...\n    └── dfd5de26...\n\n8 directories, 13 files\n```\n\nYou can see that there are three top-level directories within `~/.exodus/`: `bin`, `bundles`, and `data`.\nLet's cover these in reverse-alphabetical order, starting with the `data` directory.\n\nThe `data` directory contains the actual files from the bundles with names corresponding to SHA-256 hashes of their content.\nThis is done so that multiple versions of a file with the same filename can be extracted in the `data` directory without overwriting each other.\nOn the other hand, files that do have the same content *will* overwrite each other.\nThis avoids the need to store multiple copies of the same data, even if the identical files appear in different bundles or directories.\n\nNext, we have the `bundles` directory, which is full of subfolders that also have SHA-256 hashes as names.\nThe hashes this time are determined based on the combined directory structure and content of everything included in the bundle.\nThe hash provides a unique fingerprint for the bundle and allows multiple bundles to be extracted without their directory contents mixing.\n\nInside of each bundle subdirectory, the original directory structure of the bundle's contents on the host machine is mirrored.\nFor this particular `grep` bundle, there are `lib64`, `usr/bin`, and `usr/lib` directories.\nA more complicated bundle could include additional files from `/usr/share`, `/opt/local`, a user's home directory, or really anywhere on the system (see the `--add` and `--detect` options).\nThe files in both `lib64` and `usr/lib` simply consist of symlinks to the actual library files in the top-level `data/` directory.\nThe `usr/bin` directory is a little more complicated.\n\nThe `grep` file isn't actually the original `grep` binary, it's a special executable that `exodus` constructs called a \"launcher.\"\nA launcher is a tiny program that invokes the linker and overrides the library search path in such a way that our original binary can run without any system libraries being used and causing issues due to incompatibilities.\nThe linker in this case is the `linker-dfd5de26...` file.\nThis is located in the same directory so that resource paths can be resolved relative to the running executable.\nFinally, the `grep-x` symlink points to the actual `grep` binary that was bundled and extracted in the top-level `data/` directory (this is the ELF file that the linker interprets).\n\nWhen a C compiler and either [musl libc](https://www.musl-libc.org/) or [diet libc](https://www.fefe.de/dietlibc/) are available, exodus will compile a statically linked binary launcher.\nIf neither of these are present, it will fall back to using a shell script to perform the task of the launcher.\nThis adds a little bit of overhead relative to the binary launchers, but they are helpful for understanding what the launchers do.\nHere's the shell script version of the `grep-launcher`, for example.\n\n```bash\n#! /bin/bash\n\ncurrent_directory=\"$(dirname \"$(readlink -f \"$0\")\")\"\nexecutable=\"${current_directory}/./grep-x\"\nlibrary_path=\"../../lib64:../lib64:../../lib:../lib:../../lib32:../lib32\"\nlibrary_path=\"${current_directory}/${library_path//:/:${current_directory}/}\"\nlinker=\"${current_directory}/./linker-dfd5de2638cea087685b67786050dcdc33aac7b67f5f8c2753b7da538517880a\"\nexec \"${linker}\" --library-path \"${library_path}\" --inhibit-rpath \"\" \"${executable}\" \"$@\"\n```\n\nYou can see that the launcher first constructs the full paths for all of the `LD_LIBRARY_PATH` directories, the executable, and the linker based on its own location.\nIt then executes the linker with a set of arguments that allow it to search the proper library directories, ignore the hardcoded `RPATH`, and run the binary with any command-line arguments passed along.\nThis serves a similar purpose to something like [patchelf](https://github.com/NixOS/patchelf) that would modify the `INTERP` and `RPATH` of the binary, but it additionally allows for both the linker and library locations to be specified based *solely on their relative locations*.\nThis is what allows for the exodus bundles to be extracted in `~/.exodus`, `/opt/exodus/`, or any other location, as long as the internal bundle structure is preserved.\n\nContinuing on with our reverse-alphabetical order, we finally get to the top-level `bin` directory.\nThe top-level `bin` directory consists of symlinks of the binary names to their corresponding launchers.\nThis allows for the addition of a single directory to a user's `PATH` variable in order to make the migrated exodus binaries accessible.\nFor example, adding `export PATH=\"~/.exodus/bin:${PATH}\"` to a `~/.bashrc` file will add all of these entry points to a user's `PATH` and allow them to be run without specifying their full path.\n\n\n## Known Limitations\n\nThere are several scenarios under which bundling an application with exodus will fail.\nMany of these are things that we're working on and hope to improve in the future, but some are fundamentally by design and are unlikely to change.\nHere you can see an overview of situations where exodus will not be able to successfully relocate executables.\n\n- **Non-ELF Binaries** - Exodus currently only supports completely bundling ELF binaries.\n    Interpreted executable files, like shell scripts, can be included in bundles, but their shebang interpreter directives will not be changed.\n    This generally means that they will be interpreted using the system version of `bash`, `python`, `perl`, or whatever else.\n    The problem that exodus aims to solve is largely centered around the dynamic linking of ELF binaries, so this is unlikely to change in the foreseeable future.\n- **Incompatible CPU Architectures** - Binaries compiled for one CPU architecture will generally not be able to run on a CPU of another architecture.\n    There are some exceptions to this, for example x64 processors are backwards compatible with x86 instruction sets, but you will not be able to migrate x64 binaries to an x86 or an ARM machine.\n    Doing so would require processor emulation, and this is definitely outside the scope of the exodus project.\n    If you find yourself looking for a solution to this problem, then you might want to check out [QEMU](https://www.qemu.org/).\n- **Incompatible Glibc and Kernel Versions** - When glibc is compiled, it is configured to target a specific kernel version.\n    Trying to run any software that was compiled against glibc on a system using an older kernel version than glibc's target version will result in a `FATAL: kernel too old` error.\n    You can check the oldest supported kernel version for a binary by running `file /path/to/binary`.\n    The output should include a string like `for GNU/Linux 2.6.32` which signifies the oldest kernel version that the binary is compatible with.\n    As a workaround, you can create exodus bundles in a Docker image using an operating system image which supports older kernels (*e.g.* use an outdated version of the operating system).\n- **Driver Dependent Libraries** - Unlike some other application bundlers, exodus aims to include all of the required libraries when the bundle is created and to completely isolate the transported binary from the destination machine's system libraries.\n    This means that any libraries which are compiled for specific hardware drivers will only work on machines with the same drivers.\n    A key example of this is the `libGLX_indirect.so` library which can link to either `libGLX_mesa.so` or `libGLX_nvidia.so` depending on which graphics card drivers are used on a given system.\n    Bundling dependencies that are not locally available on the source machine is fundamentally outside the scope of what exodus is designed to do, and this will never change.\n\n\n## Development\n\nThe development environment can be setup by running the following.\n\n```bash\n# Clone the repository.\ngit clone https://github.com/intoli/exodus.git\ncd exodus\n\n# Create and enter a virtualenv.\nvirtualenv .env\n. .env/bin/activate\n\n# Install the development requirements.\npip install -r development-requirements.txt\n\n# Install the exodus package in editable mode.\npip install -e .\n```\n\nThe test suite can then be run using [tox](https://tox.readthedocs.io/en/latest/).\n\n```bash\ntox\n```\n\n## Contributing\n\nContributions are welcome, but please follow these contributor guidelines outlined in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n\n## License\n\nExodus is licensed under a [BSD 2-Clause License](LICENSE.md) and is copyright [Intoli, LLC](https://intoli.com).\n","funding_links":[],"categories":["Python","HarmonyOS"],"sub_categories":["Windows Manager"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintoli%2Fexodus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fintoli%2Fexodus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintoli%2Fexodus/lists"}