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.
@@ -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