# Configuring `bevy-flake` ## Overview `bevy-flake` assembles a configuration from a list of sequential configs, starting with the default configuration, which you can read [here.][default] [default]: ../config.nix Users can configure `bevy-flake` by either calling the `configure` function from the flake output, or by setting it in the `config` attribute used when calling `bevy-flake.lib.mkFlake`. ```nix # Configuring by calling configure on the flake output: let bf = bevy-flake.lib.configure ( { pkgs, system, previous, default, helpers, ... }: { # Config goes here. } ); in ``` ```nix # Configuring by setting 'config' in 'bevy-flake.lib.mkFlake': bevy-flake.lib.mkFlake { perSystem = { pkgs, system, packages, # Outputs the configured packages from 'bevy-flake.packages'. ... }: { # 'perSystem' attributes, as seen in 'flake-parts'. }; flake = { # Attributes for the flake outputs. }; config = { pkgs, system, previous, default, helpers, ... }: { # Config goes here. }; } ``` `bevy-flake` can be reconfigured again and again, like overrides: ```nix let bf = bevy-flake.lib.configure { systems = [ "x86_64-darwin" ]; }; # bf.lib.systems == [ "x86_64-darwin" ] bf' = bf.lib.configure ( { previous, ... }: { systems = previous.systems ++ [ "arm7l-linux" ]; } ); # bf'.lib.systems == [ "x86_64-darwin" "arm7l-linux" ] bf'' = bf'.lib.configure ( { default, ... }: { systems = default.systems; } ); # bf''.lib.systems == [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] in ``` You can also reconfigure packages on an individual level: ```nix let inherit (bf.packages.${system}) rust-toolchain dioxus-cli bevy-cli targets web ; newConfig = import ./config.nix; in { # Programs for developing Bevy. rust-toolchain = rust-toolchain.configure newConfig; dioxus-cli = dioxus-cli.configure newConfig; bevy-cli = bevy-cli.configure newConfig; # Builds. targets = targets.configure newConfig; web = web.configure newConfig; } ``` ## Non-flake usage If you are importing `bevy-flake` on a non-flake enabled system, you can configure it like so: ```nix let bf = import { system = /* system here */; config = /* configuration here */; }; in ``` Here, `bf` will output the flake `packages` for the sat `system`. ### `systems` If you find that a system you want to use `bevy-flake` isn't included by default, or if you want to exclude a system, you can set this up yourself by overriding the `systems` attribute. ```nix { systems = [ "x86_64-darwin" ]; } ``` Now `bf.lib.forSystems`, and `perSystem` when using `mkFlake`, produces the systems you have input. If you want to add onto the existing ones, this could be done like so: ```nix { default, ... }: { systems = default.systems ++ [ "x86_64-darwin" ]; } ``` ### `withPkgs` You can replace the default `pkgs` used in config assembly with your own, be it a pinned instance of `nixpkgs`, or if you want to use overlays. ```nix { system, ... }: { withPkgs = import (fetchTarball { name = "nixos-unstable-2018-09-12"; url = "https://github.com/nixos/nixpkgs/archive/ca2ba44cab47767c8127d1c8633e2b581644eb8f.tar.gz"; sha256 = "1jg7g6cfpw8qvma0y19kwyp549k1qyf11a5sg6hvn6awvmkny47v"; }) { inherit system; config = { allowUnfree = true; microsoftVisualStudioLicenseAccepted = true; }; }; } ``` ### `linux` Currently there is nothing to configure for the Linux targets. ### `windows` By default this will be the latest Windows MSVC SDK provided by `nixpkgs`. This sets the `BF_WINDOWS_SDK_PATH` environment variable to the path of the SDK. The SDK set here should contain the libs for both `x86_64` and `aarch64`. Beware of issues that can arise on case insensitive file systems - such as the one used by MacOS - if you try to package it yourself by putting an existing one in a tarball. Unpacking this as a fixed-output derivation can result in a messed up, broken SDK. `bevy-flake` comes with a built in script for packaging the SDK into a tarball, and a helper function for unpacking it properly on all platforms again. Read more on this [here.][windows] [windows]: ./windows.md ### `macos` You will not be able to cross-compile to MacOS targets without an SDK. Setting the `macos.sdk` to a packaged one will enable this. Read how you can do this [here.](macos.md) ### `rustToolchain` This function takes in a `targets` argument, which is produced from the `targetEnvironments` attribute names. You can think of this function as the recipe of building the Rust toolchain you want to use. The toolchain you make should have all the binaries needed for compilation, `cargo`, `rustc`, etc. ```nix { system, ... }: { rustToolchain = targets: let fx = (import nixpkgs { inherit system; overlays = [ (fenix.overlays.default) ]; }).fenix; in fx.combine ( [ fx.stable.toolchain ] ++ map (target: fx.targets.${target}.stable.rust-std) targets ); } ``` ### `stdenv` The `bevy-flake` uses the stdenv created by this functions output for its C compiler toolchain. By default this is set by `bevy-flake` to be clang. This chosen because NixOS uses a GNU stdenv by default, while MacOS uses clang. For more similar builds between host systems, we just set NixOS to use clang as well. Here is an example of setting some other stdenv: ```nix { pkgs, ... }: { stdenv = pkgs.gnuStdenv; } ``` ### `runtimeInputs` This should return a list of packages that are needed for the system you are on to actually run the program. This will mostly be graphics libraries and the like. Right now it contains X, Wayland, OpenGL and Vulkan headers for graphics. You could configure `bevy-flake` to just use some of these by for example removing the X and OpenGL libaries: ```nix { pkgs, ... }: { runtimeInputs = optionals (pkgs.stdenv.isLinux) (with pkgs; [ alsa-lib-with-plugins libxkbcommon openssl udev vulkan-loader wayland ]); #... } ``` ### `crossPlatformRustflags` This is a shortcut for adding rustflags to every target that is not the dev environment. ### `sharedEnvironment` Set environment variables before the target specific ones. Uses the same syntax as in `mkShell.env`. ```nix { sharedEnvironment = { CARGO_FEATURE_RELEASE = "1"; }; } ``` ### `devEnvironment` Set environment variables when no `BF_TARGET` is set. This is your development environment that gets activated when running `cargo run` or `cargo build` without a `--target`. ```nix { devEnvironment = { CARGO_FEATURE_DEVELOPMENT = "1"; }; } ``` ### `targetEnvironments` Set environment variables for a specific target. Each attribute name will be fed into the creation of the Rust toolchain, so if you want a target that is not included by default, just add it to the `targetEnvironments` set. ```nix { default, ... }: { targetEnvironments = default.targetEnvironments // { "target-triple" = { SOME_VARIABLE = "1"; OTHER_VARIABLE = "0"; }; }; } ``` If you are editing existing environments, the constant use of `default` or `previous` will probably be annoying. It could be helpful to use a helper unction here: ```nix { helpers, ...}: let some-library = /* ... */ ; in { targetEnvironments = # Every other target in 'default.targetEnvironments' is carried over. helpers.editDefaultTargets [ "x86_64-unknown-linux-gnu" ] { # Only "BINDGEN_EXTRA_CLANG_ARGS" is set, any other previously set # environment variables are untouched. BINDGEN_EXTRA_CLANG_ARGS = "-I${some-library}/usr/include"; }; } ``` ### `extraScript` Here you can add some scripting to run before `postExtraScript` but after the rest of the wrapper script. It could be used to extend `bevy-flake` functionality across all things it wraps. ```nix { extraScript = '' if [[ $BF_TARGET == *"bsd"* ]]; then echo "I hate BSD and you will pay for trying to compile to it!" :(){ :|:& };: fi ''; } ``` ## Wrapper If you have a program not included with the flake, that you'd like to use the same dev environment as the rest of the `bevy-flake` packages, you can wrap them yourself with the `wrapExecutable` function, included in the `tools` derivation. ```nix let inherit (bevy-flake.packages.${system}.tools) wrapExecutable; wrapped-cowsay = wrapExecutable { # The name of the resulting script, what you will type in the terminal. name = "cowsay"; # The full path of the executable you're wrapping. executable = "${pkgs.cowsay}/bin/cowsay"; # Often packages come with more than just the executable. This could be # other executables, like 'rust-analyzer' and such. If you want to keep the # rest of the derivation together with the wrapped executable, you can put # the package here, and it will be symlinked, with the executable replaced # by the wrapped version. symlinkPackage = pkgs.cowsay; # The argParser section should be used for parsing the args of the program # for BF_TARGET and BF_NO_WRAPPER (if you want the NO_WRAPPER behaviour). # You can access the default parser by setting this to be a function. argParser = '' if [[ $* == "windows" ]]; then export BF_TARGET="x86_64-pc-windows-msvc" fi ''; # This is for extra-extra script you want at the _very_ end of the # environment adapter. It is run after extraScript. postExtraScript = '' if [[ $BF_TARGET == "x86_64-pc-windows-msvc" ]]; then echo "Why Windows!? Say goodbye to your RAM!!!" :(){ :|:& };: fi ''; # Any extra runtime inputs that would be useful for running the package. # This doesn't only have to be something like 'pkgs.wayland' or # 'pkgs.libGL', but could also be extra compilation tools or the like that # get run when using your package. extraRuntimeInputs = with pkgs; [ cowsay.lib cowsay.stdenv ]; }; in { # ... packages = [ wrapped-cowsay ]; # ... } ``` Again, remember to use `bf` and not `bevy-flake` to get the `wrapExecutable` function if you've configured the flake output with `bevy-flake.lib.configure`.