xref: /aosp_15_r20/external/pigweed/pw_build/pw_linker_script.bzl (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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