~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to tools/autotool.py

  • Committer: Martin Decky
  • Date: 2010-03-19 18:30:12 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20100319183012-rmyqumxyx09q51kd
more autotooling: run actually the compiler in autotool.py and detect sizes of integers, generate common.h
more build system cleanup: remove redundancy, remove config.defs, merge kernel makefiles to a single file

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 
34
34
import sys
35
35
import os
 
36
import shutil
36
37
import re
37
38
import time
38
39
import subprocess
39
40
 
40
 
MAKEFILE = 'Makefile.config'
41
 
COMMON = 'Makefile.common'
 
41
SANDBOX = 'autotool'
 
42
CONFIG = 'Makefile.config'
 
43
MAKEFILE = 'Makefile.common'
 
44
HEADER = 'common.h'
 
45
GUARD = 'AUTOTOOL_COMMON_H_'
 
46
 
 
47
PROBE_SOURCE = 'probe.c'
 
48
PROBE_OUTPUT = 'probe.s'
42
49
 
43
50
PACKAGE_BINUTILS = "usually part of binutils"
44
51
PACKAGE_GCC = "preferably version 4.4.3 or newer"
45
52
PACKAGE_CROSS = "use tools/toolchain.sh to build the cross-compiler toolchain"
46
53
 
 
54
COMPILER_FAIL = "The compiler is probably not capable to compile HelenOS."
 
55
 
 
56
PROBE_HEAD = """#define AUTOTOOL_DECLARE(category, subcategory, name, value) \\
 
57
        asm volatile ( \\
 
58
                "AUTOTOOL_DECLARE\\t" category "\\t" subcategory "\\t" name "\\t%[val]\\n" \\
 
59
                : \\
 
60
                : [val] "n" (value) \\
 
61
        )
 
62
 
 
63
#define DECLARE_INTSIZE(type) \\
 
64
        AUTOTOOL_DECLARE("intsize", "unsigned", #type, sizeof(unsigned type)); \\
 
65
        AUTOTOOL_DECLARE("intsize", "signed", #type, sizeof(signed type))
 
66
 
 
67
int main(int argc, char *argv[])
 
68
{
 
69
"""
 
70
 
 
71
PROBE_TAIL = """}
 
72
"""
 
73
 
47
74
def read_config(fname, config):
48
75
        "Read HelenOS build configuration"
49
76
        
69
96
        
70
97
        sys.exit(1)
71
98
 
 
99
def sandbox_enter():
 
100
        "Create a temporal sandbox directory for running tests"
 
101
        
 
102
        if (os.path.exists(SANDBOX)):
 
103
                if (os.path.isdir(SANDBOX)):
 
104
                        try:
 
105
                                shutil.rmtree(SANDBOX)
 
106
                        except:
 
107
                                print_error(["Unable to cleanup the directory \"%s\"." % SANDBOX])
 
108
                else:
 
109
                        print_error(["Please inspect and remove unexpected directory,",
 
110
                                     "entry \"%s\"." % SANDBOX])
 
111
        
 
112
        try:
 
113
                os.mkdir(SANDBOX)
 
114
        except:
 
115
                print_error(["Unable to create sandbox directory \"%s\"." % SANDBOX])
 
116
        
 
117
        owd = os.getcwd()
 
118
        os.chdir(SANDBOX)
 
119
        
 
120
        return owd
 
121
 
 
122
def sandbox_leave(owd):
 
123
        "Leave the temporal sandbox directory"
 
124
        
 
125
        os.chdir(owd)
 
126
 
72
127
def check_config(config, key):
73
128
        "Check whether the configuration key exists"
74
129
        
77
132
                             "Try running \"make config\" again.",
78
133
                             "If the problem persists, please contact the developers of HelenOS."])
79
134
 
 
135
def check_common(common, key):
 
136
        "Check whether the common key exists"
 
137
        
 
138
        if (not key in common):
 
139
                print_error(["Failed to determine the value %s." % key,
 
140
                             "Please contact the developers of HelenOS."])
 
141
 
80
142
def check_app(args, name, details):
81
143
        "Check whether an application can be executed"
82
144
        
121
183
        check_app([common['OBJCOPY'], "--version"], "GNU Objcopy utility", details)
122
184
        check_app([common['OBJDUMP'], "--version"], "GNU Objdump utility", details)
123
185
 
124
 
def create_output(cmname, common):
125
 
        "Create common parameters output"
