Skip to content

Commit

Permalink
pw_build: Add pw_cc_binary variant to generate .map files
Browse files Browse the repository at this point in the history
Bug: b/319746242

Change-Id: I750da45d7cb188d9848f8bd0804367664343da35
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/187710
Presubmit-Verified: CQ Bot Account <[email protected]>
Reviewed-by: Ted Pudlik <[email protected]>
Commit-Queue: Austin Foxley <[email protected]>
  • Loading branch information
afoxley authored and CQ Bot Account committed Jan 13, 2024
1 parent d06ec14 commit 4c95093
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 0 deletions.
12 changes: 12 additions & 0 deletions pw_build/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

load(
"//pw_build:pigweed.bzl",
"pw_cc_binary_with_map",
"pw_cc_blob_info",
"pw_cc_blob_library",
"pw_cc_test",
Expand Down Expand Up @@ -59,6 +60,17 @@ pw_cc_test(
deps = [":test_blob"],
)

pw_cc_binary_with_map(
name = "cc_binary_with_map",
srcs = ["empty_main.cc"],
# Only enable on platforms that support -Map linker flag
target_compatible_with = select({
"@platforms//os:macos": ["@platforms//:incompatible"],
"@platforms//os:windows": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
)

# Bazel produces root-relative file paths without the -ffile-prefix-map option.
pw_cc_test(
name = "file_prefix_map_test",
Expand Down
5 changes: 5 additions & 0 deletions pw_build/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,11 @@ if (current_toolchain != default_toolchain) {
visibility = [ ":*" ]
}

pw_source_set("empty_main") {
sources = [ "empty_main.cc" ]
visibility = [ ":*" ]
}

pw_test_group("tests") {
tests = [
":cc_blob_library_test",
Expand Down
17 changes: 17 additions & 0 deletions pw_build/bazel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,23 @@ Example
} // namespace my::stuff
pw_cc_binary_with_map
---------------------
The ``pw_cc_binary_with_map`` rule can be used to build a binary like
``cc_binary`` does but also generate a .map file from the linking step.

.. code-block::
pw_cc_binary_with_map(
name = "test",
srcs = ["empty_main.cc"],
)
This should result in a ``test.map`` file generated next to the ``test`` binary.

Note that it's only partially compatible with the ``cc_binary`` interface and
certain things are not implemented like make variable substitution.

Miscellaneous utilities
-----------------------

Expand Down
60 changes: 60 additions & 0 deletions pw_build/bazel_internal/pigweed_internal.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def compile_cc(
deps,
includes = [],
defines = [],
local_defines = [],
user_compile_flags = []):
"""Compiles a list C++ source files.
Expand All @@ -57,6 +58,7 @@ def compile_cc(
deps: Dependencies to link with
includes: List of include paths
defines: List of preprocessor defines to use
local_defines: List of preprocessor defines to use only on this unit.
user_compile_flags: Extra compiler flags to pass when compiling.
Returns:
Expand All @@ -79,6 +81,7 @@ def compile_cc(
srcs = srcs,
includes = includes,
defines = defines,
local_defines = local_defines,
public_hdrs = hdrs,
user_compile_flags = user_compile_flags,
compilation_contexts = compilation_contexts,
Expand All @@ -104,3 +107,60 @@ def compile_cc(
compilation_context = compilation_context,
linking_context = linking_context,
)]

# From cc_helper.bzl. Feature names for static/dynamic linking.
linker_mode = struct(
LINKING_DYNAMIC = "dynamic_linking_mode",
LINKING_STATIC = "static_linking_mode",
)

def link_cc(
ctx,
linking_contexts,
linkstatic,
stamp,
user_link_flags = [],
additional_outputs = []):
"""Links a binary and allows custom linker output.
Args:
ctx: Rule context
linking_contexts: Dependencies to link with
linkstatic: True if binary should be linked statically.
stamp: Stamp behavior for linking.
user_link_flags: Extra linker flags to pass when linking
additional_outputs: Extra files generated by link
Returns:
DefaultInfo of output files
"""
cc_toolchain = find_cpp_toolchain(ctx)
features = ctx.features
linking_mode = linker_mode.LINKING_STATIC
if not linkstatic:
linking_mode = linker_mode.LINKING_DYNAMIC
features.append(linking_mode)
feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = features,
unsupported_features = ctx.disabled_features,
)

linking_outputs = cc_common.link(
name = ctx.label.name,
actions = ctx.actions,
stamp = stamp,
feature_configuration = feature_configuration,
cc_toolchain = cc_toolchain,
linking_contexts = linking_contexts,
user_link_flags = user_link_flags,
output_type = "executable",
additional_outputs = additional_outputs,
)

output_files = depset(
[linking_outputs.executable] + additional_outputs,
transitive = [],
)
return [DefaultInfo(files = output_files)]
15 changes: 15 additions & 0 deletions pw_build/empty_main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

int main() { return 0; }
79 changes: 79 additions & 0 deletions pw_build/pigweed.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME")
load(
"//pw_build/bazel_internal:pigweed_internal.bzl",
_compile_cc = "compile_cc",
_link_cc = "link_cc",
)

# Used by `pw_cc_test`.
Expand Down Expand Up @@ -282,6 +283,84 @@ pw_cc_blob_library = rule(
toolchains = use_cpp_toolchain(),
)

def _pw_cc_binary_with_map_impl(ctx):
[_, cc_info] = _compile_cc(
ctx,
ctx.files.srcs,
[],
deps = ctx.attr.deps + [ctx.attr.link_extra_lib, ctx.attr.malloc],
includes = ctx.attr.includes,
defines = ctx.attr.defines,
local_defines = ctx.attr.local_defines,
)

map_file = ctx.actions.declare_file(ctx.label.name + ".map")
map_flags = ["-Wl,-Map=" + map_file.path]

return _link_cc(
ctx,
[cc_info.linking_context],
ctx.attr.linkstatic,
ctx.attr.stamp,
user_link_flags = ctx.attr.linkopts + map_flags,
additional_outputs = [map_file],
)

pw_cc_binary_with_map = rule(
implementation = _pw_cc_binary_with_map_impl,
doc = """Links a binary like cc_binary does but generates a linker map file
and provides it as an output after the executable in the DefaultInfo list
returned by this rule.
This rule makes an effort to somewhat mimic cc_binary args and behavior but
doesn't fully support all options currently. Make variable substitution and
tokenization handling isn't implemented by this rule on any of it's attrs.
Args:
ctx: Rule context.
""",
attrs = {
"srcs": attr.label_list(
allow_files = True,
doc = "The list of C and C++ files that are processed to create the target.",
),
"deps": attr.label_list(
providers = [CcInfo],
doc = "The list of other libraries to be linked in to the binary target.",
),
"malloc": attr.label(
default = "@bazel_tools//tools/cpp:malloc",
doc = "Override the default dependency on malloc.",
),
"link_extra_lib": attr.label(
default = "@bazel_tools//tools/cpp:link_extra_lib",
doc = "Control linking of extra libraries.",
),
"linkstatic": attr.bool(
doc = "True if binary should be link statically",
),
"includes": attr.string_list(
doc = "List of include dirs to add to the compile line.",
),
"defines": attr.string_list(
doc = "List of defines to add to the compile line.",
),
"local_defines": attr.string_list(
doc = "List of defines to add to the compile line.",
),
"linkopts": attr.string_list(
doc = "Add these flags to the C++ linker command.",
),
"stamp": attr.int(
default = -1,
doc = "Whether to encode build information into the binary.",
),
},
provides = [DefaultInfo],
fragments = ["cpp"],
toolchains = use_cpp_toolchain(),
)

def _preprocess_linker_script_impl(ctx):
cc_toolchain = find_cpp_toolchain(ctx)
output_script = ctx.actions.declare_file(ctx.label.name + ".ld")
Expand Down

0 comments on commit 4c95093

Please sign in to comment.