• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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