| OLD | NEW |
| 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import("//build/toolchain/toolchain.gni") | 5 import("//build/toolchain/toolchain.gni") |
| 6 | 6 |
| 7 # This value will be inherited in the toolchain below. | 7 # This value will be inherited in the toolchain below. |
| 8 concurrent_links = exec_script("get_concurrent_links.py", [], "value") | 8 concurrent_links = exec_script("get_concurrent_links.py", [], "value") |
| 9 | 9 |
| 10 # This template defines a toolchain for something that works like gcc | 10 # This template defines a toolchain for something that works like gcc |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 # | 23 # |
| 24 # Optional parameters: | 24 # Optional parameters: |
| 25 # - libs_section_prefix | 25 # - libs_section_prefix |
| 26 # - libs_section_postfix | 26 # - libs_section_postfix |
| 27 # The contents of these strings, if specified, will be placed around | 27 # The contents of these strings, if specified, will be placed around |
| 28 # the libs section of the linker line. It allows one to inject libraries | 28 # the libs section of the linker line. It allows one to inject libraries |
| 29 # at the beginning and end for all targets in a toolchain. | 29 # at the beginning and end for all targets in a toolchain. |
| 30 # - solink_libs_section_prefix | 30 # - solink_libs_section_prefix |
| 31 # - solink_libs_section_postfix | 31 # - solink_libs_section_postfix |
| 32 # Same as libs_section_{pre,post}fix except used for solink instead of link
. | 32 # Same as libs_section_{pre,post}fix except used for solink instead of link
. |
| 33 # - post_solink | 33 # - link_outputs |
| 34 # The content of this string, if specified, will be appended to the solink | 34 # The content of this array, if specified, will be added to the list of |
| 35 # command. | 35 # outputs from the link command. This can be useful in conjunction with |
| 36 # the post_link parameter. |
| 37 # - post_link |
| 38 # The content of this string, if specified, will be run as a separate |
| 39 # command following the the link command. |
| 36 # - deps | 40 # - deps |
| 37 # Just forwarded to the toolchain definition. | 41 # Just forwarded to the toolchain definition. |
| 42 # - executable_extension |
| 43 # If this string is specified it will be used for the file extension |
| 44 # for an executable, rather than using no extension; targets will |
| 45 # still be able to override the extension using the output_extension |
| 46 # variable. |
| 38 # - is_clang | 47 # - is_clang |
| 39 # Whether to use clang instead of gcc. | 48 # Whether to use clang instead of gcc. |
| 49 # - is_component_build |
| 50 # Whether to forcibly enable or disable component builds for this |
| 51 # toolchain; if not specified, the toolchain will inherit the |
| 52 # default setting. |
| 53 # - rebuild_define |
| 54 # The contents of this string, if specified, will be passed as a #define |
| 55 # to the toolchain. It can be used to force recompiles whenever a |
| 56 # toolchain is updated. |
| 57 # - shlib_extension |
| 58 # If this string is specified it will be used for the file extension |
| 59 # for a shared library, rather than default value specified in |
| 60 # toolchain.gni |
| 40 # - strip | 61 # - strip |
| 41 # Location of the strip executable. When specified, strip will be run on | 62 # Location of the strip executable. When specified, strip will be run on |
| 42 # all shared libraries and executables as they are built. The pre-stripped | 63 # all shared libraries and executables as they are built. The pre-stripped |
| 43 # artifacts will be put in lib.stripped/ and exe.stripped/. | 64 # artifacts will be put in lib.stripped/ and exe.stripped/. |
| 44 template("gcc_toolchain") { | 65 template("gcc_toolchain") { |
| 45 toolchain(target_name) { | 66 toolchain(target_name) { |
| 46 assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value") | 67 assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value") |
| 47 assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value") | 68 assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value") |
| 48 assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value") | 69 assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value") |
| 49 assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value") | 70 assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value") |
| 50 assert(defined(invoker.toolchain_cpu), | 71 assert(defined(invoker.toolchain_cpu), |
| 51 "gcc_toolchain() must specify a \"toolchain_cpu\"") | 72 "gcc_toolchain() must specify a \"toolchain_cpu\"") |
| 52 assert(defined(invoker.toolchain_os), | 73 assert(defined(invoker.toolchain_os), |
| 53 "gcc_toolchain() must specify a \"toolchain_os\"") | 74 "gcc_toolchain() must specify a \"toolchain_os\"") |
| 54 | 75 |
| 76 # This define changes when the toolchain changes, forcing a rebuild. |
| 77 # Nothing should ever use this define. |
| 78 if (defined(invoker.rebuild_define)) { |
| 79 rebuild_string = "-D" + invoker.rebuild_define + " " |
| 80 } else { |
| 81 rebuild_string = "" |
| 82 } |
| 83 |
| 55 # We can't do string interpolation ($ in strings) on things with dots in | 84 # We can't do string interpolation ($ in strings) on things with dots in |
| 56 # them. To allow us to use $cc below, for example, we create copies of | 85 # them. To allow us to use $cc below, for example, we create copies of |
| 57 # these values in our scope. | 86 # these values in our scope. |
| 58 cc = invoker.cc | 87 cc = invoker.cc |
| 59 cxx = invoker.cxx | 88 cxx = invoker.cxx |
| 60 ar = invoker.ar | 89 ar = invoker.ar |
| 61 ld = invoker.ld | 90 ld = invoker.ld |
| 62 if (defined(invoker.readelf)) { | 91 if (defined(invoker.readelf)) { |
| 63 readelf = invoker.readelf | 92 readelf = invoker.readelf |
| 64 } else { | 93 } else { |
| 65 readelf = "readelf" | 94 readelf = "readelf" |
| 66 } | 95 } |
| 67 if (defined(invoker.nm)) { | 96 if (defined(invoker.nm)) { |
| 68 nm = invoker.nm | 97 nm = invoker.nm |
| 69 } else { | 98 } else { |
| 70 nm = "nm" | 99 nm = "nm" |
| 71 } | 100 } |
| 72 | 101 |
| 102 if (defined(invoker.shlib_extension)) { |
| 103 default_shlib_extension = invoker.shlib_extension |
| 104 } else { |
| 105 default_shlib_extension = shlib_extension |
| 106 } |
| 107 |
| 108 if (defined(invoker.executable_extension)) { |
| 109 default_executable_extension = invoker.executable_extension |
| 110 } else { |
| 111 default_executable_extension = "" |
| 112 } |
| 113 |
| 73 # Bring these into our scope for string interpolation with default values. | 114 # Bring these into our scope for string interpolation with default values. |
| 74 if (defined(invoker.libs_section_prefix)) { | 115 if (defined(invoker.libs_section_prefix)) { |
| 75 libs_section_prefix = invoker.libs_section_prefix | 116 libs_section_prefix = invoker.libs_section_prefix |
| 76 } else { | 117 } else { |
| 77 libs_section_prefix = "" | 118 libs_section_prefix = "" |
| 78 } | 119 } |
| 79 | 120 |
| 80 if (defined(invoker.libs_section_postfix)) { | 121 if (defined(invoker.libs_section_postfix)) { |
| 81 libs_section_postfix = invoker.libs_section_postfix | 122 libs_section_postfix = invoker.libs_section_postfix |
| 82 } else { | 123 } else { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 94 } else { | 135 } else { |
| 95 solink_libs_section_postfix = "" | 136 solink_libs_section_postfix = "" |
| 96 } | 137 } |
| 97 | 138 |
| 98 # These library switches can apply to all tools below. | 139 # These library switches can apply to all tools below. |
| 99 lib_switch = "-l" | 140 lib_switch = "-l" |
| 100 lib_dir_switch = "-L" | 141 lib_dir_switch = "-L" |
| 101 | 142 |
| 102 tool("cc") { | 143 tool("cc") { |
| 103 depfile = "{{output}}.d" | 144 depfile = "{{output}}.d" |
| 104 command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {
{cflags_c}} -c {{source}} -o {{output}}" | 145 command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_di
rs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" |
| 105 depsformat = "gcc" | 146 depsformat = "gcc" |
| 106 description = "CC {{output}}" | 147 description = "CC {{output}}" |
| 107 outputs = [ | 148 outputs = [ |
| 108 "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o", | 149 "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o", |
| 109 ] | 150 ] |
| 110 } | 151 } |
| 111 | 152 |
| 112 tool("cxx") { | 153 tool("cxx") { |
| 113 depfile = "{{output}}.d" | 154 depfile = "{{output}}.d" |
| 114 command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}}
{{cflags_cc}} -c {{source}} -o {{output}}" | 155 command = "$cxx -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_d
irs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}" |
| 115 depsformat = "gcc" | 156 depsformat = "gcc" |
| 116 description = "CXX {{output}}" | 157 description = "CXX {{output}}" |
| 117 outputs = [ | 158 outputs = [ |
| 118 "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o", | 159 "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o", |
| 119 ] | 160 ] |
| 120 } | 161 } |
| 121 | 162 |
| 122 tool("asm") { | 163 tool("asm") { |
| 123 # For GCC we can just use the C compiler to compile assembly. | 164 # For GCC we can just use the C compiler to compile assembly. |
| 124 depfile = "{{output}}.d" | 165 depfile = "{{output}}.d" |
| 125 command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {
{cflags_c}} -c {{source}} -o {{output}}" | 166 command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_di
rs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" |
| 126 depsformat = "gcc" | 167 depsformat = "gcc" |
| 127 description = "ASM {{output}}" | 168 description = "ASM {{output}}" |
| 128 outputs = [ | 169 outputs = [ |
| 129 "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o", | 170 "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o", |
| 130 ] | 171 ] |
| 131 } | 172 } |
| 132 | 173 |
| 133 tool("alink") { | 174 tool("alink") { |
| 134 rspfile = "{{output}}.rsp" | 175 rspfile = "{{output}}.rsp" |
| 135 command = "rm -f {{output}} && $ar rcs {{output}} @$rspfile" | 176 command = "rm -f {{output}} && $ar rcs {{output}} @$rspfile" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 "${invoker.strip} --strip-unneeded -o $sofile $unstripped_sofile" | 215 "${invoker.strip} --strip-unneeded -o $sofile $unstripped_sofile" |
| 175 command += " && " + strip_command | 216 command += " && " + strip_command |
| 176 } | 217 } |
| 177 rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whol
e-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" | 218 rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whol
e-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" |
| 178 | 219 |
| 179 description = "SOLINK $sofile" | 220 description = "SOLINK $sofile" |
| 180 | 221 |
| 181 # Use this for {{output_extension}} expansions unless a target manually | 222 # Use this for {{output_extension}} expansions unless a target manually |
| 182 # overrides it (in which case {{output_extension}} will be what the target | 223 # overrides it (in which case {{output_extension}} will be what the target |
| 183 # specifies). | 224 # specifies). |
| 184 default_output_extension = shlib_extension | 225 default_output_extension = default_shlib_extension |
| 185 if (defined(invoker.default_output_extension)) { | |
| 186 default_output_extension = invoker.default_output_extension | |
| 187 } | |
| 188 | 226 |
| 189 output_prefix = "lib" | 227 output_prefix = "lib" |
| 190 | 228 |
| 191 # Since the above commands only updates the .TOC file when it changes, ask | 229 # Since the above commands only updates the .TOC file when it changes, ask |
| 192 # Ninja to check if the timestamp actually changed to know if downstream | 230 # Ninja to check if the timestamp actually changed to know if downstream |
| 193 # dependencies should be recompiled. | 231 # dependencies should be recompiled. |
| 194 restat = true | 232 restat = true |
| 195 | 233 |
| 196 # Tell GN about the output files. It will link to the sofile but use the | 234 # Tell GN about the output files. It will link to the sofile but use the |
| 197 # tocfile for dependency management. | 235 # tocfile for dependency management. |
| 198 outputs = [ | 236 outputs = [ |
| 199 sofile, | 237 sofile, |
| 200 tocfile, | 238 tocfile, |
| 201 ] | 239 ] |
| 202 if (sofile != unstripped_sofile) { | 240 if (sofile != unstripped_sofile) { |
| 203 outputs += [ unstripped_sofile ] | 241 outputs += [ unstripped_sofile ] |
| 204 } | 242 } |
| 205 link_output = sofile | 243 link_output = sofile |
| 206 depend_output = tocfile | 244 depend_output = tocfile |
| 207 } | 245 } |
| 208 | 246 |
| 209 tool("link") { | 247 tool("link") { |
| 210 exename = "{{target_output_name}}{{output_extension}}" | 248 exename = "{{target_output_name}}{{output_extension}}" |
| 211 outfile = "{{root_out_dir}}/$exename" | 249 outfile = "{{root_out_dir}}/$exename" |
| 212 rspfile = "$outfile.rsp" | 250 rspfile = "$outfile.rsp" |
| 213 unstripped_outfile = outfile | 251 unstripped_outfile = outfile |
| 252 |
| 253 # Use this for {{output_extension}} expansions unless a target manually |
| 254 # overrides it (in which case {{output_extension}} will be what the target |
| 255 # specifies). |
| 256 default_output_extension = default_executable_extension |
| 257 |
| 214 if (defined(invoker.strip)) { | 258 if (defined(invoker.strip)) { |
| 215 unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$exename" | 259 unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$exename" |
| 216 } | 260 } |
| 217 | 261 |
| 218 command = "$ld {{ldflags}} -o $unstripped_outfile -Wl,--start-group @$rspf
ile {{solibs}} -Wl,--end-group $libs_section_prefix {{libs}} $libs_section_postf
ix" | 262 command = "$ld {{ldflags}} -o $unstripped_outfile -Wl,--start-group @$rspf
ile {{solibs}} -Wl,--end-group $libs_section_prefix {{libs}} $libs_section_postf
ix" |
| 219 if (defined(invoker.strip)) { | 263 if (defined(invoker.strip)) { |
| 220 strip_command = | 264 strip_command = |
| 221 "${invoker.strip} --strip-unneeded -o $outfile $unstripped_outfile" | 265 "${invoker.strip} --strip-unneeded -o $outfile $unstripped_outfile" |
| 222 command += " && " + strip_command | 266 command += " && " + strip_command |
| 223 } | 267 } |
| 268 if (defined(invoker.postlink)) { |
| 269 command += " && " + invoker.postlink |
| 270 } |
| 224 description = "LINK $outfile" | 271 description = "LINK $outfile" |
| 225 rspfile_content = "{{inputs}}" | 272 rspfile_content = "{{inputs}}" |
| 226 outputs = [ | 273 outputs = [ |
| 227 outfile, | 274 outfile, |
| 228 ] | 275 ] |
| 229 if (outfile != unstripped_outfile) { | 276 if (outfile != unstripped_outfile) { |
| 230 outputs += [ unstripped_outfile ] | 277 outputs += [ unstripped_outfile ] |
| 231 } | 278 } |
| 279 if (defined(invoker.link_outputs)) { |
| 280 outputs += invoker.link_outputs |
| 281 } |
| 232 } | 282 } |
| 233 | 283 |
| 234 tool("stamp") { | 284 tool("stamp") { |
| 235 command = "touch {{output}}" | 285 command = "touch {{output}}" |
| 236 description = "STAMP {{output}}" | 286 description = "STAMP {{output}}" |
| 237 } | 287 } |
| 238 | 288 |
| 239 tool("copy") { | 289 tool("copy") { |
| 240 command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} &
& cp -af {{source}} {{output}})" | 290 command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} &
& cp -af {{source}} {{output}})" |
| 241 description = "COPY {{source}} {{output}}" | 291 description = "COPY {{source}} {{output}}" |
| 242 } | 292 } |
| 243 | 293 |
| 244 # When invoking this toolchain not as the default one, these args will be | 294 # When invoking this toolchain not as the default one, these args will be |
| 245 # passed to the build. They are ignored when this is the default toolchain. | 295 # passed to the build. They are ignored when this is the default toolchain. |
| 246 toolchain_args() { | 296 toolchain_args() { |
| 247 current_cpu = invoker.toolchain_cpu | 297 current_cpu = invoker.toolchain_cpu |
| 248 current_os = invoker.toolchain_os | 298 current_os = invoker.toolchain_os |
| 249 | 299 |
| 250 # These values need to be passed through unchanged. | 300 # These values need to be passed through unchanged. |
| 251 target_os = target_os | 301 target_os = target_os |
| 252 target_cpu = target_cpu | 302 target_cpu = target_cpu |
| 253 | 303 |
| 254 if (defined(invoker.is_clang)) { | 304 if (defined(invoker.is_clang)) { |
| 255 is_clang = invoker.is_clang | 305 is_clang = invoker.is_clang |
| 256 } | 306 } |
| 307 if (defined(invoker.is_component_build)) { |
| 308 is_component_build = invoker.is_component_build |
| 309 } |
| 257 } | 310 } |
| 258 | 311 |
| 259 if (defined(invoker.deps)) { | 312 if (defined(invoker.deps)) { |
| 260 deps = invoker.deps | 313 deps = invoker.deps |
| 261 } | 314 } |
| 262 } | 315 } |
| 263 } | 316 } |
| OLD | NEW |