126
 
        
127
 
        outcm = file(cmname, 'w')
128
 
        
129
 
        outcm.write('#########################################\n')
130
 
        outcm.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
131
 
        outcm.write('#########################################\n\n')
 
186
def probe_compiler(common, sizes):
 
187
        "Generate, compile and parse probing source"
 
188
        
 
189
        check_common(common, "CC")
 
190
        
 
191
        outf = file(PROBE_SOURCE, 'w')
 
192
        outf.write(PROBE_HEAD)
 
193
        
 
194
        for typedef in sizes:
 
195
                outf.write("\tDECLARE_INTSIZE(%s);\n" % typedef)
 
196
        
 
197
        outf.write(PROBE_TAIL)
 
198
        outf.close()
 
199
        
 
200
        args = [common['CC'], "-S", "-o", PROBE_OUTPUT, PROBE_SOURCE]
 
201
        
 
202
        try:
 
203
                sys.stderr.write("Checking compiler properties ... ")
 
204
                output = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
 
205
        except:
 
206
                sys.stderr.write("failed\n")
 
207
                print_error(["Error executing \"%s\"." % " ".join(args),
 
208
                             "Make sure that the compiler works properly."])
 
209
        
 
210
        if (not os.path.isfile(PROBE_OUTPUT)):
 
211
                sys.stderr.write("failed\n")
 
212
                print output[1]
 
213
                print_error(["Error executing \"%s\"." % " ".join(args),
 
214
                             "The compiler did not produce the output file \"%s\"." % PROBE_OUTPUT,
 
215
                             "",
 
216
                             output[0],
 
217
                             output[1]])
 
218
        
 
219
        sys.stderr.write("ok\n")
 
220
        
 
221
        inf = file(PROBE_OUTPUT, 'r')
 
222
        lines = inf.readlines()
 
223
        inf.close()
 
224
        
 
225
        unsigned_sizes = {}
 
226
        signed_sizes = {}
 
227
        
 
228
        for j in range(len(lines)):
 
229
                tokens = lines[j].strip().split("\t")
 
230
                
 
231
                if (len(tokens) > 0):
 
232
                        if (tokens[0] == "AUTOTOOL_DECLARE"):
 
233
                                if (len(tokens) < 5):
 
