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 "-Dprotobuf_USE_EXTERNAL_GTEST=ON"
80 "-Dprotobuf_ABSL_PROVIDER=package"
81 ]
82 ++ lib.optionals enableShared [
83 "-Dprotobuf_BUILD_SHARED_LIBS=ON"
84 ]
85 ++ lib.optionals (!finalAttrs.finalPackage.doCheck) [
86 "-Dprotobuf_BUILD_TESTS=OFF"
87 ];
88
89 doCheck =
90 # Tests fail to build on 32-bit platforms; fixed in 22.x
91 # https://github.com/protocolbuffers/protobuf/issues/10418
92 # Also AnyTest.TestPackFromSerializationExceedsSizeLimit fails on 32-bit platforms
93 # https://github.com/protocolbuffers/protobuf/issues/8460
94 !stdenv.hostPlatform.is32bit;
95
96 nativeInstallCheckInputs = [
97 versionCheckHook
98 ];
99 versionCheckProgram = [ "${placeholder "out"}/bin/protoc" ];
100 versionCheckProgramArg = "--version";
101 doInstallCheck = true;
102
103 passthru = {
104 tests = {
105 pythonProtobuf = python3.pkgs.protobuf;
106 inherit grpc;
107 version = testers.testVersion { package = protobuf; };
108 };
109
110 inherit abseil-cpp;
111 };
112
113 meta = {
114 description = "Google's data interchange format";
115 longDescription = ''
116 Protocol Buffers are a way of encoding structured data in an efficient
117 yet extensible format. Google uses Protocol Buffers for almost all of
118 its internal RPC protocols and file formats.
119 '';
120 license = lib.licenses.bsd3;
121 platforms = lib.platforms.all;
122 homepage = "https://protobuf.dev/";
123 maintainers = with lib.maintainers; [ GaetanLepage ];
124 mainProgram = "protoc";
125 };
126})