1import("//llvm/utils/gn/build/toolchain/compiler.gni") 2 3unix_copy_command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})" 4 5template("unix_toolchain") { 6 toolchain(target_name) { 7 # https://groups.google.com/a/chromium.org/g/gn-dev/c/F_lv5T-tNDM 8 forward_variables_from(invoker.toolchain_args, "*") 9 not_needed("*") 10 11 forward_variables_from(invoker, "*") 12 13 cc = "cc" 14 cxx = "c++" 15 16 if (clang_base_path != "") { 17 cc = rebase_path(clang_base_path, root_build_dir) + "/bin/clang" 18 cxx = rebase_path(clang_base_path, root_build_dir) + "/bin/clang++" 19 } 20 21 ld = cxx # Don't use compiler wrapper for linking. 22 if (compiler_wrapper != "") { 23 cc = "$compiler_wrapper $cc" 24 cxx = "$compiler_wrapper $cxx" 25 } 26 27 tool("cc") { 28 depfile = "{{output}}.d" 29 command = "$cc -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}" 30 depsformat = "gcc" 31 description = "CC {{output}}" 32 outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.o" ] 33 } 34 35 tool("cxx") { 36 depfile = "{{output}}.d" 37 command = "$cxx -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}" 38 depsformat = "gcc" 39 description = "CXX {{output}}" 40 outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.o" ] 41 } 42 43 tool("objcxx") { 44 depfile = "{{output}}.d" 45 command = "$cxx -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_objcc}}" 46 depsformat = "gcc" 47 description = "OBJCXX {{output}}" 48 outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.o" ] 49 } 50 51 tool("asm") { 52 depfile = "{{output}}.d" 53 command = "$cc -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{asmflags}}" 54 depsformat = "gcc" 55 description = "ASM {{output}}" 56 outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.o" ] 57 } 58 59 tool("alink") { 60 if (current_os == "ios" || current_os == "mac") { 61 command = "libtool -D -static -no_warning_for_no_symbols {{arflags}} -o {{output}} {{inputs}}" 62 } else { 63 # Remove the output file first so that ar doesn't try to modify the 64 # existing file. 65 command = 66 "rm -f {{output}} && $ar rcsD {{arflags}} {{output}} {{inputs}}" 67 } 68 description = "AR {{output}}" 69 outputs = [ "{{output_dir}}/{{target_output_name}}.a" ] 70 output_prefix = "lib" 71 default_output_dir = "{{root_out_dir}}/lib" 72 } 73 74 if (current_os == "ios" || current_os == "mac") { 75 # gn < 1693 (e214b5d35898) doesn't support |frameworks|, requiring 76 # frameworks to be listed in |libs|, but gn >= 1808 (3028c6a426a4) forbids 77 # frameworks from appearing in |libs|. This assertion provides a helpful 78 # cue to upgrade, and is much more user-friendly than the failure that 79 # occurs when an older gn encounters |frameworks|. 80 # 81 # gn_version doesn’t actually exist in gn < 1709 (52cb644a3fb4), and 82 # defined(gn_version) doesn't actually work as expected 83 # (https://crbug.com/gn/183), so 1709 is the true minimum enforced by 84 # this construct, and if gn_version is not available, this line will still 85 # be blamed, making the resolution somewhat discoverable. 86 assert(gn_version >= 1693, 87 "Your GN is too old! " + 88 "Update it, perhaps by running llvm/utils/gn/get.py") 89 } 90 91 # Make these apply to all tools below. 92 lib_switch = "-l" 93 lib_dir_switch = "-L" 94 95 tool("solink") { 96 outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 97 if (current_os == "ios" || current_os == "mac") { 98 command = "$ld -shared {{ldflags}} -o $outfile {{inputs}} {{libs}} {{frameworks}}" 99 default_output_extension = ".dylib" 100 } else { 101 command = "$ld -shared {{ldflags}} -Wl,-soname,{{target_output_name}}{{output_extension}} -o $outfile {{inputs}} {{libs}}" 102 default_output_extension = ".so" 103 } 104 description = "SOLINK $outfile" 105 outputs = [ outfile ] 106 output_prefix = "lib" 107 default_output_dir = "{{root_out_dir}}/lib" 108 } 109 110 tool("solink_module") { 111 outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 112 if (current_os == "ios" || current_os == "mac") { 113 command = "$ld -shared {{ldflags}} -Wl,-flat_namespace -Wl,-undefined,suppress -o $outfile {{inputs}} {{libs}} {{frameworks}}" 114 default_output_extension = ".dylib" 115 } else { 116 command = "$ld -shared {{ldflags}} -Wl,-soname,{{target_output_name}}{{output_extension}} -o $outfile {{inputs}} {{libs}}" 117 default_output_extension = ".so" 118 } 119 description = "SOLINK $outfile" 120 outputs = [ outfile ] 121 default_output_dir = "{{root_out_dir}}/lib" 122 } 123 124 tool("link") { 125 outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 126 if (current_os == "ios" || current_os == "mac") { 127 command = 128 "$ld {{ldflags}} -o $outfile {{inputs}} {{libs}} {{frameworks}}" 129 } else { 130 command = "$ld {{ldflags}} -o $outfile -Wl,--start-group {{inputs}} -Wl,--end-group {{libs}}" 131 } 132 description = "LINK $outfile" 133 outputs = [ outfile ] 134 135 # Setting this allows targets to override the default executable output by 136 # setting output_dir. 137 default_output_dir = "{{root_out_dir}}/bin" 138 } 139 140 tool("copy") { 141 command = unix_copy_command 142 description = "COPY {{source}} {{output}}" 143 } 144 145 if (current_os == "ios" || current_os == "mac") { 146 tool("copy_bundle_data") { 147 # https://github.com/nico/hack/blob/master/notes/copydir.md 148 _copydir = "cd {{source}} && " + 149 "find . | cpio -pdl \"\$OLDPWD\"/{{output}} 2>/dev/null" 150 command = "rm -rf {{output}} && if [[ -d {{source}} ]]; then " + 151 _copydir + "; else " + unix_copy_command + "; fi" 152 description = "COPY_BUNDLE_DATA {{source}} {{output}}" 153 } 154 tool("compile_xcassets") { 155 command = "false" 156 description = "The LLVM build doesn't use any xcasset files" 157 } 158 } 159 160 tool("stamp") { 161 command = "touch {{output}}" 162 description = "STAMP {{output}}" 163 } 164 } 165} 166 167unix_toolchain("unix") { 168 if (current_os != "ios" && current_os != "mac") { 169 if (clang_base_path != "") { 170 ar = rebase_path(clang_base_path, root_build_dir) + "/bin/llvm-ar" 171 } else { 172 ar = "ar" 173 } 174 } 175 176 toolchain_args = { 177 current_os = host_os 178 current_cpu = host_cpu 179 } 180} 181 182# This template defines a toolchain that uses just-built clang and lld 183# as compiler and linker. 184template("stage2_unix_toolchain") { 185 unix_toolchain(target_name) { 186 toolchain_args = { 187 forward_variables_from(invoker.toolchain_args, "*") 188 189 clang_base_path = root_build_dir 190 llvm_enable_zstd = false 191 } 192 193 deps = [ 194 "//:clang($host_toolchain)", 195 "//:lld($host_toolchain)", 196 ] 197 if (toolchain_args.current_os != "ios" && 198 toolchain_args.current_os != "mac") { 199 ar = "bin/llvm-ar" 200 deps += [ "//:llvm-ar($host_toolchain)" ] 201 } 202 } 203} 204 205stage2_unix_toolchain("stage2_unix") { 206 toolchain_args = { 207 current_os = host_os 208 current_cpu = host_cpu 209 } 210} 211 212stage2_unix_toolchain("stage2_unix_x86") { 213 toolchain_args = { 214 current_os = host_os 215 current_cpu = "x86" 216 } 217} 218 219if (android_ndk_path != "") { 220 # Android compiler-rt libraries don't really work with per-target runtime 221 # directories yet so force it off. 222 # https://discourse.llvm.org/t/handling-version-numbers-in-per-target-runtime-directories/62717. 223 stage2_unix_toolchain("stage2_android_aarch64") { 224 toolchain_args = { 225 current_os = "android" 226 current_cpu = "arm64" 227 clang_enable_per_target_runtime_dir = false 228 } 229 } 230 231 stage2_unix_toolchain("stage2_android_arm") { 232 toolchain_args = { 233 current_os = "android" 234 current_cpu = "arm" 235 clang_enable_per_target_runtime_dir = false 236 } 237 } 238 239 stage2_unix_toolchain("stage2_android_x64") { 240 toolchain_args = { 241 current_os = "android" 242 current_cpu = "x64" 243 clang_enable_per_target_runtime_dir = false 244 } 245 } 246 247 stage2_unix_toolchain("stage2_android_x86") { 248 toolchain_args = { 249 current_os = "android" 250 current_cpu = "x86" 251 clang_enable_per_target_runtime_dir = false 252 } 253 } 254} 255 256if (host_os == "mac") { 257 stage2_unix_toolchain("stage2_ios_aarch64") { 258 toolchain_args = { 259 current_os = "ios" 260 current_cpu = "arm64" 261 } 262 } 263 264 stage2_unix_toolchain("stage2_iossim_x64") { 265 toolchain_args = { 266 current_os = "ios" 267 current_cpu = "x64" 268 } 269 } 270} 271 272stage2_unix_toolchain("stage2_baremetal_aarch64") { 273 toolchain_args = { 274 current_os = "baremetal" 275 current_cpu = "arm64" 276 277 # FIXME: These should be set in all toolchains building sanitizers, 278 # see discussion at https://reviews.llvm.org/D127906#3587329 279 use_asan = false 280 use_tsan = false 281 use_ubsan = false 282 } 283} 284 285template("win_toolchain") { 286 toolchain(target_name) { 287 # https://groups.google.com/a/chromium.org/d/msg/gn-dev/F_lv5T-tNDM 288 forward_variables_from(invoker.toolchain_args, "*") 289 not_needed("*") 290 291 forward_variables_from(invoker, "*") 292 293 cl = "cl" 294 link = "link" 295 296 if (clang_base_path != "") { 297 cl = rebase_path(clang_base_path, root_build_dir) + "/bin/clang-cl" 298 if (use_lld) { 299 link = rebase_path(clang_base_path, root_build_dir) + "/bin/lld-link" 300 } 301 } 302 303 if (compiler_wrapper != "") { 304 cl = "$compiler_wrapper $cl" 305 } 306 307 tool("cc") { 308 command = "$cl /nologo /showIncludes /Fo{{output}} /c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}" 309 depsformat = "msvc" 310 description = "CC {{output}}" 311 outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.obj" ] 312 } 313 314 tool("cxx") { 315 command = "$cl /nologo /showIncludes /Fo{{output}} /c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}" 316 depsformat = "msvc" 317 description = "CXX {{output}}" 318 outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.obj" ] 319 } 320 321 tool("alink") { 322 command = "$link /lib /nologo {{arflags}} /out:{{output}} {{inputs}}" 323 description = "LIB {{output}}" 324 outputs = [ "{{output_dir}}/{{target_output_name}}.lib" ] 325 default_output_dir = "{{root_out_dir}}/lib" 326 } 327 328 # Make these apply to all tools below. 329 lib_switch = "" 330 lib_dir_switch = "/LIBPATH:" 331 332 tool("solink") { 333 outprefix = "{{output_dir}}/{{target_output_name}}" 334 dllfile = "$outprefix{{output_extension}}" 335 libfile = "$outprefix.lib" 336 pdbfile = "$outprefix.pdb" 337 command = "$link /nologo /dll {{ldflags}} /out:$dllfile /implib:$libfile /pdb:$pdbfile {{inputs}} {{libs}} " 338 description = "LINK $dllfile" 339 link_output = libfile 340 depend_output = libfile 341 runtime_outputs = [ dllfile ] 342 outputs = [ 343 dllfile, 344 libfile, 345 ] 346 default_output_extension = ".dll" 347 restat = true 348 349 # Put dlls next to the executables in bin/ on Windows, since Windows 350 # doesn't have a configurable rpath. This matches initialization of 351 # module_dir to bin/ in AddLLVM.cmake's set_output_directory(). 352 default_output_dir = "{{root_out_dir}}/bin" 353 } 354 355 # Plugins for opt and clang and so on don't work in LLVM's Windows build 356 # since the code doesn't have export annotations, but there are a few 357 # standalone loadable modules used for unit-testing LLVM's dynamic library 358 # loading code. 359 tool("solink_module") { 360 outprefix = "{{output_dir}}/{{target_output_name}}" 361 dllfile = "$outprefix{{output_extension}}" 362 pdbfile = "$outprefix.pdb" 363 command = "$link /nologo /dll {{ldflags}} /out:$dllfile /pdb:$pdbfile {{inputs}} {{libs}} " 364 description = "LINK_MODULE $dllfile" 365 outputs = [ dllfile ] 366 runtime_outputs = outputs 367 default_output_extension = ".dll" 368 369 # No default_output_dir, all clients set output_dir. 370 } 371 372 tool("link") { 373 outprefix = "{{output_dir}}/{{target_output_name}}" 374 outfile = "$outprefix{{output_extension}}" 375 pdbfile = "$outprefix.pdb" 376 command = "$link /nologo {{ldflags}} /out:$outfile /pdb:$pdbfile {{inputs}} {{libs}}" 377 description = "LINK $outfile" 378 outputs = [ outfile ] 379 default_output_extension = ".exe" 380 381 # Setting this allows targets to override the default executable output by 382 # setting output_dir. 383 default_output_dir = "{{root_out_dir}}/bin" 384 } 385 386 tool("copy") { 387 if (host_os == "win") { 388 # GN hands out slash-using paths, but cmd's copy needs backslashes. 389 # Use cmd's %foo:a=b% substitution feature to convert. 390 command = "cmd /c set source=\"{{source}}\" & set output=\"{{output}}\" & call copy /Y %source:/=\% %output:\=/% > nul" 391 } else { 392 command = unix_copy_command 393 } 394 395 description = "COPY {{source}} {{output}}" 396 } 397 398 tool("stamp") { 399 if (host_os == "win") { 400 command = "cmd /c type nul > {{output}}" 401 } else { 402 command = "touch {{output}}" 403 } 404 description = "STAMP {{output}}" 405 } 406 } 407} 408 409win_toolchain("win") { 410 toolchain_args = { 411 current_os = "win" 412 current_cpu = host_cpu 413 } 414} 415 416win_toolchain("stage2_win_x64") { 417 toolchain_args = { 418 current_os = "win" 419 current_cpu = "x64" 420 421 if (host_os != "win") { 422 sysroot = win_sysroot 423 } 424 clang_base_path = root_build_dir 425 } 426 deps = [ 427 "//:clang($host_toolchain)", 428 "//:lld($host_toolchain)", 429 ] 430} 431 432win_toolchain("stage2_win_x86") { 433 toolchain_args = { 434 current_os = "win" 435 current_cpu = "x86" 436 437 if (host_os != "win") { 438 sysroot = win_sysroot 439 } 440 clang_base_path = root_build_dir 441 } 442 deps = [ 443 "//:clang($host_toolchain)", 444 "//:lld($host_toolchain)", 445 ] 446} 447