makeconf 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/makeconf/androidproject.rb +310 -0
- data/lib/makeconf/baseproject.rb +386 -0
- data/lib/makeconf/binary.rb +30 -0
- data/lib/makeconf/buildable.rb +270 -0
- data/lib/makeconf/compiler.rb +332 -0
- data/lib/makeconf/externalproject.rb +108 -0
- data/lib/makeconf/gui.rb +239 -0
- data/lib/makeconf/header.rb +37 -0
- data/lib/makeconf/installer.rb +205 -0
- data/lib/makeconf/library.rb +72 -0
- data/lib/makeconf/linker.rb +171 -0
- data/lib/makeconf/makefile.rb +126 -0
- data/lib/makeconf/packager.rb +90 -0
- data/lib/makeconf/platform.rb +213 -0
- data/lib/makeconf/project.rb +19 -0
- data/lib/makeconf/systemtype.rb +35 -0
- data/lib/makeconf/target.rb +73 -0
- data/lib/makeconf/test.rb +28 -0
- data/lib/makeconf/wxapp.rb +22 -0
- data/lib/makeconf.rb +213 -0
- metadata +64 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# An executable binary file
|
2
|
+
class Binary < Buildable
|
3
|
+
|
4
|
+
def initialize(options)
|
5
|
+
raise ArgumentError unless options.kind_of?(Hash)
|
6
|
+
super(options)
|
7
|
+
@output = @id + Platform.executable_extension
|
8
|
+
@output_type = 'binary'
|
9
|
+
end
|
10
|
+
|
11
|
+
def DEADWOOD_build
|
12
|
+
binfile = @id + Platform.executable_extension
|
13
|
+
cc = @compiler.clone
|
14
|
+
cc.is_library = false
|
15
|
+
cc.sources = @sources
|
16
|
+
cc.output = binfile
|
17
|
+
|
18
|
+
#XXX-BROKEN cc.add_targets(@makefile)
|
19
|
+
|
20
|
+
@makefile.merge!(cc.to_make(binfile))
|
21
|
+
|
22
|
+
@makefile.clean(cc.objs)
|
23
|
+
@makefile.install(binfile, '$(BINDIR)', { 'mode' => '755' }) \
|
24
|
+
if @installable
|
25
|
+
@output.push binfile
|
26
|
+
super()
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,270 @@
|
|
1
|
+
# A buildable object like a library or executable
|
2
|
+
class Buildable
|
3
|
+
|
4
|
+
attr_accessor :id, :project,
|
5
|
+
:buildable, :installable, :distributable,
|
6
|
+
:localdep, :sysdep, :enable,
|
7
|
+
:output, :output_type, :sources, :cflags, :ldadd, :rpath,
|
8
|
+
:topdir
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
raise ArgumentError unless options.kind_of?(Hash)
|
12
|
+
default = {
|
13
|
+
:id => options[:id],
|
14
|
+
:enable => true,
|
15
|
+
:buildable => true,
|
16
|
+
:distributable => true,
|
17
|
+
:installable => true,
|
18
|
+
:extension => '',
|
19
|
+
:cflags => [],
|
20
|
+
:ldflags => [],
|
21
|
+
:ldadd => [],
|
22
|
+
:rpath => '',
|
23
|
+
:topdir => '',
|
24
|
+
:depends => [],
|
25
|
+
}
|
26
|
+
default.each do |k,v|
|
27
|
+
instance_variable_set('@' + k.to_s, v)
|
28
|
+
end
|
29
|
+
@output = id
|
30
|
+
@output_type = nil # filled in by the derived class
|
31
|
+
|
32
|
+
# Local and system header dependencies for each @sources file
|
33
|
+
# These are filled in by Compiler.makedepends()
|
34
|
+
@localdep = {}
|
35
|
+
@sysdep = {}
|
36
|
+
|
37
|
+
# Filled in by sources=()
|
38
|
+
@sources = []
|
39
|
+
@source_code = {}
|
40
|
+
|
41
|
+
# Parse options
|
42
|
+
|
43
|
+
# FIXME- consider adding support for:
|
44
|
+
#%w{name enable distributable installable extension
|
45
|
+
# topdir rpath}
|
46
|
+
|
47
|
+
log.debug "Buildable options: " + options.pretty_inspect
|
48
|
+
|
49
|
+
options.each do |k,v|
|
50
|
+
log.debug "k=#{k} v=#{v.to_s}"
|
51
|
+
case k
|
52
|
+
when :id
|
53
|
+
@id = v
|
54
|
+
when :cc
|
55
|
+
@cc = v.clone
|
56
|
+
when :cflags
|
57
|
+
@cflags = v
|
58
|
+
@cflags = [ @cflags ] if @cflags.kind_of?(String)
|
59
|
+
when :ldflags
|
60
|
+
@ldflags = v
|
61
|
+
when :ldadd
|
62
|
+
@ldadd.push(v).flatten!
|
63
|
+
when :project
|
64
|
+
@project = v
|
65
|
+
when :buildable
|
66
|
+
@buildable = v
|
67
|
+
when :sources
|
68
|
+
v = [ v ] if v.kind_of?(String)
|
69
|
+
@sources = v
|
70
|
+
else
|
71
|
+
throw "Unrecognized option -- #{k}: #{v}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
log.debug "Buildable parsed as: " + self.pretty_inspect
|
75
|
+
|
76
|
+
#FIXME: move some of these to the switch statement
|
77
|
+
# # Parse simple textual child elements
|
78
|
+
# %w{cflags ldflags ldadd depends sources}.each do |k|
|
79
|
+
# instance_variable_set('@' + k, yaml[k]) if yaml.has_key? k
|
80
|
+
# end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def expand_sources(x)
|
85
|
+
log.info "expanding [#{x.to_s}] to source file list"
|
86
|
+
raise ArgumentError('Wrong type') unless x.is_a? Array
|
87
|
+
|
88
|
+
# Use glob(3) to expand the list of sources
|
89
|
+
buf = []
|
90
|
+
x.each do |src|
|
91
|
+
if src =~ /\*/
|
92
|
+
buf << Dir.glob(src)
|
93
|
+
else
|
94
|
+
buf.push src
|
95
|
+
end
|
96
|
+
end
|
97
|
+
buf.flatten
|
98
|
+
|
99
|
+
# TODO: elsewhere
|
100
|
+
# Ensure that all source files exist
|
101
|
+
#@sources.each do |src|
|
102
|
+
# throw ArgumentError("#{src} does not exist") unless File.exist? src
|
103
|
+
# end
|
104
|
+
|
105
|
+
#XXX-lame
|
106
|
+
# # Read all source code into a single array
|
107
|
+
# @source_code = {}
|
108
|
+
# @sources.each { |x| @source_code[x] = File.readlines(x) }
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# Return the list of intermediate object files
|
113
|
+
def objects
|
114
|
+
expand_sources(@sources).map { |x| x.gsub(/\.c$/, '.o') }
|
115
|
+
end
|
116
|
+
|
117
|
+
def library?
|
118
|
+
@output_type == 'shared library' or @output_type == 'static library'
|
119
|
+
end
|
120
|
+
|
121
|
+
def library_type
|
122
|
+
case @output_type
|
123
|
+
when 'shared library'
|
124
|
+
return :shared
|
125
|
+
when 'static library'
|
126
|
+
return :static
|
127
|
+
else
|
128
|
+
throw 'Not a library'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def binary?
|
133
|
+
@output_type =~ /binary/
|
134
|
+
end
|
135
|
+
|
136
|
+
def finalize
|
137
|
+
end
|
138
|
+
|
139
|
+
# Return a hash containing Makefile rules and targets
|
140
|
+
# needed to build the object.
|
141
|
+
#
|
142
|
+
def build
|
143
|
+
makefile = Makefile.new
|
144
|
+
objs = []
|
145
|
+
sources = expand_sources(@sources)
|
146
|
+
|
147
|
+
# Don't do anything if we aren't going to be built
|
148
|
+
return makefile unless @buildable
|
149
|
+
|
150
|
+
# Allow ndk-build to create the object, for Android
|
151
|
+
return makefile if SystemType.host =~ /-androideabi$/
|
152
|
+
|
153
|
+
log.debug 'buildable = ' + self.pretty_inspect
|
154
|
+
|
155
|
+
if sources.empty?
|
156
|
+
pp self
|
157
|
+
raise 'One or more source files are required' if sources.empty?
|
158
|
+
end
|
159
|
+
|
160
|
+
# Generate the targets and rules for each translation unit
|
161
|
+
sources.each do |src|
|
162
|
+
object_suffix = ''
|
163
|
+
if library?
|
164
|
+
if library_type == :shared
|
165
|
+
#DEADWOOD:cflags.push '-fpic'
|
166
|
+
else
|
167
|
+
object_suffix = '-static'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
obj = src.sub(/.c$/, object_suffix + Platform.object_extension)
|
171
|
+
cc = @project.cc.clone
|
172
|
+
cc.shared_library = library? and library_type == :shared
|
173
|
+
cc.flags = @cflags
|
174
|
+
cc.output = obj
|
175
|
+
cc.sources = src
|
176
|
+
#TODO: cc.topdir = @topdir
|
177
|
+
|
178
|
+
ld = cc.ld
|
179
|
+
ld.flags = @ldflags
|
180
|
+
@ldadd = [ @ldadd ] if @ldadd.kind_of?(String)
|
181
|
+
@ldadd.each { |lib| ld.library lib }
|
182
|
+
|
183
|
+
makefile.add_target(obj, [src, localdep[src]].flatten, cc.rule)
|
184
|
+
makefile.clean(obj)
|
185
|
+
objs.push obj
|
186
|
+
end
|
187
|
+
|
188
|
+
# Generate the targets and rules for the link stage
|
189
|
+
if library? and library_type == :static
|
190
|
+
cmd = Platform.archiver(output, objs)
|
191
|
+
else
|
192
|
+
cc = @project.cc.clone
|
193
|
+
cc.shared_library = library? and library_type == :shared
|
194
|
+
cc.flags = @cflags
|
195
|
+
cc.sources = sources
|
196
|
+
cc.ld.flags = @ldflags
|
197
|
+
@ldadd = [ @ldadd ] if @ldadd.kind_of?(String)
|
198
|
+
@ldadd.each { |lib| cc.ld.library lib }
|
199
|
+
cc.ld.output = @output
|
200
|
+
cmd = cc.ld.rule
|
201
|
+
end
|
202
|
+
makefile.add_target(output, objs, cmd)
|
203
|
+
makefile.add_dependency('all', output)
|
204
|
+
makefile.clean(output)
|
205
|
+
makefile.distribute(sources) if distributable
|
206
|
+
|
207
|
+
return makefile
|
208
|
+
end
|
209
|
+
|
210
|
+
# Return a hash containing Makefile dependencies
|
211
|
+
def makedepends
|
212
|
+
res = []
|
213
|
+
|
214
|
+
if @sources.nil?
|
215
|
+
log.error self.to_s
|
216
|
+
raise 'Missing sources'
|
217
|
+
end
|
218
|
+
|
219
|
+
# Generate the targets and rules for each translation unit
|
220
|
+
expand_sources(@sources).each do |src|
|
221
|
+
next if src =~ /\.o$/
|
222
|
+
cc = @project.cc.clone
|
223
|
+
cc.flags = [ @cflags, '-E' ]
|
224
|
+
cc.output = '-'
|
225
|
+
cc.sources = src
|
226
|
+
#TODO: topdir
|
227
|
+
cmd = cc.command + Platform.dev_null_stderr
|
228
|
+
|
229
|
+
# TODO: do @sysdep also
|
230
|
+
@localdep[src] = []
|
231
|
+
IO.popen(cmd).each do |x|
|
232
|
+
if x =~ /^# \d+ "([^\/<].*\.h)"/
|
233
|
+
@localdep[src].push $1
|
234
|
+
end
|
235
|
+
end
|
236
|
+
@localdep[src].sort!.uniq!
|
237
|
+
res.concat @localdep[src]
|
238
|
+
|
239
|
+
# Generate a list of system header dependencies
|
240
|
+
# FIXME: does a lot of duplicate work reading files in..
|
241
|
+
buf = []
|
242
|
+
@sysdep[src] = []
|
243
|
+
buf.concat File.readlines(src)
|
244
|
+
@localdep[src].each do |x|
|
245
|
+
if File.exist? x
|
246
|
+
buf.concat File.readlines(x)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
buf.each do |x|
|
250
|
+
begin
|
251
|
+
if x =~ /^#\s*include\s+<(.*?)>/
|
252
|
+
@sysdep[src].push $1
|
253
|
+
end
|
254
|
+
rescue ArgumentError
|
255
|
+
# FIXME: should give more info about which file and line
|
256
|
+
warn "** WARNING: invalid multibyte sequence encountered in one of the source code files:"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
@sysdep[src].sort!.uniq!
|
260
|
+
|
261
|
+
end
|
262
|
+
res
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
def log
|
268
|
+
Makeconf.logger
|
269
|
+
end
|
270
|
+
end
|
@@ -0,0 +1,332 @@
|
|
1
|
+
# Processes source code files to produce intermediate object files.
|
2
|
+
#
|
3
|
+
class Compiler
|
4
|
+
|
5
|
+
require 'tempfile'
|
6
|
+
|
7
|
+
attr_accessor :sysroot
|
8
|
+
attr_reader :ld
|
9
|
+
|
10
|
+
def initialize(language, extension)
|
11
|
+
@language = language
|
12
|
+
@extension = extension
|
13
|
+
@ld = Linker.new()
|
14
|
+
windows_init if Platform.is_windows?
|
15
|
+
@flags = []
|
16
|
+
@sources = [] # List of input files
|
17
|
+
@output = nil
|
18
|
+
@sysroot = nil
|
19
|
+
@quiet = false # If true, output will be suppressed
|
20
|
+
|
21
|
+
# TODO:
|
22
|
+
# If true, all source files will be passed to the compiler at one time.
|
23
|
+
# This will also combine the link and compilation phases.
|
24
|
+
# See: the -combine option in GCC
|
25
|
+
#@combine = false
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def sources=(a)
|
30
|
+
a = [ a ] if a.kind_of?(String)
|
31
|
+
throw 'Array input required' unless a.kind_of?(Array)
|
32
|
+
@sources = a
|
33
|
+
@ld.objects = a.map { |x| x.sub(/\.c$/, '.o') } #FIXME: hardcoded to C
|
34
|
+
end
|
35
|
+
|
36
|
+
def cflags
|
37
|
+
@flags
|
38
|
+
end
|
39
|
+
|
40
|
+
def clone
|
41
|
+
Marshal.load(Marshal.dump(self))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return the intermediate object files for each source file
|
45
|
+
def object_files(sources)
|
46
|
+
res = []
|
47
|
+
sources.sort.each do |s|
|
48
|
+
res.push s.sub(/.c$/, Platform.object_extension)
|
49
|
+
end
|
50
|
+
res
|
51
|
+
end
|
52
|
+
|
53
|
+
def quiet=(b)
|
54
|
+
ld.quiet = b
|
55
|
+
@quiet = b
|
56
|
+
end
|
57
|
+
|
58
|
+
def output=(s)
|
59
|
+
@output = s
|
60
|
+
ld.output = s
|
61
|
+
end
|
62
|
+
|
63
|
+
def makefile
|
64
|
+
m = Makefile.new
|
65
|
+
m.define_variable('CC', ':=', @path)
|
66
|
+
m.define_variable('LD', ':=', @ld.path)
|
67
|
+
return m
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return the command formatted as a Makefile rule
|
71
|
+
def rule
|
72
|
+
[ '$(CC)', '-c', flags, '$(CFLAGS)', @sources ].flatten.join(' ')
|
73
|
+
end
|
74
|
+
|
75
|
+
# Return the complete command line to compile an object
|
76
|
+
def command
|
77
|
+
log.debug self.pretty_inspect
|
78
|
+
|
79
|
+
throw 'Invalid linker' unless @ld.is_a?(Linker)
|
80
|
+
throw 'One or more source files are required' unless @sources.length > 0
|
81
|
+
# cflags = default_flags
|
82
|
+
# cflags.concat @flags
|
83
|
+
# end
|
84
|
+
# throw cflags
|
85
|
+
|
86
|
+
# topdir = h[:topdir] || ''
|
87
|
+
# ld = @ld.clone
|
88
|
+
# ldadd = h[:ldadd]
|
89
|
+
# ld.flags = h[:ldflags]
|
90
|
+
# ld.output = Platform.pathspec(h[:output])
|
91
|
+
# ld.rpath = h[:rpath] if h[:rpath].length > 0
|
92
|
+
|
93
|
+
# inputs = h[:sources]
|
94
|
+
# inputs = [ inputs ] if inputs.is_a? String
|
95
|
+
# inputs = inputs.map { |x| Platform.pathspec(topdir + x) }
|
96
|
+
# throw 'One or more sources are required' unless inputs.count
|
97
|
+
|
98
|
+
#TODO:if @combine
|
99
|
+
# return [ @path, cflags, '-combine', ldflags, inputs, ldadd ].flatten.join(' ')
|
100
|
+
#
|
101
|
+
|
102
|
+
cmd = [ @path, '-c', flags, @sources ].flatten.join(' ')
|
103
|
+
|
104
|
+
cmd += Platform.dev_null if @quiet
|
105
|
+
|
106
|
+
log.debug "Compiler command: #{cmd}"
|
107
|
+
|
108
|
+
cmd
|
109
|
+
end
|
110
|
+
|
111
|
+
def flags
|
112
|
+
tok = @flags
|
113
|
+
|
114
|
+
# KLUDGE: remove things that CL.EXE doesn't understand
|
115
|
+
# if @path.match(/cl.exe$/i)
|
116
|
+
# cflags += ' '
|
117
|
+
# cflags.gsub!(/ -Wall /, ' ') # /Wall generates too much noise
|
118
|
+
# cflags.gsub!(/ -Werror /, ' ') # Could use /WX here
|
119
|
+
# cflags.gsub!(/ -W /, ' ')
|
120
|
+
# cflags.gsub!(/ -Wno-.*? /, ' ')
|
121
|
+
# cflags.gsub!(/ -Wextra /, ' ')
|
122
|
+
# cflags.gsub!(/ -fpic /, ' ')
|
123
|
+
# cflags.gsub!(/ -std=.*? /, ' ')
|
124
|
+
# cflags.gsub!(/ -pedantic /, ' ')
|
125
|
+
# end
|
126
|
+
|
127
|
+
# Set the output path
|
128
|
+
unless @output.nil?
|
129
|
+
outfile = Platform.pathspec(@output)
|
130
|
+
if vendor == 'Microsoft'
|
131
|
+
tok.push '"-IC:\Program Files\Microsoft Visual Studio 10.0\VC\include"' # XXX-HARDCODED
|
132
|
+
tok.push '/Fo' + outfile
|
133
|
+
tok.push '/MD'
|
134
|
+
else
|
135
|
+
tok.push '-o', outfile
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if @ld.shared_library
|
140
|
+
if Platform.is_windows?
|
141
|
+
throw 'FIXME'
|
142
|
+
else
|
143
|
+
tok.push '-fpic' unless is_mingw?
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
tok.push '--sysroot=' + @sysroot unless @sysroot.nil?
|
148
|
+
|
149
|
+
tok.join(' ')
|
150
|
+
end
|
151
|
+
|
152
|
+
def flags=(s)
|
153
|
+
@flags = s
|
154
|
+
@flags = @flags.split(' ') if @flags.kind_of?(String)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Enable compiler and linker options to create a shared library
|
158
|
+
def shared_library=(b)
|
159
|
+
case b
|
160
|
+
when true
|
161
|
+
if Platform.is_windows?
|
162
|
+
# noop
|
163
|
+
else
|
164
|
+
@flags.push '-fpic'
|
165
|
+
@ld.shared_library = true
|
166
|
+
end
|
167
|
+
when false
|
168
|
+
# noop
|
169
|
+
else
|
170
|
+
throw 'Invalid value'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Test if the compiler supports a command line option
|
175
|
+
def has_option(opt)
|
176
|
+
|
177
|
+
# Create a simple test file
|
178
|
+
f = Tempfile.new(['test_has_option', @extension]);
|
179
|
+
f.puts 'int main() { }'
|
180
|
+
f.flush
|
181
|
+
|
182
|
+
#FIXME: /dev/null not portable
|
183
|
+
cmd = [ @path, opt, '-o /dev/null', '-c', f.path ].join(' ') + Platform.dev_null
|
184
|
+
Platform.execute cmd
|
185
|
+
end
|
186
|
+
|
187
|
+
# Check if a header is available
|
188
|
+
def check_header(path)
|
189
|
+
test_compile("#include <" + path + ">")
|
190
|
+
end
|
191
|
+
|
192
|
+
# Compile and link a test program
|
193
|
+
def test_link(code)
|
194
|
+
test_compile(code, :combined)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Run the compilation command
|
198
|
+
def compile
|
199
|
+
cmd = self.command
|
200
|
+
log.debug "Invoking the compiler"
|
201
|
+
rc = Platform.execute cmd
|
202
|
+
log.debug "Compilation complete; rc=#{rc.to_s}"
|
203
|
+
end
|
204
|
+
|
205
|
+
# Compile a test program
|
206
|
+
def test_compile(code, stage = :compile)
|
207
|
+
|
208
|
+
# Write the code to a temporary source file
|
209
|
+
f = Tempfile.new(['test_compile', @extension]);
|
210
|
+
f.print code
|
211
|
+
f.flush
|
212
|
+
###objfile = f.path + '.out'
|
213
|
+
|
214
|
+
# Run the compiler
|
215
|
+
cc = self.clone
|
216
|
+
cc.sources = f.path
|
217
|
+
### cc.output = objfile
|
218
|
+
cc.flags += '-o /dev/null' #FIXME: /dev/null not portable
|
219
|
+
cc.quiet = true
|
220
|
+
rc = cc.compile
|
221
|
+
|
222
|
+
# Delete the object file
|
223
|
+
objfile = File.basename( f.path.sub(@extension, '.o') )
|
224
|
+
File.unlink(objfile) if File.exist? objfile
|
225
|
+
|
226
|
+
return rc
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
# Try to determine a usable default set of compiler flags
|
231
|
+
def default_flags
|
232
|
+
cflags = []
|
233
|
+
|
234
|
+
# GCC on Solaris 10 produces 32-bit code by default, so add -m64
|
235
|
+
# when running in 64-bit mode.
|
236
|
+
if Platform.is_solaris? and Platform.word_size == 64
|
237
|
+
cflags.push '-m64'
|
238
|
+
end
|
239
|
+
|
240
|
+
cflags
|
241
|
+
end
|
242
|
+
|
243
|
+
private
|
244
|
+
|
245
|
+
# Special initialization for MS Windows
|
246
|
+
def windows_init
|
247
|
+
# FIXME: hardcoded to VS10 on C: drive, should pull the information from vcvars.bat
|
248
|
+
ENV['PATH'] = 'C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\;C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN;C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools' + ENV['PATH']
|
249
|
+
ENV['INCLUDE'] = 'INCLUDE=C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v7.0A\include;'
|
250
|
+
ENV['LIB'] = 'C:\Program Files\Microsoft Visual Studio 10.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v7.0A\lib;'
|
251
|
+
ENV['LIBPATH'] = 'C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319;C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\Program Files\Microsoft Visual Studio 10.0\VC\LIB;'
|
252
|
+
ENV['VCINSTALLDIR'] = "C:\Program Files\\Microsoft Visual Studio 10.0\\VC\\"
|
253
|
+
ENV['VS100COMNTOOLS'] = "C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\Tools\\"
|
254
|
+
ENV['VSINSTALLDIR'] = "C:\\Program Files\\Microsoft Visual Studio 10.0\\"
|
255
|
+
ENV['WindowsSdkDir'] = "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\"
|
256
|
+
end
|
257
|
+
|
258
|
+
# Search for a suitable compiler
|
259
|
+
def search(compilers)
|
260
|
+
res = nil
|
261
|
+
if ENV['CC']
|
262
|
+
res = ENV['CC']
|
263
|
+
else
|
264
|
+
compilers.each do |command|
|
265
|
+
if (command =~ /^\// and File.exists?(command)) or Platform.which(command)
|
266
|
+
res = command
|
267
|
+
break
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# FIXME: kludge for Windows, breaks mingw
|
273
|
+
if Platform.is_windows?
|
274
|
+
res = 'cl.exe'
|
275
|
+
end
|
276
|
+
|
277
|
+
throw 'No suitable compiler found' if res.nil? || res == ''
|
278
|
+
|
279
|
+
if Platform.is_windows? && res.match(/cl.exe/i)
|
280
|
+
help = ' /? <NUL'
|
281
|
+
else
|
282
|
+
help = ' --help'
|
283
|
+
end
|
284
|
+
|
285
|
+
# Verify the command can be executed
|
286
|
+
cmd = res + help + Platform.dev_null
|
287
|
+
unless Platform.execute(cmd)
|
288
|
+
puts "not found"
|
289
|
+
print " -- tried: " + cmd
|
290
|
+
raise
|
291
|
+
end
|
292
|
+
|
293
|
+
puts res
|
294
|
+
res
|
295
|
+
end
|
296
|
+
|
297
|
+
# Return the name of the compiler vendor
|
298
|
+
def vendor
|
299
|
+
if @path.match(/cl.exe$/i)
|
300
|
+
'Microsoft'
|
301
|
+
else
|
302
|
+
'Unknown'
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class CCompiler < Compiler
|
308
|
+
|
309
|
+
attr_accessor :output_type
|
310
|
+
attr_reader :path
|
311
|
+
|
312
|
+
def initialize(options = {})
|
313
|
+
@search_list = options.has_key?(:search) ? options[:search] : [ 'cc', 'gcc', 'clang', 'cl.exe']
|
314
|
+
@search_list = [ @search_list ] unless @search_list.kind_of?(Array)
|
315
|
+
@output_type = nil
|
316
|
+
super('C', '.c')
|
317
|
+
printf "checking for a C compiler.. "
|
318
|
+
@path = search(@search_list)
|
319
|
+
end
|
320
|
+
|
321
|
+
# Returns true if the compiler is MinGW
|
322
|
+
def is_mingw?
|
323
|
+
@path =~ /mingw/ # Kludge
|
324
|
+
end
|
325
|
+
|
326
|
+
private
|
327
|
+
|
328
|
+
def log
|
329
|
+
Makeconf.logger
|
330
|
+
end
|
331
|
+
|
332
|
+
end
|