I have a macro called ispc_cc_library
. I call it in a BUILD.bazel
file this way:
COMMON_DEFINES = select({
"@platforms//os:osx": [
"OIDN_BNNS",
"OIDN_STATIC_LIB",
"OIDN_FILTER_RT",
"OIDN_FILTER_RTLIGHTMAP",
],
"//conditions:default": [
"OIDN_DNNL",
"OIDN_STATIC_LIB",
"OIDN_FILTER_RT",
"OIDN_FILTER_RTLIGHTMAP",
],
})
ispc_cc_library(
name = "input_reorder_ispc",
srcs = [
"core/color.isph",
"core/image.isph",
"core/input_reorder.ispc",
"core/math.isph",
"core/reorder.isph",
"core/tensor.isph",
"core/vec.isph",
],
out = "input_reorder_ispc.h",
defines = COMMON_DEFINES,
ispc_main_source_file = "core/input_reorder.ispc",
)
When I call the Bazel build command (bazel build //...
), I get this error:
ERROR: Traceback (most recent call last):
File "/private/var/tmp/_bazel_vertexwahn/998288db447b21c21cab4093cf36fa19/external/oidn/BUILD.bazel", line 48, column 16, in <toplevel>
ispc_cc_library(
File "/private/var/tmp/_bazel_vertexwahn/998288db447b21c21cab4093cf36fa19/external/rules_ispc/ispc.bzl", line 5, column 11, in ispc_cc_library
if len(defines) > 0:
Error in len: select is not iterable
The implementation of ispc_cc_library
looks like this:
def ispc_cc_library(name, out, ispc_main_source_file, srcs, defines = [], target_compatible_with = [], **kwargs):
generted_header_filename = out
ispc_defines_list = ""
if len(defines) > 0:
ispc_defines_list = "-D" + " -D".join(defines)
native.genrule(
name = "%s_ispc_gen" % name,
srcs = srcs,
outs = [name + ".o", generted_header_filename],
cmd = select({
"@platforms//os:linux": "$(location @ispc_linux_x86_64//:ispc) %s --target=avx2 --target-os=linux --arch=x86-64 --addressing=64 --pic $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generted_header_filename, name),
"@rules_ispc//:osx_arm64": "$(location @ispc_osx_arm64//:ispc) %s --target=neon --target-os=macos --arch=aarch64 --addressing=64 --pic $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generted_header_filename, name),
"@rules_ispc//:osx_x86_64": "$(location @ispc_osx_x86_64//:ispc) %s --target=sse2 --target-os=macos --arch=x86-64 --addressing=64 --pic $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generted_header_filename, name),
"@platforms//os:windows": "$(location @ispc_windows_x86_64//:ispc) %s --target=avx2 --target-os=windows --arch=x86-64 --addressing=64 $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generted_header_filename, name),
}),
tools = select({
"@platforms//os:linux": ["@ispc_linux_x86_64//:ispc"],
"@rules_ispc//:osx_arm64": ["@ispc_osx_arm64//:ispc"],
"@rules_ispc//:osx_x86_64": ["@ispc_osx_x86_64//:ispc"],
"@platforms//os:windows": ["@ispc_windows_x86_64//:ispc"],
}),
target_compatible_with = target_compatible_with,
)
native.cc_library(
name = name,
srcs = [name + ".o"],
hdrs = [name + ".h"],
defines = defines,
target_compatible_with = target_compatible_with,
**kwargs
It works when I remove the select from COMMON_DEFINES
, e.g. on macOS this way:
'''
COMMON_DEFINES = select({
"@platforms//os:osx": [
"OIDN_BNNS",
"OIDN_STATIC_LIB",
"OIDN_FILTER_RT",
"OIDN_FILTER_RTLIGHTMAP",
],
"//conditions:default": [
"OIDN_DNNL",
"OIDN_STATIC_LIB",
"OIDN_FILTER_RT",
"OIDN_FILTER_RTLIGHTMAP",
],
})
'''
COMMON_DEFINES = [
"OIDN_BNNS",
"OIDN_STATIC_LIB",
"OIDN_FILTER_RT",
"OIDN_FILTER_RTLIGHTMAP",
]
As Bazel reports select is not iterable
what is the right way to solve this issue? Do I need to convert ispc_cc_library
macro to a rule? Or is there a easy workaround?
Is it breaking because macros are evaluated during loading phase and the select is resolved (afterwards) during the analysis phase?
Steps to reproduce:
git clone https://github.com/Vertexwahn/rules_ispc.git
cd rules_ispc/tests/defines
bazel build //defines:main # should work
# now remove comment from line 16 in rules_ispc/tests/defines/BUILD.bazel -> #defines = COMMON_DEFINES, # this is currenlty not working
# build again
bazel build //defines:main # should fail
You are correct that the problem is the select isn't resolved until the loading phase, which is after the macro is done. Another way to look at it: if you build the target for the host and the target, your macro is only evaluated once, but the select may resolve differently.
Your situation looks like you should write a rule. The simple approach is wrap invoking your rule and native.cc_library
in a macro together. I think all of your logic should be easy to split like that.
You could also integrate with the C/C++ rules and effectively re-implement cc_library
using the built-in helpers. For a simple usage of cc_library
like you have, that's pretty straightforwards. I recommend copying the boilerplate from the rules_cc my_c_compile example.
Another approach to this kind of problem is passing around the dicts that go inside a select
. You can manipulate those from macros (prepend to every element of the values, add more elements to the end of every value, wrap a string formatting operation around every element of the values, etc), and then wrap them in native.select
at the end. That's kind of a pain to debug though, I would not recommend it here.