diff --git a/Cargo.lock b/Cargo.lock index f7deee5..121e01f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -536,7 +536,7 @@ dependencies = [ [[package]] name = "servicepoint_binding_c" -version = "0.14.1" +version = "0.15.0" dependencies = [ "cbindgen", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 5e29900..f6bd53b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "servicepoint_binding_c" -version = "0.14.1" +version = "0.15.0" publish = true edition = "2021" license = "GPL-3.0-or-later" diff --git a/build.rs b/build.rs index 615d00f..397341d 100644 --- a/build.rs +++ b/build.rs @@ -35,7 +35,7 @@ fn main() { if let Ok(header_out) = env::var("SERVICEPOINT_HEADER_OUT") { let header_copy = header_out + "/servicepoint.h"; - if fs::exists(&header_copy).ok().unwrap_or(false) { + if fs::exists(&header_copy).unwrap_or(false) { // check if content changed to prevent rebuild of dependents if not let mut bindings_text = Vec::new(); diff --git a/devShells.nix b/devShells.nix new file mode 100644 index 0000000..498b51b --- /dev/null +++ b/devShells.nix @@ -0,0 +1,59 @@ +{ + pkgs, + fenix, + selfPkgs, + ... +}: +let + defaultAdditionalPkgs = with pkgs; [ + rustfmt + clippy + cargo-expand + cargo-tarpaulin + gdb + ]; +in +(builtins.mapAttrs ( + packageName: package: + pkgs.mkShell { + inputsFrom = [ package ]; + packages = defaultAdditionalPkgs; + RUST_BACKTRACE = 1; + RUST_LOG = "all"; + } +) selfPkgs) +// { + default = pkgs.mkShell { + inputsFrom = [ + selfPkgs.servicepoint-binding-c + selfPkgs.announce + ]; + packages = + defaultAdditionalPkgs + ++ (with pkgs; [ + (pkgs.symlinkJoin { + name = "rust-toolchain"; + paths = with pkgs; [ + rustc + cargo + rustPlatform.rustcSrc + rustPlatform.rustLibSrc + rustfmt + clippy + cargo-expand + cargo-tarpaulin + ]; + }) + gcc + gnumake + xe + libgcc + libunwind + pkgsStatic.gcc + pkgsStatic.libgcc + pkgsStatic.musl + ]); + + RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}"; + }; +} diff --git a/example/Makefile b/example/Makefile index 1e615c7..1617552 100644 --- a/example/Makefile +++ b/example/Makefile @@ -38,8 +38,6 @@ CARGO_OBJDIR := cargo/$(RUST_TARGET)/$(_profile) _rust_cli_profile := $(if $(filter $(_profile),debug),dev,$(_profile)) -# TODO: `make LINK=static` fails with linker error "undefined reference to `_dl_find_object'" in libgcc_eh.a - STRIPFLAGS += -s --strip-unneeded -R .comment -R .gnu.version -R .note -R .note.gnu.build-id -R .note.ABI-tag STATIC_LINK_LIBS += -lservicepoint_binding_c @@ -80,6 +78,11 @@ CFLAGS += $($(_libc)_CFLAGS) $($(_profile)_CFLAGS) $($(_link_type)_CFLAGS) $(_se ifeq ($(LTO), 1) CFLAGS += -flto endif +ifeq ($(_libc),gnu) + ifeq ($(_link_type),static) + CFLAGS += $(error "statically linking glibc is known to be broken") + endif +endif size_optimized_RUSTFLAGS += -Zlocation-detail=none \ -Zfmt-debug=none \ diff --git a/flake.lock b/flake.lock index 9091d9f..873e7c3 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,41 @@ { "nodes": { + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1748759782, + "narHash": "sha256-MJNhEBsAbxRp/53qsXv6/eaWkGS8zMGX9LuCz1BLeck=", + "owner": "nix-community", + "repo": "fenix", + "rev": "9be40ad995bac282160ff374a47eed67c74f9c2a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "nix-filter": { + "locked": { + "lastModified": 1731533336, + "narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "f7653272fd234696ae94229839a99b73c9ab7de0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1748302896, @@ -18,8 +54,27 @@ }, "root": { "inputs": { + "fenix": "fenix", + "nix-filter": "nix-filter", "nixpkgs": "nixpkgs" } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1748695646, + "narHash": "sha256-VwSuuRF4NvAoeHZJRRlX8zAFZ+nZyuiIvmVqBAX0Bcg=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "2a388d1103450d814a84eda98efe89c01b158343", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 2adaa88..1501caa 100644 --- a/flake.nix +++ b/flake.nix @@ -3,15 +3,21 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + nix-filter.url = "github:numtide/nix-filter"; + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = inputs@{ self, nixpkgs, + fenix, + nix-filter }: let - lib = nixpkgs.lib; supported-systems = [ "x86_64-linux" "aarch64-linux" @@ -20,56 +26,20 @@ ]; forAllSystems = f: - lib.genAttrs supported-systems ( + nixpkgs.lib.genAttrs supported-systems ( system: f rec { + inherit system self; pkgs = nixpkgs.legacyPackages.${system}; - inherit system; + lib = pkgs.lib // nix-filter.lib; + fenix = inputs.fenix.packages.${system}; + selfPkgs = self.packages.${system}; } ); in { - devShells = forAllSystems ( - { pkgs, system }: - let - toolchain = pkgs.symlinkJoin { - name = "rust-toolchain"; - paths = with pkgs; [ - rustc - cargo - rustPlatform.rustcSrc - rustPlatform.rustLibSrc - rustfmt - clippy - cargo-expand - cargo-tarpaulin - ]; - }; - in - { - default = pkgs.mkShell rec { - packages = with pkgs; [ - toolchain - gcc - gdb - gnumake - pkg-config - xe - xz - libgcc - libunwind - pkgsStatic.gcc - pkgsStatic.libgcc - pkgsStatic.musl - ]; - - RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}"; - RUST_BACKTRACE = 1; - RUST_LOG = "all"; - }; - } - ); - + packages = forAllSystems (import ./packages.nix); + devShells = forAllSystems (import ./devShells.nix); formatter = forAllSystems ({ pkgs, ... }: pkgs.nixfmt-rfc-style); }; } diff --git a/packages.nix b/packages.nix new file mode 100644 index 0000000..1716250 --- /dev/null +++ b/packages.nix @@ -0,0 +1,107 @@ +{ + pkgs, + lib, + fenix, + selfPkgs, + ... +}: +let + version = "0.15.0"; + mkServicepoint = + { + rustPlatform, + buildType, + }: + rustPlatform.buildRustPackage (finalAttrs: { + inherit buildType version; + + pname = "servicepoint-binding-c"; + src = lib.filter { + root = ./.; + include = [ + ./Cargo.lock + ./Cargo.toml + ./src + ./build.rs + ./LICENSE + ./cbindgen.toml + ]; + }; + cargoLock.lockFile = ./Cargo.lock; + 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 = with pkgs; [ pkg-config ]; + buildInputs = with 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.stdenv.mkDerivation { + inherit version; + pname = "servicepoint-c-example-${name}"; + + nativeBuildInputs = with pkgs; [ pkg-config ]; + buildInputs = [ servicepointBinding ]; + src = ./example/src; + + #dontUnpack = true; + buildPhase = '' + mkdir -p $out/bin + + gcc ${name}.c $(pkg-config --libs servicepoint --cflags) -o $out/bin/${name} + ''; + }; + rustPlatform-stable = pkgs.rustPlatform; + rustPlatform-unstable = pkgs.makeRustPlatform { + cargo = fenix.minimal.cargo; + rustc = fenix.minimal.rustc; + }; + examples = [ + "announce" + "brightness_tester" + "header_logger" + "moving_line" + "random_stuff" + "wiping_clear" + ]; +in +rec { + servicepoint-binding-c-release = mkServicepoint { + buildType = "release"; + rustPlatform = rustPlatform-stable; + }; + servicepoint-binding-c-size-optimized = mkServicepoint { + buildType = "size_optimized"; + rustPlatform = rustPlatform-unstable; + }; + servicepoint-binding-c = servicepoint-binding-c-release; + + all-examples = pkgs.symlinkJoin { + name = "servicepoint-all-examples"; + paths = builtins.map (e: selfPkgs.${e}) examples; + }; +} +// (lib.genAttrs examples ( + name: + mkExample { + inherit name; + servicepointBinding = selfPkgs.servicepoint-binding-c; + } +)) diff --git a/servicepoint.pc.in b/servicepoint.pc.in new file mode 100644 index 0000000..5f474e7 --- /dev/null +++ b/servicepoint.pc.in @@ -0,0 +1,6 @@ +Name: servicepoint +Description: C bindings for the servicepoint library +Version: $version +URL: https://git.berlin.ccc.de/servicepoint/servicepoint-binding-c +Libs: -L$out/lib -lservicepoint_binding_c +Cflags: -I$out/include