uboot: (firmwareOdroidC2/C4) don't invoke patch tool, use patches = [] instead
https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/setup.sh#L948 this can do it nicely. Signed-off-by: Anton Arapov <anton@deadbeef.mx>
This commit is contained in:
commit
56de2bcd43
30691 changed files with 3076956 additions and 0 deletions
236
doc/stdenv/cross-compilation.chapter.md
Normal file
236
doc/stdenv/cross-compilation.chapter.md
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
# Cross-compilation {#chap-cross}
|
||||
|
||||
## Introduction {#sec-cross-intro}
|
||||
|
||||
"Cross-compilation" means compiling a program on one machine for another type of machine. For example, a typical use of cross-compilation is to compile programs for embedded devices. These devices often don't have the computing power and memory to compile their own programs. One might think that cross-compilation is a fairly niche concern. However, there are significant advantages to rigorously distinguishing between build-time and run-time environments! Significant, because the benefits apply even when one is developing and deploying on the same machine. Nixpkgs is increasingly adopting the opinion that packages should be written with cross-compilation in mind, and Nixpkgs should evaluate in a similar way (by minimizing cross-compilation-specific special cases) whether or not one is cross-compiling.
|
||||
|
||||
This chapter will be organized in three parts. First, it will describe the basics of how to package software in a way that supports cross-compilation. Second, it will describe how to use Nixpkgs when cross-compiling. Third, it will describe the internal infrastructure supporting cross-compilation.
|
||||
|
||||
## Packaging in a cross-friendly manner {#sec-cross-packaging}
|
||||
|
||||
### Platform parameters {#ssec-cross-platform-parameters}
|
||||
|
||||
Nixpkgs follows the [conventions of GNU autoconf](https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html). We distinguish between 3 types of platforms when building a derivation: _build_, _host_, and _target_. In summary, _build_ is the platform on which a package is being built, _host_ is the platform on which it will run. The third attribute, _target_, is relevant only for certain specific compilers and build tools.
|
||||
|
||||
In Nixpkgs, these three platforms are defined as attribute sets under the names `buildPlatform`, `hostPlatform`, and `targetPlatform`. They are always defined as attributes in the standard environment. That means one can access them like:
|
||||
|
||||
```nix
|
||||
{ stdenv, fooDep, barDep, ... }: ...stdenv.buildPlatform...
|
||||
```
|
||||
|
||||
`buildPlatform`
|
||||
|
||||
: The "build platform" is the platform on which a package is built. Once someone has a built package, or pre-built binary package, the build platform should not matter and can be ignored.
|
||||
|
||||
`hostPlatform`
|
||||
|
||||
: The "host platform" is the platform on which a package will be run. This is the simplest platform to understand, but also the one with the worst name.
|
||||
|
||||
`targetPlatform`
|
||||
|
||||
: The "target platform" attribute is, unlike the other two attributes, not actually fundamental to the process of building software. Instead, it is only relevant for compatibility with building certain specific compilers and build tools. It can be safely ignored for all other packages.
|
||||
|
||||
: The build process of certain compilers is written in such a way that the compiler resulting from a single build can itself only produce binaries for a single platform. The task of specifying this single "target platform" is thus pushed to build time of the compiler. The root cause of this is that the compiler (which will be run on the host) and the standard library/runtime (which will be run on the target) are built by a single build process.
|
||||
|
||||
: There is no fundamental need to think about a single target ahead of time like this. If the tool supports modular or pluggable backends, both the need to specify the target at build time and the constraint of having only a single target disappear. An example of such a tool is LLVM.
|
||||
|
||||
: Although the existence of a "target platform" is arguably a historical mistake, it is a common one: examples of tools that suffer from it are GCC, Binutils, GHC and Autoconf. Nixpkgs tries to avoid sharing in the mistake where possible. Still, because the concept of a target platform is so ingrained, it is best to support it as is.
|
||||
|
||||
The exact schema these fields follow is a bit ill-defined due to a long and convoluted evolution, but this is slowly being cleaned up. You can see examples of ones used in practice in `lib.systems.examples`; note how they are not all very consistent. For now, here are few fields can count on them containing:
|
||||
|
||||
`system`
|
||||
|
||||
: This is a two-component shorthand for the platform. Examples of this would be "x86_64-darwin" and "i686-linux"; see `lib.systems.doubles` for more. The first component corresponds to the CPU architecture of the platform and the second to the operating system of the platform (`[cpu]-[os]`). This format has built-in support in Nix, such as the `builtins.currentSystem` impure string.
|
||||
|
||||
`config`
|
||||
|
||||
: This is a 3- or 4- component shorthand for the platform. Examples of this would be `x86_64-unknown-linux-gnu` and `aarch64-apple-darwin14`. This is a standard format called the "LLVM target triple", as they are pioneered by LLVM. In the 4-part form, this corresponds to `[cpu]-[vendor]-[os]-[abi]`. This format is strictly more informative than the "Nix host double", as the previous format could analogously be termed. This needs a better name than `config`!
|
||||
|
||||
`parsed`
|
||||
|
||||
: This is a Nix representation of a parsed LLVM target triple with white-listed components. This can be specified directly, or actually parsed from the `config`. See `lib.systems.parse` for the exact representation.
|
||||
|
||||
`libc`
|
||||
|
||||
: This is a string identifying the standard C library used. Valid identifiers include "glibc" for GNU libc, "libSystem" for Darwin's Libsystem, and "uclibc" for µClibc. It should probably be refactored to use the module system, like `parse`.
|
||||
|
||||
`is*`
|
||||
|
||||
: These predicates are defined in `lib.systems.inspect`, and slapped onto every platform. They are superior to the ones in `stdenv` as they force the user to be explicit about which platform they are inspecting. Please use these instead of those.
|
||||
|
||||
`platform`
|
||||
|
||||
: This is, quite frankly, a dumping ground of ad-hoc settings (it's an attribute set). See `lib.systems.platforms` for examples—there's hopefully one in there that will work verbatim for each platform that is working. Please help us triage these flags and give them better homes!
|
||||
|
||||
### Theory of dependency categorization {#ssec-cross-dependency-categorization}
|
||||
|
||||
::: {.note}
|
||||
This is a rather philosophical description that isn't very Nixpkgs-specific. For an overview of all the relevant attributes given to `mkDerivation`, see [](#ssec-stdenv-dependencies). For a description of how everything is implemented, see [](#ssec-cross-dependency-implementation).
|
||||
:::
|
||||
|
||||
In this section we explore the relationship between both runtime and build-time dependencies and the 3 Autoconf platforms.
|
||||
|
||||
A run time dependency between two packages requires that their host platforms match. This is directly implied by the meaning of "host platform" and "runtime dependency": The package dependency exists while both packages are running on a single host platform.
|
||||
|
||||
A build time dependency, however, has a shift in platforms between the depending package and the depended-on package. "build time dependency" means that to build the depending package we need to be able to run the depended-on's package. The depending package's build platform is therefore equal to the depended-on package's host platform.
|
||||
|
||||
If both the dependency and depending packages aren't compilers or other machine-code-producing tools, we're done. And indeed `buildInputs` and `nativeBuildInputs` have covered these simpler cases for many years. But if the dependency does produce machine code, we might need to worry about its target platform too. In principle, that target platform might be any of the depending package's build, host, or target platforms, but we prohibit dependencies from a "later" platform to an earlier platform to limit confusion because we've never seen a legitimate use for them.
|
||||
|
||||
Finally, if the depending package is a compiler or other machine-code-producing tool, it might need dependencies that run at "emit time". This is for compilers that (regrettably) insist on being built together with their source languages' standard libraries. Assuming build != host != target, a run-time dependency of the standard library cannot be run at the compiler's build time or run time, but only at the run time of code emitted by the compiler.
|
||||
|
||||
Putting this all together, that means that we have dependency types of the form "X→ E", which means that the dependency executes on X and emits code for E; each of X and E can be `build`, `host`, or `target`, and E can be `*` to indicate that the dependency is not a compiler-like package.
|
||||
|
||||
Dependency types describe the relationships that a package has with each of its transitive dependencies. You could think of attaching one or more dependency types to each of the formal parameters at the top of a package's `.nix` file, as well as to all of *their* formal parameters, and so on. Triples like `(foo, bar, baz)`, on the other hand, are a property of an instantiated derivation -- you could would attach a triple `(mips-linux, mips-linux, sparc-solaris)` to a `.drv` file in `/nix/store`.
|
||||
|
||||
Only nine dependency types matter in practice:
|
||||
|
||||
#### Possible dependency types {#possible-dependency-types}
|
||||
|
||||
| Dependency type | Dependency’s host platform | Dependency’s target platform |
|
||||
|-----------------|----------------------------|------------------------------|
|
||||
| build → * | build | (none) |
|
||||
| build → build | build | build |
|
||||
| build → host | build | host |
|
||||
| build → target | build | target |
|
||||
| host → * | host | (none) |
|
||||
| host → host | host | host |
|
||||
| host → target | host | target |
|
||||
| target → * | target | (none) |
|
||||
| target → target | target | target |
|
||||
|
||||
Let's use `g++` as an example to make this table clearer. `g++` is a C++ compiler written in C. Suppose we are building `g++` with a `(build, host, target)` platform triple of `(foo, bar, baz)`. This means we are using a `foo`-machine to build a copy of `g++` which will run on a `bar`-machine and emit binaries for the `baz`-machine.
|
||||
|
||||
* `g++` links against the host platform's `glibc` C library, which is a "host→ *" dependency with a triple of `(bar, bar, *)`. Since it is a library, not a compiler, it has no "target".
|
||||
|
||||
* Since `g++` is written in C, the `gcc` compiler used to compile it is a "build→ host" dependency of `g++` with a triple of `(foo, foo, bar)`. This compiler runs on the build platform and emits code for the host platform.
|
||||
|
||||
* `gcc` links against the build platform's `glibc` C library, which is a "build→ *" dependency with a triple of `(foo, foo, *)`. Since it is a library, not a compiler, it has no "target".
|
||||
|
||||
* This `gcc` is itself compiled by an *earlier* copy of `gcc`. This earlier copy of `gcc` is a "build→ build" dependency of `g++` with a triple of `(foo, foo, foo)`. This "early `gcc`" runs on the build platform and emits code for the build platform.
|
||||
|
||||
* `g++` is bundled with `libgcc`, which includes a collection of target-machine routines for exception handling and
|
||||
software floating point emulation. `libgcc` would be a "target→ *" dependency with triple `(foo, baz, *)`, because it consists of machine code which gets linked against the output of the compiler that we are building. It is a library, not a compiler, so it has no target of its own.
|
||||
|
||||
* `libgcc` is written in C and compiled with `gcc`. The `gcc` that compiles it will be a "build→ target" dependency with triple `(foo, foo, baz)`. It gets compiled *and run* at `g++`-build-time (on platform `foo`), but must emit code for the `baz`-platform.
|
||||
|
||||
* `g++` allows inline assembler code, so it depends on access to a copy of the `gas` assembler. This would be a "host→ target" dependency with triple `(foo, bar, baz)`.
|
||||
|
||||
* `g++` (and `gcc`) include a library `libgccjit.so`, which wrap the compiler in a library to create a just-in-time compiler. In nixpkgs, this library is in the `libgccjit` package; if C++ required that programs have access to a JIT, `g++` would need to add a "target→ target" dependency for `libgccjit` with triple `(foo, baz, baz)`. This would ensure that the compiler ships with a copy of `libgccjit` which both executes on and generates code for the `baz`-platform.
|
||||
|
||||
* If `g++` itself linked against `libgccjit.so` (for example, to allow compile-time-evaluated C++ expressions), then the `libgccjit` package used to provide this functionality would be a "host→ host" dependency of `g++`: it is code which runs on the `host` and emits code for execution on the `host`.
|
||||
|
||||
### Cross packaging cookbook {#ssec-cross-cookbook}
|
||||
|
||||
Some frequently encountered problems when packaging for cross-compilation should be answered here. Ideally, the information above is exhaustive, so this section cannot provide any new information, but it is ludicrous and cruel to expect everyone to spend effort working through the interaction of many features just to figure out the same answer to the same common problem. Feel free to add to this list!
|
||||
|
||||
#### My package fails to find a binutils command (`cc`/`ar`/`ld` etc.) {#cross-qa-fails-to-find-binutils}
|
||||
Many packages assume that an unprefixed binutils (`cc`/`ar`/`ld` etc.) is available, but Nix doesn't provide one. It only provides a prefixed one, just as it only does for all the other binutils programs. It may be necessary to patch the package to fix the build system to use a prefix. For instance, instead of `cc`, use `${stdenv.cc.targetPrefix}cc`.
|
||||
|
||||
```nix
|
||||
makeFlags = [ "CC=${stdenv.cc.targetPrefix}cc" ];
|
||||
```
|
||||
|
||||
#### How do I avoid compiling a GCC cross-compiler from source? {#cross-qa-avoid-compiling-gcc-cross-compiler}
|
||||
On less powerful machines, it can be inconvenient to cross-compile a package only to find out that GCC has to be compiled from source, which could take up to several hours. Nixpkgs maintains a limited [cross-related jobset on Hydra](https://hydra.nixos.org/jobset/nixpkgs/cross-trunk), which tests cross-compilation to various platforms from build platforms "x86\_64-darwin", "x86\_64-linux", and "aarch64-linux". See `pkgs/top-level/release-cross.nix` for the full list of target platforms and packages. For instance, the following invocation fetches the pre-built cross-compiled GCC for `armv6l-unknown-linux-gnueabihf` and builds GNU Hello from source.
|
||||
|
||||
```ShellSession
|
||||
$ nix-build '<nixpkgs>' -A pkgsCross.raspberryPi.hello
|
||||
```
|
||||
|
||||
#### What if my package’s build system needs to build a C program to be run under the build environment? {#cross-qa-build-c-program-in-build-environment}
|
||||
|
||||
Add the following to your `mkDerivation` invocation.
|
||||
|
||||
```nix
|
||||
depsBuildBuild = [ buildPackages.stdenv.cc ];
|
||||
```
|
||||
|
||||
#### My package’s testsuite needs to run host platform code. {#cross-testsuite-runs-host-code}
|
||||
|
||||
Add the following to your `mkDerivation` invocation.
|
||||
|
||||
```nix
|
||||
doCheck = stdenv.hostPlatform == stdenv.buildPlatform;
|
||||
```
|
||||
|
||||
## Cross-building packages {#sec-cross-usage}
|
||||
|
||||
Nixpkgs can be instantiated with `localSystem` alone, in which case there is no cross-compiling and everything is built by and for that system, or also with `crossSystem`, in which case packages run on the latter, but all building happens on the former. Both parameters take the same schema as the 3 (build, host, and target) platforms defined in the previous section. As mentioned above, `lib.systems.examples` has some platforms which are used as arguments for these parameters in practice. You can use them programmatically, or on the command line:
|
||||
|
||||
```ShellSession
|
||||
$ nix-build '<nixpkgs>' --arg crossSystem '(import <nixpkgs/lib>).systems.examples.fooBarBaz' -A whatever
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
Eventually we would like to make these platform examples an unnecessary convenience so that
|
||||
|
||||
```ShellSession
|
||||
$ nix-build '<nixpkgs>' --arg crossSystem '{ config = "<arch>-<os>-<vendor>-<abi>"; }' -A whatever
|
||||
```
|
||||
|
||||
works in the vast majority of cases. The problem today is dependencies on other sorts of configuration which aren't given proper defaults. We rely on the examples to crudely to set those configuration parameters in some vaguely sane manner on the users behalf. Issue [\#34274](https://github.com/NixOS/nixpkgs/issues/34274) tracks this inconvenience along with its root cause in crufty configuration options.
|
||||
:::
|
||||
|
||||
While one is free to pass both parameters in full, there's a lot of logic to fill in missing fields. As discussed in the previous section, only one of `system`, `config`, and `parsed` is needed to infer the other two. Additionally, `libc` will be inferred from `parse`. Finally, `localSystem.system` is also _impurely_ inferred based on the platform evaluation occurs. This means it is often not necessary to pass `localSystem` at all, as in the command-line example in the previous paragraph.
|
||||
|
||||
::: {.note}
|
||||
Many sources (manual, wiki, etc) probably mention passing `system`, `platform`, along with the optional `crossSystem` to Nixpkgs: `import <nixpkgs> { system = ..; platform = ..; crossSystem = ..; }`. Passing those two instead of `localSystem` is still supported for compatibility, but is discouraged. Indeed, much of the inference we do for these parameters is motivated by compatibility as much as convenience.
|
||||
:::
|
||||
|
||||
One would think that `localSystem` and `crossSystem` overlap horribly with the three `*Platforms` (`buildPlatform`, `hostPlatform,` and `targetPlatform`; see `stage.nix` or the manual). Actually, those identifiers are purposefully not used here to draw a subtle but important distinction: While the granularity of having 3 platforms is necessary to properly *build* packages, it is overkill for specifying the user's *intent* when making a build plan or package set. A simple "build vs deploy" dichotomy is adequate: the sliding window principle described in the previous section shows how to interpolate between the these two "end points" to get the 3 platform triple for each bootstrapping stage. That means for any package a given package set, even those not bound on the top level but only reachable via dependencies or `buildPackages`, the three platforms will be defined as one of `localSystem` or `crossSystem`, with the former replacing the latter as one traverses build-time dependencies. A last simple difference is that `crossSystem` should be null when one doesn't want to cross-compile, while the `*Platform`s are always non-null. `localSystem` is always non-null.
|
||||
|
||||
## Cross-compilation infrastructure {#sec-cross-infra}
|
||||
|
||||
### Implementation of dependencies {#ssec-cross-dependency-implementation}
|
||||
|
||||
The categories of dependencies developed in [](#ssec-cross-dependency-categorization) are specified as lists of derivations given to `mkDerivation`, as documented in [](#ssec-stdenv-dependencies). In short, each list of dependencies for "host → target" is called `deps<host><target>` (where `host`, and `target` values are either `build`, `host`, or `target`), with exceptions for backwards compatibility that `depsBuildHost` is instead called `nativeBuildInputs` and `depsHostTarget` is instead called `buildInputs`. Nixpkgs is now structured so that each `deps<host><target>` is automatically taken from `pkgs<host><target>`. (These `pkgs<host><target>`s are quite new, so there is no special case for `nativeBuildInputs` and `buildInputs`.) For example, `pkgsBuildHost.gcc` should be used at build-time, while `pkgsHostTarget.gcc` should be used at run-time.
|
||||
|
||||
Now, for most of Nixpkgs's history, there were no `pkgs<host><target>` attributes, and most packages have not been refactored to use it explicitly. Prior to those, there were just `buildPackages`, `pkgs`, and `targetPackages`. Those are now redefined as aliases to `pkgsBuildHost`, `pkgsHostTarget`, and `pkgsTargetTarget`. It is acceptable, even recommended, to use them for libraries to show that the host platform is irrelevant.
|
||||
|
||||
But before that, there was just `pkgs`, even though both `buildInputs` and `nativeBuildInputs` existed. \[Cross barely worked, and those were implemented with some hacks on `mkDerivation` to override dependencies.\] What this means is the vast majority of packages do not use any explicit package set to populate their dependencies, just using whatever `callPackage` gives them even if they do correctly sort their dependencies into the multiple lists described above. And indeed, asking that users both sort their dependencies, _and_ take them from the right attribute set, is both too onerous and redundant, so the recommended approach (for now) is to continue just categorizing by list and not using an explicit package set.
|
||||
|
||||
To make this work, we "splice" together the six `pkgsFooBar` package sets and have `callPackage` actually take its arguments from that. This is currently implemented in `pkgs/top-level/splice.nix`. `mkDerivation` then, for each dependency attribute, pulls the right derivation out from the splice. This splicing can be skipped when not cross-compiling as the package sets are the same, but still is a bit slow for cross-compiling. We'd like to do something better, but haven't come up with anything yet.
|
||||
|
||||
### Bootstrapping {#ssec-bootstrapping}
|
||||
|
||||
Each of the package sets described above come from a single bootstrapping stage. While `pkgs/top-level/default.nix`, coordinates the composition of stages at a high level, `pkgs/top-level/stage.nix` "ties the knot" (creates the fixed point) of each stage. The package sets are defined per-stage however, so they can be thought of as edges between stages (the nodes) in a graph. Compositions like `pkgsBuildTarget.targetPackages` can be thought of as paths to this graph.
|
||||
|
||||
While there are many package sets, and thus many edges, the stages can also be arranged in a linear chain. In other words, many of the edges are redundant as far as connectivity is concerned. This hinges on the type of bootstrapping we do. Currently for cross it is:
|
||||
|
||||
1. `(native, native, native)`
|
||||
|
||||
2. `(native, native, foreign)`
|
||||
|
||||
3. `(native, foreign, foreign)`
|
||||
|
||||
In each stage, `pkgsBuildHost` refers to the previous stage, `pkgsBuildBuild` refers to the one before that, and `pkgsHostTarget` refers to the current one, and `pkgsTargetTarget` refers to the next one. When there is no previous or next stage, they instead refer to the current stage. Note how all the invariants regarding the mapping between dependency and depending packages' build host and target platforms are preserved. `pkgsBuildTarget` and `pkgsHostHost` are more complex in that the stage fitting the requirements isn't always a fixed chain of "prevs" and "nexts" away (modulo the "saturating" self-references at the ends). We just special case each instead. All the primary edges are implemented is in `pkgs/stdenv/booter.nix`, and secondarily aliases in `pkgs/top-level/stage.nix`.
|
||||
|
||||
::: {.note}
|
||||
The native stages are bootstrapped in legacy ways that predate the current cross implementation. This is why the bootstrapping stages leading up to the final stages are ignored in the previous paragraph.
|
||||
:::
|
||||
|
||||
If one looks at the 3 platform triples, one can see that they overlap such that one could put them together into a chain like:
|
||||
```
|
||||
(native, native, native, foreign, foreign)
|
||||
```
|
||||
|
||||
If one imagines the saturating self references at the end being replaced with infinite stages, and then overlays those platform triples, one ends up with the infinite tuple:
|
||||
```
|
||||
(native..., native, native, native, foreign, foreign, foreign...)
|
||||
```
|
||||
One can then imagine any sequence of platforms such that there are bootstrap stages with their 3 platforms determined by "sliding a window" that is the 3 tuple through the sequence. This was the original model for bootstrapping. Without a target platform (assume a better world where all compilers are multi-target and all standard libraries are built in their own derivation), this is sufficient. Conversely if one wishes to cross compile "faster", with a "Canadian Cross" bootstrapping stage where `build != host != target`, more bootstrapping stages are needed since no sliding window provides the pesky `pkgsBuildTarget` package set since it skips the Canadian cross stage's "host".
|
||||
|
||||
|
||||
::: {.note}
|
||||
It is much better to refer to `buildPackages` than `targetPackages`, or more broadly package sets that do not mention “target”. There are three reasons for this.
|
||||
|
||||
First, it is because bootstrapping stages do not have a unique `targetPackages`. For example a `(x86-linux, x86-linux, arm-linux)` and `(x86-linux, x86-linux, x86-windows)` package set both have a `(x86-linux, x86-linux, x86-linux)` package set. Because there is no canonical `targetPackages` for such a native (`build == host == target`) package set, we set their `targetPackages`
|
||||
|
||||
Second, it is because this is a frequent source of hard-to-follow "infinite recursions" / cycles. When only package sets that don't mention target are used, the package set forms a directed acyclic graph. This means that all cycles that exist are confined to one stage. This means they are a lot smaller, and easier to follow in the code or a backtrace. It also means they are present in native and cross builds alike, and so more likely to be caught by CI and other users.
|
||||
|
||||
Thirdly, it is because everything target-mentioning only exists to accommodate compilers with lousy build systems that insist on the compiler itself and standard library being built together. Of course that is bad because bigger derivations means longer rebuilds. It is also problematic because it tends to make the standard libraries less like other libraries than they could be, complicating code and build systems alike. Because of the other problems, and because of these innate disadvantages, compilers ought to be packaged another way where possible.
|
||||
:::
|
||||
|
||||
::: {.note}
|
||||
If one explores Nixpkgs, they will see derivations with names like `gccCross`. Such `*Cross` derivations is a holdover from before we properly distinguished between the host and target platforms—the derivation with “Cross” in the name covered the `build = host != target` case, while the other covered the `host = target`, with build platform the same or not based on whether one was using its `.nativeDrv` or `.crossDrv`. This ugliness will disappear soon.
|
||||
:::
|
||||
279
doc/stdenv/meta.chapter.md
Normal file
279
doc/stdenv/meta.chapter.md
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
# Meta-attributes {#chap-meta}
|
||||
|
||||
Nix packages can declare *meta-attributes* that contain information about a package such as a description, its homepage, its license, and so on. For instance, the GNU Hello package has a `meta` declaration like this:
|
||||
|
||||
```nix
|
||||
meta = with lib; {
|
||||
description = "A program that produces a familiar, friendly greeting";
|
||||
longDescription = ''
|
||||
GNU Hello is a program that prints "Hello, world!" when you run it.
|
||||
It is fully customizable.
|
||||
'';
|
||||
homepage = "https://www.gnu.org/software/hello/manual/";
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = [ maintainers.eelco ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
```
|
||||
|
||||
Meta-attributes are not passed to the builder of the package. Thus, a change to a meta-attribute doesn’t trigger a recompilation of the package. The value of a meta-attribute must be a string.
|
||||
|
||||
The meta-attributes of a package can be queried from the command-line using `nix-env`:
|
||||
|
||||
```ShellSession
|
||||
$ nix-env -qa hello --json
|
||||
{
|
||||
"hello": {
|
||||
"meta": {
|
||||
"description": "A program that produces a familiar, friendly greeting",
|
||||
"homepage": "https://www.gnu.org/software/hello/manual/",
|
||||
"license": {
|
||||
"fullName": "GNU General Public License version 3 or later",
|
||||
"shortName": "GPLv3+",
|
||||
"url": "http://www.fsf.org/licensing/licenses/gpl.html"
|
||||
},
|
||||
"longDescription": "GNU Hello is a program that prints \"Hello, world!\" when you run it.\nIt is fully customizable.\n",
|
||||
"maintainers": [
|
||||
"Ludovic Court\u00e8s <ludo@gnu.org>"
|
||||
],
|
||||
"platforms": [
|
||||
"i686-linux",
|
||||
"x86_64-linux",
|
||||
"armv5tel-linux",
|
||||
"armv7l-linux",
|
||||
"mips32-linux",
|
||||
"x86_64-darwin",
|
||||
"i686-cygwin",
|
||||
"i686-freebsd",
|
||||
"x86_64-freebsd",
|
||||
"i686-openbsd",
|
||||
"x86_64-openbsd"
|
||||
],
|
||||
"position": "/home/user/dev/nixpkgs/pkgs/applications/misc/hello/default.nix:14"
|
||||
},
|
||||
"name": "hello-2.9",
|
||||
"system": "x86_64-linux"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`nix-env` knows about the `description` field specifically:
|
||||
|
||||
```ShellSession
|
||||
$ nix-env -qa hello --description
|
||||
hello-2.3 A program that produces a familiar, friendly greeting
|
||||
```
|
||||
|
||||
## Standard meta-attributes {#sec-standard-meta-attributes}
|
||||
|
||||
It is expected that each meta-attribute is one of the following:
|
||||
|
||||
### `description` {#var-meta-description}
|
||||
|
||||
A short (one-line) description of the package. This is shown by `nix-env -q --description` and also on the Nixpkgs release pages.
|
||||
|
||||
Don’t include a period at the end. Don’t include newline characters. Capitalise the first character. For brevity, don’t repeat the name of package --- just describe what it does.
|
||||
|
||||
Wrong: `"libpng is a library that allows you to decode PNG images."`
|
||||
|
||||
Right: `"A library for decoding PNG images"`
|
||||
|
||||
### `longDescription` {#var-meta-longDescription}
|
||||
|
||||
An arbitrarily long description of the package.
|
||||
|
||||
### `branch` {#var-meta-branch}
|
||||
|
||||
Release branch. Used to specify that a package is not going to receive updates that are not in this branch; for example, Linux kernel 3.0 is supposed to be updated to 3.0.X, not 3.1.
|
||||
|
||||
### `homepage` {#var-meta-homepage}
|
||||
|
||||
The package’s homepage. Example: `https://www.gnu.org/software/hello/manual/`
|
||||
|
||||
### `downloadPage` {#var-meta-downloadPage}
|
||||
|
||||
The page where a link to the current version can be found. Example: `https://ftp.gnu.org/gnu/hello/`
|
||||
|
||||
### `changelog` {#var-meta-changelog}
|
||||
|
||||
A link or a list of links to the location of Changelog for a package. A link may use expansion to refer to the correct changelog version. Example: `"https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v${version}"`
|
||||
|
||||
### `license` {#var-meta-license}
|
||||
|
||||
The license, or licenses, for the package. One from the attribute set defined in [`nixpkgs/lib/licenses.nix`](https://github.com/NixOS/nixpkgs/blob/master/lib/licenses.nix). At this moment using both a list of licenses and a single license is valid. If the license field is in the form of a list representation, then it means that parts of the package are licensed differently. Each license should preferably be referenced by their attribute. The non-list attribute value can also be a space delimited string representation of the contained attribute `shortNames` or `spdxIds`. The following are all valid examples:
|
||||
|
||||
- Single license referenced by attribute (preferred) `lib.licenses.gpl3Only`.
|
||||
- Single license referenced by its attribute shortName (frowned upon) `"gpl3Only"`.
|
||||
- Single license referenced by its attribute spdxId (frowned upon) `"GPL-3.0-only"`.
|
||||
- Multiple licenses referenced by attribute (preferred) `with lib.licenses; [ asl20 free ofl ]`.
|
||||
- Multiple licenses referenced as a space delimited string of attribute shortNames (frowned upon) `"asl20 free ofl"`.
|
||||
|
||||
For details, see [Licenses](#sec-meta-license).
|
||||
|
||||
### `maintainers` {#var-meta-maintainers}
|
||||
|
||||
A list of the maintainers of this Nix expression. Maintainers are defined in [`nixpkgs/maintainers/maintainer-list.nix`](https://github.com/NixOS/nixpkgs/blob/master/maintainers/maintainer-list.nix). There is no restriction to becoming a maintainer, just add yourself to that list in a separate commit titled “maintainers: add alice”, and reference maintainers with `maintainers = with lib.maintainers; [ alice bob ]`.
|
||||
|
||||
### `mainProgram` {#var-meta-mainProgram}
|
||||
|
||||
The name of the main binary for the package. This effects the binary `nix run` executes and falls back to the name of the package. Example: `"rg"`
|
||||
|
||||
### `priority` {#var-meta-priority}
|
||||
|
||||
The *priority* of the package, used by `nix-env` to resolve file name conflicts between packages. See the Nix manual page for `nix-env` for details. Example: `"10"` (a low-priority package).
|
||||
|
||||
### `platforms` {#var-meta-platforms}
|
||||
|
||||
The list of Nix platform types on which the package is supported. Hydra builds packages according to the platform specified. If no platform is specified, the package does not have prebuilt binaries. An example is:
|
||||
|
||||
```nix
|
||||
meta.platforms = lib.platforms.linux;
|
||||
```
|
||||
|
||||
Attribute Set `lib.platforms` defines [various common lists](https://github.com/NixOS/nixpkgs/blob/master/lib/systems/doubles.nix) of platforms types.
|
||||
|
||||
### `tests` {#var-meta-tests}
|
||||
|
||||
::: {.warning}
|
||||
This attribute is special in that it is not actually under the `meta` attribute set but rather under the `passthru` attribute set. This is due to how `meta` attributes work, and the fact that they are supposed to contain only metadata, not derivations.
|
||||
:::
|
||||
|
||||
An attribute set with tests as values. A test is a derivation that builds when the test passes and fails to build otherwise.
|
||||
|
||||
You can run these tests with:
|
||||
|
||||
```ShellSession
|
||||
$ cd path/to/nixpkgs
|
||||
$ nix-build -A your-package.tests
|
||||
```
|
||||
|
||||
#### Package tests
|
||||
|
||||
Tests that are part of the source package are often executed in the `installCheckPhase`.
|
||||
|
||||
Prefer `passthru.tests` for tests that are introduced in nixpkgs because:
|
||||
|
||||
* `passthru.tests` tests the 'real' package, independently from the environment in which it was built
|
||||
* we can run `passthru.tests` independently
|
||||
* `installCheckPhase` adds overhead to each build
|
||||
|
||||
For more on how to write and run package tests, see <xref linkend="sec-package-tests"/>.
|
||||
|
||||
#### NixOS tests
|
||||
|
||||
The NixOS tests are available as `nixosTests` in parameters of derivations. For instance, the OpenSMTPD derivation includes lines similar to:
|
||||
|
||||
```nix
|
||||
{ /* ... */, nixosTests }:
|
||||
{
|
||||
# ...
|
||||
passthru.tests = {
|
||||
basic-functionality-and-dovecot-integration = nixosTests.opensmtpd;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
NixOS tests run in a VM, so they are slower than regular package tests. For more information see [NixOS module tests](https://nixos.org/manual/nixos/stable/#sec-nixos-tests).
|
||||
|
||||
Alternatively, you can specify other derivations as tests. You can make use of
|
||||
the optional parameter to inject the correct package without
|
||||
relying on non-local definitions, even in the presence of `overrideAttrs`.
|
||||
Here that's `finalAttrs.finalPackage`, but you could choose a different name if
|
||||
`finalAttrs` already exists in your scope.
|
||||
|
||||
`(mypkg.overrideAttrs f).passthru.tests` will be as expected, as long as the
|
||||
definition of `tests` does not rely on the original `mypkg` or overrides it in
|
||||
all places.
|
||||
|
||||
```nix
|
||||
# my-package/default.nix
|
||||
{ stdenv, callPackage }:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
# ...
|
||||
passthru.tests.example = callPackage ./example.nix { my-package = finalAttrs.finalPackage; };
|
||||
})
|
||||
```
|
||||
|
||||
```nix
|
||||
# my-package/example.nix
|
||||
{ runCommand, lib, my-package, ... }:
|
||||
runCommand "my-package-test" {
|
||||
nativeBuildInputs = [ my-package ];
|
||||
src = lib.sources.sourcesByRegex ./. [ ".*.in" ".*.expected" ];
|
||||
} ''
|
||||
my-package --help
|
||||
my-package <example.in >example.actual
|
||||
diff -U3 --color=auto example.expected example.actual
|
||||
mkdir $out
|
||||
''
|
||||
```
|
||||
|
||||
|
||||
### `timeout` {#var-meta-timeout}
|
||||
|
||||
A timeout (in seconds) for building the derivation. If the derivation takes longer than this time to build, it can fail due to breaking the timeout. However, all computers do not have the same computing power, hence some builders may decide to apply a multiplicative factor to this value. When filling this value in, try to keep it approximately consistent with other values already present in `nixpkgs`.
|
||||
|
||||
### `hydraPlatforms` {#var-meta-hydraPlatforms}
|
||||
|
||||
The list of Nix platform types for which the Hydra instance at `hydra.nixos.org` will build the package. (Hydra is the Nix-based continuous build system.) It defaults to the value of `meta.platforms`. Thus, the only reason to set `meta.hydraPlatforms` is if you want `hydra.nixos.org` to build the package on a subset of `meta.platforms`, or not at all, e.g.
|
||||
|
||||
```nix
|
||||
meta.platforms = lib.platforms.linux;
|
||||
meta.hydraPlatforms = [];
|
||||
```
|
||||
|
||||
### `broken` {#var-meta-broken}
|
||||
|
||||
If set to `true`, the package is marked as "broken", meaning that it won’t show up in `nix-env -qa`, and cannot be built or installed. Such packages should be removed from Nixpkgs eventually unless they are fixed.
|
||||
|
||||
## Licenses {#sec-meta-license}
|
||||
|
||||
The `meta.license` attribute should preferably contain a value from `lib.licenses` defined in [`nixpkgs/lib/licenses.nix`](https://github.com/NixOS/nixpkgs/blob/master/lib/licenses.nix), or in-place license description of the same format if the license is unlikely to be useful in another expression.
|
||||
|
||||
Although it’s typically better to indicate the specific license, a few generic options are available:
|
||||
|
||||
### `lib.licenses.free`, `"free"` {#lib.licenses.free-free}
|
||||
|
||||
Catch-all for free software licenses not listed above.
|
||||
|
||||
### `lib.licenses.unfreeRedistributable`, `"unfree-redistributable"` {#lib.licenses.unfreeredistributable-unfree-redistributable}
|
||||
|
||||
Unfree package that can be redistributed in binary form. That is, it’s legal to redistribute the *output* of the derivation. This means that the package can be included in the Nixpkgs channel.
|
||||
|
||||
Sometimes proprietary software can only be redistributed unmodified. Make sure the builder doesn’t actually modify the original binaries; otherwise we’re breaking the license. For instance, the NVIDIA X11 drivers can be redistributed unmodified, but our builder applies `patchelf` to make them work. Thus, its license is `"unfree"` and it cannot be included in the Nixpkgs channel.
|
||||
|
||||
### `lib.licenses.unfree`, `"unfree"` {#lib.licenses.unfree-unfree}
|
||||
|
||||
Unfree package that cannot be redistributed. You can build it yourself, but you cannot redistribute the output of the derivation. Thus it cannot be included in the Nixpkgs channel.
|
||||
|
||||
### `lib.licenses.unfreeRedistributableFirmware`, `"unfree-redistributable-firmware"` {#lib.licenses.unfreeredistributablefirmware-unfree-redistributable-firmware}
|
||||
|
||||
This package supplies unfree, redistributable firmware. This is a separate value from `unfree-redistributable` because not everybody cares whether firmware is free.
|
||||
|
||||
## Source provenance {#sec-meta-sourceProvenance}
|
||||
|
||||
The value of a package's `meta.sourceProvenance` attribute specifies the provenance of the package's derivation outputs.
|
||||
|
||||
If a package contains elements that are not built from the original source by a nixpkgs derivation, the `meta.sourceProvenance` attribute should be a list containing one or more value from `lib.sourceTypes` defined in [`nixpkgs/lib/source-types.nix`](https://github.com/NixOS/nixpkgs/blob/master/lib/source-types.nix).
|
||||
|
||||
Adding this information helps users who have needs related to build transparency and supply-chain security to gain some visibility into their installed software or set policy to allow or disallow installation based on source provenance.
|
||||
|
||||
The presence of a particular `sourceType` in a package's `meta.sourceProvenance` list indicates that the package contains some components falling into that category, though the *absence* of that `sourceType` does not *guarantee* the absence of that category of `sourceType` in the package's contents. A package with no `meta.sourceProvenance` set implies it has no *known* `sourceType`s other than `fromSource`.
|
||||
|
||||
The meaning of the `meta.sourceProvenance` attribute does not depend on the value of the `meta.license` attribute.
|
||||
|
||||
### `lib.sourceTypes.fromSource` {#lib.sourceTypes.fromSource}
|
||||
|
||||
Package elements which are produced by a nixpkgs derivation which builds them from source code.
|
||||
|
||||
### `lib.sourceTypes.binaryNativeCode` {#lib.sourceTypes.binaryNativeCode}
|
||||
|
||||
Native code to be executed on the target system's CPU, built by a third party. This includes packages which wrap a downloaded AppImage or Debian package.
|
||||
|
||||
### `lib.sourceTypes.binaryFirmware` {#lib.sourceTypes.binaryFirmware}
|
||||
|
||||
Code to be executed on a peripheral device or embedded controller, built by a third party.
|
||||
|
||||
### `lib.sourceTypes.binaryBytecode` {#lib.sourceTypes.binaryBytecode}
|
||||
|
||||
Code to run on a VM interpreter or JIT compiled into bytecode by a third party. This includes packages which download Java `.jar` files from another source.
|
||||
128
doc/stdenv/multiple-output.chapter.md
Normal file
128
doc/stdenv/multiple-output.chapter.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# Multiple-output packages {#chap-multiple-output}
|
||||
|
||||
## Introduction {#sec-multiple-outputs-introduction}
|
||||
|
||||
The Nix language allows a derivation to produce multiple outputs, which is similar to what is utilized by other Linux distribution packaging systems. The outputs reside in separate Nix store paths, so they can be mostly handled independently of each other, including passing to build inputs, garbage collection or binary substitution. The exception is that building from source always produces all the outputs.
|
||||
|
||||
The main motivation is to save disk space by reducing runtime closure sizes; consequently also sizes of substituted binaries get reduced. Splitting can be used to have more granular runtime dependencies, for example the typical reduction is to split away development-only files, as those are typically not needed during runtime. As a result, closure sizes of many packages can get reduced to a half or even much less.
|
||||
|
||||
::: {.note}
|
||||
The reduction effects could be instead achieved by building the parts in completely separate derivations. That would often additionally reduce build-time closures, but it tends to be much harder to write such derivations, as build systems typically assume all parts are being built at once. This compromise approach of single source package producing multiple binary packages is also utilized often by rpm and deb.
|
||||
:::
|
||||
|
||||
A number of attributes can be used to work with a derivation with multiple outputs. The attribute `outputs` is a list of strings, which are the names of the outputs. For each of these names, an identically named attribute is created, corresponding to that output. The attribute `meta.outputsToInstall` is used to determine the default set of outputs to install when using the derivation name unqualified.
|
||||
|
||||
## Installing a split package {#sec-multiple-outputs-installing}
|
||||
|
||||
When installing a package with multiple outputs, the package’s `meta.outputsToInstall` attribute determines which outputs are actually installed. `meta.outputsToInstall` is a list whose [default installs binaries and the associated man pages](https://github.com/NixOS/nixpkgs/blob/f1680774340d5443a1409c3421ced84ac1163ba9/pkgs/stdenv/generic/make-derivation.nix#L310-L320). The following sections describe ways to install different outputs.
|
||||
|
||||
### Selecting outputs to install via NixOS {#sec-multiple-outputs-installing-nixos}
|
||||
|
||||
NixOS provides two ways to select the outputs to install for packages listed in `environment.systemPackages`:
|
||||
|
||||
- The configuration option `environment.extraOutputsToInstall` is appended to each package’s `meta.outputsToInstall` attribute to determine the outputs to install. It can for example be used to install `info` documentation or debug symbols for all packages.
|
||||
|
||||
- The outputs can be listed as packages in `environment.systemPackages`. For example, the `"out"` and `"info"` outputs for the `coreutils` package can be installed by including `coreutils` and `coreutils.info` in `environment.systemPackages`.
|
||||
|
||||
### Selecting outputs to install via `nix-env` {#sec-multiple-outputs-installing-nix-env}
|
||||
|
||||
`nix-env` lacks an easy way to select the outputs to install. When installing a package, `nix-env` always installs the outputs listed in `meta.outputsToInstall`, even when the user explicitly selects an output.
|
||||
|
||||
::: {.warning}
|
||||
`nix-env` silenty disregards the outputs selected by the user, and instead installs the outputs from `meta.outputsToInstall`. For example,
|
||||
|
||||
```ShellSession
|
||||
$ nix-env -iA nixpkgs.coreutils.info
|
||||
```
|
||||
|
||||
installs the `"out"` output (`coreutils.meta.outputsToInstall` is `[ "out" ]`) instead of the requested `"info"`.
|
||||
:::
|
||||
|
||||
The only recourse to select an output with `nix-env` is to override the package’s `meta.outputsToInstall`, using the functions described in [](#chap-overrides). For example, the following overlay adds the `"info"` output for the `coreutils` package:
|
||||
|
||||
```nix
|
||||
self: super:
|
||||
{
|
||||
coreutils = super.coreutils.overrideAttrs (oldAttrs: {
|
||||
meta = oldAttrs.meta // { outputsToInstall = oldAttrs.meta.outputsToInstall or [ "out" ] ++ [ "info" ]; };
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Using a split package {#sec-multiple-outputs-using-split-packages}
|
||||
|
||||
In the Nix language the individual outputs can be reached explicitly as attributes, e.g. `coreutils.info`, but the typical case is just using packages as build inputs.
|
||||
|
||||
When a multiple-output derivation gets into a build input of another derivation, the `dev` output is added if it exists, otherwise the first output is added. In addition to that, `propagatedBuildOutputs` of that package which by default contain `$outputBin` and `$outputLib` are also added. (See [](#multiple-output-file-type-groups).)
|
||||
|
||||
In some cases it may be desirable to combine different outputs under a single store path. A function `symlinkJoin` can be used to do this. (Note that it may negate some closure size benefits of using a multiple-output package.)
|
||||
|
||||
## Writing a split derivation {#sec-multiple-outputs-}
|
||||
|
||||
Here you find how to write a derivation that produces multiple outputs.
|
||||
|
||||
In nixpkgs there is a framework supporting multiple-output derivations. It tries to cover most cases by default behavior. You can find the source separated in `<nixpkgs/pkgs/build-support/setup-hooks/multiple-outputs.sh>`; it’s relatively well-readable. The whole machinery is triggered by defining the `outputs` attribute to contain the list of desired output names (strings).
|
||||
|
||||
```nix
|
||||
outputs = [ "bin" "dev" "out" "doc" ];
|
||||
```
|
||||
|
||||
Often such a single line is enough. For each output an equally named environment variable is passed to the builder and contains the path in nix store for that output. Typically you also want to have the main `out` output, as it catches any files that didn’t get elsewhere.
|
||||
|
||||
::: {.note}
|
||||
There is a special handling of the `debug` output, described at [](#stdenv-separateDebugInfo).
|
||||
:::
|
||||
|
||||
### “Binaries first” {#multiple-output-file-binaries-first-convention}
|
||||
|
||||
A commonly adopted convention in `nixpkgs` is that executables provided by the package are contained within its first output. This convention allows the dependent packages to reference the executables provided by packages in a uniform manner. For instance, provided with the knowledge that the `perl` package contains a `perl` executable it can be referenced as `${pkgs.perl}/bin/perl` within a Nix derivation that needs to execute a Perl script.
|
||||
|
||||
The `glibc` package is a deliberate single exception to the “binaries first” convention. The `glibc` has `libs` as its first output allowing the libraries provided by `glibc` to be referenced directly (e.g. `${glibc}/lib/ld-linux-x86-64.so.2`). The executables provided by `glibc` can be accessed via its `bin` attribute (e.g. `${lib.getBin stdenv.cc.libc}/bin/ldd`).
|
||||
|
||||
The reason for why `glibc` deviates from the convention is because referencing a library provided by `glibc` is a very common operation among Nix packages. For instance, third-party executables packaged by Nix are typically patched and relinked with the relevant version of `glibc` libraries from Nix packages (please see the documentation on [patchelf](https://github.com/NixOS/patchelf) for more details).
|
||||
|
||||
### File type groups {#multiple-output-file-type-groups}
|
||||
|
||||
The support code currently recognizes some particular kinds of outputs and either instructs the build system of the package to put files into their desired outputs or it moves the files during the fixup phase. Each group of file types has an `outputFoo` variable specifying the output name where they should go. If that variable isn’t defined by the derivation writer, it is guessed – a default output name is defined, falling back to other possibilities if the output isn’t defined.
|
||||
|
||||
#### `$outputDev` {#outputdev}
|
||||
|
||||
is for development-only files. These include C(++) headers (`include/`), pkg-config (`lib/pkgconfig/`), cmake (`lib/cmake/`) and aclocal files (`share/aclocal/`). They go to `dev` or `out` by default.
|
||||
|
||||
#### `$outputBin` {#outputbin}
|
||||
|
||||
is meant for user-facing binaries, typically residing in `bin/`. They go to `bin` or `out` by default.
|
||||
|
||||
#### `$outputLib` {#outputlib}
|
||||
|
||||
is meant for libraries, typically residing in `lib/` and `libexec/`. They go to `lib` or `out` by default.
|
||||
|
||||
#### `$outputDoc` {#outputdoc}
|
||||
|
||||
is for user documentation, typically residing in `share/doc/`. It goes to `doc` or `out` by default.
|
||||
|
||||
#### `$outputDevdoc` {#outputdevdoc}
|
||||
|
||||
is for _developer_ documentation. Currently we count gtk-doc and devhelp books, typically residing in `share/gtk-doc/` and `share/devhelp/`, in there. It goes to `devdoc` or is removed (!) by default. This is because e.g. gtk-doc tends to be rather large and completely unused by nixpkgs users.
|
||||
|
||||
#### `$outputMan` {#outputman}
|
||||
|
||||
is for man pages (except for section 3), typically residing in `share/man/man[0-9]/`. They go to `man` or `$outputBin` by default.
|
||||
|
||||
#### `$outputDevman` {#outputdevman}
|
||||
|
||||
is for section 3 man pages, typically residing in `share/man/man[0-9]/`. They go to `devman` or `$outputMan` by default.
|
||||
|
||||
#### `$outputInfo` {#outputinfo}
|
||||
|
||||
is for info pages, typically residing in `share/info/`. They go to `info` or `$outputBin` by default.
|
||||
|
||||
### Common caveats {#sec-multiple-outputs-caveats}
|
||||
|
||||
- Some configure scripts don’t like some of the parameters passed by default by the framework, e.g. `--docdir=/foo/bar`. You can disable this by setting `setOutputFlags = false;`.
|
||||
|
||||
- The outputs of a single derivation can retain references to each other, but note that circular references are not allowed. (And each strongly-connected component would act as a single output anyway.)
|
||||
|
||||
- Most of split packages contain their core functionality in libraries. These libraries tend to refer to various kind of data that typically gets into `out`, e.g. locale strings, so there is often no advantage in separating the libraries into `lib`, as keeping them in `out` is easier.
|
||||
|
||||
- Some packages have hidden assumptions on install paths, which complicates splitting.
|
||||
62
doc/stdenv/platform-notes.chapter.md
Normal file
62
doc/stdenv/platform-notes.chapter.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Platform Notes {#chap-platform-notes}
|
||||
|
||||
## Darwin (macOS) {#sec-darwin}
|
||||
|
||||
Some common issues when packaging software for Darwin:
|
||||
|
||||
- The Darwin `stdenv` uses clang instead of gcc. When referring to the compiler `$CC` or `cc` will work in both cases. Some builds hardcode gcc/g++ in their build scripts, that can usually be fixed with using something like `makeFlags = [ "CC=cc" ];` or by patching the build scripts.
|
||||
|
||||
```nix
|
||||
stdenv.mkDerivation {
|
||||
name = "libfoo-1.2.3";
|
||||
# ...
|
||||
buildPhase = ''
|
||||
$CC -o hello hello.c
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
- On Darwin, libraries are linked using absolute paths, libraries are resolved by their `install_name` at link time. Sometimes packages won’t set this correctly causing the library lookups to fail at runtime. This can be fixed by adding extra linker flags or by running `install_name_tool -id` during the `fixupPhase`.
|
||||
|
||||
```nix
|
||||
stdenv.mkDerivation {
|
||||
name = "libfoo-1.2.3";
|
||||
# ...
|
||||
makeFlags = lib.optional stdenv.isDarwin "LDFLAGS=-Wl,-install_name,$(out)/lib/libfoo.dylib";
|
||||
}
|
||||
```
|
||||
|
||||
- Even if the libraries are linked using absolute paths and resolved via their `install_name` correctly, tests can sometimes fail to run binaries. This happens because the `checkPhase` runs before the libraries are installed.
|
||||
|
||||
This can usually be solved by running the tests after the `installPhase` or alternatively by using `DYLD_LIBRARY_PATH`. More information about this variable can be found in the *dyld(1)* manpage.
|
||||
|
||||
```
|
||||
dyld: Library not loaded: /nix/store/7hnmbscpayxzxrixrgxvvlifzlxdsdir-jq-1.5-lib/lib/libjq.1.dylib
|
||||
Referenced from: /private/tmp/nix-build-jq-1.5.drv-0/jq-1.5/tests/../jq
|
||||
Reason: image not found
|
||||
./tests/jqtest: line 5: 75779 Abort trap: 6
|
||||
```
|
||||
|
||||
```nix
|
||||
stdenv.mkDerivation {
|
||||
name = "libfoo-1.2.3";
|
||||
# ...
|
||||
doInstallCheck = true;
|
||||
installCheckTarget = "check";
|
||||
}
|
||||
```
|
||||
|
||||
- Some packages assume xcode is available and use `xcrun` to resolve build tools like `clang`, etc. This causes errors like `xcode-select: error: no developer tools were found at '/Applications/Xcode.app'` while the build doesn’t actually depend on xcode.
|
||||
|
||||
```nix
|
||||
stdenv.mkDerivation {
|
||||
name = "libfoo-1.2.3";
|
||||
# ...
|
||||
prePatch = ''
|
||||
substituteInPlace Makefile \
|
||||
--replace '/usr/bin/xcrun clang' clang
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
The package `xcbuild` can be used to build projects that really depend on Xcode. However, this replacement is not 100% compatible with Xcode and can occasionally cause issues.
|
||||
1323
doc/stdenv/stdenv.chapter.md
Normal file
1323
doc/stdenv/stdenv.chapter.md
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue