summaryrefslogtreecommitdiff
path: root/pkgs/development/libraries/protobuf/generic.nix
blob: 91e6bc878b0105f086cd0e29519c3a02571b14c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# The cmake version of this build is meant to enable both cmake and .pc being exported
# this is important because grpc exports a .cmake file which also expects for protobuf
# to have been exported through cmake as well.
{
  lib,
  stdenv,
  abseil-cpp,
  buildPackages,
  cmake,
  fetchFromGitHub,
  fetchpatch,
  gtest,
  zlib,
  version,
  hash,
  versionCheckHook,

  # downstream dependencies
  python3,
  grpc,
  enableShared ? !stdenv.hostPlatform.isStatic,

  testers,
  protobuf,
  ...
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "protobuf";
  inherit version;

  src = fetchFromGitHub {
    owner = "protocolbuffers";
    repo = "protobuf";
    tag = "v${version}";
    inherit hash;
  };

  patches =
    lib.optionals (lib.versionOlder version "22") [
      # fix protobuf-targets.cmake installation paths, and allow for CMAKE_INSTALL_LIBDIR to be absolute
      # https://github.com/protocolbuffers/protobuf/pull/10090
      (fetchpatch {
        url = "https://github.com/protocolbuffers/protobuf/commit/a7324f88e92bc16b57f3683403b6c993bf68070b.patch";
        hash = "sha256-SmwaUjOjjZulg/wgNmR/F5b8rhYA2wkKAjHIOxjcQdQ=";
      })
    ]
    ++ lib.optionals (lib.versions.major version == "29") [
      # fix temporary directory handling to avoid test failures on darwin
      # https://github.com/NixOS/nixpkgs/issues/464439
      (fetchpatch {
        url = "https://github.com/protocolbuffers/protobuf/commit/0e9d0f6e77280b7a597ebe8361156d6bb1971dca.patch";
        hash = "sha256-rIP+Ft/SWVwh9Oy8y8GSUBgP6CtLCLvGmr6nOqmyHhY=";
      })
    ]
    ++ lib.optionals (lib.versionAtLeast version "30") [
      # workaround nvcc bug in message_lite.h
      # https://github.com/protocolbuffers/protobuf/issues/21542
      # Caused by: https://github.com/protocolbuffers/protobuf/commit/8f7aab29b21afb89ea0d6e2efeafd17ca71486a9
      #
      # A specific consequence of this bug is a test failure when building onnxruntime with cudaSupport
      # See https://github.com/NixOS/nixpkgs/pull/450587#discussion_r2698215974
      (fetchpatch {
        url = "https://github.com/protocolbuffers/protobuf/commit/211f52431b9ec30d4d4a1c76aafd64bd78d93c43.patch";
        hash = "sha256-2/vc4anc+kH7otfLHfBtW8dRowPyObiXZn0+HtQktak=";
      })
    ]
    ++ lib.optionals (lib.versionAtLeast version "33") [
      # Fix protoc plugins crashing on big-endian platforms
      # https://github.com/protocolbuffers/protobuf/pull/25363
      (fetchpatch {
        url = "https://github.com/protocolbuffers/protobuf/commit/8282f0f8ecf8b847e5964a308e041ba3b049811c.patch";
        hash = "sha256-4c/yLuAd29Cxrz6I9F2Lj02lW2bazIcGb+86uxZY7qA=";
      })
      # Fix packed enum decoding on big-endian platforms
      # https://github.com/protocolbuffers/protobuf/pull/25683
      ./fix-upb-packed-enum-be.patch
    ]
    ++ lib.optionals (lib.versionAtLeast version "34") [
      # upb linker-array fix for newer toolchains (notably GCC 15):
      # `UPB_linkarr_internal_empty_upb_AllExts` can conflict with extension
      # entries in `linkarr_upb_AllExts` during test builds.
      # Context: https://github.com/protocolbuffers/protobuf/issues/21021
      ./fix-upb-linkarr-sentinel-init.patch
    ];

  postPatch =
    lib.optionalString (stdenv.hostPlatform.isDarwin && lib.versionOlder version "29") ''
      substituteInPlace src/google/protobuf/testing/googletest.cc \
        --replace-fail 'tmpnam(b)' '"'$TMPDIR'/foo"'
    ''
    # Keep the sentinel macro non-retained for GCC 15+ to match generated
    # extension objects in linker arrays and avoid section type conflicts.
    + lib.optionalString (lib.versionAtLeast version "34") ''
      substituteInPlace upb/port/def.inc \
        --replace-fail \
          '#define UPB_LINKARR_SENTINEL UPB_RETAIN __attribute__((weak, used))' \
          '#define UPB_LINKARR_SENTINEL            __attribute__((weak, used))'
    ''
    # Fix gcc15 build failures due to missing <cstring>
    + lib.optionalString ((lib.versions.major version) == "25") ''
      sed -i '1i #include <cstring>' third_party/utf8_range/utf8_validity.cc
    '';

  preHook = ''
    export build_protobuf=${
      if (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) then
        buildPackages."protobuf_${lib.versions.major version}"
      else
        (placeholder "out")
    };
  '';

  # hook to provide the path to protoc executable, used at build time
  setupHook = ./setup-hook.sh;

  nativeBuildInputs = [
    cmake
  ];

  buildInputs = [
    gtest
    zlib
  ];

  propagatedBuildInputs = [
    abseil-cpp
  ];

  strictDeps = true;

  separateDebugInfo = true;

  cmakeDir = if lib.versionOlder version "22" then "../cmake" else null;
  cmakeFlags = [
    (lib.cmakeBool "protobuf_USE_EXTERNAL_GTEST" true)
    (lib.cmakeFeature "protobuf_ABSL_PROVIDER" "package")
    (lib.cmakeBool "protobuf_BUILD_TESTS" finalAttrs.finalPackage.doCheck)
  ]
  ++ lib.optionals enableShared [
    (lib.cmakeBool "protobuf_BUILD_SHARED_LIBS" true)
  ];

  doCheck =
    # Tests fail to build on 32-bit platforms; fixed in 22.x
    # https://github.com/protocolbuffers/protobuf/issues/10418
    # Also AnyTest.TestPackFromSerializationExceedsSizeLimit fails on 32-bit platforms
    # https://github.com/protocolbuffers/protobuf/issues/8460
    !stdenv.hostPlatform.is32bit;

  nativeInstallCheckInputs = [
    versionCheckHook
  ];
  doInstallCheck = true;

  env = lib.optionalAttrs (lib.versions.major version == "29") {
    GTEST_DEATH_TEST_STYLE = "threadsafe";
  };

  passthru = {
    tests = {
      pythonProtobuf = python3.pkgs.protobuf;
      inherit grpc;
      inherit (python3.pkgs) celery;

      version = testers.testVersion { package = protobuf; };
    };

    inherit abseil-cpp;
  };

  meta = {
    description = "Google's data interchange format";
    longDescription = ''
      Protocol Buffers are a way of encoding structured data in an efficient
      yet extensible format. Google uses Protocol Buffers for almost all of
      its internal RPC protocols and file formats.
    '';
    license = lib.licenses.bsd3;
    platforms = lib.platforms.all;
    homepage = "https://protobuf.dev/";
    maintainers = with lib.maintainers; [ GaetanLepage ];
    mainProgram = "protoc";
  };
})