You are running nix/NixOS and have ever encountered the following problem?
$ ./myapp
bash: ./myapp: No such file or directoryFear not, now there is nix-alien which will download necessary dependencies
for you.
$ nix-alien myapp # Run the binary inside a FHS shell with all needed shared dependencies to execute the binary
$ nix-alien-ld myapp # Spawns you inside a shell with NIX_LD_LIBRARY_PATH set to the needed dependencies, to be used with nix-ld
$ nix-alien-find-libs myapp # Lists all libs needed for the binaryIf your binary is located in ~/myapp, run:
$ nix --extra-experimental-features "nix-command flakes" run github:thiagokokada/nix-alien -- ~/myappTip
If you are trying to run an OpenGL binary (e.g.: blender) in non-NixOS
systems, you can wrap the command above in
nixGL:
$ nix --extra-experimental-features "nix-command flakes" run --impure github:guibou/nixGL --override-input nixpkgs nixpkgs/nixos-unstable -- nix run github:thiagokokada/nix-alien -- blenderOnce nix-alien is installed in your system, all you need to do is run:
$ nix-alien ~/myappThis will run nix-alien on ~/myapp binary with a FHSUserEnv including all
shared library dependencies. The resulting default.nix file will be saved to
$XDG_CACHE_HOME/nix-alien/<path-uuid>/fhs-env/default.nix, making the next
evaluation faster. The cache is based on the binary absolute path. You can also
pass --recreate flag to force the recreation of default.nix file, and
--destination to change where default.nix file will be saved.
To pass arguments to the app:
$ nix-alien ~/myapp -- --foo barIn case you're using nix-ld, there is also
nix-alien-ld:
$ nix-alien-ld -- ~/myappThis will spawn a wrapped binary with NIX_LD_LIBRARY_PATH and NIX_LD setup.
The resulting default.nix file will be saved to
$XDG_CACHE_HOME/nix-alien/<path-uuid>/nix-ld/default.nix, making the next
evaluation faster. The cache is based on the binary absolute path. You can also
pass --recreate flag to force the recreation of default.nix file, and
--destination to change where default.nix file will be saved.
To pass arguments to the app:
$ nix-alien-ld ~/myapp -- --foo barIf you want to use the fzf based menu to find the libraries for scripting
purposes, you can run:
$ nix-alien-find-libs ~/myappThis will print the found libraries on the stdout. The informational messages
are printed to stderr, so you can easily redirect them to /dev/null if
needed. You can also use --json flag to print the result as a JSON instead.
There are also some other options, check them using --help flag on each
program. Example for nix-alien:
usage: nix-alien [-h] [--version] [-l LIBRARY] [-p PACKAGE] [-c CANDIDATE] [-r] [-d PATH] [-P] [-E] [-s] [-f] program ...
positional arguments:
program Program to run
ellipsis Arguments to be passed to the program
options:
-h, --help show this help message and exit
--version show program's version number and exit
-l LIBRARY, --additional-libs LIBRARY
Additional library to search. May be passed multiple times
-p PACKAGE, --additional-packages PACKAGE
Additional package to add. May be passed multiple times
-c CANDIDATE, --select-candidates CANDIDATE
Library candidates that will be auto-selected if found via regex. Useful for automation.
-r, --recreate Recreate 'default.nix' file if exists
-d PATH, --destination PATH
Path where 'default.nix' file will be created
-P, --print-destination
Print where 'default.nix' file is located and exit
-E, --edit Edit 'default.nix' using $EDITOR (or 'nano' if unset)
-s, --silent Silence informational messages
-f, --flake Create and use 'flake.nix' file instead (experimental)You can run the scripts from this repo directly without cloning or installing them, assuming you're using a resonable up-to-date nix and enabled experimental Flakes support.
$ nix run "github:thiagokokada/nix-alien#nix-alien" -- ~/myapp
$ nix run "github:thiagokokada/nix-alien#nix-alien-ld" -- ~/myapp
$ nix run "github:thiagokokada/nix-alien#nix-alien-find-libs" -- ~/myappOr if you don't have Flakes enabled but still wants to run it without downloading it first:
$ nix --extra-experimental-features "nix-command flakes" run "github:thiagokokada/nix-alien#nix-alien" -- ~/myapp
$ nix --extra-experimental-features "nix-command flakes" run "github:thiagokokada/nix-alien#nix-alien-ld" -- ~/myapp
$ nix --extra-experimental-features "nix-command flakes" run "github:thiagokokada/nix-alien#nix-alien-find-libs" -- ~/myappYou can add the following contents to a /etc/nixos/nix-alien.nix file:
{ ... }:
let
nix-alien-pkgs = import (
builtins.fetchTarball "https://github.com/thiagokokada/nix-alien/tarball/master"
) { };
in
{
environment.systemPackages = with nix-alien-pkgs; [
nix-alien
];
# Optional, but this is needed for `nix-alien-ld` command
programs.nix-ld.enable = true;
}And afterwards, add it to imports section on /etc/nixos/configuration.nix
file.
Warning
Overriding nix-alien inputs may cause mismatches between the
nix-index-database and nixpkgs, causing possibly incorrect results, so it
is unsupported.
If you're using NixOS with Flakes, you can do something similar to your NixOS
setup to install nix-alien on system PATH:
{
description = "nix-alien-on-nixos";
inputs.nixpkgs.url = "github:NixOS/nixpkgs";
inputs.nix-alien.url = "github:thiagokokada/nix-alien";
outputs = { self, nixpkgs, nix-alien }: {
nixosConfigurations.nix-alien-desktop = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux"; # or aarch64-linux
specialArgs = { inherit self system; };
modules = [
({ self, system, ... }: {
environment.systemPackages = with self.inputs.nix-alien.packages.${system}; [
nix-alien
];
# Optional, needed for `nix-alien-ld`
programs.nix-ld.enable = true;
})
];
};
};
}Alternatively, you can also use the included overlay. Keep in mind that the
overlay will use your current nixpkgs pin instead the one included in this
project flake.lock file.
This has the advantage of reducing the general size of your /nix/store,
however since the version of nixpkgs you currently have is not tested this may
cause issues.
{
description = "nix-alien-on-nixos";
inputs.nixpkgs.url = "github:NixOS/nixpkgs";
inputs.nix-alien.url = "github:thiagokokada/nix-alien";
outputs = { self, nixpkgs, nix-alien }: {
nixosConfigurations.nix-alien-desktop = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; # or aarch64-linux
specialArgs = { inherit self; };
modules = [
({ self, ... }: {
nixpkgs.overlays = [
self.inputs.nix-alien.overlays.default
];
environment.systemPackages = with pkgs; [
nix-alien
];
# Optional, needed for `nix-alien-ld`
programs.nix-ld.enable = true;
})
];
};
};
}You can add the following contents to your Home-Manager configuration file:
{ ... }:
let
nix-alien-pkgs = import (
builtins.fetchTarball "https://github.com/thiagokokada/nix-alien/tarball/master"
) { };
in
{
# ...
home.packages = with nix-alien-pkgs; [
nix-alien
];
}If you're using Home-Manager with Flakes, you can use:
{
description = "nix-alien-on-home-manager";
inputs.nixpkgs.url = "github:NixOS/nixpkgs";
inputs.home-manager.url = "github:nix-community/home-manager";
inputs.nix-alien.url = "github:thiagokokada/nix-alien";
outputs = { self, nixpkgs, home-manager, nix-alien }:
let
system = "x86_64-linux"; # or aarch64-linux
pkgs = import nixpkgs { inherit system; };
in {
homeConfigurations.nix-alien-home = home-manager.lib.homeManagerConfiguration rec {
inherit pkgs;
extraSpecialArgs = { inherit self system; };
modules = [
({ self, system, ... }: {
home.packages = with self.inputs.nix-alien.packages.${system}; [
nix-alien
];
})
];
};
};
}On non-Flakes system, you can use nix-shell to start a development shell.
On Flakes enabled system, you can use nix develop instead.
If you have nix-direnv
installed, there is a .envrc file configured to start the Flakes enabled
setup automatically. Just run direnv allow inside this repo.
Binaries loading shared libraries dynamically (e.g.: with dlopen) will
probably not work with this script. However, this can be workarounded using
either --additional-libs/-l or --additional-packages/-p flag. The first one
can be used as:
$ nix-alien -l libGL.so.1 -l libz.so.1 ~/myappAnd this will be searched using nix-locate in a similar way as the other
libraries found in the binary. The second one can be used as:
$ nix-alien -p libGL -p zlib ~/myappTo direct add the package to default.nix file.
Warning
There is no validation in -p flag, so you can receive an undefied variable error in case of an inexistent package.
This is achieved by enumerating the shared library dependencies from the ELF
header using ldd (actually,
pylddwrap) and then searching for the
equivalent library in nixpkgs. This is done by querying nix-locate locally.
To solve possible conflicts, human intervation is needed, but thanks to
fzf and
pyfzf this is made easy by
showing an interactive list.
- Inspired by Lassulus/nix-autobahn
- Thanks to Mic92/nix-ld, Mic92/nix-index-database and bennofs/nix-index, since without them this project wouldn't be possible
