1
1
{ sources ? import ./nix/sources.nix # managed by https://github.com/nmattia/niv
2
2
, 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
+ } ;
39
82
} ;
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
+ } ) ;
41
101
}
42
- , meta ? pkgs . lib . importJSON ./nix/meta.json
102
+ , meta ? pkgsLocal . lib . importJSON ./nix/meta.json
43
103
, dockerName ? "oci.stackable.tech/sandbox/${ meta . operator . name } "
44
104
, 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
45
123
} :
46
124
rec {
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 ;
48
128
build = cargo . allWorkspaceMembers ;
49
129
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" { }
51
132
''
52
133
${ entrypoint } crd > $out
53
134
'' ;
54
135
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 {
56
141
name = dockerName ;
57
142
tag = dockerTag ;
58
143
contents = [
59
- # Common debugging tools
60
- pkgs . bashInteractive pkgs . coreutils pkgs . util-linuxMinimal
61
144
# Kerberos 5 must be installed globally to load plugins correctly
62
- pkgs . krb5
145
+ pkgsTarget . krb5
63
146
# Make the whole cargo workspace available on $PATH
64
147
build
148
+ ] ++ lib . optional includeShell [
149
+ pkgsTarget . bashInteractive
150
+ pkgsTarget . coreutils
151
+ pkgsTarget . util-linuxMinimal
65
152
] ;
66
153
config = {
67
154
Env =
68
155
let
69
156
fileRefVars = {
70
157
PRODUCT_CONFIG = deploy/config-spec/properties.yaml ;
71
158
} ;
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 ) ;
73
160
Entrypoint = [ entrypoint ] ;
74
161
Cmd = [ "run" ] ;
75
162
} ;
76
163
} ;
77
- docker = pkgs . linkFarm "listener-operator -docker" [
164
+ docker = pkgsLocal . linkFarm "${ dockerImage . name } -docker" [
78
165
{
79
166
name = "load-image" ;
80
167
path = dockerImage ;
81
168
}
82
169
{
83
170
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 } " ;
85
172
}
86
173
{
87
174
name = "image-repo" ;
88
- path = pkgs . writeText "${ dockerImage . name } -repo" dockerImage . imageName ;
175
+ path = pkgsLocal . writeText "${ dockerImage . name } -repo" dockerImage . imageName ;
89
176
}
90
177
{
91
178
name = "image-tag" ;
92
- path = pkgs . writeText "${ dockerImage . name } -tag" dockerImage . imageTag ;
179
+ path = pkgsLocal . writeText "${ dockerImage . name } -tag" dockerImage . imageTag ;
93
180
}
94
181
{
95
182
name = "crds.yaml" ;
@@ -98,10 +185,10 @@ rec {
98
185
] ;
99
186
100
187
# 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 ;
103
190
104
- regenerateNixLockfiles = pkgs . writeScriptBin "regenerate-nix-lockfiles"
191
+ regenerateNixLockfiles = pkgsLocal . writeScriptBin "regenerate-nix-lockfiles"
105
192
''
106
193
#!/usr/bin/env bash
107
194
set -euo pipefail
@@ -114,10 +201,6 @@ rec {
114
201
# (see https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#trailing-whitespace).
115
202
# So, remove the trailing newline already here to avoid that an
116
203
# 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
122
205
'' ;
123
206
}
0 commit comments