{ pkgs, lib, fenix, selfPkgs, ... }: let version = "0.15.0"; mkServicepoint = { rustPlatform, pkgs, buildType ? "release", buildNoDefaultFeatures ? false, cargoBuildFlags ? [ ], nativeBuildInputs ? [] }: rustPlatform.buildRustPackage (finalAttrs: { inherit version buildType cargoBuildFlags; pname = "servicepoint-binding-c"; src = lib.filter { root = ./.; include = [ ./Cargo.lock ./Cargo.toml ./src ./build.rs ./LICENSE ./cbindgen.toml ]; }; cargoLock.lockFile = ./Cargo.lock; useFetchCargoVendor = true; meta = { description = "C bindings for the servicepoint crate."; homepage = "https://git.berlin.ccc.de/servicepoint/servicepoint-binding-c"; license = lib.licenses.gpl3Plus; pkgConfigModules = [ "servicepoint" ]; }; nativeBuildInputs = [ pkgs.pkg-config ] ++ nativeBuildInputs; buildInputs = [ pkgs.xz ]; preBuild = '' mkdir -p include export SERVICEPOINT_HEADER_OUT=$(realpath "include") echo "Rust version: $(rustc --version)" echo "preBuild hook: set SERVICEPOINT_HEADER_OUT to $SERVICEPOINT_HEADER_OUT" ''; postInstall = '' cp -r include $out mkdir -p $out/lib/pkgconfig sed "s:\$out:$out:g" ${./servicepoint.pc.in} | sed "s:\$version:$version:g" > $out/lib/pkgconfig/servicepoint.pc ''; }); mkExample = { name, servicepointBinding, pkgs, EXTRA_CFLAGS ? "", static ? false, }: let staticPkgConfigParam = if static then "--static" else ""; in pkgs.gccStdenv.mkDerivation { inherit version EXTRA_CFLAGS; pname = "servicepoint-c-example-${name}"; nativeBuildInputs = [ pkgs.pkg-config ]; buildInputs = [ servicepointBinding pkgs.xz ]; src = ./example/src; buildPhase = '' set -e set -x mkdir -p $out/bin $CC ${name}.c ${if static then "-static" else ""} $CFLAGS $EXTRA_CFLAGS \ $(pkg-config --libs --cflags ${staticPkgConfigParam} servicepoint) \ $(pkg-config --libs --cflags ${staticPkgConfigParam} liblzma) \ -o $out/bin/${name} ''; }; examples = [ "announce" "brightness_tester" "header_logger" "moving_line" "random_stuff" "wiping_clear" ]; mkAllExamples = suffix: pkgs.symlinkJoin { name = "servicepoint-all-examples"; paths = builtins.map (e: selfPkgs."${e}${suffix}") examples; }; size-cflags = [ "-Oz" "-fwrapv" "-fomit-frame-pointer" "-fno-stack-protector" "-fno-unroll-loops" "-fno-unwind-tables" "-fno-asynchronous-unwind-tables" "-fmerge-all-constants" "-fvisibility=hidden" "-Bsymbolic" "-fno-ident" "-fno-exceptions" "-ffunction-sections" "-fdata-sections" "-Wl,-z,norelro" "-Wl,--hash-style=gnu" "-Wl,--gc-sections" "-Wl,--exclude-libs,ALL" ]; rustPlatform-stable = pkgs.rustPlatform; rustPlatform-nightly = pkgs.makeRustPlatform fenix.complete; rustPlatform-musl-stable = pkgs.pkgsMusl.rustPlatform; rustPlatform-musl-nightly = pkgs.pkgsMusl.makeRustPlatform fenix.complete; stable-release-args = { inherit pkgs; rustPlatform = rustPlatform-stable; }; nightly-release-args = { inherit pkgs; rustPlatform = rustPlatform-nightly; }; musl-stable-release-args = { pkgs = pkgs.pkgsMusl; rustPlatform = rustPlatform-musl-stable; }; musl-nightly-release-args = { pkgs = pkgs.pkgsMusl; rustPlatform = rustPlatform-musl-nightly; }; stable-size-args = { buildType = "size_optimized"; buildNoDefaultFeatures = true; }; nightly-size-args = { cargoBuildFlags = [ "-Zbuild-std=core,std,alloc,proc_macro,panic_abort" "-Zbuild-std-features=panic_immediate_abort" ]; # TODO: remove hard-coded target nativeBuildInputs = [fenix.targets."x86_64-unknown-linux-gnu".latest.rust-std]; # TODO: those override the nix flags # NIX_CFLAGS_COMPILE = builtins.toString ["-Oz" "-fwrapv" "-fomit-frame-pointer" "-fno-stack-protector" "-fno-unroll-loops" "-fno-unwind-tables" "-fno-asynchronous-unwind-tables" "-fmerge-all-constants" "-fvisibility=hidden" "-Bsymbolic" "-fno-ident" "-fno-exceptions" "-ffunction-sections" "-fdata-sections"]; # NIX_CFLAGS_LINK = builtins.toString ["Wl,-z,norelro" "-Wl,--hash-style=gnu" "-Wl,--gc-sections" "-Wl,--exclude-libs,ALL"]; }; in rec { servicepoint-binding-c-stable-release = mkServicepoint stable-release-args; servicepoint-binding-c-nightly-release = mkServicepoint nightly-release-args; servicepoint-binding-c-musl-stable-release = mkServicepoint musl-stable-release-args; servicepoint-binding-c-musl-nightly-release = mkServicepoint musl-nightly-release-args; servicepoint-binding-c-stable-size = mkServicepoint (stable-release-args // stable-size-args); servicepoint-binding-c-nightly-size = mkServicepoint ( nightly-release-args // stable-size-args // nightly-size-args ); servicepoint-binding-c-musl-stable-size = mkServicepoint ( musl-stable-release-args // stable-size-args ); servicepoint-binding-c-musl-nightly-size = mkServicepoint ( musl-nightly-release-args // stable-size-args // nightly-size-args ); # default variants servicepoint-binding-c = servicepoint-binding-c-stable-release; servicepoint-binding-c-musl = servicepoint-binding-c-musl-stable-release; all-examples = mkAllExamples ""; all-examples-size = mkAllExamples "-size"; all-examples-nightly-size = mkAllExamples "-nightly-size"; # TODO: musl targets do not work on darwin all-examples-musl = mkAllExamples "-musl"; all-examples-musl-static = mkAllExamples "-musl-static"; all-examples-musl-static-size = mkAllExamples "-musl-static-size"; } # construct one package per example // (lib.genAttrs examples ( name: mkExample { inherit name pkgs; servicepointBinding = selfPkgs.servicepoint-binding-c; } )) # construct another pakage per example, but optimized for size with stable rust // (lib.mapAttrs' (name: value: lib.nameValuePair ("${name}-size") value) ( lib.genAttrs examples ( name: mkExample { inherit name pkgs; servicepointBinding = selfPkgs.servicepoint-binding-c-stable-size; EXTRA_CFLAGS = builtins.toString size-cflags; } ) )) # construct another pakage per example, but optimized for size with unstable rust // (lib.mapAttrs' (name: value: lib.nameValuePair ("${name}-unstable-size") value) ( lib.genAttrs examples ( name: mkExample { inherit name pkgs; servicepointBinding = selfPkgs.servicepoint-binding-c-nightly-size; EXTRA_CFLAGS = builtins.toString size-cflags; } ) )) # construct another pakage per example, but with musl // (lib.mapAttrs' (name: value: lib.nameValuePair ("${name}-musl") value) ( lib.genAttrs examples ( name: mkExample { inherit name; pkgs = pkgs.pkgsMusl; servicepointBinding = selfPkgs.servicepoint-binding-c-musl-stable-release; } ) )) # construct another pakage per example, but statically linked with musl // (lib.mapAttrs' (name: value: lib.nameValuePair ("${name}-musl-static") value) ( lib.genAttrs examples ( name: mkExample { inherit name; pkgs = pkgs.pkgsMusl; servicepointBinding = selfPkgs.servicepoint-binding-c-musl-stable-release; static = true; } ) )) # construct another pakage per example, but statically linked with musl and size optimized // (lib.mapAttrs' (name: value: lib.nameValuePair ("${name}-musl-static-size") value) ( lib.genAttrs examples ( name: mkExample { inherit name; pkgs = pkgs.pkgsMusl; servicepointBinding = selfPkgs.servicepoint-binding-c-musl-stable-size; static = true; EXTRA_CFLAGS = builtins.toString size-cflags; } ) ))