touch WORKSPACE cat < BUILD.bazel load(":rules.bzl", "build_setting", "library_no_transition", "library_input_outdir", "library_input_outdir_bs1") load(":setup_graph.bzl", "setup_graph") build_setting( name = "bs1", build_setting_default = "bs1_default", ) [ setup_graph(case=case, rule=rule, rule_args=rule_args) for case, rule, rule_args in [ ("1", library_no_transition, {}), ("2", library_input_outdir, { "input_settings": { "//command_line_option:output directory name": "any", }}, ), ("3", library_input_outdir_bs1, { "input_settings": { "//command_line_option:output directory name": "any", "//:bs1": "bs1_default", }}, ), ] ] EOF cat < setup_graph.bzl load(":rules.bzl", "no_transition", "input_bs1", "library_input_bs1") def setup_graph(*, case, rule, rule_args): no_transition( name = "A" + case, deps = [":B" + case, ":C" + case], ) input_bs1( name = "B" + case, deps = [":D" + case], input_settings = {"//:bs1": "bs1_B"}, ) input_bs1( name = "C" + case, deps = [":D" + case], input_settings = {"//:bs1": "bs1_C"}, ) rule( name = "D" + case, deps = [":E" + case], **rule_args ) library_input_bs1( name = "E" + case, path_resolution = ["//:bs1"], ) EOF cat < rules.bzl load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") BuildSettingInfo = provider(fields = ["value"]) def _build_setting_impl(ctx): return BuildSettingInfo(value = ctx.build_setting_value) def _dummy_rule_impl(ctx, files = []): transitive = [dep[DefaultInfo].files for dep in ctx.attr.deps] return [DefaultInfo(files = depset(direct = files, transitive = transitive))] def _library_rule_impl(ctx): path_resolution = "".join(["_%s" % dep[BuildSettingInfo].value for dep in ctx.attr.path_resolution]) name = ctx.label.name + path_resolution src = ctx.actions.declare_file(name + ".c") ctx.actions.write(src, "int %s() {return 1;}\n" % name) cc_toolchain = find_cpp_toolchain(ctx) feature_configuration = cc_common.configure_features(ctx = ctx, cc_toolchain = cc_toolchain) cc_args = {"actions": ctx.actions, "feature_configuration": feature_configuration, "cc_toolchain": cc_toolchain} compilation_context, compilation_outputs = cc_common.compile( name = name, srcs = [src], **cc_args) linking_context, linking_outputs = cc_common.create_linking_context_from_compilation_outputs( name = name, compilation_outputs = compilation_outputs, **cc_args) library_to_link = linking_outputs.library_to_link files = [] files += [library_to_link.static_library] if library_to_link.static_library else [] files += [library_to_link.pic_static_library] if library_to_link.pic_static_library else [] return _dummy_rule_impl(ctx, files = files) + [CcInfo( compilation_context = compilation_context, linking_context = linking_context)] def _input_transition_impl(settings, attr): settings = {setting: settings[setting] for setting in attr._input_settings} settings.update(attr.input_settings) return settings def _create_custom_rule(implementation, input = [], cpp = False): attrs = {"deps": attr.label_list(), "path_resolution": attr.label_list()} args = {"attrs": attrs, "implementation": implementation} if cpp: args["fragments"] = ["cpp"] args["toolchains"] = ["@bazel_tools//tools/cpp:toolchain_type"] attrs["_cc_toolchain"] = attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain") if input: attrs.update({ "input_settings": attr.string_dict(), "_input_settings": attr.string_list(default = input), "_whitelist_function_transition": attr.label( default = "@bazel_tools//tools/whitelists/function_transition_whitelist"), }) args["cfg"] = transition(inputs = input, outputs = input, implementation = _input_transition_impl) return rule(**args) build_setting = rule( implementation = _build_setting_impl, build_setting = config.string(flag = False), ) outdir = "//command_line_option:output directory name" no_transition = _create_custom_rule(_dummy_rule_impl) input_bs1 = _create_custom_rule(_dummy_rule_impl, ["//:bs1"]) library_no_transition = _create_custom_rule(_library_rule_impl, cpp = True) library_input_bs1 = _create_custom_rule(_library_rule_impl, ["//:bs1"], cpp = True) library_input_outdir = _create_custom_rule(_library_rule_impl, [outdir], cpp = True) library_input_outdir_bs1 = _create_custom_rule(_library_rule_impl, [outdir, "//:bs1"], cpp = True) EOF