1# Copyright 2020 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 15import("//build_overrides/pigweed.gni") 16 17import("$dir_pw_build/exec.gni") 18import("$dir_pw_build/target_types.gni") 19import("$dir_pw_toolchain/generate_toolchain.gni") 20 21# Preprocess a linker script and turn it into a target. 22# 23# In lieu of direct GN support for linker scripts, this template makes it 24# possible to run the C Preprocessor on a linker script file so defines can 25# be properly evaluated before the linker script is passed to the dir_pw_build 26# 27# TODO(pwbug/53): This template serves as a stand-in until native GN support for 28# linker scripts is added. 29# 30# Args: 31# linker_script: The linker script to send through the C preprocessor. 32# 33# defines: Preprocessor defines to apply when running the C preprocessor. 34# 35# cflags: Flags to pass to the C compiler. 36# 37# includes: Include these files when running the C preprocessor. 38# 39# inputs: Files that, when changed, should trigger a re-build of the linker 40# script. linker_script and includes are implicitly added to this by the 41# template. 42# 43# Example: 44# 45# pw_linker_script("generic_linker_script") { 46# defines = [ 47# "PW_HEAP_SIZE=1K", 48# "PW_NOINIT_SIZE=512" 49# ] 50# linker_script = "basic_script.ld" 51# } 52# 53template("pw_linker_script") { 54 assert( 55 defined(invoker.linker_script) && invoker.linker_script != "", 56 "$target_name did not set `linker_script` to refer to a valid linker " + 57 "script. This variable is required for linker script targets.") 58 59 _final_linker_script = "${target_gen_dir}/${target_name}_final.ld" 60 61 # This action invokes the C compiler provided by the target to preprocess the 62 # linker script. 63 pw_exec("${target_name}_preprocess") { 64 program = pw_toolchain_SCOPE.cxx 65 inputs = [ invoker.linker_script ] 66 args = [ 67 # Run compiler in preprocessor-only mode. 68 "-E", 69 70 # Do not generate linemarkers in output. 71 "-P", 72 73 # Do not discard comments. 74 "-C", 75 76 # Treat the following file as a C file. 77 "-x", 78 "c", 79 rebase_path(invoker.linker_script, root_build_dir), 80 ] 81 82 # Trigger a re-generation of the linker script when these inputs change. 83 if (defined(invoker.inputs)) { 84 inputs += invoker.inputs 85 } 86 87 # Include any explicitly listed C flags. 88 if (defined(invoker.cflags)) { 89 args += invoker.cflags 90 } 91 92 # Include files from the command line. 93 if (defined(invoker.includes)) { 94 inputs += invoker.includes 95 foreach(include_file, invoker.includes) { 96 args += [ "-include" + rebase_path(include_file, root_build_dir) ] 97 } 98 } 99 100 # Add defines. 101 if (defined(invoker.defines)) { 102 foreach(compiler_define, invoker.defines) { 103 args += [ "-D${compiler_define}" ] 104 } 105 } 106 107 # Set output file. 108 args += [ 109 "-o", 110 rebase_path(_final_linker_script, root_build_dir), 111 ] 112 outputs = [ _final_linker_script ] 113 } 114 115 # This config adds a the linker script produced by the preprocess action to 116 # the linker flags. 117 config("${target_name}_config") { 118 inputs = [ invoker.linker_script ] 119 if (!defined(invoker.ldflags)) { 120 ldflags = [] 121 } 122 ldflags += [ "-T" + rebase_path(_final_linker_script, root_build_dir) ] 123 rustflags = [] 124 foreach(f, ldflags) { 125 rustflags += [ "-Clink-args=$f" ] 126 } 127 } 128 129 # The target that adds the linker script config to this library and everything 130 # that depends on it. 131 pw_source_set(target_name) { 132 inputs = [ _final_linker_script ] 133 all_dependent_configs = [ ":${target_name}_config" ] 134 deps = [ ":${target_name}_preprocess" ] 135 } 136} 137