234
                                        print_error(["Malformed declaration in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
 
235
                                
 
236
                                category = tokens[1]
 
237
                                subcategory = tokens[2]
 
238
                                name = tokens[3]
 
239
                                value = tokens[4]
 
240
                                
 
241
                                if (category == "intsize"):
 
242
                                        base = 10
 
243
                                        
 
244
                                        if ((value.startswith('$')) or (value.startswith('#'))):
 
245
                                                value = value[1:]
 
246
                                        
 
247
                                        if (value.startswith('0x')):
 
248
                                                value = value[2:]
 
249
                                                base = 16
 
250
                                        
 
251
                                        try:
 
252
                                                value_int = int(value, base)
 
253
                                        except:
 
254
                                                print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
 
255
                                        
 
256
                                        if (subcategory == "unsigned"):
 
257
                                                unsigned_sizes[name] = value_int
 
258
                                        elif (subcategory == "signed"):
 
259
                                                signed_sizes[name] = value_int
 
260
                                        else:
 
261
                                                print_error(["Unexpected keyword \"%s\" in \"%s\" on line %s." % (subcategory, PROBE_OUTPUT, j), COMPILER_FAIL])
 
262
        
 
263
        return {'unsigned_sizes' : unsigned_sizes, 'signed_sizes' : signed_sizes}
 
264
 
 
265
def detect_uints(unsigned_sizes, signed_sizes, bytes):
 
266
        "Detect correct types for fixed-size integer types"
 
267
        
 
268
        typedefs = []
 
269
        
 
270
        for b in bytes:
 
271
                fnd = False
 
272
                newtype = "uint%s_t" % (b * 8)
 
273
                
 
274
                for name, value in unsigned_sizes.items():
 
275
                        if (value == b):
 
276
                                oldtype = "unsigned %s" % name
 
277
                                typedefs.append({'oldtype' : oldtype, 'newtype' : newtype})
 
278
                                fnd = True
 
279
                                break
 
280
                
 
281
                if (not fnd):
 
282
                        print_error(['Unable to find appropriate integer type for %s' % newtype,
 
283
                                     COMPILER_FAIL])
 
284
                
 
285
                
 
286
                fnd = False
 
287
                newtype = "int%s_t" % (b * 8)
 
288
                
 
289
                for name, value in signed_sizes.items():
 
290
                        if (value == b):
 
291
                                oldtype = "signed %s" % name
 
292
                                typedefs.append({'oldtype' : oldtype, 'newtype' : newtype})
 
293
                                fnd = True
 
294
                                break
 
295
                
 
296
                if (not fnd):
 
297
                        print_error(['Unable to find appropriate integer type for %s' % newtype,
 
298
                                     COMPILER_FAIL])
 
299
        
 
300
        return typedefs
 
301
 
 
302
def create_makefile(mkname, common):
 
303
        "Create makefile output"
 
304
        
 
305
        outmk = file(mkname, 'w')
 
306
        
 
307
        outmk.write('#########################################\n')
 
308
        outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
 
309
        outmk.write('#########################################\n\n')
132
310
        
133
311
        for key, value in common.items():
134
 
                outcm.write('%s = %s\n' % (key, value))
135
 
        
136
 
        outcm.close()
 
312
                outmk.write('%s = %s\n' % (key, value))
 
313
        
 
314
        outmk.close()
 
315
 
 
316
def create_header(hdname, typedefs):
 
317
        "Create header output"
 
318
        
 
319
        outhd = file(hdname, 'w')
 
320
        
 
321
        outhd.write('/***************************************\n')
 
322
        outhd.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
 
323
        outhd.write(' ***************************************/\n\n')
 
324
        
 
325
        outhd.write('#ifndef %s\n' % GUARD)
 
326
        outhd.write('#define %s\n\n' % GUARD)
 
327
        
 
328
        for typedef in typedefs:
 
329
                outhd.write('typedef %s %s;\n' % (typedef['oldtype'], typedef['newtype']))
 
330
        
 
331
        outhd.write('\n#endif\n')
 
332
        outhd.close()
137
333
 
138
334
def main():
139
335
        config = {}
140
336
        common = {}
141
337
        
142
338
        # Read and check configuration
143
 
        if os.path.exists(MAKEFILE):
144
 
                read_config(MAKEFILE, config)
 
339
        if os.path.exists(CONFIG):
 
340
                read_config(CONFIG, config)
145
341
        else:
146
 
                print_error(["Configuration file %s not found! Make sure that the" % MAKEFILE,
 
342
                print_error(["Configuration file %s not found! Make sure that the" % CONFIG,
147
343
                             "configuration phase of HelenOS build went OK. Try running",
148
344
                             "\"make config\" again."])
149
345
        
163
359
        else:
164
360
                binutils_prefix = ""
165
361
        
166
 
        # Common utilities
167
 
        check_app(["ln", "--version"], "Symlink utility", "usually part of coreutils")
168
 
        check_app(["rm", "--version"], "File remove utility", "usually part of coreutils")
169
 
        check_app(["mkdir", "--version"], "Directory creation utility", "usually part of coreutils")
170
 
        check_app(["cp", "--version"], "Copy utility", "usually part of coreutils")
171
 
        check_app(["find", "--version"], "Find utility", "usually part of findutils")
172
 
        check_app(["diff", "--version"], "Diff utility", "usually part of diffutils")
173
 
        check_app(["make", "--version"], "Make utility", "preferably GNU Make")
174
 
        check_app(["makedepend", "-f", "-"], "Makedepend utility", "usually part of imake or xutils")
 
362
        owd = sandbox_enter()
175
363
        
176
 
        # Compiler
177
 
        if (config['COMPILER'] == "gcc_cross"):
178
 
                if (config['PLATFORM'] == "abs32le"):
179
 
                        check_config(config, "CROSS_TARGET")
180
 
                        target = config['CROSS_TARGET']
181
 
                        
182
 
                        if (config['CROSS_TARGET'] == "arm32"):
 
364
        try:
 
365
                # Common utilities
 
366
                check_app(["ln", "--version"], "Symlink utility", "usually part of coreutils")
 
367
                check_app(["rm", "--version"], "File remove utility", "usually part of coreutils")
 
368
                check_app(["mkdir", "--version"], "Directory creation utility", "usually part of coreutils")
 
369
                check_app(["cp", "--version"], "Copy utility", "usually part of coreutils")
 
370
                check_app(["find", "--version"], "Find utility", "usually part of findutils")
 
371
                check_app(["diff", "--version"], "Diff utility", "usually part of diffutils")
 
372
                check_app(["make", "--version"], "Make utility", "preferably GNU Make")
 
373
                check_app(["makedepend", "-f", "-"], "Makedepend utility", "usually part of imake or xutils")
 
374
                
 
375
                # Compiler
 
376
                if (config['COMPILER'] == "gcc_cross"):
 
377
                        if (config['PLATFORM'] == "abs32le"):
 
378
                                check_config(config, "CROSS_TARGET")
 
379
                                target = config['CROSS_TARGET']
 
380
                                
 
381
                                if (config['CROSS_TARGET'] == "arm32"):
 
382
                                        gnu_target = "arm-linux-gnu"
 
383
                                
 
384
                                if (config['CROSS_TARGET'] == "ia32"):
 
385
                                        gnu_target = "i686-pc-linux-gnu"
 
386
                                
 
387
                                if (config['CROSS_TARGET'] == "mips32"):
 
388
                                        gnu_target = "mipsel-linux-gnu"
 
389
                        
 
390
                        if (config['PLATFORM'] == "amd64"):
 
391
                                target = config['PLATFORM']
 
392
                                gnu_target = "amd64-linux-gnu"
 
393
                        
 
394
                        if (config['PLATFORM'] == "arm32"):
 
395
                                target = config['PLATFORM']
183
396
                                gnu_target = "arm-linux-gnu"
184
397
                        
185
 
                        if (config['CROSS_TARGET'] == "ia32"):
 
398
                        if (config['PLATFORM'] == "ia32"):
 
399
                                target = config['PLATFORM']
186
400
                                gnu_target = "i686-pc-linux-gnu"
187
401
                        
188
 
                        if (config['CROSS_TARGET'] == "mips32"):
189
 
                                gnu_target = "mipsel-linux-gnu"
190
 
                
191
 
                if (config['PLATFORM'] == "amd64"):
192
 
                        target = config['PLATFORM']
193
 
                        gnu_target = "amd64-linux-gnu"
194
 
                
195
 
                if (config['PLATFORM'] == "arm32"):
196
 
                        target = config['PLATFORM']
197
 
                        gnu_target = "arm-linux-gnu"
198
 
                
199
 
                if (config['PLATFORM'] == "ia32"):
200
 
                        target = config['PLATFORM']
201
 
                        gnu_target = "i686-pc-linux-gnu"
202
 
                
203
 
                if (config['PLATFORM'] == "ia64"):
204
 
                        target = config['PLATFORM']
205
 
                        gnu_target = "ia64-pc-linux-gnu"
206
 
                
207
 
                if (config['PLATFORM'] == "mips32"):
208
 
                        check_config(config, "MACHINE")
209
 
                        
210
 
                        if ((config['MACHINE'] == "lgxemul") or (config['MACHINE'] == "msim")):
211
 
                                target = config['PLATFORM']
212
 
                                gnu_target = "mipsel-linux-gnu"
213
 
                        
214
 
                        if (config['MACHINE'] == "bgxemul"):
215
 
                                target = "mips32eb"
216
 
                                gnu_target = "mips-linux-gnu"
217
 
                
218
 
                if (config['PLATFORM'] == "ppc32"):
219
 
                        target = config['PLATFORM']
220
 
                        gnu_target = "ppc-linux-gnu"
221
 
                
222
 
                if (config['PLATFORM'] == "sparc64"):
223
 
                        target = config['PLATFORM']
224
 
                        gnu_target = "sparc64-linux-gnu"
225
 
                
226
 
                path = "%s/%s/bin" % (cross_prefix, target)
227
 
                prefix = "%s-" % gnu_target
228
 
                
229
 
                check_gcc(path, prefix, common, PACKAGE_CROSS)
230
 
                check_binutils(path, prefix, common, PACKAGE_CROSS)
231
 
                common['CC'] = common['GCC']
232
 
        
233
 
        if (config['COMPILER'] == "gcc_native"):
234
 
                check_gcc(None, "", common, PACKAGE_GCC)
235
 
                check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
236
 
                common['CC'] = common['GCC']
237
 
        
238
 
        if (config['COMPILER'] == "icc"):
239
 
                common['CC'] = "icc"
240
 
                check_app([common['CC'], "-V"], "Intel C++ Compiler", "support is experimental")
241
 
                check_gcc(None, "", common, PACKAGE_GCC)
242
 
                check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
243
 
        
244
 
        if (config['COMPILER'] == "suncc"):
245
 
                common['CC'] = "suncc"
246
 
                check_app([common['CC'], "-V"], "Sun Studio Compiler", "support is experimental")
247
 
                check_gcc(None, "", common, PACKAGE_GCC)
248
 
                check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
249
 
        
250
 
        if (config['COMPILER'] == "clang"):
251
 
                common['CC'] = "clang"
252
 
                check_app([common['CC'], "--version"], "Clang compiler", "preferably version 1.0 or newer")
253
 
                check_gcc(None, "", common, PACKAGE_GCC)
254
 
                check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
255
 
        
256
 
        # Platform-specific utilities
257
 
        if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
258
 
                check_app(["mkisofs", "--version"], "ISO 9660 creation utility", "usually part of genisoimage")
259
 
        
260
 
        create_output(COMMON, common)
 
402
                        if (config['PLATFORM'] == "ia64"):
 
403
                                target = config['PLATFORM']
 
404
                                gnu_target = "ia64-pc-linux-gnu"
 
405
                        
 
406
                        if (config['PLATFORM'] == "mips32"):
 
407
                                check_config(config, "MACHINE")
 
408
                                
 
409
                                if ((config['MACHINE'] == "lgxemul") or (config['MACHINE'] == "msim")):
 
410
                                        target = config['PLATFORM']
 
411
                                        gnu_target = "mipsel-linux-gnu"
 
412
                                
 
413
                                if (config['MACHINE'] == "bgxemul"):
 
414
                                        target = "mips32eb"
 
415
                                        gnu_target = "mips-linux-gnu"
 
416
                        
 
417
                        if (config['PLATFORM'] == "ppc32"):
 
418
                                target = config['PLATFORM']
 
419
                                gnu_target = "ppc-linux-gnu"
 
420
                        
 
421
                        if (config['PLATFORM'] == "sparc64"):
 
422
                                target = config['PLATFORM']
 
423
                                gnu_target = "sparc64-linux-gnu"
 
424
                        
 
425
                        path = "%s/%s/bin" % (cross_prefix, target)
 
426
                        prefix = "%s-" % gnu_target
 
427
                        
 
428
                        check_gcc(path, prefix, common, PACKAGE_CROSS)
 
429
                        check_binutils(path, prefix, common, PACKAGE_CROSS)
 
430
                        
 
431
                        check_common(common, "GCC")
 
432
                        common['CC'] = common['GCC']
 
433
                
 
434
                if (config['COMPILER'] == "gcc_native"):
 
435
                        check_gcc(None, "", common, PACKAGE_GCC)
 
436
                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
 
437
                        
 
438
                        check_common(common, "GCC")
 
439
                        common['CC'] = common['GCC']
 
440
                
 
441
                if (config['COMPILER'] == "icc"):
 
442
                        common['CC'] = "icc"
 
443
                        check_app([common['CC'], "-V"], "Intel C++ Compiler", "support is experimental")
 
444
                        check_gcc(None, "", common, PACKAGE_GCC)
 
445
                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
 
446
                
 
447
                if (config['COMPILER'] == "suncc"):
 
448
                        common['CC'] = "suncc"
 
449
                        check_app([common['CC'], "-V"], "Sun Studio Compiler", "support is experimental")
 
450
                        check_gcc(None, "", common, PACKAGE_GCC)
 
451
                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
 
452
                
 
453
                if (config['COMPILER'] == "clang"):
 
454
                        common['CC'] = "clang"
 
455
                        check_app([common['CC'], "--version"], "Clang compiler", "preferably version 1.0 or newer")
 
456
                        check_gcc(None, "", common, PACKAGE_GCC)
 
457
                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
 
458
                
 
459
                # Platform-specific utilities
 
460
                if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
 
461
                        check_app(["mkisofs", "--version"], "ISO 9660 creation utility", "usually part of genisoimage")
 
462
                
 
463
                probe = probe_compiler(common,
 
464
                        [
 
465
                                "char",
 
466
                                "short int",
 
467
                                "int",
 
468
                                "long int",
 
469
                                "long long int",
 
470
                        ]
 
471
                )
 
472
                
 
473
                typedefs = detect_uints(probe['unsigned_sizes'], probe['signed_sizes'], [1, 2, 4, 8])
 
474
                
 
475
        finally:
 
476
                sandbox_leave(owd)
 
477
        
 
478
        create_makefile(MAKEFILE, common)
 
479
        create_header(HEADER, typedefs)
261
480
        
262
481
        return 0
263
482