diff --git a/cuda/private/repositories.bzl b/cuda/private/repositories.bzl index 486bd018..c23f84b3 100644 --- a/cuda/private/repositories.bzl +++ b/cuda/private/repositories.bzl @@ -234,7 +234,7 @@ def config_cuda_toolkit_and_nvcc(repository_ctx, cuda): # Generate @cuda//BUILD if is_local_ctk == None: - repository_ctx.symlink(Label("//cuda/private:templates/BUILD.cuda_disabled"), "BUILD") + template_helper.generate_disabled_build(repository_ctx) elif is_local_ctk: libpath = "lib64" if _is_linux(repository_ctx) else "lib" template_helper.generate_build(repository_ctx, libpath) diff --git a/cuda/private/template_helper.bzl b/cuda/private/template_helper.bzl index ced33b8d..20e77e5d 100644 --- a/cuda/private/template_helper.bzl +++ b/cuda/private/template_helper.bzl @@ -239,6 +239,42 @@ def _generate_build(repository_ctx, libpath, components = None, is_cuda_repo = T _generate_build_impl(repository_ctx, libpath, components, is_cuda_repo, is_deliverable) +# Targets a generated `@cuda` repo defines besides the REGISTRY ones. +_CUDA_REPO_TARGETS = ["cuda_all_files", "cuda_device_runtime_static_libs", "cuda_headers", "cuda_license"] + +def _generate_disabled_build(repository_ctx): + """Generate `@cuda//BUILD` when no CUDA Toolkit is found + + Besides the targets the disabled toolchain needs, it declares an incompatible + placeholder for every other target an enabled `@cuda` exposes, so `select()` + branches naming them still load in `bazel query`. + + Args: + repository_ctx: repository_ctx + """ + content = repository_ctx.read(Label("//cuda/private:templates/BUILD.cuda_disabled")) + names = {name: None for name in _CUDA_REPO_TARGETS} + for targets in REGISTRY.values(): + for name in targets: + names[name] = None + placeholders = sorted([name for name in names if 'name = "{}"'.format(name) not in content]) + lines = [ + content, + "# Placeholders for the targets an enabled @cuda repo exposes.", + "[", + " filegroup(", + " name = name,", + " srcs = [],", + " target_compatible_with = [\"@platforms//:incompatible\"],", + " )", + " for name in [", + ] + [' "{}",'.format(name) for name in placeholders] + [ + " ]", + "]", + "", + ] + repository_ctx.file("BUILD", content = "\n".join(lines), executable = False) + def _generate_defs_bzl(repository_ctx, version_major, version_minor, is_local_ctk): tpl_label = Label("//cuda/private:templates/defs.bzl.tpl") substitutions = { @@ -467,6 +503,7 @@ def _generate_toolchain_clang_build(repository_ctx, cuda, clang_path_or_label): template_helper = struct( generate_build = _generate_build, + generate_disabled_build = _generate_disabled_build, generate_defs_bzl = _generate_defs_bzl, generate_redist_bzl = _generate_redist_bzl, generate_toolchain_build = _generate_toolchain_build, diff --git a/tests/integration/BUILD.to_symlink b/tests/integration/BUILD.to_symlink index fdba839f..cfc9dcc3 100644 --- a/tests/integration/BUILD.to_symlink +++ b/tests/integration/BUILD.to_symlink @@ -7,6 +7,18 @@ cc_library( deps = ["@cuda//:cuda_runtime"], ) +cc_library( + name = "optionally_use_library", + tags = ["manual"], + deps = select({ + "@rules_cuda//cuda:is_enabled": [ + "@cuda//:cuda_headers", + "@cuda//:cuda_runtime_static", + ], + "//conditions:default": [], + }), +) + cuda_library( name = "use_rule", srcs = ["@rules_cuda_examples//basic:kernel.cu"], diff --git a/tests/integration/test_all.sh b/tests/integration/test_all.sh index 8a7a2818..89c4dcda 100755 --- a/tests/integration/test_all.sh +++ b/tests/integration/test_all.sh @@ -108,6 +108,12 @@ pushd "$this_dir/toolchain_none" # use library should analyse build successfully (empty cuda_runtime target exists) bazel build //:use_library + # every @cuda target loads, so query works through select() branches that name them + bazel query 'deps(//:optionally_use_library)' + bazel build //:optionally_use_library --@rules_cuda//cuda:enable=False + ERR=$(bazel build //:optionally_use_library --@rules_cuda//cuda:enable=True 2>&1 || true) + if ! [[ $ERR =~ "is incompatible" ]]; then exit 1; fi + # use rule analyses correctly but fails during compilation because cuda toolkit doesn't exist ERR=$(bazel build //:use_rule 2>&1 || true) # nvcc toolchain fails with "nvcc of cuda toolkit does not exist", clang toolchain fails with "cannot find CUDA installation"