• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 Google Inc.
2#
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6declare_args() {
7  ar = "ar"
8  cc = "cc"
9  cxx = "c++"
10
11  if (is_android) {
12    if (host_os == "win") {
13      ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar.exe"
14      cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang.exe"
15      cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++.exe"
16    } else {
17      ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar"
18      cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang"
19      cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++"
20    }
21  }
22
23  msvc = 2015
24
25  extra_cflags = []
26  extra_cflags_c = []
27  extra_cflags_cc = []
28  extra_ldflags = []
29
30  cc_wrapper = ""
31  malloc = ""
32}
33declare_args() {
34  if (msvc == 2015) {
35    windk = "C:/Program Files (x86)/Microsoft Visual Studio 14.0"
36  } else {
37    windk = "C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional"
38  }
39}
40
41if (host_os == "win") {
42  python = "python.bat"
43  stamp = "cmd.exe /c echo >"
44} else {
45  python = "python"
46  stamp = "touch"
47}
48
49is_clang = is_android || is_ios || is_mac || (cc == "clang" && cxx == "clang++")
50if (!is_clang && !is_win) {
51  is_clang = exec_script("is_clang.py",
52                         [
53                           cc,
54                           cxx,
55                         ],
56                         "value")
57}
58
59if (is_ios) {
60  if (is_tvos) {
61    sdk = "appletvos"
62    if (target_cpu == "x86" || target_cpu == "x64") {
63      sdk = "appletvsimulator"
64    }
65  } else {
66    sdk = "iphoneos"
67    if (target_cpu == "x86" || target_cpu == "x64") {
68      sdk = "iphonesimulator"
69    }
70  }
71  ios_sysroot = exec_script("find_ios_sysroot.py", [ sdk ], "trim string")
72}
73
74config("default") {
75  asmflags = []
76  cflags = []
77  cflags_c = []
78  cflags_cc = []
79  defines = []
80  ldflags = []
81  libs = []
82
83  if (is_win) {
84    cflags += [
85      "/FS",  # Preserve previous PDB behavior.
86      "/bigobj",  # Some of our files are bigger than the regular limits.
87      "/WX",  # Treat warnings as errors.
88      "/utf-8",  # Set Source and Executable character sets to UTF-8.
89    ]
90    defines += [
91      "_CRT_SECURE_NO_WARNINGS",  # Disables warnings about sscanf().
92      "_HAS_EXCEPTIONS=0",  # Disables exceptions in MSVC STL.
93      "WIN32_LEAN_AND_MEAN",
94      "NOMINMAX",
95    ]
96    include_dirs = [
97      #2017
98      "$windk/VC/Tools/MSVC/14.10.25017/include",
99
100      #2015
101      "$windk/VC/include",
102
103      # For local builds.
104      # 2017
105      "$windk/../../../Windows Kits/10/Include/10.0.14393.0/shared",
106      "$windk/../../../Windows Kits/10/Include/10.0.14393.0/ucrt",
107      "$windk/../../../Windows Kits/10/Include/10.0.14393.0/um",
108      "$windk/../../../Windows Kits/10/Include/10.0.14393.0/winrt",
109
110      # 2015
111      "$windk/../Windows Kits/8.1/Include/shared",
112      "$windk/../Windows Kits/10/Include/10.0.10150.0/ucrt",
113      "$windk/../Windows Kits/8.1/Include/um",
114      "$windk/../Windows Kits/8.1/Include/winrt",
115
116      # For builds using win_toolchain asset.
117      "$windk/win_sdk/Include/10.0.14393.0/shared",
118      "$windk/win_sdk/Include/10.0.14393.0/ucrt",
119      "$windk/win_sdk/Include/10.0.14393.0/um",
120      "$windk/win_sdk/Include/10.0.14393.0/winrt",
121    ]
122    lib_dirs = [
123      # For local builds.
124      # 2017
125      "$windk/../../../Windows Kits/10/Lib/10.0.14393.0/ucrt/$target_cpu",
126      "$windk/../../../Windows Kits/10/Lib/10.0.14393.0/um/$target_cpu",
127
128      #2015
129      "$windk/../Windows Kits/10/Lib/10.0.10150.0/ucrt/$target_cpu",
130      "$windk/../Windows Kits/8.1/Lib/winv6.3/um/$target_cpu",
131
132      # For builds using win_toolchain asset.
133      "$windk/win_sdk/Lib/10.0.14393.0/ucrt/$target_cpu",
134      "$windk/win_sdk/Lib/10.0.14393.0/um/$target_cpu",
135    ]
136
137    #2017
138    lib_dirs += [ "$windk/VC/Tools/MSVC/14.10.25017/lib/$target_cpu" ]
139
140    #2015
141    if (target_cpu == "x86") {
142      lib_dirs += [ "$windk/VC/lib" ]
143    } else {
144      lib_dirs += [ "$windk/VC/lib/amd64" ]
145    }
146  } else {
147    cflags += [
148      "-fstrict-aliasing",
149      "-fPIC",
150      "-Werror",
151    ]
152    cflags_cc += [
153      "-std=c++11",
154      "-fno-threadsafe-statics",
155    ]
156
157    # The main idea is to slim the exported API, but these flags also improve link time on Mac.
158    # These would make stack traces worse on Linux, so we don't just set them willy-nilly.
159    if (is_component_build || is_mac) {
160      cflags += [ "-fvisibility=hidden" ]
161      cflags_cc += [ "-fvisibility-inlines-hidden" ]
162    }
163  }
164
165  if (current_cpu == "arm") {
166    cflags += [
167      "-march=armv7-a",
168      "-mfpu=neon",
169      "-mthumb",
170    ]
171  } else if (current_cpu == "mipsel") {
172    cflags += [
173      "-no-integrated-as",  # Clang <4.0 doesn't understand 'usw' mnemonic.
174      "-march=mips32r2",
175      "-mdspr2",
176    ]
177  } else if (current_cpu == "x86" && !is_win) {
178    asmflags += [ "-m32" ]
179    cflags += [
180      "-m32",
181      "-msse2",
182      "-mfpmath=sse",
183    ]
184    ldflags += [ "-m32" ]
185  }
186
187  if (malloc != "" && !is_win) {
188    cflags += [
189      "-fno-builtin-malloc",
190      "-fno-builtin-calloc",
191      "-fno-builtin-realloc",
192      "-fno-builtin-free",
193    ]
194    libs += [ malloc ]
195  }
196
197  if (is_android) {
198    asmflags += [
199      "--target=$ndk_target",
200      "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin",
201    ]
202    cflags += [
203      "--sysroot=$ndk/platforms/$ndk_platform",
204      "--target=$ndk_target",
205      "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin",
206    ]
207    cflags_cc += [
208      "-isystem$ndk/sources/android/support/include",
209      "-isystem$ndk/sources/cxx-stl/gnu-libstdc++/4.9/include",
210      "-isystem$ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/$ndk_stdlib/include",
211    ]
212    ldflags += [
213      "--sysroot=$ndk/platforms/$ndk_platform",
214      "--target=$ndk_target",
215      "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin",
216    ]
217    lib_dirs = [
218      "$ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/$ndk_stdlib",
219      "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/lib/gcc/$ndk_target/4.9.x",
220    ]
221
222    if (current_cpu == "mips64el") {
223      # The r13 NDK omits /usr/lib from the MIPS64 sysroots, but Clang searches
224      # for /usr/lib64 as $PATH_TO_USR_LIB/../lib64.  If there's no /usr/lib,
225      # it can't find /usr/lib64.  We must point Clang at /usr/lib64 manually.
226      lib_dirs += [ "$ndk/platforms/$ndk_platform/usr/lib64" ]
227      ldflags += [ "-B$ndk/platforms/$ndk_platform/usr/lib64" ]
228    }
229
230    libs += [ "gnustl_static" ]
231  }
232
233  if (is_ios) {
234    _target = target_cpu
235    if (target_cpu == "arm") {
236      _target = "armv7"
237    } else if (target_cpu == "x86") {
238      _target = "i386"
239    } else if (target_cpu == "x64") {
240      _target = "x86_64"
241    }
242    asmflags += [
243      "-isysroot",
244      ios_sysroot,
245      "-arch",
246      _target,
247    ]
248    cflags += [
249      "-isysroot",
250      ios_sysroot,
251      "-arch",
252      _target,
253    ]
254    cflags_cc += [ "-stdlib=libc++" ]
255    ldflags += [
256      "-isysroot",
257      ios_sysroot,
258      "-arch",
259      _target,
260      "-stdlib=libc++",
261    ]
262    libs += [ "objc" ]
263  }
264
265  if (is_linux) {
266    libs += [ "pthread" ]
267  }
268
269  if (sanitize != "") {
270    # You can either pass the sanitizers directly, e.g. "address,undefined",
271    # or pass one of the couple common aliases used by the bots.
272    sanitizers = sanitize
273    if (sanitize == "ASAN") {
274      sanitizers = "address,bool,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr"
275    } else if (sanitize == "TSAN") {
276      sanitizers = "thread"
277    } else if (sanitize == "MSAN") {
278      sanitizers = "memory"
279    }
280
281    cflags += [
282      "-fsanitize=$sanitizers",
283      "-fno-sanitize-recover=$sanitizers",
284      "-fsanitize-blacklist=" + rebase_path("../tools/xsan.blacklist"),
285    ]
286    ldflags += [ "-fsanitize=$sanitizers" ]
287    if (sanitizers == "memory") {
288      cflags += [ "-fsanitize-memory-track-origins" ]
289      cflags_cc += [ "-stdlib=libc++" ]
290      ldflags += [ "-stdlib=libc++" ]
291    }
292  }
293}
294
295config("no_exceptions") {
296  # Exceptions are disabled by default on Windows.  (Use /EHsc to enable them.)
297  if (!is_win) {
298    cflags_cc = [ "-fno-exceptions" ]
299  }
300}
301
302config("warnings") {
303  cflags = []
304  cflags_cc = []
305  cflags_objc = []
306  if (is_win) {
307    cflags += [
308      "/W3",  # Turn on lots of warnings.
309
310      # Disable a bunch of warnings:
311      "/wd4244",  # conversion from 'float' to 'int', possible loss of data
312      "/wd4267",  # conversion from 'size_t' to 'int', possible loss of data
313      "/wd4800",  # forcing value to bool 'true' or 'false' (performance warning)
314
315      # Probably only triggers when /EHsc is enabled.
316      "/wd4291",  # no matching operator delete found;
317                  # memory will not be freed if initialization throws an exception
318    ]
319  } else {
320    cflags += [
321      "-Wall",
322      "-Wextra",
323      "-Winit-self",
324      "-Wpointer-arith",
325      "-Wsign-compare",
326      "-Wvla",
327
328      "-Wno-deprecated-declarations",
329      "-Wno-maybe-uninitialized",
330    ]
331    cflags_cc += [ "-Wnon-virtual-dtor" ]
332
333    if (is_clang) {
334      cflags += [
335        "-Weverything",
336        "-Wno-unknown-warning-option",  # Let older Clangs ignore newer Clangs' warnings.
337      ]
338
339      if ((target_cpu == "x86" && is_android) ||
340          (target_cpu == "arm" && is_ios)) {
341        # Clang seems to think new/malloc will only be 4-byte aligned on x86 Android and 32-bit iOS.
342        # We're pretty sure it's actually 8-byte alignment.
343        cflags += [ "-Wno-over-aligned" ]
344      }
345
346      cflags += [
347        "-Wno-cast-align",
348        "-Wno-conditional-uninitialized",
349        "-Wno-conversion",
350        "-Wno-disabled-macro-expansion",
351        "-Wno-documentation",
352        "-Wno-documentation-unknown-command",
353        "-Wno-double-promotion",
354        "-Wno-exit-time-destructors",  # TODO: OK outside libskia
355        "-Wno-float-conversion",
356        "-Wno-float-equal",
357        "-Wno-format-nonliteral",
358        "-Wno-global-constructors",  # TODO: OK outside libskia
359        "-Wno-gnu-zero-variadic-macro-arguments",
360        "-Wno-missing-prototypes",
361        "-Wno-missing-variable-declarations",
362        "-Wno-pedantic",
363        "-Wno-reserved-id-macro",
364        "-Wno-shadow",
365        "-Wno-shift-sign-overflow",
366        "-Wno-sign-conversion",
367        "-Wno-signed-enum-bitfield",
368        "-Wno-switch-enum",
369        "-Wno-undef",
370        "-Wno-unreachable-code",
371        "-Wno-unreachable-code-break",
372        "-Wno-unreachable-code-return",
373        "-Wno-unused-macros",
374        "-Wno-unused-member-function",
375      ]
376      cflags_cc += [
377        "-Wno-abstract-vbase-init",
378        "-Wno-weak-vtables",
379      ]
380
381      # We are unlikely to want to fix these.
382      cflags += [
383        "-Wno-covered-switch-default",
384        "-Wno-deprecated",
385        "-Wno-implicit-fallthrough",
386        "-Wno-missing-noreturn",
387        "-Wno-old-style-cast",
388        "-Wno-padded",
389      ]
390      cflags_cc += [
391        "-Wno-c++98-compat",
392        "-Wno-c++98-compat-pedantic",
393        "-Wno-undefined-func-template",
394      ]
395      cflags_objc += [
396        "-Wno-direct-ivar-access",
397        "-Wno-objc-interface-ivars",
398      ]
399    }
400  }
401}
402config("warnings_except_public_headers") {
403  if (!is_win) {
404    cflags = [ "-Wno-unused-parameter" ]
405  }
406}
407
408config("extra_flags") {
409  cflags = extra_cflags
410  cflags_c = extra_cflags_c
411  cflags_cc = extra_cflags_cc
412  ldflags = extra_ldflags
413}
414
415config("debug_symbols") {
416  # It's annoying to wait for full debug symbols to push over
417  # to Android devices.  -gline-tables-only is a lot slimmer.
418  if (is_android) {
419    cflags = [ "-gline-tables-only" ]
420  } else if (is_win) {
421    cflags = [ "/Zi" ]
422    ldflags = [ "/DEBUG" ]
423  } else {
424    cflags = [ "-g" ]
425  }
426}
427
428config("no_rtti") {
429  if (sanitize != "ASAN") {  # -fsanitize=vptr requires RTTI
430    if (is_win) {
431      cflags_cc = [ "/GR-" ]
432    } else {
433      cflags_cc = [ "-fno-rtti" ]
434    }
435  }
436}
437
438config("release") {
439  if (is_win) {
440    cflags = [
441      "/O2",
442      "/Zc:inline",
443      "/GS-",
444    ]
445    ldflags = [
446      "/OPT:ICF",
447      "/OPT:REF",
448    ]
449  } else {
450    cflags = [
451      "-O3",
452      "-fdata-sections",
453      "-ffunction-sections",
454    ]
455    if (is_mac || is_ios) {
456      ldflags = [ "-dead_strip" ]
457    } else {
458      ldflags = [ "-Wl,--gc-sections" ]
459    }
460  }
461  defines = [ "NDEBUG" ]
462}
463
464config("executable") {
465  if (is_android) {
466    ldflags = [ "-pie" ]
467  } else if (is_mac) {
468    ldflags = [ "-Wl,-rpath,@loader_path/." ]
469  } else if (is_linux) {
470    ldflags = [
471      "-rdynamic",
472      "-Wl,-rpath,\$ORIGIN",
473    ]
474  } else if (is_win) {
475    ldflags = [
476      "/SUBSYSTEM:CONSOLE",  # Quiet "no subsystem specified; CONSOLE assumed".
477      "/INCREMENTAL:NO",  # Quiet warnings about failing to incrementally link by never trying to.
478    ]
479  }
480}
481
482toolchain("msvc") {
483  lib_dir_switch = "/LIBPATH:"
484
485  if (msvc == 2015) {
486    bin = "$windk/VC/bin/amd64"
487    env_setup = ""
488    if (target_cpu == "x86") {
489      bin += "_x86"
490      env_setup = "cmd /c $windk/win_sdk/bin/SetEnv.cmd /x86 && "
491    }
492  } else {
493    bin = "$windk/VC/Tools/MSVC/14.10.25017/bin/HostX64/$target_cpu"
494    env_setup = ""
495    if (target_cpu == "x86") {
496      print("Be sure to run")
497      print("$windk/VC/Auxiliary/Build/vcvarsall.bat amd64_x86")
498      print("to set up your environment before running ninja.")
499    }
500  }
501
502  tool("asm") {
503    command = "$env_setup$bin/ml64.exe /nologo /c /Fo {{output}} {{source}}"
504    outputs = [
505      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
506    ]
507    description = "assemble {{source}}"
508  }
509
510  tool("cc") {
511    rspfile = "{{output}}.rsp"
512    precompiled_header_type = "msvc"
513    pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
514
515    # Label names may have spaces so pdbname must be quoted.
516    command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
517    depsformat = "msvc"
518    outputs = [
519      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
520    ]
521    rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
522    description = "compile {{source}}"
523  }
524
525  tool("cxx") {
526    rspfile = "{{output}}.rsp"
527    precompiled_header_type = "msvc"
528    pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
529
530    # Label names may have spaces so pdbname must be quoted.
531    command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
532    depsformat = "msvc"
533    outputs = [
534      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
535    ]
536    rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
537    description = "compile {{source}}"
538  }
539
540  tool("alink") {
541    rspfile = "{{output}}.rsp"
542
543    command = "$env_setup$bin/lib.exe /nologo /ignore:4221 {{arflags}} /OUT:{{output}} @$rspfile"
544    outputs = [
545      # Ignore {{output_extension}} and always use .lib, there's no reason to
546      # allow targets to override this extension on Windows.
547      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
548    ]
549    default_output_extension = ".lib"
550    default_output_dir = "{{target_out_dir}}"
551
552    # inputs_newline works around a fixed per-line buffer size in the linker.
553    rspfile_content = "{{inputs_newline}}"
554    description = "link {{output}}"
555  }
556
557  tool("solink") {
558    dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
559    libname = "${dllname}.lib"
560    pdbname = "${dllname}.pdb"
561    rspfile = "${dllname}.rsp"
562
563    command = "$env_setup$bin/link.exe /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
564    outputs = [
565      dllname,
566      libname,
567      pdbname,
568    ]
569    default_output_extension = ".dll"
570    default_output_dir = "{{root_out_dir}}"
571
572    link_output = libname
573    depend_output = libname
574    runtime_outputs = [
575      dllname,
576      pdbname,
577    ]
578
579    # I don't quite understand this.  Aping Chrome's toolchain/win/BUILD.gn.
580    restat = true
581
582    # inputs_newline works around a fixed per-line buffer size in the linker.
583    rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
584    description = "link {{output}}"
585  }
586
587  tool("link") {
588    exename = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
589    pdbname = "$exename.pdb"
590    rspfile = "$exename.rsp"
591
592    command =
593        "$env_setup$bin/link.exe /nologo /OUT:$exename /PDB:$pdbname @$rspfile"
594
595    default_output_extension = ".exe"
596    default_output_dir = "{{root_out_dir}}"
597    outputs = [
598      exename,
599    ]
600
601    # inputs_newline works around a fixed per-line buffer size in the linker.
602    rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
603    description = "link {{output}}"
604  }
605
606  tool("stamp") {
607    command = "$stamp {{output}}"
608    description = "stamp {{output}}"
609  }
610
611  tool("copy") {
612    cp_py = rebase_path("cp.py")
613    command = "$python $cp_py {{source}} {{output}}"
614    description = "copy {{source}} {{output}}"
615  }
616}
617
618toolchain("gcc_like") {
619  lib_switch = "-l"
620  lib_dir_switch = "-L"
621
622  tool("cc") {
623    depfile = "{{output}}.d"
624    command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
625    depsformat = "gcc"
626    outputs = [
627      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
628    ]
629    description = "compile {{source}}"
630  }
631
632  tool("cxx") {
633    depfile = "{{output}}.d"
634    command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
635    depsformat = "gcc"
636    outputs = [
637      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
638    ]
639    description = "compile {{source}}"
640  }
641
642  tool("objc") {
643    depfile = "{{output}}.d"
644    command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}"
645    depsformat = "gcc"
646    outputs = [
647      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
648    ]
649    description = "compile {{source}}"
650  }
651
652  tool("objcxx") {
653    depfile = "{{output}}.d"
654    command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} {{cflags_objc}} -c {{source}} -o {{output}}"
655    depsformat = "gcc"
656    outputs = [
657      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
658    ]
659    description = "compile {{source}}"
660  }
661
662  tool("asm") {
663    depfile = "{{output}}.d"
664    command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
665    depsformat = "gcc"
666    outputs = [
667      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
668    ]
669    description = "compile {{source}}"
670  }
671
672  tool("alink") {
673    rspfile = "{{output}}.rsp"
674    rspfile_content = "{{inputs}}"
675    ar_py = rebase_path("ar.py")
676    command = "$python $ar_py $ar {{output}} $rspfile"
677    outputs = [
678      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
679    ]
680    default_output_extension = ".a"
681    output_prefix = "lib"
682    description = "link {{output}}"
683  }
684
685  tool("solink") {
686    soname = "{{target_output_name}}{{output_extension}}"
687
688    rpath = "-Wl,-soname,$soname"
689    if (is_mac) {
690      rpath = "-Wl,-install_name,@rpath/$soname"
691    }
692
693    command = "$cc_wrapper $cxx -shared {{ldflags}} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
694    outputs = [
695      "{{root_out_dir}}/$soname",
696    ]
697    output_prefix = "lib"
698    default_output_extension = ".so"
699    description = "link {{output}}"
700  }
701
702  tool("link") {
703    command = "$cc_wrapper $cxx {{ldflags}} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
704    outputs = [
705      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
706    ]
707    description = "link {{output}}"
708  }
709
710  tool("stamp") {
711    command = "$stamp {{output}}"
712    description = "stamp {{output}}"
713  }
714
715  tool("copy") {
716    cp_py = rebase_path("cp.py")
717    command = "$python $cp_py {{source}} {{output}}"
718    description = "copy {{source}} {{output}}"
719  }
720}
721