diff options
Diffstat (limited to 'doc/languages-frameworks')
-rw-r--r-- | doc/languages-frameworks/android.section.md | 2 | ||||
-rw-r--r-- | doc/languages-frameworks/coq.section.md | 6 | ||||
-rw-r--r-- | doc/languages-frameworks/dotnet.section.md | 2 | ||||
-rw-r--r-- | doc/languages-frameworks/lua.section.md | 4 | ||||
-rw-r--r-- | doc/languages-frameworks/python.section.md | 29 | ||||
-rw-r--r-- | doc/languages-frameworks/qt.section.md | 2 | ||||
-rw-r--r-- | doc/languages-frameworks/ruby.section.md | 2 | ||||
-rw-r--r-- | doc/languages-frameworks/rust.section.md | 238 |
8 files changed, 259 insertions, 26 deletions
diff --git a/doc/languages-frameworks/android.section.md b/doc/languages-frameworks/android.section.md index 62e544cd48b6..416073df078e 100644 --- a/doc/languages-frameworks/android.section.md +++ b/doc/languages-frameworks/android.section.md @@ -80,7 +80,7 @@ Most of the function arguments have reasonable default settings. You can specify license names: -* `extraLicenses` is a list of of license names. +* `extraLicenses` is a list of license names. You can get these names from repo.json or `querypackages.sh licenses`. The SDK license (`android-sdk-license`) is accepted for you if you set accept_license to true. If you are doing something like working with preview SDKs, you will diff --git a/doc/languages-frameworks/coq.section.md b/doc/languages-frameworks/coq.section.md index 8f564c6e46b6..5964d46e2f80 100644 --- a/doc/languages-frameworks/coq.section.md +++ b/doc/languages-frameworks/coq.section.md @@ -21,8 +21,8 @@ The recommended way of defining a derivation for a Coq library, is to use the `c * if it is a string of the form `owner:branch` then it tries to download the `branch` of owner `owner` for a project of the same name using the same vcs, and the `version` attribute of the resulting derivation is set to `"dev"`, additionally if the owner is not provided (i.e. if the `owner:` prefix is missing), it defaults to the original owner of the package (see below), * if it is a string of the form `"#N"`, and the domain is github, then it tries to download the current head of the pull request `#N` from github, * `defaultVersion` (optional). Coq libraries may be compatible with some specific versions of Coq only. The `defaultVersion` attribute is used when no `version` is provided (or if `version = null`) to select the version of the library to use by default, depending on the context. This selection will mainly depend on a `coq` version number but also possibly on other packages versions (e.g. `mathcomp`). If its value ends up to be `null`, the package is marked for removal in end-user `coqPackages` attribute set. -* `release` (optional, defaults to `{}`), lists all the known releases of the library and for each of them provides an attribute set with at least a `sha256` attribute (you may use the shell command `nix-prefetch-url --unpack <archive-url>` to find it, where `<archive-url>` is for example `https://github.com/owner/repo/archive/version.tar.gz`), each attribute set of the list of releases also takes optional overloading arguments for the fetcher as below (i.e.`domain`, `owner`, `repo`, `rev` assuming the default fetcher is used) and optional overrides for the result of the fetcher (i.e. `version` and `src`). -* `fetcher` (optional, default to a generic fetching mechanism supporting github or gitlab based infrastructures), is a function that takes at least an `owner`, a `repo`, a `rev`, and a `sha256` and returns an attribute set with a `version` and `src`. +* `release` (optional, defaults to `{}`), lists all the known releases of the library and for each of them provides an attribute set with at least a `sha256` attribute (you may put the empty string `""` in order to automatically insert a fake sha256, this will trigger an error which will allow you to find the correct sha256), each attribute set of the list of releases also takes optional overloading arguments for the fetcher as below (i.e.`domain`, `owner`, `repo`, `rev` assuming the default fetcher is used) and optional overrides for the result of the fetcher (i.e. `version` and `src`). +* `fetcher` (optional, defaults to a generic fetching mechanism supporting github or gitlab based infrastructures), is a function that takes at least an `owner`, a `repo`, a `rev`, and a `sha256` and returns an attribute set with a `version` and `src`. * `repo` (optional, defaults to the value of `pname`), * `owner` (optional, defaults to `"coq-community"`). * `domain` (optional, defaults to `"github.com"`), domains including the strings `"github"` or `"gitlab"` in their names are automatically supported, otherwise, one must change the `fetcher` argument to support them (cf `pkgs/development/coq-modules/heq/default.nix` for an example), @@ -31,6 +31,8 @@ The recommended way of defining a derivation for a Coq library, is to use the `c * `namePrefix` (optional), provides a way to alter the computation of `name` from `pname`, by explaining which dependencies must occur in `name`, * `extraBuildInputs` (optional), by default `buildInputs` just contains `coq`, this allows to add more build inputs, * `mlPlugin` (optional, defaults to `false`). Some extensions (plugins) might require OCaml and sometimes other OCaml packages. Standard dependencies can be added by setting the current option to `true`. For a finer grain control, the `coq.ocamlPackages` attribute can be used in `extraBuildInputs` to depend on the same package set Coq was built against. +* `useDune2ifVersion` (optional, default to `(x: false)` uses Dune2 to build the package if the provided predicate evaluates to true on the version, e.g. `useDune2if = versions.isGe "1.1"` will use dune if the version of the package is greater or equal to `"1.1"`, +* `useDune2` (optional, defaults to `false`) uses Dune2 to build the package if set to true, the presence of this attribute overrides the behavior of the previous one. * `enableParallelBuilding` (optional, defaults to `true`), since it is activated by default, we provide a way to disable it. * `extraInstallFlags` (optional), allows to extend `installFlags` which initializes the variable `COQMF_COQLIB` so as to install in the proper subdirectory. Indeed Coq libraries should be installed in `$(out)/lib/coq/${coq.coq-version}/user-contrib/`. Such directories are automatically added to the `$COQPATH` environment variable by the hook defined in the Coq derivation. * `setCOQBIN` (optional, defaults to `true`), by default, the environment variable `$COQBIN` is set to the current Coq's binary, but one can disable this behavior by setting it to `false`, diff --git a/doc/languages-frameworks/dotnet.section.md b/doc/languages-frameworks/dotnet.section.md index 88fd74db8256..c3947042494d 100644 --- a/doc/languages-frameworks/dotnet.section.md +++ b/doc/languages-frameworks/dotnet.section.md @@ -64,7 +64,7 @@ $ dotnet --info The `dotnetCorePackages.sdk_X_Y` is preferred over the old dotnet-sdk as both major and minor version are very important for a dotnet environment. If a given minor version isn't present (or was changed), then this will likely break your ability to build a project. -## dotnetCorePackages.sdk vs vs dotnetCorePackages.net vs dotnetCorePackages.netcore vs dotnetCorePackages.aspnetcore +## dotnetCorePackages.sdk vs dotnetCorePackages.net vs dotnetCorePackages.netcore vs dotnetCorePackages.aspnetcore The `dotnetCorePackages.sdk` contains both a runtime and the full sdk of a given version. The `net`, `netcore` and `aspnetcore` packages are meant to serve as minimal runtimes to deploy alongside already built applications. For runtime versions >= .NET 5 `net` is used while `netcore` is used for older .NET Core runtime version. diff --git a/doc/languages-frameworks/lua.section.md b/doc/languages-frameworks/lua.section.md index d81949c75f69..5935cbd7bd52 100644 --- a/doc/languages-frameworks/lua.section.md +++ b/doc/languages-frameworks/lua.section.md @@ -50,7 +50,7 @@ and install it in your profile with ```shell nix-env -iA nixpkgs.myLuaEnv ``` -The environment is is installed by referring to the attribute, and considering +The environment is installed by referring to the attribute, and considering the `nixpkgs` channel was used. #### Lua environment defined in `/etc/nixos/configuration.nix` @@ -129,7 +129,7 @@ the whitelist maintainers/scripts/luarocks-packages.csv and updated by running m [luarocks2nix](https://github.com/nix-community/luarocks) is a tool capable of generating nix derivations from both rockspec and src.rock (and favors the src.rock). The automation only goes so far though and some packages need to be customized. These customizations go in `pkgs/development/lua-modules/overrides.nix`. -For instance if the rockspec defines `external_dependencies`, these need to be manually added in in its rockspec file then it won't work. +For instance if the rockspec defines `external_dependencies`, these need to be manually added in its rockspec file then it won't work. You can try converting luarocks packages to nix packages with the command `nix-shell -p luarocks-nix` and then `luarocks nix PKG_NAME`. Nix rely on luarocks to install lua packages, basically it runs: diff --git a/doc/languages-frameworks/python.section.md b/doc/languages-frameworks/python.section.md index 1d5d9ebb7d73..f6d87b14be34 100644 --- a/doc/languages-frameworks/python.section.md +++ b/doc/languages-frameworks/python.section.md @@ -334,7 +334,7 @@ Above, we were mostly just focused on use cases and what to do to get started creating working Python environments in nix. Now that you know the basics to be up and running, it is time to take a step -back and take a deeper look at at how Python packages are packaged on Nix. Then, +back and take a deeper look at how Python packages are packaged on Nix. Then, we will look at how you can use development mode with your code. #### Python library packages in Nixpkgs @@ -611,7 +611,7 @@ Using the example above, the analagous pytestCheckHook usage would be: "update" ]; - disabledTestFiles = [ + disabledTestPaths = [ "tests/test_failing.py" ]; ``` @@ -638,7 +638,7 @@ are disabled. #### Using pythonImportsCheck -Although unit tests are highly prefered to valid correctness of a package. Not +Although unit tests are highly prefered to validate correctness of a package, not all packages have test suites that can be ran easily, and some have none at all. To help ensure the package still works, `pythonImportsCheck` can attempt to import the listed modules. @@ -918,7 +918,7 @@ because their behaviour is different: * `nativeBuildInputs ? []`: Build-time only dependencies. Typically executables as well as the items listed in `setup_requires`. -* `buildInputs ? []`: Build and/or run-time dependencies that need to be be +* `buildInputs ? []`: Build and/or run-time dependencies that need to be compiled for the host machine. Typically non-Python libraries which are being linked. * `checkInputs ? []`: Dependencies needed for running the `checkPhase`. These @@ -1188,7 +1188,8 @@ community to help save time. No tool is preferred at the moment. expressions for your Python project. Note that [sharing derivations from pypi2nix with nixpkgs is possible but not encouraged](https://github.com/nix-community/pypi2nix/issues/222#issuecomment-443497376). -- [python2nix](https://github.com/proger/python2nix) by Vladimir Kirillov. +- [nixpkgs-pytools](https://github.com/nix-community/nixpkgs-pytools) +- [poetry2nix](https://github.com/nix-community/poetry2nix) ### Deterministic builds @@ -1554,13 +1555,11 @@ In a `setup.py` or `setup.cfg` it is common to declare dependencies: ### Contributing guidelines -Following rules are desired to be respected: +The following rules are desired to be respected: * Python libraries are called from `python-packages.nix` and packaged with `buildPythonPackage`. The expression of a library should be in - `pkgs/development/python-modules/<name>/default.nix`. Libraries in - `pkgs/top-level/python-packages.nix` are sorted quasi-alphabetically to avoid - merge conflicts. + `pkgs/development/python-modules/<name>/default.nix`. * Python applications live outside of `python-packages.nix` and are packaged with `buildPythonApplication`. * Make sure libraries build for all Python interpreters. @@ -1570,7 +1569,11 @@ Following rules are desired to be respected: case, when you disable tests, leave a comment explaining why. * Commit names of Python libraries should reflect that they are Python libraries, so write for example `pythonPackages.numpy: 1.11 -> 1.12`. -* Attribute names in `python-packages.nix` should be normalized according to - [PEP 0503](https://www.python.org/dev/peps/pep-0503/#normalized-names). This - means that characters should be converted to lowercase and `.` and `_` should - be replaced by a single `-` (foo-bar-baz instead of Foo__Bar.baz ) +* Attribute names in `python-packages.nix` as well as `pname`s should match the + library's name on PyPI, but be normalized according to [PEP + 0503](https://www.python.org/dev/peps/pep-0503/#normalized-names). This means + that characters should be converted to lowercase and `.` and `_` should be + replaced by a single `-` (foo-bar-baz instead of Foo__Bar.baz). + If necessary, `pname` has to be given a different value within `fetchPypi`. +* Attribute names in `python-packages.nix` should be sorted alphanumerically to + avoid merge conflicts and ease locating attributes. diff --git a/doc/languages-frameworks/qt.section.md b/doc/languages-frameworks/qt.section.md index b6525490c85e..9747c1037adb 100644 --- a/doc/languages-frameworks/qt.section.md +++ b/doc/languages-frameworks/qt.section.md @@ -121,7 +121,7 @@ Use the `meta.broken` attribute to disable the package for unsupported Qt versio stdenv.mkDerivation { # ... - # Disable this library with Qt < 5.9.0 + # Disable this library with Qt < 5.9.0 meta.broken = lib.versionOlder qtbase.version "5.9.0"; } ``` diff --git a/doc/languages-frameworks/ruby.section.md b/doc/languages-frameworks/ruby.section.md index aeec154586c7..c519d79d3daf 100644 --- a/doc/languages-frameworks/ruby.section.md +++ b/doc/languages-frameworks/ruby.section.md @@ -229,7 +229,7 @@ end If you want to package a specific version, you can use the standard Gemfile syntax for that, e.g. `gem 'mdl', '0.5.0'`, but if you want the latest stable version anyway, it's easier to update by simply running the `bundle lock` and `bundix` steps again. -Now you can also also make a `default.nix` that looks like this: +Now you can also make a `default.nix` that looks like this: ```nix { bundlerApp }: diff --git a/doc/languages-frameworks/rust.section.md b/doc/languages-frameworks/rust.section.md index 8f6db28ab4d6..8121d03e046b 100644 --- a/doc/languages-frameworks/rust.section.md +++ b/doc/languages-frameworks/rust.section.md @@ -72,14 +72,41 @@ For `cargoHash` you can use: Per the instructions in the [Cargo Book](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html) best practices guide, Rust applications should always commit the `Cargo.lock` file in git to ensure a reproducible build. However, a few packages do not, and -Nix depends on this file, so if it missing you can use `cargoPatches` to apply -it in the `patchPhase`. Consider sending a PR upstream with a note to the +Nix depends on this file, so if it is missing you can use `cargoPatches` to +apply it in the `patchPhase`. Consider sending a PR upstream with a note to the maintainer describing why it's important to include in the application. The fetcher will verify that the `Cargo.lock` file is in sync with the `src` attribute, and fail the build if not. It will also will compress the vendor directory into a tar.gz archive. +The tarball with vendored dependencies contains a directory with the +package's `name`, which is normally composed of `pname` and +`version`. This means that the vendored dependencies hash +(`cargoSha256`/`cargoHash`) is dependent on the package name and +version. The `cargoDepsName` attribute can be used to use another name +for the directory of vendored dependencies. For example, the hash can +be made invariant to the version by setting `cargoDepsName` to +`pname`: + +```nix +rustPlatform.buildRustPackage rec { + pname = "broot"; + version = "1.2.0"; + + src = fetchCrate { + inherit pname version; + sha256 = "1mqaynrqaas82f5957lx31x80v74zwmwmjxxlbywajb61vh00d38"; + }; + + cargoHash = "sha256-JmBZcDVYJaK1cK05cxx5BrnGWp4t8ca6FLUbvIot67s="; + cargoDepsName = pname; + + # ... +} +``` + + ### Cross compilation By default, Rust packages are compiled for the host platform, just like any @@ -119,6 +146,7 @@ where they are known to differ. But there are ways to customize the argument: rustc.platform = { foo = ""; bar = ""; }; }; } + ``` will result in: ```shell --target /nix/store/asdfasdfsadf-thumb-crazy.json # contains {"foo":"","bar":""} @@ -129,7 +157,7 @@ path) can be passed directly to `buildRustPackage`: ```nix pkgs.rustPlatform.buildRustPackage { - (...) + /* ... */ target = "x86_64-fortanix-unknown-sgx"; } ``` @@ -164,6 +192,13 @@ rustPlatform.buildRustPackage { Please note that the code will be compiled twice here: once in `release` mode for the `buildPhase`, and again in `debug` mode for the `checkPhase`. +Test flags, e.g., `--features xxx/yyy`, can be passed to `cargo test` via the +`cargoTestFlags` attribute. + +Another attribute, called `checkFlags`, is used to pass arguments to the test +binary itself, as stated +(here)[https://doc.rust-lang.org/cargo/commands/cargo-test.html]. + #### Tests relying on the structure of the `target/` directory Some tests may rely on the structure of the `target/` directory. Those tests @@ -196,7 +231,7 @@ sometimes it may be necessary to disable this so the tests run consecutively. ```nix rustPlatform.buildRustPackage { /* ... */ - cargoParallelTestThreads = false; + dontUseCargoParallelTests = true; } ``` @@ -237,6 +272,199 @@ rustPlatform.buildRustPackage rec { } ``` +## Compiling non-Rust packages that include Rust code + +Several non-Rust packages incorporate Rust code for performance- or +security-sensitive parts. `rustPlatform` exposes several functions and +hooks that can be used to integrate Cargo in non-Rust packages. + +### Vendoring of dependencies + +Since network access is not allowed in sandboxed builds, Rust crate +dependencies need to be retrieved using a fetcher. `rustPlatform` +provides the `fetchCargoTarball` fetcher, which vendors all +dependencies of a crate. For example, given a source path `src` +containing `Cargo.toml` and `Cargo.lock`, `fetchCargoTarball` +can be used as follows: + +```nix +cargoDeps = rustPlatform.fetchCargoTarball { + inherit src; + hash = "sha256-BoHIN/519Top1NUBjpB/oEMqi86Omt3zTQcXFWqrek0="; +}; +``` + +The `src` attribute is required, as well as a hash specified through +one of the `sha256` or `hash` attributes. The following optional +attributes can also be used: + +* `name`: the name that is used for the dependencies tarball. If + `name` is not specified, then the name `cargo-deps` will be used. +* `sourceRoot`: when the `Cargo.lock`/`Cargo.toml` are in a + subdirectory, `sourceRoot` specifies the relative path to these + files. +* `patches`: patches to apply before vendoring. This is useful when + the `Cargo.lock`/`Cargo.toml` files need to be patched before + vendoring. + +### Hooks + +`rustPlatform` provides the following hooks to automate Cargo builds: + +* `cargoSetupHook`: configure Cargo to use depenencies vendored + through `fetchCargoTarball`. This hook uses the `cargoDeps` + environment variable to find the vendored dependencies. If a project + already vendors its dependencies, the variable `cargoVendorDir` can + be used instead. When the `Cargo.toml`/`Cargo.lock` files are not in + `sourceRoot`, then the optional `cargoRoot` is used to specify the + Cargo root directory relative to `sourceRoot`. +* `cargoBuildHook`: use Cargo to build a crate. If the crate to be + built is a crate in e.g. a Cargo workspace, the relative path to the + crate to build can be set through the optional `buildAndTestSubdir` + environment variable. Additional Cargo build flags can be passed + through `cargoBuildFlags`. +* `maturinBuildHook`: use [Maturin](https://github.com/PyO3/maturin) + to build a Python wheel. Similar to `cargoBuildHook`, the optional + variable `buildAndTestSubdir` can be used to build a crate in a + Cargo workspace. Additional maturin flags can be passed through + `maturinBuildFlags`. +* `cargoCheckHook`: run tests using Cargo. The build type for checks + can be set using `cargoCheckType`. Additional flags can be passed to + the tests using `checkFlags` and `checkFlagsArray`. By default, + tests are run in parallel. This can be disabled by setting + `dontUseCargoParallelTests`. +* `cargoInstallHook`: install binaries and static/shared libraries + that were built using `cargoBuildHook`. + +### Examples + +#### Python package using `setuptools-rust` + +For Python packages using `setuptools-rust`, you can use +`fetchCargoTarball` and `cargoSetupHook` to retrieve and set up Cargo +dependencies. The build itself is then performed by +`buildPythonPackage`. + +The following example outlines how the `tokenizers` Python package is +built. Since the Python package is in the `source/bindings/python` +directory of the *tokenizers* project's source archive, we use +`sourceRoot` to point the tooling to this directory: + +```nix +{ fetchFromGitHub +, buildPythonPackage +, rustPlatform +, setuptools-rust +}: + +buildPythonPackage rec { + pname = "tokenizers"; + version = "0.10.0"; + + src = fetchFromGitHub { + owner = "huggingface"; + repo = pname; + rev = "python-v${version}"; + hash = "sha256-rQ2hRV52naEf6PvRsWVCTN7B1oXAQGmnpJw4iIdhamw="; + }; + + cargoDeps = rustPlatform.fetchCargoTarball { + inherit src sourceRoot; + name = "${pname}-${version}"; + hash = "sha256-BoHIN/519Top1NUBjpB/oEMqi86Omt3zTQcXFWqrek0="; + }; + + sourceRoot = "source/bindings/python"; + + nativeBuildInputs = [ setuptools-rust ] ++ (with rustPlatform; [ + cargoSetupHook + rust.cargo + rust.rustc + ]); + + # ... +} +``` + +In some projects, the Rust crate is not in the main Python source +directory. In such cases, the `cargoRoot` attribute can be used to +specify the crate's directory relative to `sourceRoot`. In the +following example, the crate is in `src/rust`, as specified in the +`cargoRoot` attribute. Note that we also need to specify the correct +path for `fetchCargoTarball`. + +```nix + +{ buildPythonPackage +, fetchPypi +, rustPlatform +, setuptools-rust +, openssl +}: + +buildPythonPackage rec { + pname = "cryptography"; + version = "3.4.2"; # Also update the hash in vectors.nix + + src = fetchPypi { + inherit pname version; + sha256 = "1i1mx5y9hkyfi9jrrkcw804hmkcglxi6rmf7vin7jfnbr2bf4q64"; + }; + + cargoDeps = rustPlatform.fetchCargoTarball { + inherit src; + sourceRoot = "${pname}-${version}/${cargoRoot}"; + name = "${pname}-${version}"; + hash = "sha256-PS562W4L1NimqDV2H0jl5vYhL08H9est/pbIxSdYVfo="; + }; + + cargoRoot = "src/rust"; + + # ... +} +``` + +#### Python package using `maturin` + +Python packages that use [Maturin](https://github.com/PyO3/maturin) +can be built with `fetchCargoTarball`, `cargoSetupHook`, and +`maturinBuildHook`. For example, the following (partial) derivation +builds the `retworkx` Python package. `fetchCargoTarball` and +`cargoSetupHook` are used to fetch and set up the crate dependencies. +`maturinBuildHook` is used to perform the build. + +```nix +{ lib +, buildPythonPackage +, rustPlatform +, fetchFromGitHub +}: + +buildPythonPackage rec { + pname = "retworkx"; + version = "0.6.0"; + + src = fetchFromGitHub { + owner = "Qiskit"; + repo = "retworkx"; + rev = version; + sha256 = "11n30ldg3y3y6qxg3hbj837pnbwjkqw3nxq6frds647mmmprrd20"; + }; + + cargoDeps = rustPlatform.fetchCargoTarball { + inherit src; + name = "${pname}-${version}"; + hash = "sha256-heOBK8qi2nuc/Ib+I/vLzZ1fUUD/G/KTw9d7M4Hz5O0="; + }; + + format = "pyproject"; + + nativeBuildInputs = with rustPlatform; [ cargoSetupHook maturinBuildHook ]; + + # ... +} +``` + ## Compiling Rust crates using Nix instead of Cargo ### Simple operation @@ -518,7 +746,7 @@ with import "${src.out}/rust-overlay.nix" pkgs pkgs; stdenv.mkDerivation { name = "rust-env"; buildInputs = [ - # Note: to use use stable, just replace `nightly` with `stable` + # Note: to use stable, just replace `nightly` with `stable` latest.rustChannels.nightly.rust # Add some extra dependencies from `pkgs` |