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,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
|