OLD | NEW |
1 # Copyright 2016 Google Inc. | 1 # Copyright 2016 Google Inc. |
2 # | 2 # |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 declare_args() { | 6 declare_args() { |
7 ar = "ar" | 7 ar = "ar" |
8 cc = "cc" | 8 cc = "cc" |
9 cxx = "c++" | 9 cxx = "c++" |
10 | 10 |
11 if (is_android) { | 11 if (is_android) { |
12 ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar" | 12 ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar" |
13 cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang" | 13 cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang" |
14 cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++" | 14 cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++" |
15 } | 15 } |
16 | 16 |
17 windk = "" | 17 windk = "" |
18 | 18 |
19 extra_cflags = "" | 19 extra_cflags = "" |
20 extra_cflags_c = "" | 20 extra_cflags_c = "" |
21 extra_cflags_cc = "" | 21 extra_cflags_cc = "" |
22 extra_ldflags = "" | 22 extra_ldflags = "" |
23 | 23 |
24 compiler_prefix = "" | 24 compiler_prefix = "" |
25 } | 25 } |
26 | 26 |
27 if (is_win) { | 27 config("default") { |
28 config("default") { | 28 asmflags = [] |
29 cflags = [ | 29 cflags = [] |
30 "/FS", # Preserve previous PDB behavior. | 30 cflags_c = [] |
| 31 cflags_cc = [] |
| 32 defines = [] |
| 33 ldflags = [] |
| 34 |
| 35 if (is_win) { |
| 36 cflags += [ |
| 37 "/FS", # Preserve previous PDB behavior. |
31 "/bigobj", # Some of our files are bigger than the regular limits. | 38 "/bigobj", # Some of our files are bigger than the regular limits. |
32 ] | 39 ] |
33 cflags_c = ["/TC"] | 40 cflags_c += [ "/TC" ] |
34 cflags_cc = ["/TP"] | 41 cflags_cc += [ "/TP" ] |
35 defines = [ | 42 defines += [ |
36 "_HAS_EXCEPTIONS=0", | 43 "_HAS_EXCEPTIONS=0", |
37 "WIN32_LEAN_AND_MEAN", | 44 "WIN32_LEAN_AND_MEAN", |
38 "NOMINMAX", | 45 "NOMINMAX", |
39 ] | 46 ] |
40 } | 47 } else { |
41 config("no_rtti") { } | 48 cflags += [ |
42 | |
43 config("debug_symbols") { } | |
44 | |
45 } else { | |
46 config("debug_symbols") { | |
47 # It's annoying to wait for full debug symbols to push over | |
48 # to Android devices. -gline-tables-only is a lot slimmer. | |
49 if (is_android) { | |
50 cflags = [ "-gline-tables-only" ] | |
51 } else { | |
52 cflags = [ "-g" ] | |
53 } | |
54 } | |
55 | |
56 config("no_rtti") { | |
57 if (sanitize != "ASAN") { # -fsanitize=vptr requires RTTI | |
58 cflags_cc = [ "-fno-rtti" ] | |
59 } | |
60 } | |
61 | |
62 config("default") { | |
63 asmflags = [] | |
64 cflags = [ | |
65 "-O1", | 49 "-O1", |
66 "-fstrict-aliasing", | 50 "-fstrict-aliasing", |
67 "-fPIC", | 51 "-fPIC", |
68 "-fvisibility=hidden", | 52 "-fvisibility=hidden", |
69 | 53 |
70 "-Werror", | 54 "-Werror", |
71 "-Wall", | 55 "-Wall", |
72 "-Wextra", | 56 "-Wextra", |
73 "-Winit-self", | 57 "-Winit-self", |
74 "-Wpointer-arith", | 58 "-Wpointer-arith", |
75 "-Wsign-compare", | 59 "-Wsign-compare", |
76 "-Wvla", | 60 "-Wvla", |
77 | 61 |
78 "-Wno-deprecated-declarations", | 62 "-Wno-deprecated-declarations", |
79 "-Wno-unused-parameter", | 63 "-Wno-unused-parameter", |
80 ] | 64 ] |
81 cflags_cc = [ | 65 cflags_cc += [ |
82 "-std=c++11", | 66 "-std=c++11", |
83 "-fno-exceptions", | 67 "-fno-exceptions", |
84 "-fno-threadsafe-statics", | 68 "-fno-threadsafe-statics", |
85 "-fvisibility-inlines-hidden", | 69 "-fvisibility-inlines-hidden", |
86 | 70 |
87 "-Wnon-virtual-dtor", | 71 "-Wnon-virtual-dtor", |
88 ] | 72 ] |
89 ldflags = [] | 73 } |
90 | 74 |
91 if (current_cpu == "arm") { | 75 if (current_cpu == "arm") { |
92 cflags += [ | 76 cflags += [ |
93 "-march=armv7-a", | 77 "-march=armv7-a", |
94 "-mfpu=neon", | 78 "-mfpu=neon", |
95 "-mthumb", | 79 "-mthumb", |
96 ] | 80 ] |
97 } else if (current_cpu == "mipsel") { | 81 } else if (current_cpu == "mipsel") { |
98 cflags += [ | 82 cflags += [ |
99 "-march=mips32r2", | 83 "-march=mips32r2", |
100 "-mdspr2", | 84 "-mdspr2", |
101 ] | 85 ] |
102 } else if (current_cpu == "x86") { | 86 } else if (current_cpu == "x86") { |
103 asmflags += [ "-m32" ] | 87 asmflags += [ "-m32" ] |
104 cflags += [ | 88 cflags += [ |
105 "-m32", | 89 "-m32", |
106 "-msse2", | 90 "-msse2", |
107 "-mfpmath=sse", | 91 "-mfpmath=sse", |
108 ] | 92 ] |
109 ldflags += [ "-m32" ] | 93 ldflags += [ "-m32" ] |
110 } | 94 } |
111 | 95 |
112 if (is_android) { | 96 if (is_android) { |
113 asmflags += [ | 97 asmflags += [ |
114 "--target=$ndk_target", | 98 "--target=$ndk_target", |
115 "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin", | 99 "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin", |
116 ] | 100 ] |
117 cflags += [ | 101 cflags += [ |
118 "--sysroot=$ndk/platforms/$ndk_platform", | 102 "--sysroot=$ndk/platforms/$ndk_platform", |
119 "--target=$ndk_target", | 103 "--target=$ndk_target", |
120 "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin", | 104 "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin", |
121 ] | 105 ] |
122 cflags_cc += [ | 106 cflags_cc += [ |
123 "-isystem$ndk/sources/android/support/include", | 107 "-isystem$ndk/sources/android/support/include", |
124 "-isystem$ndk/sources/cxx-stl/llvm-libc++/libcxx/include", | 108 "-isystem$ndk/sources/cxx-stl/llvm-libc++/libcxx/include", |
125 ] | 109 ] |
126 ldflags += [ | 110 ldflags += [ |
127 "--sysroot=$ndk/platforms/$ndk_platform", | 111 "--sysroot=$ndk/platforms/$ndk_platform", |
128 "--target=$ndk_target", | 112 "--target=$ndk_target", |
129 "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin", | 113 "-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin", |
130 "-pie", | 114 "-pie", |
131 ] | 115 ] |
132 lib_dirs = [ | 116 lib_dirs = [ |
133 "$ndk/sources/cxx-stl/llvm-libc++/libs/$ndk_stdlib", | 117 "$ndk/sources/cxx-stl/llvm-libc++/libs/$ndk_stdlib", |
134 "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/lib/gcc/$ndk_target/
4.9.x", | 118 "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/lib/gcc/$ndk_target/4.
9.x", |
135 ] | 119 ] |
136 | 120 |
137 libs = [ | 121 libs = [ |
138 # Order matters here! Keep these three in exactly this order. | 122 # Order matters here! Keep these three in exactly this order. |
139 "c++_static", | 123 "c++_static", |
140 "c++abi", | 124 "c++abi", |
141 "android_support", | 125 "android_support", |
142 ] | 126 ] |
143 if (target_cpu == "arm") { | 127 if (target_cpu == "arm") { |
144 libs += [ "unwind" ] | 128 libs += [ "unwind" ] |
145 } | |
146 } | |
147 | |
148 if (is_linux) { | |
149 libs = [ "pthread" ] | |
150 } | |
151 | |
152 if (sanitize != "") { | |
153 # You can either pass the sanitizers directly, e.g. "address,undefined", | |
154 # or pass one of the couple common aliases used by the bots. | |
155 sanitizers = sanitize | |
156 if (sanitize == "ASAN") { | |
157 sanitizers = "address,bool,function,integer-divide-by-zero,nonnull-attri
bute,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-over
flow,unreachable,vla-bound,vptr" | |
158 } else if (sanitize == "TSAN") { | |
159 sanitizers = "thread" | |
160 } else if (sanitize == "MSAN") { | |
161 sanitizers = "memory" | |
162 } | |
163 | |
164 cflags += [ | |
165 "-fsanitize=$sanitizers", | |
166 "-fno-sanitize-recover=$sanitizers", | |
167 "-fsanitize-blacklist=" + rebase_path("../tools/xsan.blacklist"), | |
168 ] | |
169 ldflags += [ "-fsanitize=$sanitizers" ] | |
170 if (sanitizers == "memory") { | |
171 cflags += [ "-fsanitize-memory-track-origins" ] | |
172 cflags_cc += [ "-stdlib=libc++" ] | |
173 ldflags += [ "-stdlib=libc++" ] | |
174 } | |
175 } | 129 } |
176 } | 130 } |
177 | 131 |
178 config("release") { | 132 if (is_linux) { |
179 cflags = [ "-O3" ] | 133 libs = [ "pthread" ] |
180 defines = [ "NDEBUG" ] | |
181 } | 134 } |
182 | 135 |
| 136 if (sanitize != "") { |
| 137 # You can either pass the sanitizers directly, e.g. "address,undefined", |
| 138 # or pass one of the couple common aliases used by the bots. |
| 139 sanitizers = sanitize |
| 140 if (sanitize == "ASAN") { |
| 141 sanitizers = "address,bool,function,integer-divide-by-zero,nonnull-attribu
te,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overfl
ow,unreachable,vla-bound,vptr" |
| 142 } else if (sanitize == "TSAN") { |
| 143 sanitizers = "thread" |
| 144 } else if (sanitize == "MSAN") { |
| 145 sanitizers = "memory" |
| 146 } |
| 147 |
| 148 cflags += [ |
| 149 "-fsanitize=$sanitizers", |
| 150 "-fno-sanitize-recover=$sanitizers", |
| 151 "-fsanitize-blacklist=" + rebase_path("../tools/xsan.blacklist"), |
| 152 ] |
| 153 ldflags += [ "-fsanitize=$sanitizers" ] |
| 154 if (sanitizers == "memory") { |
| 155 cflags += [ "-fsanitize-memory-track-origins" ] |
| 156 cflags_cc += [ "-stdlib=libc++" ] |
| 157 ldflags += [ "-stdlib=libc++" ] |
| 158 } |
| 159 } |
| 160 } |
| 161 |
| 162 config("debug_symbols") { |
| 163 # It's annoying to wait for full debug symbols to push over |
| 164 # to Android devices. -gline-tables-only is a lot slimmer. |
| 165 if (is_android) { |
| 166 cflags = [ "-gline-tables-only" ] |
| 167 } else if (!is_win) { |
| 168 cflags = [ "-g" ] |
| 169 } |
| 170 } |
| 171 |
| 172 config("no_rtti") { |
| 173 if (sanitize != "ASAN") { # -fsanitize=vptr requires RTTI |
| 174 if (!is_win) { |
| 175 cflags_cc = [ "-fno-rtti" ] |
| 176 } |
| 177 } |
| 178 } |
| 179 |
| 180 config("release") { |
| 181 if (!is_win) { |
| 182 cflags = [ "-O3" ] |
| 183 } |
| 184 defines = [ "NDEBUG" ] |
183 } | 185 } |
184 | 186 |
185 config("executable") { | 187 config("executable") { |
186 if (is_mac) { | 188 if (is_mac) { |
187 ldflags = [ "-Wl,-rpath,@loader_path/." ] | 189 ldflags = [ "-Wl,-rpath,@loader_path/." ] |
188 } else if (is_linux) { | 190 } else if (is_linux) { |
189 ldflags = [ | 191 ldflags = [ |
190 "-rdynamic", | 192 "-rdynamic", |
191 "-Wl,-rpath,\$ORIGIN", | 193 "-Wl,-rpath,\$ORIGIN", |
192 ] | 194 ] |
193 } | 195 } |
194 } | 196 } |
195 | 197 |
196 toolchain("msvc") { | 198 toolchain("msvc") { |
197 vc = "$windk\VC\bin\amd64\cl.exe" | 199 vc = "$windk\VC\bin\amd64\cl.exe" |
198 vlink = "$windk\VC\bin\amd64\link.exe" | 200 vlink = "$windk\VC\bin\amd64\link.exe" |
199 vlib = "$windk\VC\bin\amd64\lib.exe" | 201 vlib = "$windk\VC\bin\amd64\lib.exe" |
| 202 |
200 # TODO: add a python function that generates the includes using <VSPATH>/win_s
dk/bin/SetEnv.<cpu>.json | 203 # TODO: add a python function that generates the includes using <VSPATH>/win_s
dk/bin/SetEnv.<cpu>.json |
201 windk_include_dirs = "/I$windk\win_sdk\bin\..\..\win_sdk\Include\10.0.10586.0\
um /I$windk\win_sdk\bin\..\..\win_sdk\Include\10.0.10586.0\shared /I$windk\win_s
dk\bin\..\..\win_sdk\Include\10.0.10586.0\winrt /I$windk\win_sdk\bin\..\..\win_s
dk\Include\10.0.10586.0\ucrt /I$windk\win_sdk\bin\..\..\VC\include /I$windk\win_
sdk\bin\..\..\VC\atlmfc\include " | 204 windk_include_dirs = "/I$windk\win_sdk\bin\..\..\win_sdk\Include\10.0.10586.0\
um /I$windk\win_sdk\bin\..\..\win_sdk\Include\10.0.10586.0\shared /I$windk\win_s
dk\bin\..\..\win_sdk\Include\10.0.10586.0\winrt /I$windk\win_sdk\bin\..\..\win_s
dk\Include\10.0.10586.0\ucrt /I$windk\win_sdk\bin\..\..\VC\include /I$windk\win_
sdk\bin\..\..\VC\atlmfc\include " |
202 | 205 |
203 tool("cc") { | 206 tool("cc") { |
204 rspfile = "{{output}}.rsp" | 207 rspfile = "{{output}}.rsp" |
205 precompiled_header_type = "msvc" | 208 precompiled_header_type = "msvc" |
206 pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" | 209 pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" |
207 | 210 |
208 # Label names may have spaces in them so the pdbname must be quoted. The | 211 # Label names may have spaces in them so the pdbname must be quoted. The |
209 # source and output don't need to be quoted because GN knows they're a | 212 # source and output don't need to be quoted because GN knows they're a |
210 # full file name and will quote automatically when necessary. | 213 # full file name and will quote automatically when necessary. |
211 | 214 |
212 command = "$vc /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output
}} /Fd\"$pdbname\"" | 215 command = "$vc /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output
}} /Fd\"$pdbname\"" |
213 depsformat = "msvc" | 216 depsformat = "msvc" |
214 description = "CC {{output}}" | 217 description = "CC {{output}}" |
215 outputs = [ | 218 outputs = [ |
216 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", | 219 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", |
217 # "$object_subdir/{{source_name_part}}.obj", | 220 # "$object_subdir/{{source_name_part}}.obj", |
218 ] | 221 ] |
219 rspfile_content = "$windk_include_dirs {{defines}} {{include_dirs}} {{cflags
}} {{cflags_c}}" | 222 rspfile_content = "$windk_include_dirs {{defines}} {{include_dirs}} {{cflags
}} {{cflags_c}}" |
220 } | 223 } |
221 | 224 |
222 tool("cxx") { | 225 tool("cxx") { |
223 rspfile = "{{output}}.rsp" | 226 rspfile = "{{output}}.rsp" |
224 precompiled_header_type = "msvc" | 227 precompiled_header_type = "msvc" |
225 pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" | 228 pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" |
226 | 229 |
227 # Label names may have spaces in them so the pdbname must be quoted. The | 230 # Label names may have spaces in them so the pdbname must be quoted. The |
228 # source and output don't need to be quoted because GN knows they're a | 231 # source and output don't need to be quoted because GN knows they're a |
229 # full file name and will quote automatically when necessary. | 232 # full file name and will quote automatically when necessary. |
230 command = "$vc /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output
}} /Fd\"$pdbname\"" | 233 command = "$vc /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output
}} /Fd\"$pdbname\"" |
231 depsformat = "msvc" | 234 depsformat = "msvc" |
232 description = "C++ {{output}}" | 235 description = "C++ {{output}}" |
233 outputs = [ | 236 outputs = [ |
234 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", | 237 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", |
235 ] | 238 ] |
236 rspfile_content = "$windk_include_dirs {{defines}} {{include_dirs}} {{cflags
}} {{cflags_cc}}" | 239 rspfile_content = "$windk_include_dirs {{defines}} {{include_dirs}} {{cflags
}} {{cflags_cc}}" |
237 } | 240 } |
238 | 241 |
239 tool("alink") { | 242 tool("alink") { |
240 rspfile = "{{output}}.rsp" | 243 rspfile = "{{output}}.rsp" |
| 244 |
241 # gyp_win_tool_path = rebase_path("../third_party/externals/gyp/pylib/gyp/wi
n_tool.py") | 245 # gyp_win_tool_path = rebase_path("../third_party/externals/gyp/pylib/gyp/wi
n_tool.py") |
242 command = "$vlib /nologo {{arflags}} /OUT:{{output}} @$rspfile" | 246 command = "$vlib /nologo {{arflags}} /OUT:{{output}} @$rspfile" |
243 description = "LIB {{output}}" | 247 description = "LIB {{output}}" |
244 outputs = [ | 248 outputs = [ |
245 # Ignore {{output_extension}} and always use .lib, there's no reason to | 249 # Ignore {{output_extension}} and always use .lib, there's no reason to |
246 # allow targets to override this extension on Windows. | 250 # allow targets to override this extension on Windows. |
247 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", | 251 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", |
248 ] | 252 ] |
249 default_output_extension = ".lib" | 253 default_output_extension = ".lib" |
250 default_output_dir = "{{target_out_dir}}" | 254 default_output_dir = "{{target_out_dir}}" |
(...skipping 11 matching lines...) Expand all Loading... |
262 # gyp_win_tool_path = rebase_path("../third_party/externals/gyp/pylib/gyp/wi
n_tool.py") | 266 # gyp_win_tool_path = rebase_path("../third_party/externals/gyp/pylib/gyp/wi
n_tool.py") |
263 command = "$vlink /nologo /OUT:$exename /PDB:$pdbname @$rspfile" | 267 command = "$vlink /nologo /OUT:$exename /PDB:$pdbname @$rspfile" |
264 | 268 |
265 default_output_extension = ".exe" | 269 default_output_extension = ".exe" |
266 default_output_dir = "{{root_out_dir}}" | 270 default_output_dir = "{{root_out_dir}}" |
267 description = "LINK {{output}}" | 271 description = "LINK {{output}}" |
268 outputs = [ | 272 outputs = [ |
269 #"{{root_out_dir}}/{{target_output_name}}{{output_extension}}", | 273 #"{{root_out_dir}}/{{target_output_name}}{{output_extension}}", |
270 exename, | 274 exename, |
271 ] | 275 ] |
| 276 |
272 #if (symbol_level != 0) { | 277 #if (symbol_level != 0) { |
273 # outputs += [ pdbname ] | 278 # outputs += [ pdbname ] |
274 #} | 279 #} |
275 #runtime_outputs = outputs | 280 #runtime_outputs = outputs |
276 | 281 |
277 # The use of inputs_newline is to work around a fixed per-line buffer | 282 # The use of inputs_newline is to work around a fixed per-line buffer |
278 # size in the linker. | 283 # size in the linker. |
279 rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}" | 284 rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}" |
280 } | 285 } |
281 | 286 |
282 | |
283 tool("stamp") { | 287 tool("stamp") { |
284 win_stamp_path = rebase_path("win_stamp.py") | 288 win_stamp_path = rebase_path("win_stamp.py") |
285 command = "python $win_stamp_path {{output}}" | 289 command = "python $win_stamp_path {{output}}" |
286 } | 290 } |
287 } | 291 } |
288 | 292 |
289 | |
290 toolchain("gcc_like") { | 293 toolchain("gcc_like") { |
291 lib_switch = "-l" | 294 lib_switch = "-l" |
292 lib_dir_switch = "-L" | 295 lib_dir_switch = "-L" |
293 | 296 |
294 tool("cc") { | 297 tool("cc") { |
295 depfile = "{{output}}.d" | 298 depfile = "{{output}}.d" |
296 command = "$compiler_prefix $cc -MMD -MF $depfile {{defines}} {{include_dirs
}} {{cflags}} {{cflags_c}} $extra_cflags $extra_cflags_c -c {{source}} -o {{outp
ut}}" | 299 command = "$compiler_prefix $cc -MMD -MF $depfile {{defines}} {{include_dirs
}} {{cflags}} {{cflags_c}} $extra_cflags $extra_cflags_c -c {{source}} -o {{outp
ut}}" |
297 depsformat = "gcc" | 300 depsformat = "gcc" |
298 outputs = [ | 301 outputs = [ |
299 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o", | 302 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o", |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 } | 363 } |
361 | 364 |
362 tool("stamp") { | 365 tool("stamp") { |
363 command = "touch {{output}}" | 366 command = "touch {{output}}" |
364 } | 367 } |
365 | 368 |
366 tool("copy") { | 369 tool("copy") { |
367 command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} &&
cp -af {{source}} {{output}})" | 370 command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} &&
cp -af {{source}} {{output}})" |
368 } | 371 } |
369 } | 372 } |
OLD | NEW |