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# inputs: Files that, when changed, should trigger a re-build of the linker 38# script. linker_script is implicitly added to this by the template. 39# 40# Example: 41# 42# pw_linker_script("generic_linker_script") { 43# defines = [ 44# "PW_HEAP_SIZE=1K", 45# "PW_NOINIT_SIZE=512" 46# ] 47# linker_script = "basic_script.ld" 48# } 49# 50template("pw_linker_script") { 51 assert( 52 defined(invoker.linker_script) && invoker.linker_script != "", 53 "$target_name did not set `linker_script` to refer to a valid linker " + 54 "script. This variable is required for linker script targets.") 55 56 _final_linker_script = "${target_gen_dir}/${target_name}_final.ld" 57 58 # This action invokes the C compiler provided by the target to preprocess the 59 # linker script. 60 pw_exec("${target_name}_preprocess") { 61 program = pw_toolchain_SCOPE.cxx 62 inputs = [ invoker.linker_script ] 63 args = [ 64 # Run compiler in preprocessor-only mode. 65 "-E", 66 67 # Do not generate linemarkers in output. 68 "-P", 69 70 # Do not discard comments. 71 "-C", 72 73 # Treat the following file as a C file. 74 "-x", 75 "c", 76 rebase_path(invoker.linker_script), 77 ] 78 79 # Include any explicitly listed c flags. 80 if (defined(invoker.cflags)) { 81 args += cflags 82 } 83 84 # Add defines. 85 if (defined(invoker.defines)) { 86 foreach(compiler_define, invoker.defines) { 87 args += [ "-D${compiler_define}" ] 88 } 89 } 90 91 # Set output file. 92 args += [ 93 "-o", 94 rebase_path(_final_linker_script), 95 ] 96 outputs = [ _final_linker_script ] 97 } 98 99 # This config adds a the linker script produced by the preprocess action to 100 # the linker flags. 101 config("${target_name}_config") { 102 inputs = [ invoker.linker_script ] 103 if (!defined(invoker.ldflags)) { 104 ldflags = [] 105 } 106 ldflags += [ "-T" + rebase_path(_final_linker_script) ] 107 } 108 109 # The target that adds the linker script config to this library and everything 110 # that depends on it. 111 pw_source_set(target_name) { 112 inputs = [ _final_linker_script ] 113 if (defined(invoker.inputs)) { 114 inputs += invoker.inputs 115 } 116 all_dependent_configs = [ ":${target_name}_config" ] 117 deps = [ ":${target_name}_preprocess" ] 118 } 119} 120