makeconf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,310 @@
1
+ class AndroidProject < BaseProject
2
+
3
+ attr_accessor :target_arch,
4
+ :target_arch_abi,
5
+ :target_abi,
6
+ :target_platform
7
+
8
+ def initialize(options)
9
+ super(options)
10
+
11
+ # Public
12
+ @target_platform = 'android-14'
13
+ @target_arch = 'arm'
14
+ @target_arch_abi = 'armeabi'
15
+ @target_abi = 'armeabi-v7a'
16
+ @ndk_path = nil
17
+ @sdk_path = nil
18
+
19
+ # Private
20
+ @prebuilt_libs = []
21
+
22
+ # KLUDGE: We need to know the NDK and SDK paths very early on.
23
+ # Peek at the original ARGV to find them.
24
+ Makeconf.original_argv.each do |arg|
25
+ if arg =~ /^--with-ndk=(.*)/
26
+ @ndk_path = $1
27
+ end
28
+ if arg =~ /^--with-sdk=(.*)/
29
+ @sdk_path = $1
30
+ end
31
+ end
32
+
33
+ self.ndk_toolchain_version = '4.6'
34
+ end
35
+
36
+ # Parse ARGV options
37
+ # Should only be called from Makeconf.parse_options()
38
+ # Note that ndk_path and sdk_path are previously parsed during initialize()
39
+ def parse_options(opts)
40
+ super(opts)
41
+
42
+ opts.separator ""
43
+ opts.separator "Android options:"
44
+
45
+ opts.on('--with-ndk=DIRECTORY', "Path to the Android NDK") do |arg|
46
+ @ndk_path = arg
47
+ end
48
+ opts.on('--with-sdk=DIRECTORY', "Path to the Android SDK") do |arg|
49
+ @sdk_path = arg
50
+ end
51
+
52
+ end
53
+
54
+ def ndk_toolchain_version
55
+ @ndk_toolchain_version
56
+ end
57
+
58
+ def ndk_toolchain_version=(version)
59
+ @ndk_toolchain_version = version
60
+
61
+ ndk_cc = toolchain_binary('gcc')
62
+
63
+ #FIXME -overwrites previous Compiler object
64
+ @cc = CCompiler.new(
65
+ :search => ndk_cc
66
+ )
67
+ @cc.sysroot = ndk_sysroot
68
+ end
69
+
70
+ def preconfigure
71
+
72
+ printf 'checking for the Android NDK.. '
73
+ throw 'Unable to locate the NDK. Please set the --with-ndk variable to the correct path' if @ndk_path.nil?
74
+ puts @ndk_path
75
+ printf 'checking for the Android SDK.. '
76
+ throw 'Unable to locate the SDK. Please set the --with-sdk variable to the correct path' if @sdk_path.nil?
77
+ puts @sdk_path
78
+ end
79
+
80
+ def to_make
81
+
82
+ write_android_mk
83
+ write_application_mk
84
+
85
+ # Generate the ndk-build command
86
+ ndk_build = '$(NDK)/ndk-build V=1 NDK_DEBUG=1 NDK_PROJECT_PATH=.'
87
+ unless @ndk_toolchain_version.nil?
88
+ ndk_build += " NDK_TOOLCHAIN_VERSION=#{@ndk_toolchain_version}"
89
+ end
90
+
91
+ mf = super
92
+
93
+ mf.define_variable('NDK_LIBDIR', ':=', ndk_libdir)
94
+ mf.define_variable('NDK', '?=', @ndk_path)
95
+ mf.define_variable('SDK', '?=', @sdk_path)
96
+ mf.define_variable('GDB', '?=', toolchain_binary('gdb'))
97
+ mf.define_variable('ADB', '?=', '$(SDK)/platform-tools/adb')
98
+ mf.target('all').rules.push ndk_build
99
+
100
+ # Copy objects from obj/ to the top level, to match the behavior
101
+ # of non-Android platforms
102
+ # FIXME: this is very crude and should use the actual :output filenames
103
+ # also, it will only copy libraries and not executables
104
+ #
105
+ mf.target('all').rules.push 'cp obj/local/*/*.a obj/local/*/*.so .'
106
+
107
+ # Generate the 'make clean' target
108
+ mf.target('clean').rules = [ ndk_build + ' clean' ]
109
+
110
+ # Generate the 'make check' target
111
+ mf.target('check').deps = [] # FIXME: should depend on 'all'
112
+ @build.each do |obj|
113
+ if obj.kind_of?(Test)
114
+ mf.target('check').rules.push([
115
+ '$(ADB) push libs/' + @target_abi + '/' + obj.output + ' /data/local/tmp',
116
+ '$(ADB) shell chmod 751 /data/local/tmp/' + obj.output,
117
+ '$(ADB) shell /data/local/tmp/' + obj.output,
118
+ '$(ADB) shell rm /data/local/tmp/' + obj.output
119
+ ])
120
+ end
121
+ end
122
+
123
+ # Run a $(BINARY) under the Android debugger
124
+ # see: http://www.kandroid.org/online-pdk/guide/debugging_gdb.html
125
+ mf.add_target('debug', [], [
126
+ '$(ADB) forward tcp:5039 tcp:5039',
127
+ '$(ADB) push $(BINARY) /data/local/tmp',
128
+ '$(ADB) shell chmod 751 /data/local/tmp/`basename $(BINARY)`',
129
+ '$(ADB) shell gdbserver :5039 /data/local/tmp/`basename $(BINARY)` &',
130
+ 'sleep 2', # give gdbserver time to start
131
+
132
+ # Pull things from the device that are needed for debugging
133
+ '$(ADB) pull /system/bin/linker obj/local/armeabi/linker',
134
+ '$(ADB) pull /system/lib/libc.so obj/local/armeabi/libc.so',
135
+ '$(ADB) pull /system/lib/libm.so obj/local/armeabi/libm.so',
136
+ '$(ADB) pull /system/lib/libstdc++.so obj/local/armeabi/libstdc++.so',
137
+
138
+ 'echo "set solib-search-path obj/local/armeabi" > .gdb-commands',
139
+ 'echo "target remote :5039" >> .gdb-commands',
140
+ '$(GDB) -x .gdb-commands $(BINARY)',
141
+ 'rm .gdb-commands',
142
+ ])
143
+
144
+ # Connect to the device and run a shell
145
+ # TODO: add to makeconf
146
+ mf.add_target('shell', [], [ '$(ADB) shell' ])
147
+
148
+ mf
149
+ end
150
+
151
+ # Return the path to the Android NDK system root
152
+ def ndk_sysroot
153
+ @ndk_path + '/platforms/' + @target_platform + '/arch-' + @target_arch
154
+ end
155
+
156
+ # Return the path to the Android NDK /usr/lib
157
+ def ndk_libdir
158
+ ndk_sysroot + '/usr/lib/'
159
+ end
160
+
161
+ private
162
+
163
+ # Create the Android.mk makefile
164
+ def write_android_mk
165
+ ofile = 'Android.mk'
166
+ buf = [
167
+ '# Automatically generated by ./configure -- do not edit',
168
+ '',
169
+ 'TARGET_PLATFORM := ' + @target_platform,
170
+ 'TARGET_ARCH_ABI := ' + @target_arch_abi,
171
+ 'LOCAL_PATH := $(call my-dir)',
172
+ '',
173
+ ]
174
+
175
+ @build.each do |obj|
176
+ next if obj.kind_of? Header
177
+ next if obj.kind_of? ExternalProject
178
+ buf.push 'include $(CLEAR_VARS)',
179
+ '';
180
+
181
+ id = obj.id
182
+ id += '-static' if obj.kind_of? StaticLibrary
183
+
184
+ buf.push "LOCAL_MODULE := #{id}"
185
+ buf.push "LOCAL_MODULE_FILENAME := #{obj.id}" if obj.kind_of? StaticLibrary
186
+ buf.push "LOCAL_SRC_FILES := " + obj.expand_sources(obj.sources).join(' ')
187
+ buf.push "LOCAL_CFLAGS := " + obj.cflags.join(' ')
188
+ buf.push translate_ldadd(obj.ldadd) if obj.ldadd
189
+ buf.push ''
190
+ case obj.class.to_s
191
+ when 'StaticLibrary'
192
+ buf.push 'include $(BUILD_STATIC_LIBRARY)'
193
+ when 'SharedLibrary'
194
+ buf.push 'include $(BUILD_SHARED_LIBRARY)'
195
+ when 'Binary', 'Test'
196
+ buf.push 'include $(BUILD_EXECUTABLE)'
197
+ else
198
+ throw "Unsuported class #{obj.class}"
199
+ end
200
+ buf.push ''
201
+ end
202
+
203
+ buf.push prebuilt_libraries
204
+
205
+ puts 'creating ' + ofile
206
+ f = File.open(ofile, 'w')
207
+ buf.each do |str|
208
+ f.printf "#{str}\n"
209
+ end
210
+ f.close
211
+
212
+ end
213
+
214
+ # Create the jni/Application.mk makefile
215
+ def write_application_mk
216
+ ofile = 'jni/Application.mk'
217
+ buf = [
218
+ '# Automatically generated by ./configure -- do not edit',
219
+ 'APP_PROJECT_PATH := .',
220
+ 'APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/Android.mk',
221
+ 'APP_PLATFORM := ' + @target_platform,
222
+ 'APP_ABI := ' + @target_abi,
223
+ 'APP_OPTIM := debug',
224
+ ]
225
+
226
+ Dir.mkdir 'jni' unless File.exists?('jni')
227
+ puts 'creating ' + ofile
228
+ f = File.open(ofile, 'w')
229
+ buf.each do |str|
230
+ f.printf "#{str}\n"
231
+ end
232
+ f.close
233
+ end
234
+
235
+ private
236
+
237
+ # Translate LDADD flags into the corresponding Android.mk prebuilt definitions
238
+ def prebuilt_libraries
239
+ buf = []
240
+ @build.each do |obj|
241
+ # TODO: shared libs
242
+ obj.ldadd.each do |item|
243
+ next if provides?(item) or item =~ /^obj\/local\//
244
+ prebuilt = File.basename(item).sub(/\.a$/, '-prebuilt')
245
+ if item =~ /\.a$/ and item =~ /\// and not @prebuilt_libs.include? prebuilt
246
+ # FIXME: assumes it is a prebuilt library in a different path
247
+ buf.push('',
248
+ 'include $(CLEAR_VARS)',
249
+ 'LOCAL_MODULE := ' + File.basename(item).sub(/\.a$/, '-prebuilt'),
250
+ 'LOCAL_SRC_FILES := ' + item,
251
+ 'include $(PREBUILT_STATIC_LIBRARY)'
252
+ )
253
+ @prebuilt_libs.push prebuilt
254
+ end
255
+ end
256
+ end
257
+ buf.join "\n"
258
+ end
259
+
260
+ # Translate LDADD flags into the corresponding Android.mk variables
261
+ def translate_ldadd(ldadd)
262
+ static_libs = []
263
+ # TODO: shared libs
264
+ ldadd.each do |item|
265
+ if item =~ /\.a$/
266
+ if provides?(item) or item =~ /^obj\/local\//
267
+ static_libs.push File.basename(item).sub(/\.a$/, '-static')
268
+ else
269
+ static_libs.push File.basename(item).sub(/\.a$/, '-prebuilt')
270
+ end
271
+ end
272
+ end
273
+
274
+ buf = ''
275
+ buf += 'LOCAL_STATIC_LIBRARIES := ' + static_libs.join(' ') if static_libs
276
+ buf
277
+ end
278
+
279
+ # Determine the path to the Android NDK
280
+ def find_ndk()
281
+ [ ENV['NDK'] ].each do |x|
282
+ if !x.nil? and File.exists?(x)
283
+ return x
284
+ end
285
+ end
286
+ nil
287
+ end
288
+
289
+ # Return the full path to a prebuilt binary in the toolchain
290
+ #
291
+ def toolchain_binary(file)
292
+
293
+ # Determine the type of prebuilt binary to use
294
+ if RbConfig::CONFIG['host_os'] =~ /linux/
295
+ build_os = 'linux-x86';
296
+ elsif RbConfig::CONFIG['host_os'] =~ /darwin/
297
+ build_os = 'darwin-x86';
298
+ else
299
+ throw 'Unknown build OS: ' + RbConfig::CONFIG['host_os']
300
+ end
301
+
302
+ @ndk_path +
303
+ '/toolchains/'+ @target_arch + '-linux-androideabi-' +
304
+ @ndk_toolchain_version +
305
+ '/prebuilt/' +
306
+ build_os +
307
+ '/bin/' + @target_arch + '-linux-androideabi-' + file
308
+ end
309
+
310
+ end
@@ -0,0 +1,386 @@
1
+ # A project contains all of the information about the build.
2
+ # This is the base class from which all other Project subclasses are built
3
+ #
4
+ class BaseProject
5
+
6
+ require 'net/http'
7
+
8
+ attr_accessor :id, :version, :summary, :description,
9
+ :author, :license, :license_file, :config_h
10
+
11
+ attr_reader :cc
12
+
13
+ # KLUDGE: remove these if possible
14
+ attr_accessor :makefile, :installer, :packager
15
+
16
+ def log
17
+ Makeconf.logger
18
+ end
19
+
20
+ # Called by the object constructor
21
+ def initialize(options)
22
+ raise ArgumentError unless options.kind_of?(Hash)
23
+ @id = 'myproject'
24
+ @version = '0.1'
25
+ @summary = 'Undefined project summary'
26
+ @description = 'Undefined project description'
27
+ @license = 'Unknown license'
28
+ @license_file = nil
29
+ @author = 'Unknown author'
30
+ @config_h = 'config.h'
31
+ @header = {} # Hash of system header availablity
32
+ @build = [] # List of items to build
33
+ @distribute = [] # List of items to distribute
34
+ @install = [] # List of items to install
35
+ @target = [] # List of additional Makefile targets
36
+ @decls = {} # List of declarations discovered via check_decl()
37
+ @funcs = {} # List of functions discovered via check_func()
38
+ @packager = Packager.new(self)
39
+ @cc = nil
40
+
41
+ # Provided by the parent Makeconf object
42
+ @installer = nil
43
+ @makefile = nil
44
+
45
+ # # Initialize missing variables to be empty Arrays
46
+ # [:manpages, :headers, :libraries, :tests, :check_decls, :check_funcs,
47
+ # :extra_dist, :targets, :binaries].each do |k|
48
+ # h[k] = [] unless h.has_key? k
49
+ # h[k] = [ h[k] ] if h[k].kind_of?(String)
50
+ # end
51
+ # h[:scripts] = {} unless h.has_key?(:scripts)
52
+
53
+ # Generate a hash containing all the different element types
54
+ #items = {}
55
+ #%w{manpage header library binary test check_decl check_func extra_dist targets}.each do |k|
56
+ # items[k] = xml.elements[k] || []
57
+ #end
58
+
59
+ options.each do |key,val|
60
+ #p "key=#{key} val=#{val}"
61
+ case key
62
+ when :id
63
+ @id = val
64
+ when :version
65
+ @version = val.to_s
66
+ when :cc
67
+ @cc = val
68
+ when :license_file
69
+ @license_file = val
70
+ when 'library', 'libraries'
71
+ val.each do |id, e|
72
+ build SharedLibrary.new(id, @cc.clone).parse(e)
73
+ build StaticLibrary.new(id, @cc.clone).parse(e)
74
+ end
75
+ when 'manpage'
76
+ manpage(val)
77
+ when 'header'
78
+ header(val)
79
+ when 'extra_dist'
80
+ distribute val
81
+ when 'targets'
82
+ target val
83
+ when 'script', 'check_decl', 'check_func'
84
+ throw 'FIXME'
85
+ #items['script'].each { |k,v| script(k,v) }
86
+ #items['check_decl'].each { |id,decl| check_decl(id,decl) }
87
+ #items['check_func'].each { |f| check_func(f) }
88
+ else
89
+ throw "Unknown option -- #{key}: #{val}"
90
+ end
91
+ end
92
+
93
+ # Determine the path to the license file
94
+ if @license_file.nil?
95
+ %w{COPYING LICENSE}.each do |p|
96
+ if File.exists?(p)
97
+ @license_file = p
98
+ break
99
+ end
100
+ end
101
+ end
102
+
103
+ @cc ||= CCompiler.new
104
+
105
+
106
+ yield self if block_given?
107
+ end
108
+
109
+ # Parse ARGV options
110
+ # Should only be called from Makeconf.parse_options()
111
+ def parse_options(opts)
112
+ opts.separator ""
113
+ opts.separator "Project options:"
114
+ #none yet
115
+ end
116
+
117
+ # Examine the operating environment and set configuration options
118
+ def configure
119
+
120
+ preconfigure if respond_to? 'preconfigure'
121
+
122
+ # Run each buildable object's preconfigure() method
123
+ @build.each { |x| x.preconfigure if x.respond_to? 'preconfigure' }
124
+
125
+ # Run each buildable object's configure() method
126
+ @build.each { |x| x.configure if x.respond_to? 'configure' }
127
+
128
+ postconfigure if respond_to? 'postconfigure'
129
+
130
+ # Run each buildable object's postconfigure() method
131
+ @build.each { |x| x.postconfigure if x.respond_to? 'postconfigure' }
132
+
133
+ # Build a list of local headers
134
+ local_headers = []
135
+ @build.each do |x|
136
+ local_headers.concat x.makedepends
137
+ end
138
+ local_headers.sort!.uniq!
139
+
140
+ # Test for the existence of each referenced system header
141
+ sysdeps.each do |header|
142
+ printf "checking for #{header}... "
143
+ @header[header] = @cc.check_header(header)
144
+ puts @header[header] ? 'yes' : 'no'
145
+ end
146
+
147
+ # make_installable(@ast['data'], '$(PKGDATADIR)')
148
+ # make_installable(@ast['manpages'], '$(MANDIR)') #FIXME: Needs a subdir
149
+ end
150
+
151
+ # Return the Makefile for the project
152
+ # This should only be done after finalize() has been called.
153
+ def to_make
154
+ makefile = Makefile.new
155
+
156
+ makefile.add_dependency('dist', distfile)
157
+ makefile.distclean(distfile)
158
+ makefile.distclean(@config_h)
159
+ makefile.merge!(@cc.makefile)
160
+ makefile.merge!(@packager.makefile)
161
+ makefile.make_dist(@id, @version)
162
+ @distribute.each { |f| @makefile.distribute f }
163
+ @build.each { |x| makefile.merge!(x.build) if x.enable }
164
+ makefile.merge! @installer.to_make
165
+
166
+ # Add custom targets
167
+ @target.each { |t| makefile.add_target t }
168
+
169
+ makefile
170
+ end
171
+
172
+ def finalize
173
+ @packager.finalize
174
+ @build.each { |x| x.finalize }
175
+ @install.each { |x| @installer.install x }
176
+ end
177
+
178
+ # Check if a system header declares a macro or symbol
179
+ def check_decl(header,decl)
180
+ throw ArgumentError unless header.kind_of? String
181
+ decl = [ decl ] if decl.kind_of? String
182
+ throw ArgumentError unless decl.kind_of? Array
183
+
184
+ @cc ||= CCompiler.new() #FIXME: stop this
185
+
186
+ decl.each do |x|
187
+ next if @decls.has_key? x
188
+ printf "checking whether #{x} is declared... "
189
+ @decls[x] = @cc.test_compile "#define _GNU_SOURCE\n#include <#{header}>\nint main() { #{x}; }"
190
+ puts @decls[x] ? 'yes' : 'no'
191
+ end
192
+ end
193
+
194
+ # Check if a function is available in the standard C library
195
+ # TODO: probably should add :ldadd when checking..
196
+ def check_func(func)
197
+ func = [ func ] if func.kind_of? String
198
+ throw ArgumentError unless func.kind_of? Array
199
+
200
+ @cc ||= CCompiler.new() #FIXME: stop this
201
+ func.each do |x|
202
+ next if @funcs.has_key? x
203
+ printf "checking for #{x}... "
204
+ @funcs[x] = @cc.test_link "void *#{x}();\nint main() { void *p;\np = &#{x}; }"
205
+ puts @funcs[x] ? 'yes' : 'no'
206
+ end
207
+ end
208
+
209
+ def add_binary(options)
210
+ options[:cc] ||= @cc
211
+ id = options[:id] + Platform.executable_extension
212
+ build Binary.new(options)
213
+ end
214
+
215
+ def add(*objs)
216
+ objs.each do |obj|
217
+ if obj.kind_of?(Library)
218
+ obj.buildable.each do |e|
219
+ add(e)
220
+ end
221
+ else
222
+ obj.project = self if obj.kind_of?(Buildable)
223
+ build(obj)
224
+ end
225
+ end
226
+ end
227
+
228
+ # Add item(s) to build
229
+ # FIXME: this violates OOP encapsulation
230
+ def build(*arg)
231
+ arg.each do |x|
232
+
233
+ # Add a custom Makefile target
234
+ if x.kind_of? Target
235
+ @target.push x
236
+ next
237
+ end
238
+
239
+ unless x.respond_to?(:build)
240
+ pp x
241
+ throw ArgumentError.new('Invalid argument')
242
+ end
243
+
244
+ if x.kind_of?(SharedLibrary) or x.kind_of?(StaticLibrary)
245
+ dest = '$(LIBDIR)'
246
+ else
247
+ dest = '$(BINDIR)'
248
+ end
249
+ sources = x.output
250
+ mode = '0755'
251
+
252
+ @build.push x
253
+
254
+ next if x.kind_of?(Header) #ugly
255
+
256
+ @install.push({
257
+ :sources => sources,
258
+ :dest => dest,
259
+ :mode => mode,
260
+ }) if x.installable
261
+ end
262
+ end
263
+
264
+ # Add item(s) to install
265
+ def install(*arg)
266
+ arg.each do |x|
267
+ # FIXME: shouldn't something be installed now?
268
+ @distribute.push Dir.glob(x)
269
+ end
270
+ end
271
+
272
+ # Add item(s) to distribute in the source tarball
273
+ def distribute(*arg)
274
+ arg.each do |x|
275
+ @distribute.push Dir.glob(x)
276
+ end
277
+ end
278
+
279
+ # Add a C/C++ header file to be installed
280
+ def header(path, opt = {})
281
+ throw ArgumentError, 'bad options' unless opt.kind_of? Hash
282
+ @install.push({
283
+ :sources => path,
284
+ :dest => (opt[:dest].nil? ? '$(INCLUDEDIR)' : opt[:dest]),
285
+ :mode => '0644',
286
+ })
287
+ end
288
+
289
+ # Add a manpage file to be installed
290
+ def manpage(path, opt = {})
291
+ throw ArgumentError, 'bad options' unless opt.kind_of? Hash
292
+ section = path.gsub(/.*\./, '')
293
+ @install.push({
294
+ :sources => path,
295
+ :dest => (opt[:dest].nil? ? "$(MANDIR)/man#{section}" : opt[:dest]),
296
+ :mode => '0644',
297
+ })
298
+ end
299
+
300
+ # Add a script to be installed
301
+ def script(id, opt = {})
302
+ throw ArgumentError, 'bad options' unless opt.kind_of? Hash
303
+ @install.push({
304
+ :sources => opt[:sources],
305
+ :dest => (opt[:dest].nil? ? "$(BINDIR)" : opt[:dest]),
306
+ :rename => opt[:rename],
307
+ :mode => '0755',
308
+ })
309
+ end
310
+
311
+ # Return the compiler associated with the project
312
+ def compiler(language = 'C')
313
+ throw 'Not implemented' if language != 'C'
314
+ throw 'Undefined compiler' if @cc.nil?
315
+ @cc
316
+ end
317
+
318
+ # Return a library definition
319
+ def library(id)
320
+ @ast['libraries'][id]
321
+ end
322
+
323
+ # Return a list of all system header dependencies for all Buildable
324
+ # objects in the project.
325
+ def sysdeps
326
+ res = []
327
+ @build.each do |x|
328
+ x.sysdep.each { |k,v| res.concat v }
329
+ end
330
+ res.sort.uniq
331
+ end
332
+
333
+ # Returns the filename of the source code distribution archive
334
+ def distfile
335
+ @id + '-' + @version.to_s + '.tar.gz'
336
+ end
337
+
338
+ # Generate the config.h header file
339
+ def write_config_h
340
+ ofile = @config_h
341
+ buf = {}
342
+
343
+ @header.keys.sort.each { |k| buf["HAVE_#{k}".upcase] = @header[k] }
344
+ @decls.keys.sort.each { |x| buf["HAVE_DECL_#{x}".upcase] = @decls[x] }
345
+ @funcs.keys.sort.each { |x| buf["HAVE_#{x}".upcase] = @funcs[x] }
346
+
347
+ puts 'creating ' + ofile
348
+ f = File.open(ofile, 'w')
349
+ f.print "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n"
350
+ buf.keys.sort.each do |k|
351
+ v = buf[k]
352
+ id = k.upcase.gsub(%r{[/.-]}, '_')
353
+ if v == true
354
+ f.printf "#define #{id} 1\n"
355
+ else
356
+ f.printf "#undef #{id}\n"
357
+ end
358
+ end
359
+ f.close
360
+ end
361
+
362
+ # Add an additional Makefile target
363
+ def target(t)
364
+ throw ArgumentError.new('Invalid data type') unless t.kind_of?(Target)
365
+ @target.push t
366
+ end
367
+
368
+ #XXX fixme -- testing
369
+ def mount(uri,subdir)
370
+ x = Net::HTTP.get(URI(uri))
371
+ puts x.length
372
+ end
373
+
374
+ # Test if the project will build a library with a given pathname.
375
+ # This is used for inter-dependency analysis
376
+ def provides?(path)
377
+ fn = File.basename(path)
378
+ @build.each do |obj|
379
+ if obj.respond_to?(:output)
380
+ return true if obj.output == fn
381
+ end
382
+ end
383
+ return false
384
+ end
385
+
386
+ end