diff options
author | Alexandros Liarokapis <liarokapis.v@gmail.com> | 2024-02-13 02:25:13 +0200 |
---|---|---|
committer | Alexandros Liarokapis <liarokapis.v@gmail.com> | 2024-06-26 22:15:27 +0300 |
commit | e36b4564d2860f2d61fbf7631c77ebc324a437e9 (patch) | |
tree | a9f9eff732e3aad7910b8a800d42f174ce70a8c1 /pkgs/by-name/na | |
parent | 4d58d59beb8636911088704d940dd2ca03c013f6 (diff) |
nanopb: 0.4.6 -> 0.4.8
This commit: - Bumps the nanopb version - Adds all runtime configuration options - Implements proper cross-compilation support which is the main use-case of the library. - Uses newer `finalAttrs` form of `mkDerivation` to allow for easier attribute overrides. The cross-compilation support is achieved by splitting the package into two sub-packages consisting of the build-time generator and the runtime library. Nanopb explicitely supports this by providing specialized `GENERATOR` and `RUNTIME` CMake configuration options. The top-level package uses `propagatedNativeBuildInputs` and `propagatedBuildInputs` to propagate the sub-packages and also adds convenient symlinks to make certain use cases easier. == GENERATOR == The generator is a mostly ready-to-be-packaged python module tree. We patch the library to also include the missing `__init__.py` and we also fix the `PYTHON_INSTDIR` variable to follow best practice and to prevent the library from attempting to install to a global directory. We package the python module using `buildPythonPackage` and internally override python in order to wrap the `nanopb_generator.py` executable. We do *not* wrap `nanob_generator.py` due to it also being imported directly from python when used through `protoc-gen-nanopb`. == RUNTIME == The runtime is a simple library that consists of the common functionality among generated headers/sources. It is configured through `preprocessor definitions` and consumer projects *must* be compiled with the same definitions. This is currently achieved by exposing all configuration options through the top-level overrides and patching the CMakeLists.txt so that the definitions are added to the to-be-installed CMake targets as PUBLIC properties.
Diffstat (limited to 'pkgs/by-name/na')
14 files changed, 441 insertions, 0 deletions
diff --git a/pkgs/by-name/na/nanopb/generator-out.nix b/pkgs/by-name/na/nanopb/generator-out.nix new file mode 100644 index 0000000000000..a9e179d902988 --- /dev/null +++ b/pkgs/by-name/na/nanopb/generator-out.nix @@ -0,0 +1,59 @@ +{ stdenv +, cmake +, python3 +, writeTextFile +, protobuf +, src +, version +}: +let + pyproject_toml = writeTextFile { + name = "pyproject.toml"; + text = '' + [build-system] + requires = ["setuptools"] + build-backend = "setuptools.build_meta" + + [tool.setuptools] + include-package-data = true + + [tool.setuptools.packages.find] + where = ["src"] + + [tool.setuptools.package-data] + "*" = ["nanopb.proto"] + + [project] + name = "nanopb" + version = "${version}" + dependencies = [ + "setuptools", + "protobuf", + "six" + ] + ''; + }; +in +stdenv.mkDerivation { + pname = "nanopb-generator-out"; + inherit src version; + + nativeBuildInputs = [ cmake protobuf python3 ]; + + cmakeFlags = [ + "-Dnanopb_BUILD_RUNTIME=OFF" + "-Dnanopb_BUILD_GENERATOR=ON" + "-Dnanopb_PYTHON_INSTDIR_OVERRIDE=$out/lib/python/site-packages" + ]; + + preConfigure = '' + cmakeFlags+=" -Dnanopb_PYTHON_INSTDIR_OVERRIDE=$out/lib/python/site-packages" + ''; + + postInstall = '' + rm -rf $out/include + rm -rf $out/lib/cmake + ln -s $out/lib/python/site-packages $out/src + ln -s ${pyproject_toml} $out/pyproject.toml + ''; +} diff --git a/pkgs/by-name/na/nanopb/generator.nix b/pkgs/by-name/na/nanopb/generator.nix new file mode 100644 index 0000000000000..15d4e0605b80e --- /dev/null +++ b/pkgs/by-name/na/nanopb/generator.nix @@ -0,0 +1,27 @@ +{ python3 +, stdenvNoCC +, protobuf +, version +, generator-out +}: +stdenvNoCC.mkDerivation { + pname = "nanopb-generator"; + inherit version; + + dontUnpack = true; + + nativeBuildInputs = [ python3.pkgs.wrapPython ]; + + propagatedBuildInputs = [ + protobuf + python3.pkgs.nanopb-proto + ]; + + installPhase = '' + mkdir -p $out/bin + cp ${generator-out}/bin/protoc-gen-nanopb $out/bin/ + cp ${generator-out}/bin/nanopb_generator $out/bin/ + wrapPythonPrograms + cp ${generator-out}/bin/nanopb_generator.py $out/bin/ + ''; +} diff --git a/pkgs/by-name/na/nanopb/package.nix b/pkgs/by-name/na/nanopb/package.nix new file mode 100644 index 0000000000000..bd14e9d8c75bb --- /dev/null +++ b/pkgs/by-name/na/nanopb/package.nix @@ -0,0 +1,122 @@ +{ stdenvNoCC +, callPackage +, fetchFromGitHub +, buildPackages +, lib +, enableMalloc ? false +, noPackedStructs ? false +, maxRequiredFields ? null +, field32bit ? false +, noErrmsg ? false +, bufferOnly ? false +, systemHeader ? null +, without64bit ? false +, encodeArraysUnpacked ? false +, convertDoubleFloat ? false +, validateUtf8 ? false +, littleEndian8bit ? false +, c99StaticAssert ? false +, noStaticAssert ? false +}: +stdenvNoCC.mkDerivation (self: +let + generator-out = buildPackages.callPackage ./generator-out.nix { inherit (self) src version; }; + python-module = buildPackages.callPackage ./python-module.nix { + inherit (self) version; + inherit (self.passthru) generator-out; + }; + python3 = buildPackages.python3.override { + packageOverrides = _: _: { + nanopb-proto = self.passthru.python-module; + }; + }; + generator = buildPackages.callPackage ./generator.nix { + inherit python3; + inherit (self) version; + inherit (self.passthru) generator-out; + }; + runtime = callPackage ./runtime.nix { + inherit python3; + inherit (self) src version; + inherit + enableMalloc + noPackedStructs + maxRequiredFields + field32bit + noErrmsg + bufferOnly + systemHeader + without64bit + encodeArraysUnpacked + convertDoubleFloat + validateUtf8 + littleEndian8bit + c99StaticAssert + noStaticAssert; + }; +in +{ + pname = "nanopb"; + version = "0.4.8"; + + src = fetchFromGitHub { + owner = "nanopb"; + repo = "nanopb"; + rev = self.version; + hash = "sha256-LfARVItT+7dczg2u08RlXZLrLR7ScvC44tgmcy/Zv48="; + }; + + dontPatch = true; + dontUnpack = true; + + propagatedNativeBuildInputs = [ generator ]; + + propagatedBuildInputs = [ runtime ]; + + postInstall = '' + mkdir $out + ln -s ${generator}/bin $out/bin + ln -s ${runtime}/include $out/include + ln -s ${runtime}/lib $out/lib + mkdir -p $out/share/nanopb/generator/proto + ln -s ${self.src}/generator/proto/nanopb.proto $out/share/nanopb/generator/proto/nanopb.proto + ''; + + passthru = { + inherit runtime generator-out python-module generator; + tests = { + simple-proto2 = callPackage ./test-simple-proto2 { }; + simple-proto3 = callPackage ./test-simple-proto3 { }; + message-with-annotations = callPackage ./test-message-with-annotations { }; + message-with-options = callPackage ./test-message-with-options { }; + }; + }; + + meta = with lib; { + platforms = platforms.all; + + description = "Protocol Buffers with small code size"; + homepage = "https://jpa.kapsi.fi/nanopb/"; + license = licenses.zlib; + maintainers = with maintainers; [ kalbasit liarokapisv ]; + + longDescription = '' + Nanopb is a small code-size Protocol Buffers implementation in ansi C. It + is especially suitable for use in microcontrollers, but fits any memory + restricted system. + + - Homepage: jpa.kapsi.fi/nanopb + - Documentation: jpa.kapsi.fi/nanopb/docs + - Downloads: jpa.kapsi.fi/nanopb/download + - Forum: groups.google.com/forum/#!forum/nanopb + + In order to use the nanopb options in your proto files, you'll need to + tell protoc where to find the nanopb.proto file. + You can do so with the --proto_path (-I) option to add the directory + ''${nanopb}/share/nanopb/generator/proto like so: + + protoc --proto_path=. --proto_path=''${nanopb}/share/nanopb/generator/proto --plugin=protoc-gen-nanopb=''${nanopb}/bin/protoc-gen-nanopb --nanopb_out=out file.proto + ''; + }; +}) + diff --git a/pkgs/by-name/na/nanopb/python-module.nix b/pkgs/by-name/na/nanopb/python-module.nix new file mode 100644 index 0000000000000..f58c955307d84 --- /dev/null +++ b/pkgs/by-name/na/nanopb/python-module.nix @@ -0,0 +1,16 @@ +{ python3 +, version +, generator-out +}: +python3.pkgs.buildPythonPackage { + pname = "nanopb-python-module"; + inherit version; + src = generator-out; + pyproject = true; + pythonImportsCheck = [ "nanopb" ]; + propagatedBuildInputs = with python3.pkgs; [ + setuptools + protobuf + six + ]; +} diff --git a/pkgs/by-name/na/nanopb/runtime.nix b/pkgs/by-name/na/nanopb/runtime.nix new file mode 100644 index 0000000000000..2af7d2cedd5d7 --- /dev/null +++ b/pkgs/by-name/na/nanopb/runtime.nix @@ -0,0 +1,69 @@ +{ cmake +, lib +, stdenv +, protobuf +, python3 +, src +, version +, enableMalloc +, noPackedStructs +, maxRequiredFields +, field32bit +, noErrmsg +, bufferOnly +, systemHeader +, without64bit +, encodeArraysUnpacked +, convertDoubleFloat +, validateUtf8 +, littleEndian8bit +, c99StaticAssert +, noStaticAssert +}: + +stdenv.mkDerivation + ({ + pname = "nanopb-runtime"; + inherit src version; + + nativeBuildInputs = [ cmake protobuf python3 ]; + + patchPhase = + let + compile_definitions = target: '' + target_compile_definitions(${target} + PUBLIC + ${lib.concatStringsSep "\n\t" (map (x: "PB_${x.flag}") + (builtins.filter (x: x.cond) [ + { cond = enableMalloc; flag = "ENABLE_MALLOC=1"; } + { cond = noPackedStructs; flag = "NO_PACKED_STRUCTS=1"; } + { cond = maxRequiredFields != null; flag = "MAX_REQUIRED_FIELDS=${maxRequiredFields}"; } + { cond = field32bit; flag = "FIELD_32BIT=1"; } + { cond = noErrmsg; flag = "NO_ERRMSG=1"; } + { cond = bufferOnly; flag = "BUFFER_ONLY=1"; } + { cond = systemHeader != null; flag = "SYSTEM_HEADER=${systemHeader}"; } + { cond = without64bit; flag = "WITHOUT_64BIT=1"; } + { cond = encodeArraysUnpacked; flag = "ENCODE_ARRAYS_UNPACKED=1"; } + { cond = convertDoubleFloat; flag = "CONVERT_DOUBLE_FLOAT=1"; } + { cond = validateUtf8; flag = "VALIDATE_UTF8=1"; } + { cond = littleEndian8bit; flag = "LITTLE_ENDIAN_8BIT=1"; } + { cond = c99StaticAssert; flag = "C99_STATIC_ASSERT=1"; } + { cond = noStaticAssert; flag = "NO_STATIC_ASSERT=1"; } + ]))} + ) + ''; + in + '' + cat << EOF >> CMakeLists.txt + ${compile_definitions "protobuf-nanopb"} + ${compile_definitions "protobuf-nanopb-static"} + EOF + ''; + + cmakeFlags = [ + "-DBUILD_SHARED_LIBS=ON" + "-DBUILD_STATIC_LIBS=ON" + "-Dnanopb_BUILD_GENERATOR=OFF" + "-Dnanopb_BUILD_RUNTIME=ON" + ]; + }) diff --git a/pkgs/by-name/na/nanopb/test-message-with-annotations/default.nix b/pkgs/by-name/na/nanopb/test-message-with-annotations/default.nix new file mode 100644 index 0000000000000..5e53e72c62e63 --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-message-with-annotations/default.nix @@ -0,0 +1,32 @@ +{ lib, stdenv, nanopb }: + +stdenv.mkDerivation { + name = "nanopb-test-message-with-annotations"; + meta.timeout = 60; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ ./withannotations.proto ]; + }; + + buildInputs = [ nanopb ]; + + # protoc requires any .proto file to be compiled to reside within it's + # proto_path. By default the current directory is automatically added to the + # proto_path. I tried using --proto_path ${./.} ${./simple.proto} and it did + # not work because they end up in the store at different locations. + dontInstall = true; + buildPhase = '' + mkdir $out + + protoc --proto_path=. --proto_path=${nanopb}/share/nanopb/generator/proto --plugin=protoc-gen-nanopb=${nanopb}/bin/protoc-gen-nanopb --nanopb_out=$out withannotations.proto + ''; + + doCheck = true; + checkPhase = '' + grep -q WithAnnotations $out/withannotations.pb.c || (echo "error: WithAnnotations not found in $out/withannotations.pb.c"; exit 1) + grep -q WithAnnotations $out/withannotations.pb.h || (echo "error: WithAnnotations not found in $out/withannotations.pb.h"; exit 1) + grep -q "pb_byte_t uuid\[16\]" $out/withannotations.pb.h || (echo "error: uuid is not of type pb_byte_t and of size 16 in $out/withannotations.pb.h"; exit 1) + grep -q "FIXED_LENGTH_BYTES, uuid" $out/withannotations.pb.h || (echo "error: uuid is not of fixed lenght bytes in $out/withannotations.pb.h"; exit 1) + grep -q "#define WithAnnotations_size" $out/withannotations.pb.h || (echo "error: the size of WithAnnotations is not known in $out/withannotations.pb.h"; exit 1) + ''; +} diff --git a/pkgs/by-name/na/nanopb/test-message-with-annotations/withannotations.proto b/pkgs/by-name/na/nanopb/test-message-with-annotations/withannotations.proto new file mode 100644 index 0000000000000..d8109e877d68b --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-message-with-annotations/withannotations.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +import "nanopb.proto"; + +message WithAnnotations { + bytes uuid = 1 [(nanopb).max_size = 16, (nanopb).fixed_length = true]; +} diff --git a/pkgs/by-name/na/nanopb/test-message-with-options/default.nix b/pkgs/by-name/na/nanopb/test-message-with-options/default.nix new file mode 100644 index 0000000000000..78be532d569d7 --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-message-with-options/default.nix @@ -0,0 +1,35 @@ +{ lib, stdenv, nanopb }: + +stdenv.mkDerivation { + name = "nanopb-test-message-with-options"; + meta.timeout = 60; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./withoptions.proto + ./withoptions.options + ]; + }; + + buildInputs = [ nanopb ]; + + # protoc requires any .proto file to be compiled to reside within it's + # proto_path. By default the current directory is automatically added to the + # proto_path. I tried using --proto_path ${./.} ${./simple.proto} and it did + # not work because they end up in the store at different locations. + dontInstall = true; + buildPhase = '' + mkdir $out + + protoc --plugin=protoc-gen-nanopb=${nanopb}/bin/protoc-gen-nanopb --nanopb_out=$out withoptions.proto + ''; + + doCheck = true; + checkPhase = '' + grep -q WithOptions $out/withoptions.pb.c || (echo "error: WithOptions not found in $out/withoptions.pb.c"; exit 1) + grep -q WithOptions $out/withoptions.pb.h || (echo "error: WithOptions not found in $out/withoptions.pb.h"; exit 1) + grep -q "pb_byte_t uuid\[16\]" $out/withoptions.pb.h || (echo "error: uuid is not of type pb_byte_t and of size 16 in $out/withoptions.pb.h"; exit 1) + grep -q "FIXED_LENGTH_BYTES, uuid" $out/withoptions.pb.h || (echo "error: uuid is not of fixed lenght bytes in $out/withoptions.pb.h"; exit 1) + grep -q "#define WithOptions_size" $out/withoptions.pb.h || (echo "error: the size of WithOptions is not known in $out/withoptions.pb.h"; exit 1) + ''; +} diff --git a/pkgs/by-name/na/nanopb/test-message-with-options/withoptions.options b/pkgs/by-name/na/nanopb/test-message-with-options/withoptions.options new file mode 100644 index 0000000000000..ecf98a2173678 --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-message-with-options/withoptions.options @@ -0,0 +1 @@ + WithOptions.uuid max_size:16 fixed_length:true diff --git a/pkgs/by-name/na/nanopb/test-message-with-options/withoptions.proto b/pkgs/by-name/na/nanopb/test-message-with-options/withoptions.proto new file mode 100644 index 0000000000000..5a5da3a1c9732 --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-message-with-options/withoptions.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +message WithOptions { + bytes uuid = 1; +} diff --git a/pkgs/by-name/na/nanopb/test-simple-proto2/default.nix b/pkgs/by-name/na/nanopb/test-simple-proto2/default.nix new file mode 100644 index 0000000000000..5896679567486 --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-simple-proto2/default.nix @@ -0,0 +1,29 @@ +{ lib, stdenv, nanopb }: + +stdenv.mkDerivation { + name = "nanopb-test-simple-proto2"; + meta.timeout = 60; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ ./simple.proto ]; + }; + + buildInputs = [ nanopb ]; + + # protoc requires any .proto file to be compiled to reside within it's + # proto_path. By default the current directory is automatically added to the + # proto_path. I tried using --proto_path ${./.} ${./simple.proto} and it did + # not work because they end up in the store at different locations. + dontInstall = true; + buildPhase = '' + mkdir $out + + protoc --plugin=protoc-gen-nanopb=${nanopb}/bin/protoc-gen-nanopb --nanopb_out=$out simple.proto + ''; + + doCheck = true; + checkPhase = '' + grep -q SimpleMessage $out/simple.pb.c || (echo "ERROR: SimpleMessage not found in $out/simple.pb.c"; exit 1) + grep -q SimpleMessage $out/simple.pb.h || (echo "ERROR: SimpleMessage not found in $out/simple.pb.h"; exit 1) + ''; +} diff --git a/pkgs/by-name/na/nanopb/test-simple-proto2/simple.proto b/pkgs/by-name/na/nanopb/test-simple-proto2/simple.proto new file mode 100644 index 0000000000000..b02936b1ae267 --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-simple-proto2/simple.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +message SimpleMessage { + required int32 lucky_number = 1; +} diff --git a/pkgs/by-name/na/nanopb/test-simple-proto3/default.nix b/pkgs/by-name/na/nanopb/test-simple-proto3/default.nix new file mode 100644 index 0000000000000..6276126131c86 --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-simple-proto3/default.nix @@ -0,0 +1,29 @@ +{ lib, stdenv, nanopb }: + +stdenv.mkDerivation { + name = "nanopb-test-simple-proto3"; + meta.timeout = 60; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ ./simple.proto ]; + }; + + buildInputs = [ nanopb ]; + + # protoc requires any .proto file to be compiled to reside within it's + # proto_path. By default the current directory is automatically added to the + # proto_path. I tried using --proto_path ${./.} ${./simple.proto} and it did + # not work because they end up in the store at different locations. + dontInstall = true; + buildPhase = '' + mkdir $out + + protoc --plugin=protoc-gen-nanopb=${nanopb}/bin/protoc-gen-nanopb --nanopb_out=$out simple.proto + ''; + + doCheck = true; + checkPhase = '' + grep -q SimpleMessage $out/simple.pb.c || (echo "ERROR: SimpleMessage not found in $out/simple.pb.c"; exit 1) + grep -q SimpleMessage $out/simple.pb.h || (echo "ERROR: SimpleMessage not found in $out/simple.pb.h"; exit 1) + ''; +} diff --git a/pkgs/by-name/na/nanopb/test-simple-proto3/simple.proto b/pkgs/by-name/na/nanopb/test-simple-proto3/simple.proto new file mode 100644 index 0000000000000..6b99cdb5daa7c --- /dev/null +++ b/pkgs/by-name/na/nanopb/test-simple-proto3/simple.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +message SimpleMessage { + int32 lucky_number = 1; +} |