1# Copyright 2024 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Rules for declaring preprocessed linker scripts.""" 15 16load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain") 17load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME") 18 19def _preprocess_linker_script_impl(ctx): 20 cc_toolchain = find_cpp_toolchain(ctx) 21 output_script = ctx.actions.declare_file(ctx.label.name + ".ld") 22 feature_configuration = cc_common.configure_features( 23 ctx = ctx, 24 cc_toolchain = cc_toolchain, 25 requested_features = ctx.features, 26 unsupported_features = ctx.disabled_features, 27 ) 28 cxx_compiler_path = cc_common.get_tool_for_action( 29 feature_configuration = feature_configuration, 30 action_name = C_COMPILE_ACTION_NAME, 31 ) 32 compilation_context = cc_common.merge_compilation_contexts( 33 compilation_contexts = [dep[CcInfo].compilation_context for dep in ctx.attr.deps], 34 ) 35 c_compile_variables = cc_common.create_compile_variables( 36 feature_configuration = feature_configuration, 37 cc_toolchain = cc_toolchain, 38 user_compile_flags = ctx.fragments.cpp.copts + ctx.fragments.cpp.conlyopts, 39 include_directories = compilation_context.includes, 40 quote_include_directories = compilation_context.quote_includes, 41 system_include_directories = compilation_context.system_includes, 42 preprocessor_defines = depset(ctx.attr.defines, transitive = [compilation_context.defines]), 43 ) 44 cmd_line = cc_common.get_memory_inefficient_command_line( 45 feature_configuration = feature_configuration, 46 action_name = C_COMPILE_ACTION_NAME, 47 variables = c_compile_variables, 48 ) 49 env = cc_common.get_environment_variables( 50 feature_configuration = feature_configuration, 51 action_name = C_COMPILE_ACTION_NAME, 52 variables = c_compile_variables, 53 ) 54 ctx.actions.run( 55 outputs = [output_script], 56 inputs = depset( 57 [ctx.file.linker_script], 58 transitive = [compilation_context.headers, cc_toolchain.all_files], 59 ), 60 executable = cxx_compiler_path, 61 arguments = [ 62 "-E", 63 "-P", 64 "-xc", 65 ctx.file.linker_script.path, 66 "-o", 67 output_script.path, 68 ] + cmd_line, 69 env = env, 70 ) 71 linker_input = cc_common.create_linker_input( 72 owner = ctx.label, 73 user_link_flags = ["-T", output_script.path], 74 additional_inputs = depset(direct = [output_script]), 75 ) 76 linking_context = cc_common.create_linking_context( 77 linker_inputs = depset(direct = [linker_input]), 78 ) 79 return [ 80 DefaultInfo(files = depset([output_script])), 81 CcInfo(linking_context = linking_context), 82 ] 83 84pw_linker_script = rule( 85 _preprocess_linker_script_impl, 86 doc = """Create a linker script target. Supports preprocessing with the C 87 preprocessor and adding the resulting linker script to linkopts. Also 88 provides a DefaultInfo containing the processed linker script. 89 """, 90 attrs = { 91 "copts": attr.string_list(doc = "C compile options."), 92 "defines": attr.string_list(doc = "C preprocessor defines."), 93 "deps": attr.label_list( 94 providers = [CcInfo], 95 doc = """Dependencies of this linker script. Can be used to provide 96 header files and defines. Only the CompilationContext of 97 the provided dependencies are used.""", 98 ), 99 "linker_script": attr.label( 100 mandatory = True, 101 allow_single_file = True, 102 doc = "Linker script to preprocess.", 103 ), 104 "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), 105 }, 106 toolchains = use_cpp_toolchain(), 107 fragments = ["cpp"], 108) 109