third_party.pigweed.src/pw_build/linker_script.gni
Michael Spang c8b939009b Remove absolute paths from build command lines
The GN convention is to specify paths in command lines relative to the
build directory. Unfortunately and contrary to pigweed's expectations
this is not what rebase_path(path) does; that outputs an absolute path.

Absolute paths are not desirable in most circumstances as they contain
sources of nondeterminism such as the developer's home directory. Using
them can for example reduce hit rate in build caches.

Replace rebase_path(path) with rebase_path(path, root_build_dir) which
is the correct idiom and matches GN's builtin behavior (e.g. for
sources, include_dirs, etc).

This also removes the --directory argument to python_action(). Changing
the directory during the build while using relative paths is likely to
result in confusion and should be discouraged.

There's a couple more things to do on top of this for identical
binaries between build directories / machines / developers:

- pass options to avoid embedding the working directory
- pass options to use relative paths for the vendored clang & libc++

See [1]-[2] for how to do that.

[1] https://source.chromium.org/chromium/chromium/src/+/main:build/config/compiler/BUILD.gn;l=1170-1239;drc=ab531c265c533cba1c2f6d8240cc0bf7679f605a
[2] https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILD.gn;l=145-216;drc=f6d705f0937c778d5d5f807a4580113612b02f5a

Change-Id: I17708102c03d6488d68c8571b6e9343191fd47de
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/47461
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Michael Spang <spang@google.com>
2021-06-09 19:15:51 +00:00

120 lines
3.6 KiB
Plaintext

# Copyright 2020 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.
import("//build_overrides/pigweed.gni")
import("$dir_pw_build/exec.gni")
import("$dir_pw_build/target_types.gni")
import("$dir_pw_toolchain/generate_toolchain.gni")
# Preprocess a linker script and turn it into a target.
#
# In lieu of direct GN support for linker scripts, this template makes it
# possible to run the C Preprocessor on a linker script file so defines can
# be properly evaluated before the linker script is passed to the dir_pw_build
#
# TODO(pwbug/53): This template serves as a stand-in until native GN support for
# linker scripts is added.
#
# Args:
# linker_script: The linker script to send through the C preprocessor.
#
# defines: Preprocessor defines to apply when running the C preprocessor.
#
# cflags: Flags to pass to the C compiler.
#
# inputs: Files that, when changed, should trigger a re-build of the linker
# script. linker_script is implicitly added to this by the template.
#
# Example:
#
# pw_linker_script("generic_linker_script") {
# defines = [
# "PW_HEAP_SIZE=1K",
# "PW_NOINIT_SIZE=512"
# ]
# linker_script = "basic_script.ld"
# }
#
template("pw_linker_script") {
assert(
defined(invoker.linker_script) && invoker.linker_script != "",
"$target_name did not set `linker_script` to refer to a valid linker " +
"script. This variable is required for linker script targets.")
_final_linker_script = "${target_gen_dir}/${target_name}_final.ld"
# This action invokes the C compiler provided by the target to preprocess the
# linker script.
pw_exec("${target_name}_preprocess") {
program = pw_toolchain_SCOPE.cxx
inputs = [ invoker.linker_script ]
args = [
# Run compiler in preprocessor-only mode.
"-E",
# Do not generate linemarkers in output.
"-P",
# Do not discard comments.
"-C",
# Treat the following file as a C file.
"-x",
"c",
rebase_path(invoker.linker_script, root_build_dir),
]
# Include any explicitly listed c flags.
if (defined(invoker.cflags)) {
args += cflags
}
# Add defines.
if (defined(invoker.defines)) {
foreach(compiler_define, invoker.defines) {
args += [ "-D${compiler_define}" ]
}
}
# Set output file.
args += [
"-o",
rebase_path(_final_linker_script, root_build_dir),
]
outputs = [ _final_linker_script ]
}
# This config adds a the linker script produced by the preprocess action to
# the linker flags.
config("${target_name}_config") {
inputs = [ invoker.linker_script ]
if (!defined(invoker.ldflags)) {
ldflags = []
}
ldflags += [ "-T" + rebase_path(_final_linker_script, root_build_dir) ]
}
# The target that adds the linker script config to this library and everything
# that depends on it.
pw_source_set(target_name) {
inputs = [ _final_linker_script ]
if (defined(invoker.inputs)) {
inputs += invoker.inputs
}
all_dependent_configs = [ ":${target_name}_config" ]
deps = [ ":${target_name}_preprocess" ]
}
}