@ -9,9 +9,13 @@
inputs . nixpkgs . follows = " n i x p k g s " ;
} ;
crane = {
url = " g i t h u b : i p e t k o v / c r a n e " ;
# TODO: Switch back to upstream after [this issue][0] is fixed
#
# [0]: https://github.com/ipetkov/crane/issues/497
url = " g i t h u b : C o b a l t C a u s e / c r a n e ? r e f = c r i m e s - f o r - c r o s s " ;
inputs . nixpkgs . follows = " n i x p k g s " ;
} ;
attic . url = " g i t h u b : z h a o f e n g l i / a t t i c ? r e f = m a i n " ;
} ;
outputs =
@ -22,59 +26,122 @@
, fenix
, crane
, . . .
} : flake-utils . lib . eachDefaultSystem ( system :
let
pkgs = nixpkgs . legacyPackages . ${ system } ;
# Use mold on Linux
stdenv = if pkgs . stdenv . isLinux then
pkgs . stdenvAdapters . useMoldLinker pkgs . stdenv
else
pkgs . stdenv ;
pkgsHost = nixpkgs . legacyPackages . ${ system } ;
# Nix-accessible `Cargo.toml`
cargoToml = builtins . fromTOML ( builtins . readFile ./Cargo.toml ) ;
# The Rust toolchain to use
toolchain = fenix . packages . ${ system } . toolchainOf {
# Use the Rust version defined in `Cargo.toml`
channel = cargoToml . package . rust-version ;
toolchain = fenix . packages . ${ system } . fromToolchainFile {
file = ./rust-toolchain.toml ;
# THE rust-version HASH
# See also `rust-toolchain.toml`
sha256 = " s h a 2 5 6 - g d Y q n g 0 y 9 i H Y z Y P A d k C / k a 3 D R n y 3 L a / S 5 G 8 A S j 0 A y y c = " ;
} ;
mkToolchain = fenix . packages . ${ system } . combine ;
buildToolchain = mkToolchain ( with toolchain ; [
cargo
rustc
] ) ;
devToolchain = mkToolchain ( with toolchain ; [
cargo
clippy
rust-src
rustc
# Always use nightly rustfmt because most of its options are unstable
fenix . packages . ${ system } . latest . rustfmt
] ) ;
builder = pkgs :
( ( crane . mkLib pkgs ) . overrideToolchain toolchain ) . buildPackage ;
builder =
( ( crane . mkLib pkgs ) . overrideToolchain buildToolchain ) . buildPackage ;
nativeBuildInputs = pkgs : [
# bindgen needs the build platform's libclang. Apparently due to
# "splicing weirdness", pkgs.rustPlatform.bindgenHook on its own doesn't
# quite do the right thing here.
pkgs . buildPackages . rustPlatform . bindgenHook
] ;
nativeBuildInputs = ( with pkgs . rustPlatform ; [
bindgenHook
] ) ;
env = {
env = pkgs : {
ROCKSDB_INCLUDE_DIR = " ${ pkgs . rocksdb } / i n c l u d e " ;
ROCKSDB_LIB_DIR = " ${ pkgs . rocksdb } / l i b " ;
} ;
in
{
packages . default = builder {
}
// pkgs . lib . optionalAttrs pkgs . stdenv . hostPlatform . isStatic {
ROCKSDB_STATIC = " " ;
}
// {
CARGO_BUILD_RUSTFLAGS = let inherit ( pkgs ) lib stdenv ; in
lib . concatStringsSep " " ( [ ]
++ lib . optionals
# This disables PIE for static builds, which isn't great in terms
# of security. Unfortunately, my hand is forced because nixpkgs'
# `libstdc++.a` is built without `-fPIE`, which precludes us from
# leaving PIE enabled.
stdenv . hostPlatform . isStatic
[ " - C " " r e l o c a t i o n - m o d e l = s t a t i c " ]
++ lib . optionals
( stdenv . buildPlatform . config != pkgs . stdenv . hostPlatform . config )
[ " - l " " c " ]
++ lib . optionals
# This check has to match the one [here][0]. We only need to set
# these flags when using a different linker. Don't ask me why,
# though, because I don't know. All I know is it breaks otherwise.
#
# [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L36-L39
(
pkgs . stdenv . hostPlatform . isAarch64
&& pkgs . stdenv . hostPlatform . isStatic
&& ! pkgs . stdenv . isDarwin
&& ! pkgs . stdenv . cc . bintools . isLLVM
)
[
" - l "
" s t d c + + "
" - L "
" ${ stdenv . cc . cc . lib } / ${ stdenv . hostPlatform . config } / l i b "
]
) ;
}
# What follows is stolen from [here][0]. Its purpose is to properly
# configure compilers and linkers for various stages of the build, and
# even covers the case of build scripts that need native code compiled and
# run on the build platform (I think).
#
# [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L64-L78
// (
let
inherit ( pkgs . rust . lib ) envVars ;
in
pkgs . lib . optionalAttrs
( pkgs . stdenv . targetPlatform . rust . rustcTarget
!= pkgs . stdenv . hostPlatform . rust . rustcTarget )
(
let
inherit ( pkgs . stdenv . targetPlatform . rust ) cargoEnvVarTarget ;
in
{
" C C _ ${ cargoEnvVarTarget } " = envVars . ccForTarget ;
" C X X _ ${ cargoEnvVarTarget } " = envVars . cxxForTarget ;
" C A R G O _ T A R G E T _ ${ cargoEnvVarTarget } _ L I N K E R " =
envVars . linkerForTarget ;
}
)
// (
let
inherit ( pkgs . stdenv . hostPlatform . rust ) cargoEnvVarTarget rustcTarget ;
in
{
" C C _ ${ cargoEnvVarTarget } " = envVars . ccForHost ;
" C X X _ ${ cargoEnvVarTarget } " = envVars . cxxForHost ;
" C A R G O _ T A R G E T _ ${ cargoEnvVarTarget } _ L I N K E R " = envVars . linkerForHost ;
CARGO_BUILD_TARGET = rustcTarget ;
}
)
// (
let
inherit ( pkgs . stdenv . buildPlatform . rust ) cargoEnvVarTarget ;
in
{
" C C _ ${ cargoEnvVarTarget } " = envVars . ccForBuild ;
" C X X _ ${ cargoEnvVarTarget } " = envVars . cxxForBuild ;
" C A R G O _ T A R G E T _ ${ cargoEnvVarTarget } _ L I N K E R " = envVars . linkerForBuild ;
HOST_CC = " ${ pkgs . buildPackages . stdenv . cc } / b i n / c c " ;
HOST_CXX = " ${ pkgs . buildPackages . stdenv . cc } / b i n / c + + " ;
}
) ) ;
package = pkgs : builder pkgs {
src = nix-filter {
root = ./. ;
include = [
@ -87,46 +154,79 @@
# This is redundant with CI
doCheck = false ;
inherit
env
nativeBuildInputs
stdenv ;
env = env pkgs ;
nativeBuildInputs = nativeBuildInputs pkgs ;
meta . mainProgram = cargoToml . package . name ;
} ;
packages . oci-image =
let
package = self . packages . ${ system } . default ;
in
pkgs . dockerTools . buildImage {
name = package . pname ;
tag = " l a t e s t " ;
config = {
# Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) are
# handled as expected
Entrypoint = [
" ${ pkgs . lib . getExe' pkgs . tini " t i n i " } "
" - - "
] ;
Cmd = [
" ${ pkgs . lib . getExe package } "
] ;
mkOciImage = pkgs : package :
pkgs . dockerTools . buildImage {
name = package . pname ;
tag = " l a t e s t " ;
config = {
# Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT)
# are handled as expected
Entrypoint = [
" ${ pkgs . lib . getExe' pkgs . tini " t i n i " } "
" - - "
] ;
Cmd = [
" ${ pkgs . lib . getExe package } "
] ;
} ;
} ;
} ;
devShells . default = ( pkgs . mkShell . override { inherit stdenv ; } ) {
env = env // {
in
{
packages = {
default = package pkgsHost ;
oci-image = mkOciImage pkgsHost self . packages . ${ system } . default ;
# Build an OCI image from the musl aarch64 build so we don't have to
# build for aarch64 twice (to make a gnu version specifically for the
# OCI image)
oci-image-aarch64-unknown-linux-musl = mkOciImage
pkgsHost
self . packages . ${ system } . static-aarch64-unknown-linux-musl ;
# Don't build a musl x86_64 OCI image because that would be pointless.
# Just use the gnu one (i.e. `self.packages."x86_64-linux".oci-image`).
} // builtins . listToAttrs (
builtins . map
( crossSystem : {
name = " s t a t i c - ${ crossSystem } " ;
value = package ( import nixpkgs {
inherit system ;
crossSystem = {
config = crossSystem ;
} ;
} ) . pkgsStatic ;
} )
[
" x 8 6 _ 6 4 - u n k n o w n - l i n u x - m u s l "
" a a r c h 6 4 - u n k n o w n - l i n u x - m u s l "
]
) ;
devShells . default = pkgsHost . mkShell {
env = env pkgsHost // {
# Rust Analyzer needs to be able to find the path to default crate
# sources, and it can read this environment variable to do so. The
# `rust-src` component is required in order for this to work.
RUST_SRC_PATH = " ${ devToolchain } / l i b / r u s t l i b / s r c / r u s t / l i b r a r y " ;
RUST_SRC_PATH = " ${ t oolchain} / l i b / r u s t l i b / s r c / r u s t / l i b r a r y " ;
} ;
# Development tools
nativeBuildInputs = nativeBuildInputs ++ [
devToolchain
] ++ ( with pkgs ; [
nativeBuildInputs = nativeBuildInputs pkgsHost ++ [
# Always use nightly rustfmt because most of its options are unstable
#
# This needs to come before `toolchain` in this list, otherwise
# `$PATH` will have stable rustfmt instead.
fenix . packages . ${ system } . latest . rustfmt
toolchain
] ++ ( with pkgsHost ; [
engage
] ) ;
} ;