1{
2 aiohttp,
3 appdirs,
4 appnope,
5 black,
6 build,
7 clang-tools,
8 click,
9 colorama,
10 coloredlogs,
11 coverage,
12 cryptography,
13 diskcache,
14 fetchFromGitHub,
15 glib,
16 gn,
17 googleapis-common-protos,
18 google-cloud-storage,
19 ipython,
20 jinja2,
21 json5,
22 jsonschema,
23 lark,
24 lib,
25 libnl,
26 mobly,
27 mypy,
28 mypy-extensions,
29 mypy-protobuf,
30 ninja,
31 openssl,
32 packaging,
33 parameterized,
34 pip-tools,
35 pkg-config,
36 pkgconfig,
37 prompt-toolkit,
38 protobuf,
39 psutil,
40 ptpython,
41 pyelftools,
42 pygments,
43 pykwalify,
44 pylint,
45 pyperclip,
46 pyserial,
47 python,
48 python-daemon,
49 pythonOlder,
50 pyyaml,
51 requests,
52 setuptools,
53 six,
54 sphinx,
55 sphinx-argparse,
56 sphinx-design,
57 stdenv,
58 stringcase,
59 toml,
60 tornado,
61 types-protobuf,
62 types-pyyaml,
63 types-requests,
64 types-setuptools,
65 watchdog,
66 websockets,
67 wheel,
68 yapf,
69 zap-chip,
70}:
71
72stdenv.mkDerivation rec {
73 pname = "home-assistant-chip-wheels";
74 version = "2025.4.0";
75 src = fetchFromGitHub {
76 owner = "home-assistant-libs";
77 repo = "chip-wheels";
78 tag = version;
79 fetchSubmodules = false;
80 leaveDotGit = true;
81 hash = "sha256-20dqVXHPgSxBveTxlbHEjTtp9NI1oVCVpBTDbjDI2QA=";
82 postFetch = ''
83 cd $out
84 # Download connectedhomeip.
85 git fetch
86 git reset --hard HEAD
87 git submodule update --init --depth 1 connectedhomeip
88
89 # Initialize only necessary submodules.
90 cd connectedhomeip
91 ${python.interpreter} scripts/checkout_submodules.py --platform linux --shallow
92
93 # Keep the output deterministic.
94 cd $out
95 # in case python decided to leave a .pyc file, for example
96 git clean -fxd
97 rm -rf .git/
98 '';
99 };
100
101 strictDeps = true;
102
103 nativeBuildInputs = [
104 gn
105 pkg-config
106 ninja
107 clang-tools
108 zap-chip
109 # gdbus-codegen
110 glib
111 pkgconfig
112 python
113 # dependencies of build scripts
114 click
115 jinja2
116 lark
117 setuptools
118 stringcase
119 build
120 pip-tools
121 black
122 yapf
123 ];
124
125 propagatedBuildInputs = [
126 openssl
127 glib
128 libnl
129 ];
130
131 postPatch = ''
132 cd connectedhomeip
133 export HOME=$(mktemp -d)
134
135 patchShebangs --build scripts
136
137 for patch in ../*.patch; do
138 patch -p1 < $patch
139 done
140
141 # unpin dependencies
142 # there are many files to modify, in different formats
143 sed -i 's/==.*$//' third_party/pigweed/repo/pw_env_setup/py/pw_env_setup/virtualenv_setup/python_base_requirements.txt
144 sed -i 's/==[^;]*//' scripts/setup/constraints.txt
145 sed -i 's/\(^ \+[a-zA-Z0-9-]*\)[=~><]=[^;]*/\1/' third_party/pigweed/repo/pw_protobuf_compiler/py/setup.cfg third_party/pigweed/repo/pw_protobuf/py/setup.cfg third_party/pigweed/repo/pw_protobuf_compiler/py/setup.cfg
146 # remove a few dependencies not packaged in nixpkgs and which are apparently
147 # not needed to build the python bindings of chip
148 sed -i -e '/sphinxcontrib-mermaid/d' -e '/types-six/d' -e '/types-pygment/d' -e '/types-pyserial/d' third_party/pigweed/repo/*/py/setup.cfg
149
150 # obtained by running a build in nix-shell with internet access
151 cp ${./pigweed_environment.gni} build_overrides/pigweed_environment.gni
152
153 # some code is generated by a templating tool (zap-cli)
154 scripts/codepregen.py ./zzz_pregenerated/
155 '';
156
157 # the python parts of the build system work as follows
158 # gn calls pigweed to read a dozen different files to generate
159 # a file looking like requirements.txt. It then calls pip
160 # to install this computed list of dependencies into a virtualenv.
161 # Of course, pip fails in the sandbox, because it cannot download
162 # the python packages.
163 # The documented way of doing offline builds is to create a folder
164 # with wheel files for all dependencies and point pip to it
165 # via its configuration file or environment variables.
166 # https://pigweed.dev/python_build.html#installing-offline
167 # The wheel of a python package foo is available as foo.dist.
168 # So that would be easy, but we also need wheels for transitive dependencies.
169 # the function saturateDependencies below computes this transitive closure.
170 #
171 # yes this list of dependencies contains both build tools and proper dependencies.
172 env.PIP_NO_INDEX = "1";
173 env.PIP_FIND_LINKS =
174 let
175 dependencies = [
176 aiohttp
177 appdirs
178 appnope
179 black
180 build
181 colorama
182 coloredlogs
183 coverage
184 click
185 cryptography
186 diskcache
187 googleapis-common-protos
188 google-cloud-storage
189 ipython
190 jinja2
191 json5
192 jsonschema
193 lark
194 mobly
195 mypy
196 mypy-extensions
197 mypy-protobuf
198 packaging
199 parameterized
200 pip-tools
201 pkgconfig
202 prompt-toolkit
203 protobuf
204 psutil
205 ptpython
206 pyelftools
207 pygments
208 pykwalify
209 (pylint.overridePythonAttrs { doCheck = pythonOlder "3.13"; })
210 pyperclip
211 pyserial
212 python-daemon
213 pyyaml
214 requests
215 setuptools
216 six
217 sphinx
218 sphinx-argparse
219 sphinx-design
220 stringcase
221 toml
222 tornado
223 types-protobuf
224 types-pyyaml
225 types-requests
226 types-setuptools
227 watchdog
228 websockets
229 wheel
230 yapf
231 ];
232 filterNull = list: lib.filter (dep: dep != null) list;
233 toItem = dep: {
234 inherit dep;
235 key = dep.name;
236 };
237 saturatedDependencies = lib.genericClosure {
238 startSet = map toItem (filterNull dependencies);
239 operator = item: map toItem (filterNull ((item.dep).propagatedBuildInputs or [ ]));
240 };
241 saturatedDependencyList = lib.filter (dep: dep ? dist && dep != null) (
242 map (item: item.dep) saturatedDependencies
243 );
244 in
245 lib.concatMapStringsSep " " (dep: "file://${dep.dist}") saturatedDependencyList;
246
247 gnFlags = [
248 ''chip_project_config_include_dirs=["//.."]''
249 ''chip_crypto="openssl"''
250 ''enable_rtti=true''
251 ''chip_config_memory_debug_checks=false''
252 ''chip_config_memory_debug_dmalloc=false''
253 ''chip_mdns="minimal"''
254 ''chip_minmdns_default_policy="libnl"''
255 ''chip_python_version="${lib.versions.majorMinor python.version}"''
256 ''chip_python_platform_tag="any"''
257 ''chip_python_package_prefix="home-assistant-chip"''
258 ''custom_toolchain="custom"''
259 ''target_cc="${stdenv.cc.targetPrefix}cc"''
260 ''target_cxx="${stdenv.cc.targetPrefix}c++"''
261 ''target_ar="${stdenv.cc.targetPrefix}ar"''
262 ];
263
264 preBuild = ''
265 export NIX_CFLAGS_COMPILE="$($PKG_CONFIG --cflags glib-2.0) -O2 -Wno-error"
266 export NIX_CFLAGS_LINK="$($PKG_CONFIG --libs gio-2.0) $($PKG_CONFIG --libs gobject-2.0) $($PKG_CONFIG --libs glib-2.0)"
267 '';
268
269 ninjaFlags = [ "chip-repl" ];
270
271 installPhase = ''
272 runHook preInstall
273
274 cp -r controller/python $out
275
276 runHook postInstall
277 '';
278
279 meta = {
280 description = "Python wheels for APIs and tools related to CHIP";
281 homepage = "https://github.com/home-assistant-libs/chip-wheels";
282 changelog = "https://github.com/home-assistant-libs/chip-wheels/releases/tag/${src.tag}";
283 license = lib.licenses.asl20;
284 teams = [ lib.teams.home-assistant ];
285 };
286
287}