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") 18load("@rules_cc//cc/common:cc_common.bzl", "cc_common") 19load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") 20 21def _preprocess_linker_script_impl(ctx): 22 cc_toolchain = find_cpp_toolchain(ctx) 23 output_script = ctx.actions.declare_file(ctx.label.name + ".ld") 24 feature_configuration = cc_common.configure_features( 25 ctx = ctx, 26 cc_toolchain = cc_toolchain, 27 requested_features = ctx.features, 28 unsupported_features = ctx.disabled_features + [ 29 "module_maps", 30 ], 31 ) 32 cxx_compiler_path = cc_common.get_tool_for_action( 33 feature_configuration = feature_configuration, 34 action_name = C_COMPILE_ACTION_NAME, 35 ) 36 compilation_context = cc_common.merge_compilation_contexts( 37 compilation_contexts = [dep[CcInfo].compilation_context for dep in ctx.attr.deps], 38 ) 39 c_compile_variables = cc_common.create_compile_variables( 40 feature_configuration = feature_configuration, 41 cc_toolchain = cc_toolchain, 42 user_compile_flags = ctx.fragments.cpp.copts + ctx.fragments.cpp.conlyopts, 43 include_directories = compilation_context.includes, 44 quote_include_directories = compilation_context.quote_includes, 45 system_include_directories = compilation_context.system_includes, 46 preprocessor_defines = depset(ctx.attr.defines, transitive = [compilation_context.defines]), 47 ) 48 cmd_line = cc_common.get_memory_inefficient_command_line( 49 feature_configuration = feature_configuration, 50 action_name = C_COMPILE_ACTION_NAME, 51 variables = c_compile_variables, 52 ) 53 env = cc_common.get_environment_variables( 54 feature_configuration = feature_configuration, 55 action_name = C_COMPILE_ACTION_NAME, 56 variables = c_compile_variables, 57 ) 58 ctx.actions.run( 59 outputs = [output_script], 60 inputs = depset( 61 [ctx.file.linker_script], 62 transitive = [compilation_context.headers, cc_toolchain.all_files], 63 ), 64 executable = cxx_compiler_path, 65 arguments = [ 66 "-E", 67 "-P", 68 "-xc", 69 ctx.file.linker_script.path, 70 "-o", 71 output_script.path, 72 ] + cmd_line, 73 env = env, 74 ) 75 linker_input = cc_common.create_linker_input( 76 owner = ctx.label, 77 user_link_flags = ["-T", output_script.path], 78 additional_inputs = depset(direct = [output_script]), 79 ) 80 linking_context = cc_common.create_linking_context( 81 linker_inputs = depset(direct = [linker_input]), 82 ) 83 return [ 84 DefaultInfo(files = depset([output_script])), 85 CcInfo(linking_context = linking_context), 86 ] 87 88pw_linker_script = rule( 89 _preprocess_linker_script_impl, 90 doc = """Create a linker script target. Supports preprocessing with the C 91 preprocessor and adding the resulting linker script to linkopts. Also 92 provides a DefaultInfo containing the processed linker script. 93 """, 94 attrs = { 95 "copts": attr.string_list(doc = "C compile options."), 96 "defines": attr.string_list(doc = "C preprocessor defines."), 97 "deps": attr.label_list( 98 providers = [CcInfo], 99 doc = """Dependencies of this linker script. Can be used to provide 100 header files and defines. Only the CompilationContext of 101 the provided dependencies are used.""", 102 ), 103 "linker_script": attr.label( 104 mandatory = True, 105 allow_single_file = True, 106 doc = "Linker script to preprocess.", 107 ), 108 }, 109 toolchains = use_cpp_toolchain(), 110 fragments = ["cpp"], 111) 112