11{ sources ? import ./nix/sources.nix # managed by https://github.com/nmattia/niv
22, nixpkgs ? sources . nixpkgs
3- , pkgs ? import nixpkgs { }
4- , cargo ? import ./Cargo.nix {
5- inherit nixpkgs pkgs ; release = false ;
6- defaultCrateOverrides = pkgs . defaultCrateOverrides // {
7- prost-build = attrs : {
8- buildInputs = [ pkgs . protobuf ] ;
9- } ;
10- tonic-reflection = attrs : {
11- buildInputs = [ pkgs . rustfmt ] ;
12- } ;
13- csi-grpc = attrs : {
14- nativeBuildInputs = [ pkgs . protobuf ] ;
15- } ;
16- stackable-secret-operator = attrs : {
17- buildInputs = [ pkgs . protobuf pkgs . rustfmt ] ;
18- } ;
19- stackable-opa-user-info-fetcher = attrs : {
20- # TODO: why is this not pulled in via libgssapi-sys?
21- buildInputs = [ pkgs . krb5 ] ;
22- } ;
23- krb5-sys = attrs : {
24- nativeBuildInputs = [ pkgs . pkg-config ] ;
25- buildInputs = [ pkgs . krb5 ] ;
26- LIBCLANG_PATH = "${ pkgs . libclang . lib } /lib" ;
27- # Clang's resource directory is located at ${pkgs.clang.cc.lib}/lib/clang/<version>.
28- # Starting with Clang 16, only the major version is used for the resource directory,
29- # whereas the full version was used in prior Clang versions (see
30- # https://github.com/llvm/llvm-project/commit/e1b88c8a09be25b86b13f98755a9bd744b4dbf14).
31- # The clang wrapper ${pkgs.clang} provides a symlink to the resource directory, which
32- # we use instead.
33- BINDGEN_EXTRA_CLANG_ARGS = "-I${ pkgs . glibc . dev } /include -I${ pkgs . clang } /resource-root/include" ;
34- } ;
35- libgssapi-sys = attrs : {
36- buildInputs = [ pkgs . krb5 ] ;
37- LIBCLANG_PATH = "${ pkgs . libclang . lib } /lib" ;
38- BINDGEN_EXTRA_CLANG_ARGS = "-I${ pkgs . glibc . dev } /include -I${ pkgs . clang } /resource-root/include" ;
3+ , overlays ? [ ( self : super : {
4+ # fakeroot (used for building the Docker image) seems to freeze or crash
5+ # on Darwin (macOS), but doesn't seem to actually be necessary beyond
6+ # production hardening.
7+ fakeroot =
8+ if self . buildPlatform . isDarwin then
9+ self . writeScriptBin "fakeroot" ''exec "$@"''
10+ else
11+ super . fakeroot ;
12+ } ) ]
13+ # When cross-/remote-building, some binaries still need to run on the local machine instead
14+ # (non-Nix build tools like Tilt, as well as the container composition scripts)
15+ , pkgsLocal ? import nixpkgs { inherit overlays ; }
16+ # Default to building for the local CPU architecture
17+ , targetArch ? pkgsLocal . hostPlatform . linuxArch
18+ , targetSystem ? "${ targetArch } -unknown-linux-gnu"
19+ , pkgsTarget ? import nixpkgs {
20+ inherit overlays ;
21+
22+ # Build our containers for Linux for the local CPU architecture
23+ # A remote Linux builder can be set up using https://github.com/stackabletech/nix-docker-builder
24+ system = targetSystem ;
25+
26+ # Currently using remote builders rather than cross-compilation,
27+ # because the latter requires us to recompile the world several times
28+ # just to get the full cross-toolchain up and running.
29+ # (Or I (@nightkr) am just dumb and missing something obvious.)
30+ # If uncommenting this, make sure to comment the `system =` clause above.
31+ #crossSystem = { config = targetSystem; };
32+ }
33+ , cargo ? import ./Cargo.nix rec {
34+ inherit nixpkgs ;
35+ pkgs = pkgsTarget ;
36+ # We're only using this for dev builds at the moment,
37+ # so don't pay for release optimization.
38+ release = false ;
39+
40+ buildRustCrateForPkgs = pkgs : attrs : pkgs . buildRustCrate . override {
41+ # Consider migrating to mold for faster linking, but in my (@nightkr's)
42+ # quick testing so far it actually seems to perform slightly worse than
43+ # the default one.
44+ # stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.stdenv;
45+
46+ defaultCrateOverrides = pkgs . defaultCrateOverrides // {
47+ # Attributes applied here apply to a single crate
48+
49+ prost-build = attrs : {
50+ buildInputs = [ pkgs . protobuf ] ;
51+ } ;
52+ tonic-reflection = attrs : {
53+ buildInputs = [ pkgs . rustfmt ] ;
54+ } ;
55+ csi-grpc = attrs : {
56+ nativeBuildInputs = [ pkgs . protobuf ] ;
57+ } ;
58+ stackable-secret-operator = attrs : {
59+ buildInputs = [ pkgs . protobuf pkgs . rustfmt ] ;
60+ } ;
61+ stackable-opa-user-info-fetcher = attrs : {
62+ # TODO: why is this not pulled in via libgssapi-sys?
63+ buildInputs = [ pkgs . krb5 ] ;
64+ } ;
65+ krb5-sys = attrs : {
66+ nativeBuildInputs = [ pkgs . pkg-config ] ;
67+ buildInputs = [ pkgs . krb5 ] ;
68+ LIBCLANG_PATH = "${ pkgs . libclang . lib } /lib" ;
69+ # Clang's resource directory is located at ${pkgs.clang.cc.lib}/lib/clang/<version>.
70+ # Starting with Clang 16, only the major version is used for the resource directory,
71+ # whereas the full version was used in prior Clang versions (see
72+ # https://github.com/llvm/llvm-project/commit/e1b88c8a09be25b86b13f98755a9bd744b4dbf14).
73+ # The clang wrapper ${pkgs.clang} provides a symlink to the resource directory, which
74+ # we use instead.
75+ BINDGEN_EXTRA_CLANG_ARGS = "-I${ pkgs . glibc . dev } /include -I${ pkgs . clang } /resource-root/include" ;
76+ } ;
77+ libgssapi-sys = attrs : {
78+ buildInputs = [ pkgs . krb5 ] ;
79+ LIBCLANG_PATH = "${ pkgs . libclang . lib } /lib" ;
80+ BINDGEN_EXTRA_CLANG_ARGS = "-I${ pkgs . glibc . dev } /include -I${ pkgs . clang } /resource-root/include" ;
81+ } ;
3982 } ;
40- } ;
83+ } ( attrs // {
84+ # Attributes applied here apply to all built crates
85+ # Note that these *take precedence over* per-crate overrides
86+
87+ dontStrip = ! strip ;
88+
89+ extraRustcOpts = [
90+ "-C debuginfo=${ toString debuginfo } "
91+ # Enabling optimization shrinks the binaries further, but also *vastly*
92+ # increases the build time.
93+ # "-C opt-level=3"
94+ ] ++ attrs . extraRustcOpts ;
95+
96+ # Parallel codegen allows Rustc to use more cores.
97+ # This should help speed up compiling "bottleneck" crates that Nix can't
98+ # parallelize (like the operator binary itself).
99+ codegenUnits = 32 ;
100+ } ) ;
41101 }
42- , meta ? pkgs . lib . importJSON ./nix/meta.json
102+ , meta ? pkgsLocal . lib . importJSON ./nix/meta.json
43103, dockerName ? "oci.stackable.tech/sandbox/${ meta . operator . name } "
44104, dockerTag ? null
105+ # Controls the amount of debug information included in the built operator binaries,
106+ # see https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo
107+ # For comparison, `cargo build --release` defaults to 0, and the debug profile
108+ # (no `--release`) defaults to 2.
109+ # see https://doc.rust-lang.org/cargo/reference/profiles.html#debug
110+ # Set to 2 if you want to run a debugger, but note that it bloats the Docker
111+ # images *significantly* (hundreds of megabytes).
112+ , debuginfo ? 0
113+ # Strip operator binaries if we don't include debuginfo, because *something*
114+ # still something still includes a reference to gcc (~230MiB), causing it to be
115+ # added to the docker images.
116+ , strip ? if debuginfo == 0 then true else false
117+ # We normally don't include a shell in the (dev) operator images, but it can be
118+ # enabled by enabling this flag.
119+ # TODO(@nightkr): Re-enabled for now, since some operators ship with bash init
120+ # scripts (like secret-operator's CSI path migration job). Consider either
121+ # removing them or integrating them into the main operator binary instead.
122+ , includeShell ? true
45123} :
46124rec {
47- inherit cargo sources pkgs meta ;
125+ inherit cargo sources pkgsLocal pkgsTarget meta ;
126+ inherit ( pkgsLocal ) lib ;
127+ pkgs = lib . warn "pkgs is not cross-compilation-aware, explicitly use either pkgsLocal or pkgsTarget" pkgsLocal ;
48128 build = cargo . allWorkspaceMembers ;
49129 entrypoint = build + "/bin/stackable-${ meta . operator . name } " ;
50- crds = pkgs . runCommand "${ meta . operator . name } -crds.yaml" { }
130+ # Run crds in the target environment, to avoid compiling everything twice
131+ crds = pkgsTarget . runCommand "${ meta . operator . name } -crds.yaml" { }
51132 ''
52133 ${ entrypoint } crd > $out
53134 '' ;
54135
55- dockerImage = pkgs . dockerTools . streamLayeredImage {
136+ # We're building the docker image *for* Linux, but we need to
137+ # build it in the local environment so that the generated load-image
138+ # can run locally.
139+ # That's still fine, as long as we only refer to pkgsTarget *inside* of the image.
140+ dockerImage = pkgsLocal . dockerTools . streamLayeredImage {
56141 name = dockerName ;
57142 tag = dockerTag ;
58143 contents = [
59- # Common debugging tools
60- pkgs . bashInteractive pkgs . coreutils pkgs . util-linuxMinimal
61144 # Kerberos 5 must be installed globally to load plugins correctly
62- pkgs . krb5
145+ pkgsTarget . krb5
63146 # Make the whole cargo workspace available on $PATH
64147 build
148+ ] ++ lib . optional includeShell [
149+ pkgsTarget . bashInteractive
150+ pkgsTarget . coreutils
151+ pkgsTarget . util-linuxMinimal
65152 ] ;
66153 config = {
67154 Env =
68155 let
69156 fileRefVars = {
70157 PRODUCT_CONFIG = deploy/config-spec/properties.yaml ;
71158 } ;
72- in pkgs . lib . concatLists ( pkgs . lib . mapAttrsToList ( env : path : pkgs . lib . optional ( pkgs . lib . pathExists path ) "${ env } =${ path } " ) fileRefVars ) ;
159+ in lib . concatLists ( lib . mapAttrsToList ( env : path : lib . optional ( lib . pathExists path ) "${ env } =${ path } " ) fileRefVars ) ;
73160 Entrypoint = [ entrypoint ] ;
74161 Cmd = [ "run" ] ;
75162 } ;
76163 } ;
77- docker = pkgs . linkFarm "listener-operator -docker" [
164+ docker = pkgsLocal . linkFarm "${ dockerImage . name } -docker" [
78165 {
79166 name = "load-image" ;
80167 path = dockerImage ;
81168 }
82169 {
83170 name = "ref" ;
84- path = pkgs . writeText "${ dockerImage . name } -image-tag" "${ dockerImage . imageName } :${ dockerImage . imageTag } " ;
171+ path = pkgsLocal . writeText "${ dockerImage . name } -image-tag" "${ dockerImage . imageName } :${ dockerImage . imageTag } " ;
85172 }
86173 {
87174 name = "image-repo" ;
88- path = pkgs . writeText "${ dockerImage . name } -repo" dockerImage . imageName ;
175+ path = pkgsLocal . writeText "${ dockerImage . name } -repo" dockerImage . imageName ;
89176 }
90177 {
91178 name = "image-tag" ;
92- path = pkgs . writeText "${ dockerImage . name } -tag" dockerImage . imageTag ;
179+ path = pkgsLocal . writeText "${ dockerImage . name } -tag" dockerImage . imageTag ;
93180 }
94181 {
95182 name = "crds.yaml" ;
@@ -98,10 +185,10 @@ rec {
98185 ] ;
99186
100187 # need to use vendored crate2nix because of https://github.com/kolloch/crate2nix/issues/264
101- crate2nix = import sources . crate2nix { } ;
102- tilt = pkgs . tilt ;
188+ crate2nix = import sources . crate2nix { pkgs = pkgsLocal ; } ;
189+ tilt = pkgsLocal . tilt ;
103190
104- regenerateNixLockfiles = pkgs . writeScriptBin "regenerate-nix-lockfiles"
191+ regenerateNixLockfiles = pkgsLocal . writeScriptBin "regenerate-nix-lockfiles"
105192 ''
106193 #!/usr/bin/env bash
107194 set -euo pipefail
@@ -114,10 +201,6 @@ rec {
114201 # (see https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#trailing-whitespace).
115202 # So, remove the trailing newline already here to avoid that an
116203 # unnecessary change is shown in Git.
117- if [[ "$(uname)" == "Darwin" ]]; then
118- sed -i \"\" '$d' Cargo.nix
119- else
120- sed -i '$d' Cargo.nix
121- fi
204+ ${ pkgsLocal . gnused } /bin/sed -i '$d' Cargo.nix
122205 '' ;
123206}
0 commit comments