@@ -112,7 +112,9 @@ def _nixpkgs_package_impl(repository_ctx):
112
112
output_path = exec_result .stdout .splitlines ()[- 1 ]
113
113
# Build a forest of symlinks (like new_local_package() does) to the
114
114
# Nix store.
115
- _symlink_children (repository_ctx , output_path )
115
+ for target in _find_children (repository_ctx , output_path ):
116
+ basename = target .rpartition ("/" )[- 1 ]
117
+ repository_ctx .symlink (target , basename )
116
118
117
119
118
120
_nixpkgs_package = repository_rule (
@@ -130,6 +132,7 @@ _nixpkgs_package = repository_rule(
130
132
local = True ,
131
133
)
132
134
135
+
133
136
def nixpkgs_package (* args , ** kwargs ):
134
137
# Because of https://github.com/bazelbuild/bazel/issues/5356 we can't
135
138
# directly pass a dict from strings to labels to the rule (which we'd like
@@ -147,6 +150,67 @@ def nixpkgs_package(*args, **kwargs):
147
150
else :
148
151
_nixpkgs_package (* args , ** kwargs )
149
152
153
+
154
+ def _nixpkgs_cc_autoconf_impl (repository_ctx ):
155
+ # Calling repository_ctx.path() on anything but a regular file
156
+ # fails. So the roundabout way to do the same thing is to find
157
+ # a regular file we know is in the workspace (i.e. the WORKSPACE
158
+ # file itself) and then use dirname to get the path of the workspace
159
+ # root.
160
+ workspace_file_path = repository_ctx .path (
161
+ Label ("@nixpkgs_cc_toolchain//:WORKSPACE" )
162
+ )
163
+ workspace_root = repository_ctx .execute (
164
+ ["dirname" , workspace_file_path ]
165
+ ).stdout .rstrip ()
166
+
167
+ # Make a list of all available tools in the Nix derivation. Override
168
+ # the Bazel autoconfiguration with the tools we found.
169
+ bin_contents = _find_children (repository_ctx , workspace_root + "/bin" )
170
+ overriden_tools = {
171
+ tool : repository_ctx .path (Label ("@nixpkgs_cc_toolchain//:bin/" + tool ))
172
+ for entry in bin_contents
173
+ for tool in [entry .rpartition ("/" )[- 1 ]] # Compute basename
174
+ }
175
+ cc_autoconf_impl (repository_ctx , overriden_tools = overriden_tools )
176
+
177
+ _nixpkgs_cc_autoconf = repository_rule (
178
+ implementation = _nixpkgs_cc_autoconf_impl
179
+ )
180
+
181
+
182
+ def nixpkgs_cc_configure (
183
+ repository = None ,
184
+ repositories = None ,
185
+ nix_file_content = """
186
+ with import <nixpkgs> {}; buildEnv {
187
+ name = "bazel-cc-toolchain";
188
+ paths = [ gcc binutils ];
189
+ }
190
+ """ ):
191
+ """Use a CC toolchain from Nixpkgs.
192
+
193
+ By default, Bazel auto-configures a CC toolchain from commands (e.g.
194
+ `gcc`) available in the environment. To make builds more hermetic, use
195
+ this rule to specific explicitly which commands the toolchain should
196
+ use.
197
+ """
198
+ if repository and repositories or not repository and not repositories :
199
+ fail ("Specify one of repository or repositories (but not both)." )
200
+ elif repository :
201
+ repositories = {"nixpkgs" : repository }
202
+
203
+ nixpkgs_package (
204
+ name = "nixpkgs_cc_toolchain" ,
205
+ repositories = repositories ,
206
+ nix_file_content = nix_file_content ,
207
+ build_file_content = """exports_files(glob(["bin/*"]))""" ,
208
+ )
209
+ _nixpkgs_cc_autoconf (name = "local_config_cc" )
210
+ native .bind (name = "cc_toolchain" , actual = "@local_config_cc//:toolchain" )
211
+ native .register_toolchains ("@local_config_cc//:all" )
212
+
213
+
150
214
def _execute_or_fail (repository_ctx , arguments , failure_message = "" , * args , ** kwargs ):
151
215
"""Call repository_ctx.execute() and fail if non-zero return code."""
152
216
result = repository_ctx .execute (arguments , * args , ** kwargs )
@@ -167,11 +231,10 @@ Error output:
167
231
return result
168
232
169
233
170
- def _symlink_children (repository_ctx , target_dir ):
171
- """Create a symlink to all children of `target_dir` in the current
172
- build directory."""
234
+ def _find_children (repository_ctx , target_dir ):
173
235
find_args = [
174
236
_executable_path (repository_ctx , "find" ),
237
+ "-L" ,
175
238
target_dir ,
176
239
"-maxdepth" , "1" ,
177
240
# otherwise the directory is printed as well
@@ -180,10 +243,8 @@ def _symlink_children(repository_ctx, target_dir):
180
243
"-print0" ,
181
244
]
182
245
exec_result = _execute_or_fail (repository_ctx , find_args )
183
- for target in exec_result .stdout .rstrip ("\0 " ).split ("\0 " ):
184
- basename = target .rpartition ("/" )[- 1 ]
185
- repository_ctx .symlink (target , basename )
186
-
246
+ return exec_result .stdout .rstrip ("\0 " ).split ("\0 " )
247
+
187
248
188
249
def _executable_path (repository_ctx , exe_name , extra_msg = "" ):
189
250
"""Try to find the executable, fail with an error."""
@@ -192,70 +253,3 @@ def _executable_path(repository_ctx, exe_name, extra_msg=""):
192
253
fail ("Could not find the `{}` executable in PATH.{}\n "
193
254
.format (exe_name , " " + extra_msg if extra_msg else "" ))
194
255
return path
195
-
196
-
197
- def _cc_configure_custom (ctx ):
198
- overriden_tools = {
199
- "gcc" : ctx .path (ctx .attr .gcc ),
200
- "ld" : ctx .path (ctx .attr .ld ),
201
- }
202
- return cc_autoconf_impl (ctx , overriden_tools )
203
-
204
-
205
- cc_configure_custom = repository_rule (
206
- implementation = _cc_configure_custom ,
207
- attrs = {
208
- "gcc" : attr .label (
209
- executable = True ,
210
- cfg = "host" ,
211
- allow_single_file = True ,
212
- doc = "`gcc` to use in cc toolchain" ,
213
- ),
214
- "ld" : attr .label (
215
- executable = True ,
216
- cfg = "host" ,
217
- allow_single_file = True ,
218
- doc = "`ld` to use in cc toolchain" ,
219
- ),
220
- },
221
- local = True ,
222
- environ = [
223
- "ABI_LIBC_VERSION" ,
224
- "ABI_VERSION" ,
225
- "BAZEL_COMPILER" ,
226
- "BAZEL_HOST_SYSTEM" ,
227
- "BAZEL_LINKOPTS" ,
228
- "BAZEL_PYTHON" ,
229
- "BAZEL_SH" ,
230
- "BAZEL_TARGET_CPU" ,
231
- "BAZEL_TARGET_LIBC" ,
232
- "BAZEL_TARGET_SYSTEM" ,
233
- "BAZEL_USE_CPP_ONLY_TOOLCHAIN" ,
234
- "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN" ,
235
- "BAZEL_USE_LLVM_NATIVE_COVERAGE" ,
236
- "BAZEL_VC" ,
237
- "BAZEL_VS" ,
238
- "CC" ,
239
- "CC_CONFIGURE_DEBUG" ,
240
- "CC_TOOLCHAIN_NAME" ,
241
- "CPLUS_INCLUDE_PATH" ,
242
- "CUDA_COMPUTE_CAPABILITIES" ,
243
- "CUDA_PATH" ,
244
- "GCOV" ,
245
- "HOMEBREW_RUBY_PATH" ,
246
- "NO_WHOLE_ARCHIVE_OPTION" ,
247
- "SYSTEMROOT" ,
248
- "USE_DYNAMIC_CRT" ,
249
- "USE_MSVC_WRAPPER" ,
250
- "VS90COMNTOOLS" ,
251
- "VS100COMNTOOLS" ,
252
- "VS110COMNTOOLS" ,
253
- "VS120COMNTOOLS" ,
254
- "VS140COMNTOOLS" ,
255
- ],
256
- )
257
- """Overwrite cc toolchain by supplying custom `gcc` and `ld` (e.g. from
258
- Nix). This allows to fix mismatch of `gcc` versions between what is used by
259
- packages that come from Nix (e.g. `ghc`) and what Bazel detects
260
- automatically (i.e. system-level `gcc`).
261
- """
0 commit comments