Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: fea3171893e6
Choose a base ref
...
head repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: cf5cca58d390
Choose a head ref
Loading
Showing 377 changed files with 13,806 additions and 5,794 deletions.
35 changes: 35 additions & 0 deletions doc/builders/packages/cataclysm-dda.section.md
Original file line number Diff line number Diff line change
@@ -34,6 +34,41 @@ cataclysm-dda.override {
}
```

## Important note for overriding packages

After applying `overrideAttrs`, you need to fix `passthru.pkgs` and
`passthru.withMods` attributes either manually or by using `attachPkgs`:

```nix
let
# You enabled parallel building.
myCDDA = cataclysm-dda-git.overrideAttrs (_: {
enableParallelBuilding = true;
});
# Unfortunately, this refers to the package before overriding and
# parallel building is still disabled.
badExample = myCDDA.withMods (_: []);
inherit (cataclysmDDA) attachPkgs pkgs wrapCDDA;
# You can fix it by hand
goodExample1 = myCDDA.overrideAttrs (old: {
passthru = old.passthru // {
pkgs = pkgs.override { build = goodExample1; };
withMods = wrapCDDA goodExample1;
};
});
# or by using a helper function `attachPkgs`.
goodExample2 = attachPkgs pkgs myCDDA;
in
# badExample # parallel building disabled
# goodExample1.withMods (_: []) # parallel building enabled
goodExample2.withMods (_: []) # parallel building enabled
```

## Customizing with mods

To install Cataclysm DDA with mods of your choice, you can use `withMods`
217 changes: 208 additions & 9 deletions doc/languages-frameworks/beam.section.md
Original file line number Diff line number Diff line change
@@ -2,15 +2,15 @@

## Introduction {#beam-introduction}

In this document and related Nix expressions, we use the term, *BEAM*, to describe the environment. BEAM is the name of the Erlang Virtual Machine and, as far as we're concerned, from a packaging perspective, all languages that run on the BEAM are interchangeable. That which varies, like the build system, is transparent to users of any given BEAM package, so we make no distinction.
In this document and related Nix expressions, we use the term, _BEAM_, to describe the environment. BEAM is the name of the Erlang Virtual Machine and, as far as we're concerned, from a packaging perspective, all languages that run on the BEAM are interchangeable. That which varies, like the build system, is transparent to users of any given BEAM package, so we make no distinction.

## Structure {#beam-structure}

All BEAM-related expressions are available via the top-level `beam` attribute, which includes:

- `interpreters`: a set of compilers running on the BEAM, including multiple Erlang/OTP versions (`beam.interpreters.erlangR19`, etc), Elixir (`beam.interpreters.elixir`) and LFE (`beam.interpreters.lfe`).
- `interpreters`: a set of compilers running on the BEAM, including multiple Erlang/OTP versions (`beam.interpreters.erlangR19`, etc), Elixir (`beam.interpreters.elixir`) and LFE (Lisp Flavoured Erlang) (`beam.interpreters.lfe`).

- `packages`: a set of package builders (Mix and rebar3), each compiled with a specific Erlang/OTP version, e.g. `beam.packages.erlangR19`.
- `packages`: a set of package builders (Mix and rebar3), each compiled with a specific Erlang/OTP version, e.g. `beam.packages.erlangR19`.

The default Erlang compiler, defined by `beam.interpreters.erlang`, is aliased as `erlang`. The default BEAM package set is defined by `beam.packages.erlang` and aliased at the top level as `beamPackages`.

@@ -26,7 +26,9 @@ We provide a version of Rebar3, under `rebar3`. We also provide a helper to fetc

### Mix & Erlang.mk {#build-tools-other}

Both Mix and Erlang.mk work exactly as expected. There is a bootstrap process that needs to be run for both, however, which is supported by the `buildMix` and `buildErlangMk` derivations, respectively.
Erlang.mk works exactly as expected. There is a bootstrap process that needs to be run, which is supported by the `buildErlangMk` derivation.

For Elixir applications use `mixRelease` to make a release. See examples for more details.

## How to Install BEAM Packages {#how-to-install-beam-packages}

@@ -52,15 +54,150 @@ Erlang.mk functions similarly to Rebar3, except we use `buildErlangMk` instead o

#### Mix Packages {#mix-packages}

Mix functions similarly to Rebar3, except we use `buildMix` instead of `buildRebar3`.
`mixRelease` is used to make a release in the mix sense. Dependencies will need to be fetched with `fetchMixDeps` and passed to it.

#### mixRelease - Elixir Phoenix example

Here is how your `default.nix` file would look.

```nix
with import <nixpkgs> { };
let
packages = beam.packagesWith beam.interpreters.erlang;
src = builtins.fetchgit {
url = "ssh://git@github.com/your_id/your_repo";
rev = "replace_with_your_commit";
};
pname = "your_project";
version = "0.0.1";
mixEnv = "prod";
mixDeps = packages.fetchMixDeps {
pname = "mix-deps-${pname}";
inherit src mixEnv version;
# nix will complain and tell you the right value to replace this with
sha256 = lib.fakeSha256;
# if you have build time environment variables add them here
MY_ENV_VAR="my_value";
};
nodeDependencies = (pkgs.callPackage ./assets/default.nix { }).shell.nodeDependencies;
frontEndFiles = stdenvNoCC.mkDerivation {
pname = "frontend-${pname}";
nativeBuildInputs = [ nodejs ];
inherit version src;
buildPhase = ''
cp -r ./assets $TEMPDIR
mkdir -p $TEMPDIR/assets/node_modules/.cache
cp -r ${nodeDependencies}/lib/node_modules $TEMPDIR/assets
export PATH="${nodeDependencies}/bin:$PATH"
cd $TEMPDIR/assets
webpack --config ./webpack.config.js
cd ..
'';
installPhase = ''
cp -r ./priv/static $out/
'';
outputHashAlgo = "sha256";
outputHashMode = "recursive";
# nix will complain and tell you the right value to replace this with
outputHash = lib.fakeSha256;
impureEnvVars = lib.fetchers.proxyImpureEnvVars;
};
in packages.mixRelease {
inherit src pname version mixEnv mixDeps;
# if you have build time environment variables add them here
MY_ENV_VAR="my_value";
preInstall = ''
mkdir -p ./priv/static
cp -r ${frontEndFiles} ./priv/static
'';
}
```

Setup will require the following steps:

- Move your secrets to runtime environment variables. For more information refer to the [runtime.exs docs](https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-runtime-configuration). On a fresh Phoenix build that would mean that both `DATABASE_URL` and `SECRET_KEY` need to be moved to `runtime.exs`.
- `cd assets` and `nix-shell -p node2nix --run node2nix --development` will generate a Nix expression containing your frontend dependencies
- commit and push those changes
- you can now `nix-build .`
- To run the release, set the `RELEASE_TMP` environment variable to a directory that your program has write access to. It will be used to store the BEAM settings.

Alternatively, we can use `buildHex` as a shortcut:
#### Example of creating a service for an Elixir - Phoenix project

In order to create a service with your release, you could add a `service.nix`
in your project with the following

```nix
{config, pkgs, lib, ...}:
let
release = pkgs.callPackage ./default.nix;
release_name = "app";
working_directory = "/home/app";
in
{
systemd.services.${release_name} = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "postgresql.service" ];
requires = [ "network-online.target" "postgresql.service" ];
description = "my app";
environment = {
# RELEASE_TMP is used to write the state of the
# VM configuration when the system is running
# it needs to be a writable directory
RELEASE_TMP = working_directory;
# can be generated in an elixir console with
# Base.encode32(:crypto.strong_rand_bytes(32))
RELEASE_COOKIE = "my_cookie";
MY_VAR = "my_var";
};
serviceConfig = {
Type = "exec";
DynamicUser = true;
WorkingDirectory = working_directory;
# Implied by DynamicUser, but just to emphasize due to RELEASE_TMP
PrivateTmp = true;
ExecStart = ''
${release}/bin/${release_name} start
'';
ExecStop = ''
${release}/bin/${release_name} stop
'';
ExecReload = ''
${release}/bin/${release_name} restart
'';
Restart = "on-failure";
RestartSec = 5;
StartLimitBurst = 3;
StartLimitInterval = 10;
};
# disksup requires bash
path = [ pkgs.bash ];
};
environment.systemPackages = [ release ];
}
```

## How to Develop {#how-to-develop}

### Creating a Shell {#creating-a-shell}

Usually, we need to create a `shell.nix` file and do our development inside of the environment specified therein. Just install your version of erlang and other interpreter, and then user your normal build tools. As an example with elixir:
Usually, we need to create a `shell.nix` file and do our development inside of the environment specified therein. Just install your version of Erlang and any other interpreters, and then use your normal build tools. As an example with Elixir:

```nix
{ pkgs ? import "<nixpkgs"> {} }:
@@ -79,6 +216,68 @@ mkShell {
}
```

#### Building in a Shell (for Mix Projects) {#building-in-a-shell}
#### Elixir - Phoenix project

Here is an example `shell.nix`.

```nix
with import <nixpkgs> { };
let
# define packages to install
basePackages = [
git
# replace with beam.packages.erlang.elixir_1_11 if you need
beam.packages.erlang.elixir
nodejs-15_x
postgresql_13
# only used for frontend dependencies
# you are free to use yarn2nix as well
nodePackages.node2nix
# formatting js file
nodePackages.prettier
];
inputs = basePackages ++ lib.optionals stdenv.isLinux [ inotify-tools ]
++ lib.optionals stdenv.isDarwin
(with darwin.apple_sdk.frameworks; [ CoreFoundation CoreServices ]);
# define shell startup command
hooks = ''
# this allows mix to work on the local directory
mkdir -p .nix-mix .nix-hex
export MIX_HOME=$PWD/.nix-mix
export HEX_HOME=$PWD/.nix-mix
export PATH=$MIX_HOME/bin:$HEX_HOME/bin:$PATH
# TODO: not sure how to make hex available without installing it afterwards.
mix local.hex --if-missing
export LANG=en_US.UTF-8
export ERL_AFLAGS="-kernel shell_history enabled"
# postges related
# keep all your db data in a folder inside the project
export PGDATA="$PWD/db"
# phoenix related env vars
export POOL_SIZE=15
export DB_URL="postgresql://postgres:postgres@localhost:5432/db"
export PORT=4000
export MIX_ENV=dev
# add your project env vars here, word readable in the nix store.
export ENV_VAR="your_env_var"
'';
in mkShell {
buildInputs = inputs;
shellHook = hooks;
}
```

Initializing the project will require the following steps:

Using a `shell.nix` as described (see <xref linkend="creating-a-shell"/>) should just work.
- create the db directory `initdb ./db` (inside your mix project folder)
- create the postgres user `createuser postgres -ds`
- create the db `createdb db`
- start the postgres instance `pg_ctl -l "$PGDATA/server.log" start`
- add the `/db` folder to your `.gitignore`
- you can start your phoenix server and get a shell with `iex -S mix phx.server`
2 changes: 1 addition & 1 deletion lib/systems/doubles.nix
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ in {
darwin = filterDoubles predicates.isDarwin;
freebsd = filterDoubles predicates.isFreeBSD;
# Should be better, but MinGW is unclear.
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.elfv1; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.elfv2; });
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
illumos = filterDoubles predicates.isSunOS;
linux = filterDoubles predicates.isLinux;
netbsd = filterDoubles predicates.isNetBSD;
12 changes: 5 additions & 7 deletions lib/systems/examples.nix
Original file line number Diff line number Diff line change
@@ -21,14 +21,10 @@ rec {
config = "powerpc64le-unknown-linux-musl";
};

ppc64-elfv1 = {
config = "powerpc64-unknown-linux-elfv1";
};
ppc64-elfv2 = {
config = "powerpc64-unknown-linux-elfv2";
ppc64 = {
config = "powerpc64-unknown-linux-gnu";
gcc = { abi = "elfv2"; }; # for gcc configuration
};
ppc64 = ppc64-elfv2; # default to modern elfv2

ppc64-musl = {
config = "powerpc64-unknown-linux-musl";
gcc = { abi = "elfv2"; }; # for gcc configuration
@@ -60,13 +56,15 @@ rec {

armv7a-android-prebuilt = {
config = "armv7a-unknown-linux-androideabi";
rustc.config = "armv7-linux-androideabi";
sdkVer = "29";
ndkVer = "21";
useAndroidPrebuilt = true;
} // platforms.armv7a-android;

aarch64-android-prebuilt = {
config = "aarch64-unknown-linux-android";
rustc.config = "aarch64-linux-android";
sdkVer = "29";
ndkVer = "21";
useAndroidPrebuilt = true;
9 changes: 0 additions & 9 deletions lib/systems/parse.nix
Original file line number Diff line number Diff line change
@@ -337,18 +337,10 @@ rec {
The "gnu" ABI is ambiguous on 32-bit ARM. Use "gnueabi" or "gnueabihf" instead.
'';
}
{ assertion = platform: platform.system != "powerpc64-linux";
message = ''
The "gnu" ABI is ambiguous on big-endian 64-bit PPC. Use "elfv1" or "elfv2" instead.
'';
}
];
};
gnuabi64 = { abi = "64"; };

elfv1 = { abi = "elfv1"; };
elfv2 = { abi = "elfv2"; };

musleabi = { float = "soft"; };
musleabihf = { float = "hard"; };
musl = {};
@@ -452,7 +444,6 @@ rec {
if lib.versionAtLeast (parsed.cpu.version or "0") "6"
then abis.gnueabihf
else abis.gnueabi
else if cpu == "powerpc64" then abis.elfv2
else abis.gnu
else abis.unknown;
};
Loading