makeconf 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,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
|