1# The cmake version of this build is meant to enable both cmake and .pc being exported
2# this is important because grpc exports a .cmake file which also expects for protobuf
3# to have been exported through cmake as well.
4{
5 lib,
6 stdenv,
7 abseil-cpp,
8 buildPackages,
9 cmake,
10 fetchFromGitHub,
11 fetchpatch,
12 gtest,
13 zlib,
14 version,
15 hash,
16 replaceVars,
17 versionCheckHook,
18
19 # downstream dependencies
20 python3,
21 grpc,
22 enableShared ? !stdenv.hostPlatform.isStatic,
23
24 testers,
25 protobuf,
26 ...
27}:
28
29stdenv.mkDerivation (finalAttrs: {
30 pname = "protobuf";
31 inherit version;
32
33 src = fetchFromGitHub {
34 owner = "protocolbuffers";
35 repo = "protobuf";
36 tag = "v${version}";
37 inherit hash;
38 };
39
40 postPatch = lib.optionalString (stdenv.hostPlatform.isDarwin && lib.versionOlder version "29") ''
41 substituteInPlace src/google/protobuf/testing/googletest.cc \
42 --replace-fail 'tmpnam(b)' '"'$TMPDIR'/foo"'
43 '';
44
45 patches = lib.optionals (lib.versionOlder version "22") [
46 # fix protobuf-targets.cmake installation paths, and allow for CMAKE_INSTALL_LIBDIR to be absolute
47 # https://github.com/protocolbuffers/protobuf/pull/10090
48 (fetchpatch {
49 url = "https://github.com/protocolbuffers/protobuf/commit/a7324f88e92bc16b57f3683403b6c993bf68070b.patch";
50 hash = "sha256-SmwaUjOjjZulg/wgNmR/F5b8rhYA2wkKAjHIOxjcQdQ=";
51 })
52 ];
53
54 # hook to provide the path to protoc executable, used at build time
55 build_protobuf =
56 if (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) then
57 buildPackages."protobuf_${lib.versions.major version}"
58 else
59 (placeholder "out");
60 setupHook = ./setup-hook.sh;
61
62 nativeBuildInputs = [
63 cmake
64 ];
65
66 buildInputs = [
67 gtest
68 zlib
69 ];
70
71 propagatedBuildInputs = [
72 abseil-cpp
73 ];
74
75 strictDeps = true;
76
77 cmakeDir = if lib.versionOlder version "22" then "../cmake" else null;
78 cmakeFlags =
79 [
80 "-Dprotobuf_USE_EXTERNAL_GTEST=ON"
81 "-Dprotobuf_ABSL_PROVIDER=package"
82 ]
83 ++ lib.optionals enableShared [
84 "-Dprotobuf_BUILD_SHARED_LIBS=ON"
85 ]
86 ++ lib.optionals (!finalAttrs.finalPackage.doCheck) [
87 "-Dprotobuf_BUILD_TESTS=OFF"
88 ];
89
90 doCheck =
91 # Tests fail to build on 32-bit platforms; fixed in 22.x
92 # https://github.com/protocolbuffers/protobuf/issues/10418
93 # Also AnyTest.TestPackFromSerializationExceedsSizeLimit fails on 32-bit platforms
94 # https://github.com/protocolbuffers/protobuf/issues/8460
95 !stdenv.hostPlatform.is32bit;
96
97 nativeInstallCheckInputs = [
98 versionCheckHook
99 ];
100 versionCheckProgram = [ "${placeholder "out"}/bin/protoc" ];
101 versionCheckProgramArg = "--version";
102 doInstallCheck = true;
103
104 passthru = {
105 tests = {
106 pythonProtobuf = python3.pkgs.protobuf;
107 inherit grpc;
108 version = testers.testVersion { package = protobuf; };
109 };
110
111 inherit abseil-cpp;
112 };
113
114 meta = {
115 description = "Google's data interchange format";
116 longDescription = ''
117 Protocol Buffers are a way of encoding structured data in an efficient
118 yet extensible format. Google uses Protocol Buffers for almost all of
119 its internal RPC protocols and file formats.
120 '';
121 license = lib.licenses.bsd3;
122 platforms = lib.platforms.all;
123 homepage = "https://protobuf.dev/";
124 maintainers = with lib.maintainers; [ GaetanLepage ];
125 mainProgram = "protoc";
126 };
127})