This repository has been archived by the owner on Mar 12, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 236
/
cc
executable file
·375 lines (325 loc) · 9.88 KB
/
cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
#!/bin/sh
# Make sure this shim uses the same Ruby interpreter that is used by Homebrew.
unset RUBYLIB
unset RUBYOPT
if [ -z "$HOMEBREW_RUBY_PATH" ]
then
echo "${0##*/}: The build tool has reset ENV; --env=std required." >&2
exit 1
fi
exec "$HOMEBREW_RUBY_PATH" -x "$0" "$@"
#!/usr/bin/env ruby -W0
require "pathname"
require "set"
class Cmd
attr_reader :config, :prefix, :cellar, :opt, :tmpdir, :deps
attr_reader :archflags, :optflags, :keg_regex, :formula_prefix
def initialize(arg0, args)
@arg0 = arg0
@args = args.freeze
@config = ENV.fetch("HOMEBREW_CCCFG") { "" }
@prefix = ENV["HOMEBREW_PREFIX"]
@cellar = ENV["HOMEBREW_CELLAR"]
@opt = ENV["HOMEBREW_OPT"]
@tmpdir = ENV["HOMEBREW_TEMP"]
@archflags = ENV.fetch("HOMEBREW_ARCHFLAGS") { "" }.split(" ")
@optflags = ENV.fetch("HOMEBREW_OPTFLAGS") { "" }.split(" ")
@deps = Set.new(ENV.fetch("HOMEBREW_DEPENDENCIES") { "" }.split(","))
@formula_prefix = ENV["HOMEBREW_FORMULA_PREFIX"]
# matches opt or cellar prefix and formula name
@keg_regex = %r[(#{Regexp.escape(opt)}|#{Regexp.escape(cellar)})/([\w+-.@]+)]
end
def mode
if @arg0 == "cpp" || @arg0 == "ld"
@arg0.to_sym
elsif @arg0 == "gold" || @arg0 == "ld.gold"
:ld
elsif @args.include? "-c"
if @arg0 =~ /(?:c|g|clang)\+\+/
:cxx
else
:cc
end
elsif @args.include?("-xc++-header") || @args.each_cons(2).include?(["-x", "c++-header"])
:cxx
elsif @args.include? "-E"
:ccE
else
if @arg0 =~ /(?:c|g|clang)\+\+/
:cxxld
else
:ccld
end
end
end
def tool
@tool ||= case @arg0
when "ld" then "ld"
when "gold", "ld.gold" then "ld.gold"
when "cpp" then "cpp"
when /llvm_(clang(\+\+)?)/
"#{ENV["HOMEBREW_PREFIX"]}/opt/llvm/bin/#{$1}"
when /\w\+\+(-\d(\.\d)?)?$/
case ENV["HOMEBREW_CC"]
when /clang/
"clang++"
when /llvm-gcc/
"llvm-g++-4.2"
when /gcc(-\d(\.\d)?)?$/
"g++" + $1.to_s
end
else
# Note that this is a universal fallback, so that we'll always invoke
# HOMEBREW_CC regardless of what name under which the tool was invoked.
ENV["HOMEBREW_CC"]
end
end
def args
if @args.length == 1 && @args[0] == "-v"
# Don't add linker arguments if -v passed as sole option. This stops gcc
# -v with no other arguments from outputting a linker error. Some
# software uses gcc -v (wrongly) to sniff the GCC version.
return @args.dup
end
if !refurbish_args? || tool == "ld" || configure?
args = @args.dup
else
args = refurbished_args
end
case mode
when :ccld
cflags + args + cppflags + ldflags
when :cxxld
cxxflags + args + cppflags + ldflags
when :cc
cflags + args + cppflags
when :cxx
cxxflags + args + cppflags
when :ccE
args + cppflags
when :cpp
args + cppflags
when :ld
ldflags + args
end
end
def refurbished_args
@lset = Set.new(library_paths)
@iset = Set.new(isystem_paths + include_paths)
args = []
enum = @args.each
loop do
case arg = enum.next
when "-arch"
if permit_arch_flags?
args << arg << enum.next
else
enum.next
end
when "-m32", "-m64"
args << arg if permit_arch_flags?
when /^-Xarch_/
refurbished = refurbish_arg(enum.next, enum)
unless refurbished.empty?
args << arg
args += refurbished
end
else
args += refurbish_arg(arg, enum)
end
end
args
end
def refurbish_arg(arg, enum)
args = []
case arg
when /^-g\d?$/, /^-gstabs\d+/, "-gstabs+", /^-ggdb\d?/,
/^-march=.+/, /^-mtune=.+/, /^-mcpu=.+/,
/^-O[0-9zs]?$/, "-fast", "-no-cpp-precomp",
"-pedantic", "-pedantic-errors", "-Wno-long-double",
"-Wno-unused-but-set-variable"
when "-liconv", "-lintl"
# Not needed on Linux.
when "-fopenmp", "-lgomp", "-mno-fused-madd", "-fforce-addr", "-fno-defer-pop",
"-mno-dynamic-no-pic", "-fearly-inlining", /^-f(?:no-)?inline-functions-called-once/,
/^-finline-limit/, /^-f(?:no-)?check-new/, "-fno-delete-null-pointer-checks",
"-fcaller-saves", "-fthread-jumps", "-fno-reorder-blocks", "-fcse-skip-blocks",
"-frerun-cse-after-loop", "-frerun-loop-opt", "-fcse-follow-jumps",
"-fno-regmove", "-fno-for-scope", "-fno-tree-pre", "-fno-tree-dominator-opts",
"-fuse-linker-plugin", "-frounding-math"
# clang doesn't support these flags
args << arg unless tool =~ /^clang/
when "--fast-math"
arg = "-ffast-math" if tool =~ /^clang/
args << arg
when "-Wno-deprecated-register"
# older gccs don't support these flags
args << arg unless tool =~ /^g..-4.[02]/
when /^-Wl,-z,defs/
# -Wl,-undefined,error is already the default
when /^-W[alp],/, /^-Wno-/
args << arg
when /^-W.*/
# prune warnings
when "-multiply_definedsuppress"
args << "-Wl,-multiply_defined,suppress"
when "-undefineddynamic_lookup"
args << "-Wl,-undefined,dynamic_lookup"
when /^-I(.+)?/
# Support both "-Ifoo" (one argument) and "-I foo" (two arguments)
val = chuzzle($1) || enum.next
path = canonical_path(val)
args << "-I#{val}" if keep?(path) && @iset.add?(path)
when /^-L(.+)?/
val = chuzzle($1) || enum.next
path = canonical_path(val)
args << "-L#{val}" if keep?(path) && @lset.add?(path)
when /^-R(.+)?/
# -R is not the correct way to pass rpaths to the linker
path = chuzzle($1) || enum.next
wl = "-Wl," unless mode == :ld
args << "#{wl}-rpath=" if keep?(path)
else
args << arg
end
args
end
def keep?(path)
# The logic in this method will eventually become the default,
# but is currently opt-in.
return keep_orig?(path) unless ENV["HOMEBREW_EXPERIMENTAL_FILTER_FLAGS_ON_DEPS"]
# Allow references to self
if formula_prefix && path.start_with?("#{formula_prefix}/")
true
# first two paths: reject references to Cellar or opt paths
# for unspecified dependencies
elsif path.start_with?(cellar) || path.start_with?(opt)
dep = path[keg_regex, 2]
dep && @deps.include?(dep)
else
path.start_with?(prefix, tmpdir)
end
end
# The original less-smart version of keep_orig; will eventually be removed
def keep_orig?(path)
path.start_with?(prefix, cellar, tmpdir)
end
def cflags
args = []
return args unless refurbish_args? || configure?
args << "-pipe"
args << "-w" unless configure?
args << "-#{ENV["HOMEBREW_OPTIMIZATION_LEVEL"]}"
args.concat(optflags)
args.concat(archflags)
args << "-std=#{@arg0}" if @arg0 =~ /c[89]9/
args
end
def cxxflags
args = cflags
args << "-std=c++11" if cxx11?
args << "-stdlib=libc++" if libcxx?
args << "-stdlib=libstdc++" if libstdcxx?
args
end
def cppflags
path_flags("-isystem", isystem_paths) + path_flags("-I", include_paths)
end
def ldflags
wl = "-Wl," unless mode == :ld
args = []
args += ["#{wl}--dynamic-linker=#{dynamic_linker_path}"] if dynamic_linker_path
args << "-B#{@opt}/glibc/lib" unless mode == :ld
args += path_flags("-L", library_paths)
args += rpath_flags("#{wl}-rpath=", rpath_paths)
end
def isystem_paths
path_split("HOMEBREW_ISYSTEM_PATHS")
end
def include_paths
path_split("HOMEBREW_INCLUDE_PATHS")
end
def library_paths
path_split("HOMEBREW_LIBRARY_PATHS")
end
def rpath_paths
path_split("HOMEBREW_RPATH_PATHS")
end
def dynamic_linker_path
chuzzle(ENV["HOMEBREW_DYNAMIC_LINKER"])
end
def configure?
# configure scripts generated with autoconf 2.61 or later export as_nl
ENV.key? "as_nl"
end
def refurbish_args?
config.include?("O")
end
def cxx11?
config.include?("x")
end
def libcxx?
config.include?("g")
end
def libstdcxx?
config.include?("h")
end
def permit_arch_flags?
config.include?("K")
end
def canonical_path(path)
path = Pathname.new(path)
path = path.realpath if path.exist?
path.to_s
end
def path_flags(prefix, paths)
paths = paths.uniq.select { |path| File.directory?(path) }
paths.map! { |path| prefix + path }
end
# Unlike path_flags, do not prune non-existant directories.
# formula.lib for example does not yet exist, but should not be pruned.
def rpath_flags(prefix, paths)
paths.uniq.map { |path| prefix + path }
end
def path_split(key)
ENV.fetch(key) { "" }.split(File::PATH_SEPARATOR)
end
def chuzzle(val)
return val if val.nil?
val = val.chomp
return val unless val.empty?
end
end
def log(basename, argv, tool, args)
return unless ENV.key?("HOMEBREW_CC_LOG_PATH")
adds = args - argv
dels = argv - args
s = ""
s << "#{basename} called with: #{argv.join(" ")}\n"
s << "superenv removed: #{dels.join(" ")}\n" unless dels.empty?
s << "superenv added: #{adds.join(" ")}\n" unless adds.empty?
s << "superenv executed: #{tool} #{args.join(" ")}\n\n"
File.open("#{ENV["HOMEBREW_CC_LOG_PATH"]}.cc", "a+") { |f| f.write(s) }
end
if __FILE__ == $PROGRAM_NAME
##################################################################### sanity
if (cc = ENV["HOMEBREW_CC"]).nil? || cc.empty? || cc == "cc"
# those values are not allowed
ENV["HOMEBREW_CC"] = "gcc"
end
####################################################################### main
dirname, basename = File.split($0)
cmd = Cmd.new(basename, ARGV)
tool = cmd.tool
args = cmd.args
log(basename, ARGV, tool, args)
superbin = Pathname.new(__FILE__).dirname.realpath
paths = ENV["PATH"].split(":").reject do |x|
path = Pathname.new(x)
path.directory? && path.realpath == superbin
end
paths.unshift "#{ENV["HOMEBREW_PREFIX"]}/bin"
ENV["PATH"] = paths.join(":")
args << { :close_others => false }
exec tool, *args
end