source: mainline/tools/autotool.py@ 75b24cd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 75b24cd was ff87f70, checked in by Martin Decky <martin@…>, 8 years ago

prioritize genisoimage over mkisofs
(mkisofs tents to be an alias for xorriso on modern systems, but xorriso does not support all options of genisoimage in its compatibility mode so far)

  • Property mode set to 100755
File size: 32.3 KB
Line 
1#!/usr/bin/env python
2#
3# Copyright (c) 2010 Martin Decky
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# - Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer.
12# - Redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions and the following disclaimer in the
14# documentation and/or other materials provided with the distribution.
15# - The name of the author may not be used to endorse or promote products
16# derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29
30"""
31Detect important prerequisites and parameters for building HelenOS
32"""
33
34import sys
35import os
36import shutil
37import re
38import time
39import subprocess
40
41SANDBOX = 'autotool'
42CONFIG = 'Makefile.config'
43MAKEFILE = 'Makefile.common'
44HEADER = 'common.h'
45GUARD = 'AUTOTOOL_COMMON_H_'
46
47PROBE_SOURCE = 'probe.c'
48PROBE_OUTPUT = 'probe.s'
49
50PROBE_INT128_SOURCE = 'probe_int128.c'
51PROBE_INT128_OUTPUT = 'probe_int128.s'
52
53PACKAGE_BINUTILS = "usually part of binutils"
54PACKAGE_GCC = "preferably version 4.7.0 or newer"
55PACKAGE_CROSS = "use tools/toolchain.sh to build the cross-compiler toolchain"
56
57COMPILER_FAIL = "The compiler is probably not capable to compile HelenOS."
58COMPILER_WARNING = "The compilation of HelenOS might fail."
59
60PROBE_HEAD = """#define AUTOTOOL_DECLARE(category, subcategory, tag, name, strc, conc, value) \\
61 asm volatile ( \\
62 "AUTOTOOL_DECLARE\\t" category "\\t" subcategory "\\t" tag "\\t" name "\\t" strc "\\t" conc "\\t%[val]\\n" \\
63 : \\
64 : [val] "n" (value) \\
65 )
66
67#define STRING(arg) STRING_ARG(arg)
68#define STRING_ARG(arg) #arg
69
70#define DECLARE_BUILTIN_TYPE(tag, type) \\
71 AUTOTOOL_DECLARE("builtin_size", "", tag, STRING(type), "", "", sizeof(type)); \\
72 AUTOTOOL_DECLARE("builtin_sign", "unsigned long long int", tag, STRING(type), "unsigned", "", __builtin_types_compatible_p(type, unsigned long long int)); \\
73 AUTOTOOL_DECLARE("builtin_sign", "unsigned long int", tag, STRING(type), "unsigned", "", __builtin_types_compatible_p(type, unsigned long int)); \\
74 AUTOTOOL_DECLARE("builtin_sign", "unsigned int", tag, STRING(type), "unsigned", "", __builtin_types_compatible_p(type, unsigned int)); \\
75 AUTOTOOL_DECLARE("builtin_sign", "unsigned short int", tag, STRING(type), "unsigned", "", __builtin_types_compatible_p(type, unsigned short int)); \\
76 AUTOTOOL_DECLARE("builtin_sign", "unsigned char", tag, STRING(type), "unsigned", "", __builtin_types_compatible_p(type, unsigned char)); \\
77 AUTOTOOL_DECLARE("builtin_sign", "signed long long int", tag, STRING(type), "signed", "", __builtin_types_compatible_p(type, signed long long int)); \\
78 AUTOTOOL_DECLARE("builtin_sign", "signed long int", tag, STRING(type), "signed", "", __builtin_types_compatible_p(type, signed long int)); \\
79 AUTOTOOL_DECLARE("builtin_sign", "signed int", tag, STRING(type), "signed", "", __builtin_types_compatible_p(type, signed int)); \\
80 AUTOTOOL_DECLARE("builtin_sign", "signed short int", tag, STRING(type), "signed", "", __builtin_types_compatible_p(type, signed short int)); \\
81 AUTOTOOL_DECLARE("builtin_sign", "signed char", tag, STRING(type), "signed", "", __builtin_types_compatible_p(type, signed char));
82
83#define DECLARE_INTSIZE(tag, type, strc, conc) \\
84 AUTOTOOL_DECLARE("intsize", "unsigned", tag, #type, strc, conc, sizeof(unsigned type)); \\
85 AUTOTOOL_DECLARE("intsize", "signed", tag, #type, strc, conc, sizeof(signed type));
86
87#define DECLARE_FLOATSIZE(tag, type) \\
88 AUTOTOOL_DECLARE("floatsize", "", tag, #type, "", "", sizeof(type));
89
90extern int main(int, char *[]);
91
92int main(int argc, char *argv[])
93{
94#ifdef __SIZE_TYPE__
95 DECLARE_BUILTIN_TYPE("size", __SIZE_TYPE__);
96#endif
97#ifdef __WCHAR_TYPE__
98 DECLARE_BUILTIN_TYPE("wchar", __WCHAR_TYPE__);
99#endif
100#ifdef __WINT_TYPE__
101 DECLARE_BUILTIN_TYPE("wint", __WINT_TYPE__);
102#endif
103"""
104
105PROBE_TAIL = """}
106"""
107
108PROBE_INT128_HEAD = """#define AUTOTOOL_DECLARE(category, subcategory, tag, name, strc, conc, value) \\
109 asm volatile ( \\
110 "AUTOTOOL_DECLARE\\t" category "\\t" subcategory "\\t" tag "\\t" name "\\t" strc "\\t" conc "\\t%[val]\\n" \\
111 : \\
112 : [val] "n" (value) \\
113 )
114
115#define DECLARE_INTSIZE(tag, type) \\
116 AUTOTOOL_DECLARE("intsize", "unsigned", tag, #type, "", "", sizeof(unsigned type)); \\
117 AUTOTOOL_DECLARE("intsize", "signed", tag, #type, "", "", sizeof(signed type));
118
119extern int main(int, char *[]);
120
121int main(int argc, char *argv[])
122{
123"""
124
125PROBE_INT128_TAIL = """}
126"""
127
128def read_config(fname, config):
129 "Read HelenOS build configuration"
130
131 inf = open(fname, 'r')
132
133 for line in inf:
134 res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line)
135 if (res):
136 config[res.group(1)] = res.group(2)
137
138 inf.close()
139
140def print_error(msg):
141 "Print a bold error message"
142
143 sys.stderr.write("\n")
144 sys.stderr.write("######################################################################\n")
145 sys.stderr.write("HelenOS build sanity check error:\n")
146 sys.stderr.write("\n")
147 sys.stderr.write("%s\n" % "\n".join(msg))
148 sys.stderr.write("######################################################################\n")
149 sys.stderr.write("\n")
150
151 sys.exit(1)
152
153def print_warning(msg):
154 "Print a bold error message"
155
156 sys.stderr.write("\n")
157 sys.stderr.write("######################################################################\n")
158 sys.stderr.write("HelenOS build sanity check warning:\n")
159 sys.stderr.write("\n")
160 sys.stderr.write("%s\n" % "\n".join(msg))
161 sys.stderr.write("######################################################################\n")
162 sys.stderr.write("\n")
163
164 time.sleep(5)
165
166def sandbox_enter():
167 "Create a temporal sandbox directory for running tests"
168
169 if (os.path.exists(SANDBOX)):
170 if (os.path.isdir(SANDBOX)):
171 try:
172 shutil.rmtree(SANDBOX)
173 except:
174 print_error(["Unable to cleanup the directory \"%s\"." % SANDBOX])
175 else:
176 print_error(["Please inspect and remove unexpected directory,",
177 "entry \"%s\"." % SANDBOX])
178
179 try:
180 os.mkdir(SANDBOX)
181 except:
182 print_error(["Unable to create sandbox directory \"%s\"." % SANDBOX])
183
184 owd = os.getcwd()
185 os.chdir(SANDBOX)
186
187 return owd
188
189def sandbox_leave(owd):
190 "Leave the temporal sandbox directory"
191
192 os.chdir(owd)
193
194def check_config(config, key):
195 "Check whether the configuration key exists"
196
197 if (not key in config):
198 print_error(["Build configuration of HelenOS does not contain %s." % key,
199 "Try running \"make config\" again.",
200 "If the problem persists, please contact the developers of HelenOS."])
201
202def check_common(common, key):
203 "Check whether the common key exists"
204
205 if (not key in common):
206 print_error(["Failed to determine the value %s." % key,
207 "Please contact the developers of HelenOS."])
208
209def get_target(config):
210 target = None
211 gnu_target = None
212 clang_target = None
213 helenos_target = None
214 cc_args = []
215
216 if (config['PLATFORM'] == "abs32le"):
217 check_config(config, "CROSS_TARGET")
218 target = config['CROSS_TARGET']
219
220 if (config['CROSS_TARGET'] == "arm32"):
221 gnu_target = "arm-linux-gnueabi"
222 clang_target = "arm-unknown-none"
223 helenos_target = "arm-helenos-gnueabi"
224
225 if (config['CROSS_TARGET'] == "ia32"):
226 gnu_target = "i686-pc-linux-gnu"
227 clang_target = "i686-unknown-none"
228 helenos_target = "i686-pc-helenos"
229
230 if (config['CROSS_TARGET'] == "mips32"):
231 cc_args.append("-mabi=32")
232 gnu_target = "mipsel-linux-gnu"
233 clang_target = "mipsel-unknown-none"
234 helenos_target = "mipsel-helenos"
235
236 if (config['PLATFORM'] == "amd64"):
237 target = config['PLATFORM']
238 gnu_target = "amd64-linux-gnu"
239 clang_target = "x86_64-unknown-none"
240 helenos_target = "amd64-helenos"
241
242 if (config['PLATFORM'] == "arm32"):
243 target = config['PLATFORM']
244 gnu_target = "arm-linux-gnueabi"
245 clang_target = "arm-unknown-none-eabi"
246 helenos_target = "arm-helenos-gnueabi"
247
248 if (config['PLATFORM'] == "ia32"):
249 target = config['PLATFORM']
250 gnu_target = "i686-pc-linux-gnu"
251 clang_target = "i686-unknown-none"
252 helenos_target = "i686-pc-helenos"
253
254 if (config['PLATFORM'] == "ia64"):
255 target = config['PLATFORM']
256 gnu_target = "ia64-pc-linux-gnu"
257 helenos_target = "ia64-pc-helenos"
258
259 if (config['PLATFORM'] == "mips32"):
260 check_config(config, "MACHINE")
261 cc_args.append("-mabi=32")
262
263 if ((config['MACHINE'] == "msim") or (config['MACHINE'] == "lmalta")):
264 target = config['PLATFORM']
265 gnu_target = "mipsel-linux-gnu"
266 clang_target = "mipsel-unknown-none"
267 helenos_target = "mipsel-helenos"
268
269 if ((config['MACHINE'] == "bmalta")):
270 target = "mips32eb"
271 gnu_target = "mips-linux-gnu"
272 clang_target = "mips-unknown-none"
273 helenos_target = "mips-helenos"
274
275 if (config['PLATFORM'] == "mips64"):
276 check_config(config, "MACHINE")
277 cc_args.append("-mabi=64")
278
279 if (config['MACHINE'] == "msim"):
280 target = config['PLATFORM']
281 gnu_target = "mips64el-linux-gnu"
282 clang_target = "mips64el-unknown-none"
283 helenos_target = "mips64el-helenos"
284
285 if (config['PLATFORM'] == "ppc32"):
286 target = config['PLATFORM']
287 gnu_target = "ppc-linux-gnu"
288 clang_target = "ppc-unknown-none"
289 helenos_target = "ppc-helenos"
290
291 if (config['PLATFORM'] == "riscv64"):
292 target = config['PLATFORM']
293 gnu_target = "riscv64-unknown-linux-gnu"
294 clang_target = "riscv-unknown-none"
295 helenos_target = "riscv64-helenos"
296
297 if (config['PLATFORM'] == "sparc64"):
298 target = config['PLATFORM']
299 gnu_target = "sparc64-linux-gnu"
300 clang_target = "sparc-unknown-none"
301 helenos_target = "sparc64-helenos"
302
303 return (target, cc_args, gnu_target, clang_target, helenos_target)
304
305def check_app(args, name, details):
306 "Check whether an application can be executed"
307
308 try:
309 sys.stderr.write("Checking for %s ... " % args[0])
310 subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
311 except:
312 sys.stderr.write("failed\n")
313 print_error(["%s is missing." % name,
314 "",
315 "Execution of \"%s\" has failed. Please make sure that it" % " ".join(args),
316 "is installed in your system (%s)." % details])
317
318 sys.stderr.write("ok\n")
319
320def check_app_alternatives(alts, args, name, details):
321 "Check whether an application can be executed (use several alternatives)"
322
323 tried = []
324 found = None
325
326 for alt in alts:
327 working = True
328 cmdline = [alt] + args
329 tried.append(" ".join(cmdline))
330
331 try:
332 sys.stderr.write("Checking for %s ... " % alt)
333 subprocess.Popen(cmdline, stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
334 except:
335 sys.stderr.write("failed\n")
336 working = False
337
338 if (working):
339 sys.stderr.write("ok\n")
340 found = alt
341 break
342
343 if (found is None):
344 print_error(["%s is missing." % name,
345 "",
346 "Please make sure that it is installed in your",
347 "system (%s)." % details,
348 "",
349 "The following alternatives were tried:"] + tried)
350
351 return found
352
353def check_gcc(path, prefix, common, details):
354 "Check for GCC"
355
356 common['GCC'] = "%sgcc" % prefix
357
358 if (not path is None):
359 common['GCC'] = "%s/%s" % (path, common['GCC'])
360
361 check_app([common['GCC'], "--version"], "GNU GCC", details)
362
363def check_binutils(path, prefix, common, details):
364 "Check for binutils toolchain"
365
366 common['AS'] = "%sas" % prefix
367 common['LD'] = "%sld" % prefix
368 common['AR'] = "%sar" % prefix
369 common['OBJCOPY'] = "%sobjcopy" % prefix
370 common['OBJDUMP'] = "%sobjdump" % prefix
371 common['STRIP'] = "%sstrip" % prefix
372
373 if (not path is None):
374 for key in ["AS", "LD", "AR", "OBJCOPY", "OBJDUMP", "STRIP"]:
375 common[key] = "%s/%s" % (path, common[key])
376
377 check_app([common['AS'], "--version"], "GNU Assembler", details)
378 check_app([common['LD'], "--version"], "GNU Linker", details)
379 check_app([common['AR'], "--version"], "GNU Archiver", details)
380 check_app([common['OBJCOPY'], "--version"], "GNU Objcopy utility", details)
381 check_app([common['OBJDUMP'], "--version"], "GNU Objdump utility", details)
382 check_app([common['STRIP'], "--version"], "GNU strip", details)
383
384def check_python():
385 "Check for Python dependencies"
386
387 try:
388 sys.stderr.write("Checking for PyYAML ... ")
389 import yaml
390 except ImportError:
391 print_error(["PyYAML is missing.",
392 "",
393 "Please make sure that it is installed in your",
394 "system (usually part of PyYAML package)."])
395
396 sys.stderr.write("ok\n")
397
398def decode_value(value):
399 "Decode integer value"
400
401 base = 10
402
403 if ((value.startswith('$')) or (value.startswith('#'))):
404 value = value[1:]
405
406 if (value.startswith('0x')):
407 value = value[2:]
408 base = 16
409
410 return int(value, base)
411
412def probe_compiler(common, intsizes, floatsizes):
413 "Generate, compile and parse probing source"
414
415 check_common(common, "CC")
416
417 outf = open(PROBE_SOURCE, 'w')
418 outf.write(PROBE_HEAD)
419
420 for typedef in intsizes:
421 outf.write("\tDECLARE_INTSIZE(\"%s\", %s, %s, %s);\n" % (typedef['tag'], typedef['type'], typedef['strc'], typedef['conc']))
422
423 for typedef in floatsizes:
424 outf.write("\tDECLARE_FLOATSIZE(\"%s\", %s);\n" % (typedef['tag'], typedef['type']))
425
426 outf.write(PROBE_TAIL)
427 outf.close()
428
429 args = [common['CC']]
430 args.extend(common['CC_ARGS'])
431 args.extend(["-S", "-o", PROBE_OUTPUT, PROBE_SOURCE])
432
433 try:
434 sys.stderr.write("Checking compiler properties ... ")
435 output = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
436 except:
437 sys.stderr.write("failed\n")
438 print_error(["Error executing \"%s\"." % " ".join(args),
439 "Make sure that the compiler works properly."])
440
441 if (not os.path.isfile(PROBE_OUTPUT)):
442 sys.stderr.write("failed\n")
443 print(output[1])
444 print_error(["Error executing \"%s\"." % " ".join(args),
445 "The compiler did not produce the output file \"%s\"." % PROBE_OUTPUT,
446 "",
447 output[0],
448 output[1]])
449
450 sys.stderr.write("ok\n")
451
452 inf = open(PROBE_OUTPUT, 'r')
453 lines = inf.readlines()
454 inf.close()
455
456 unsigned_sizes = {}
457 signed_sizes = {}
458
459 unsigned_tags = {}
460 signed_tags = {}
461
462 unsigned_strcs = {}
463 signed_strcs = {}
464
465 unsigned_concs = {}
466 signed_concs = {}
467
468 float_tags = {}
469
470 builtin_sizes = {}
471 builtin_signs = {}
472
473 for j in range(len(lines)):
474 tokens = lines[j].strip().split("\t")
475
476 if (len(tokens) > 0):
477 if (tokens[0] == "AUTOTOOL_DECLARE"):
478 if (len(tokens) < 7):
479 print_error(["Malformed declaration in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
480
481 category = tokens[1]
482 subcategory = tokens[2]
483 tag = tokens[3]
484 name = tokens[4]
485 strc = tokens[5]
486 conc = tokens[6]
487 value = tokens[7]
488
489 if (category == "intsize"):
490 try:
491 value_int = decode_value(value)
492 except:
493 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
494
495 if (subcategory == "unsigned"):
496 unsigned_sizes[value_int] = name
497 unsigned_tags[tag] = value_int
498 unsigned_strcs[value_int] = strc
499 unsigned_concs[value_int] = conc
500 elif (subcategory == "signed"):
501 signed_sizes[value_int] = name
502 signed_tags[tag] = value_int
503 signed_strcs[value_int] = strc
504 signed_concs[value_int] = conc
505 else:
506 print_error(["Unexpected keyword \"%s\" in \"%s\" on line %s." % (subcategory, PROBE_OUTPUT, j), COMPILER_FAIL])
507
508 if (category == "floatsize"):
509 try:
510 value_int = decode_value(value)
511 except:
512 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
513
514 float_tags[tag] = value_int
515
516 if (category == "builtin_size"):
517 try:
518 value_int = decode_value(value)
519 except:
520 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
521
522 builtin_sizes[tag] = {'name': name, 'value': value_int}
523
524 if (category == "builtin_sign"):
525 try:
526 value_int = decode_value(value)
527 except:
528 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
529
530 if (value_int == 1):
531 if (not tag in builtin_signs):
532 builtin_signs[tag] = strc;
533 elif (builtin_signs[tag] != strc):
534 print_error(["Inconsistent builtin type detection in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
535
536 return {'unsigned_sizes': unsigned_sizes, 'signed_sizes': signed_sizes, 'unsigned_tags': unsigned_tags, 'signed_tags': signed_tags, 'unsigned_strcs': unsigned_strcs, 'signed_strcs': signed_strcs, 'unsigned_concs': unsigned_concs, 'signed_concs': signed_concs, 'float_tags': float_tags, 'builtin_sizes': builtin_sizes, 'builtin_signs': builtin_signs}
537
538def probe_int128(common):
539 "Generate, compile and parse probing source for 128-bit integers"
540
541 check_common(common, "CC")
542
543 outf = open(PROBE_INT128_SOURCE, 'w')
544 outf.write(PROBE_INT128_HEAD)
545 outf.write("\tDECLARE_INTSIZE(\"INT128\", int __attribute((mode(TI))));\n")
546 outf.write(PROBE_INT128_TAIL)
547 outf.close()
548
549 args = [common['CC']]
550 args.extend(common['CC_ARGS'])
551 args.extend(["-S", "-o", PROBE_INT128_OUTPUT, PROBE_INT128_SOURCE])
552
553 try:
554 sys.stderr.write("Checking whether the compiler has intrinsic support for 128-bit integers ... ")
555 output = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
556 except:
557 sys.stderr.write("no\n")
558 return False
559
560 if (not os.path.isfile(PROBE_INT128_OUTPUT)):
561 sys.stderr.write("no\n")
562 return False
563
564 inf = open(PROBE_INT128_OUTPUT, 'r')
565 lines = inf.readlines()
566 inf.close()
567
568 for j in range(len(lines)):
569 tokens = lines[j].strip().split("\t")
570
571 if (len(tokens) > 0):
572 if (tokens[0] == "AUTOTOOL_DECLARE"):
573 if (len(tokens) < 7):
574 print_error(["Malformed declaration in \"%s\" on line %s." % (PROBE_INT128_OUTPUT, j), COMPILER_FAIL])
575
576 category = tokens[1]
577 subcategory = tokens[2]
578 tag = tokens[3]
579 name = tokens[4]
580 strc = tokens[5]
581 conc = tokens[6]
582 value = tokens[7]
583
584 if (category == "intsize"):
585 try:
586 value_int = decode_value(value)
587 except:
588 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_INT128_OUTPUT, j), COMPILER_FAIL])
589
590 if (subcategory == "unsigned"):
591 if (value_int != 16):
592 sys.stderr.write("no\n")
593 return False
594 elif (subcategory == "signed"):
595 if (value_int != 16):
596 sys.stderr.write("no\n")
597 return False
598 else:
599 print_error(["Unexpected keyword \"%s\" in \"%s\" on line %s." % (subcategory, PROBE_INT128_OUTPUT, j), COMPILER_FAIL])
600
601 sys.stderr.write("yes\n")
602 return True
603
604def detect_sizes(probe, bytes, inttags, floattags):
605 "Detect correct types for fixed-size types"
606
607 macros = []
608 typedefs = []
609
610 for b in bytes:
611 if (not b in probe['unsigned_sizes']):
612 print_error(['Unable to find appropriate unsigned integer type for %u bytes.' % b,
613 COMPILER_FAIL])
614
615 if (not b in probe['signed_sizes']):
616 print_error(['Unable to find appropriate signed integer type for %u bytes.' % b,
617 COMPILER_FAIL])
618
619 if (not b in probe['unsigned_strcs']):
620 print_error(['Unable to find appropriate unsigned printf formatter for %u bytes.' % b,
621 COMPILER_FAIL])
622
623 if (not b in probe['signed_strcs']):
624 print_error(['Unable to find appropriate signed printf formatter for %u bytes.' % b,
625 COMPILER_FAIL])
626
627 if (not b in probe['unsigned_concs']):
628 print_error(['Unable to find appropriate unsigned literal macro for %u bytes.' % b,
629 COMPILER_FAIL])
630
631 if (not b in probe['signed_concs']):
632 print_error(['Unable to find appropriate signed literal macro for %u bytes.' % b,
633 COMPILER_FAIL])
634
635 typedefs.append({'oldtype': "unsigned %s" % probe['unsigned_sizes'][b], 'newtype': "uint%u_t" % (b * 8)})
636 typedefs.append({'oldtype': "signed %s" % probe['signed_sizes'][b], 'newtype': "int%u_t" % (b * 8)})
637
638 macros.append({'oldmacro': "unsigned %s" % probe['unsigned_sizes'][b], 'newmacro': "UINT%u_T" % (b * 8)})
639 macros.append({'oldmacro': "signed %s" % probe['signed_sizes'][b], 'newmacro': "INT%u_T" % (b * 8)})
640
641 macros.append({'oldmacro': "\"%so\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIo%u" % (b * 8)})
642 macros.append({'oldmacro': "\"%su\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIu%u" % (b * 8)})
643 macros.append({'oldmacro': "\"%sx\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIx%u" % (b * 8)})
644 macros.append({'oldmacro': "\"%sX\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIX%u" % (b * 8)})
645 macros.append({'oldmacro': "\"%sd\"" % probe['signed_strcs'][b], 'newmacro': "PRId%u" % (b * 8)})
646
647 name = probe['unsigned_concs'][b]
648 if ((name.startswith('@')) or (name == "")):
649 macros.append({'oldmacro': "c ## U", 'newmacro': "UINT%u_C(c)" % (b * 8)})
650 else:
651 macros.append({'oldmacro': "c ## U%s" % name, 'newmacro': "UINT%u_C(c)" % (b * 8)})
652
653 name = probe['unsigned_concs'][b]
654 if ((name.startswith('@')) or (name == "")):
655 macros.append({'oldmacro': "c", 'newmacro': "INT%u_C(c)" % (b * 8)})
656 else:
657 macros.append({'oldmacro': "c ## %s" % name, 'newmacro': "INT%u_C(c)" % (b * 8)})
658
659 for tag in inttags:
660 newmacro = "U%s" % tag
661 if (not tag in probe['unsigned_tags']):
662 print_error(['Unable to find appropriate size macro for %s.' % newmacro,
663 COMPILER_FAIL])
664
665 oldmacro = "UINT%s" % (probe['unsigned_tags'][tag] * 8)
666 macros.append({'oldmacro': "%s_MIN" % oldmacro, 'newmacro': "%s_MIN" % newmacro})
667 macros.append({'oldmacro': "%s_MAX" % oldmacro, 'newmacro': "%s_MAX" % newmacro})
668 macros.append({'oldmacro': "1", 'newmacro': 'U%s_SIZE_%s' % (tag, probe['unsigned_tags'][tag] * 8)})
669
670 newmacro = tag
671 if (not tag in probe['signed_tags']):
672 print_error(['Unable to find appropriate size macro for %s' % newmacro,
673 COMPILER_FAIL])
674
675 oldmacro = "INT%s" % (probe['signed_tags'][tag] * 8)
676 macros.append({'oldmacro': "%s_MIN" % oldmacro, 'newmacro': "%s_MIN" % newmacro})
677 macros.append({'oldmacro': "%s_MAX" % oldmacro, 'newmacro': "%s_MAX" % newmacro})
678 macros.append({'oldmacro': "1", 'newmacro': '%s_SIZE_%s' % (tag, probe['signed_tags'][tag] * 8)})
679
680 for tag in floattags:
681 if (not tag in probe['float_tags']):
682 print_error(['Unable to find appropriate size macro for %s' % tag,
683 COMPILER_FAIL])
684
685 macros.append({'oldmacro': "1", 'newmacro': '%s_SIZE_%s' % (tag, probe['float_tags'][tag] * 8)})
686
687 if (not 'size' in probe['builtin_signs']):
688 print_error(['Unable to determine whether size_t is signed or unsigned.',
689 COMPILER_FAIL])
690
691 if (probe['builtin_signs']['size'] != 'unsigned'):
692 print_error(['The type size_t is not unsigned.',
693 COMPILER_FAIL])
694
695 fnd = True
696
697 if (not 'wchar' in probe['builtin_sizes']):
698 print_warning(['The compiler does not provide the macro __WCHAR_TYPE__',
699 'for defining the compiler-native type wchar_t. We are',
700 'forced to define wchar_t as a hardwired type int32_t.',
701 COMPILER_WARNING])
702 fnd = False
703
704 if (probe['builtin_sizes']['wchar']['value'] != 4):
705 print_warning(['The compiler provided macro __WCHAR_TYPE__ for defining',
706 'the compiler-native type wchar_t is not compliant with',
707 'HelenOS. We are forced to define wchar_t as a hardwired',
708 'type int32_t.',
709 COMPILER_WARNING])
710 fnd = False
711
712 if (not fnd):
713 macros.append({'oldmacro': "int32_t", 'newmacro': "wchar_t"})
714 else:
715 macros.append({'oldmacro': "__WCHAR_TYPE__", 'newmacro': "wchar_t"})
716
717 if (not 'wchar' in probe['builtin_signs']):
718 print_error(['Unable to determine whether wchar_t is signed or unsigned.',
719 COMPILER_FAIL])
720
721 if (probe['builtin_signs']['wchar'] == 'unsigned'):
722 macros.append({'oldmacro': "1", 'newmacro': 'WCHAR_IS_UNSIGNED'})
723 if (probe['builtin_signs']['wchar'] == 'signed'):
724 macros.append({'oldmacro': "1", 'newmacro': 'WCHAR_IS_SIGNED'})
725
726 fnd = True
727
728 if (not 'wint' in probe['builtin_sizes']):
729 print_warning(['The compiler does not provide the macro __WINT_TYPE__',
730 'for defining the compiler-native type wint_t. We are',
731 'forced to define wint_t as a hardwired type int32_t.',
732 COMPILER_WARNING])
733 fnd = False
734
735 if (probe['builtin_sizes']['wint']['value'] != 4):
736 print_warning(['The compiler provided macro __WINT_TYPE__ for defining',
737 'the compiler-native type wint_t is not compliant with',
738 'HelenOS. We are forced to define wint_t as a hardwired',
739 'type int32_t.',
740 COMPILER_WARNING])
741 fnd = False
742
743 if (not fnd):
744 macros.append({'oldmacro': "int32_t", 'newmacro': "wint_t"})
745 else:
746 macros.append({'oldmacro': "__WINT_TYPE__", 'newmacro': "wint_t"})
747
748 if (not 'wint' in probe['builtin_signs']):
749 print_error(['Unable to determine whether wint_t is signed or unsigned.',
750 COMPILER_FAIL])
751
752 if (probe['builtin_signs']['wint'] == 'unsigned'):
753 macros.append({'oldmacro': "1", 'newmacro': 'WINT_IS_UNSIGNED'})
754 if (probe['builtin_signs']['wint'] == 'signed'):
755 macros.append({'oldmacro': "1", 'newmacro': 'WINT_IS_SIGNED'})
756
757 return {'macros': macros, 'typedefs': typedefs}
758
759def create_makefile(mkname, common):
760 "Create makefile output"
761
762 outmk = open(mkname, 'w')
763
764 outmk.write('#########################################\n')
765 outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
766 outmk.write('## Generated by: tools/autotool.py ##\n')
767 outmk.write('#########################################\n\n')
768
769 for key, value in common.items():
770 if (type(value) is list):
771 outmk.write('%s = %s\n' % (key, " ".join(value)))
772 else:
773 outmk.write('%s = %s\n' % (key, value))
774
775 outmk.close()
776
777def create_header(hdname, maps, int128):
778 "Create header output"
779
780 outhd = open(hdname, 'w')
781
782 outhd.write('/***************************************\n')
783 outhd.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
784 outhd.write(' * Generated by: tools/autotool.py *\n')
785 outhd.write(' ***************************************/\n\n')
786
787 outhd.write('#ifndef %s\n' % GUARD)
788 outhd.write('#define %s\n\n' % GUARD)
789
790 for macro in maps['macros']:
791 outhd.write('#define %s %s\n' % (macro['newmacro'], macro['oldmacro']))
792
793 outhd.write('\n')
794
795 for typedef in maps['typedefs']:
796 outhd.write('typedef %s %s;\n' % (typedef['oldtype'], typedef['newtype']))
797
798 if (int128):
799 outhd.write('typedef unsigned int __attribute((mode(TI))) uint128_t;\n')
800 outhd.write('typedef signed int __attribute((mode(TI))) int128_t;\n')
801
802 outhd.write('\n#endif\n')
803 outhd.close()
804
805def main():
806 config = {}
807 common = {}
808
809 # Read and check configuration
810 if os.path.exists(CONFIG):
811 read_config(CONFIG, config)
812 else:
813 print_error(["Configuration file %s not found! Make sure that the" % CONFIG,
814 "configuration phase of HelenOS build went OK. Try running",
815 "\"make config\" again."])
816
817 check_config(config, "PLATFORM")
818 check_config(config, "COMPILER")
819 check_config(config, "BARCH")
820
821 # Cross-compiler prefix
822 if ('CROSS_PREFIX' in os.environ):
823 cross_prefix = os.environ['CROSS_PREFIX']
824 else:
825 cross_prefix = "/usr/local/cross"
826
827 # HelenOS cross-compiler prefix
828 if ('CROSS_HELENOS_PREFIX' in os.environ):
829 cross_helenos_prefix = os.environ['CROSS_HELENOS_PREFIX']
830 else:
831 cross_helenos_prefix = "/usr/local/cross-helenos"
832
833 # Prefix binutils tools on Solaris
834 if (os.uname()[0] == "SunOS"):
835 binutils_prefix = "g"
836 else:
837 binutils_prefix = ""
838
839 owd = sandbox_enter()
840
841 try:
842 # Common utilities
843 check_app(["ln", "--version"], "Symlink utility", "usually part of coreutils")
844 check_app(["rm", "--version"], "File remove utility", "usually part of coreutils")
845 check_app(["mkdir", "--version"], "Directory creation utility", "usually part of coreutils")
846 check_app(["cp", "--version"], "Copy utility", "usually part of coreutils")
847 check_app(["find", "--version"], "Find utility", "usually part of findutils")
848 check_app(["diff", "--version"], "Diff utility", "usually part of diffutils")
849 check_app(["make", "--version"], "Make utility", "preferably GNU Make")
850 check_app(["makedepend", "-f", "-"], "Makedepend utility", "usually part of imake or xutils")
851
852 # Compiler
853 common['CC_ARGS'] = []
854 if (config['COMPILER'] == "gcc_cross"):
855 target, cc_args, gnu_target, clang_target, helenos_target = get_target(config)
856
857 if (target is None) or (gnu_target is None):
858 print_error(["Unsupported compiler target for GNU GCC.",
859 "Please contact the developers of HelenOS."])
860
861 path = "%s/%s/bin" % (cross_prefix, target)
862 prefix = "%s-" % gnu_target
863
864 check_gcc(path, prefix, common, PACKAGE_CROSS)
865 check_binutils(path, prefix, common, PACKAGE_CROSS)
866
867 check_common(common, "GCC")
868 common['CC'] = common['GCC']
869 common['CC_ARGS'].extend(cc_args)
870
871 if (config['COMPILER'] == "gcc_helenos"):
872 target, cc_args, gnu_target, clang_target, helenos_target = get_target(config)
873
874 if (target is None) or (helenos_target is None):
875 print_error(["Unsupported compiler target for GNU GCC.",
876 "Please contact the developers of HelenOS."])
877
878 path = "%s/%s/bin" % (cross_helenos_prefix, target)
879 prefix = "%s-" % helenos_target
880
881 check_gcc(path, prefix, common, PACKAGE_CROSS)
882 check_binutils(path, prefix, common, PACKAGE_CROSS)
883
884 check_common(common, "GCC")
885 common['CC'] = common['GCC']
886 common['CC_ARGS'].extend(cc_args)
887
888 if (config['COMPILER'] == "gcc_native"):
889 check_gcc(None, "", common, PACKAGE_GCC)
890 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
891
892 check_common(common, "GCC")
893 common['CC'] = common['GCC']
894
895 if (config['COMPILER'] == "icc"):
896 check_app([common['CC'], "-V"], "Intel C++ Compiler", "support is experimental")
897 check_gcc(None, "", common, PACKAGE_GCC)
898 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
899
900 common['CC'] = "icc"
901
902 if (config['COMPILER'] == "clang"):
903 target, cc_args, gnu_target, clang_target, helenos_target = get_target(config)
904
905 if (target is None) or (gnu_target is None) or (clang_target is None):
906 print_error(["Unsupported compiler target for clang.",
907 "Please contact the developers of HelenOS."])
908
909 path = "%s/%s/bin" % (cross_prefix, target)
910 prefix = "%s-" % gnu_target
911
912 check_app(["clang", "--version"], "clang compiler", "preferably version 1.0 or newer")
913 check_gcc(path, prefix, common, PACKAGE_GCC)
914 check_binutils(path, prefix, common, PACKAGE_BINUTILS)
915
916 check_common(common, "GCC")
917 common['CC'] = "clang"
918 common['CC_ARGS'].extend(cc_args)
919 common['CC_ARGS'].append("-target")
920 common['CC_ARGS'].append(clang_target)
921 common['CLANG_TARGET'] = clang_target
922
923 check_python()
924
925 # Platform-specific utilities
926 if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
927 common['GENISOIMAGE'] = check_app_alternatives(["genisoimage", "mkisofs", "xorriso"], ["--version"], "ISO 9660 creation utility", "usually part of genisoimage")
928 if common['GENISOIMAGE'] == 'xorriso':
929 common['GENISOIMAGE'] += ' -as genisoimage'
930
931 probe = probe_compiler(common,
932 [
933 {'type': 'long long int', 'tag': 'LLONG', 'strc': '"ll"', 'conc': '"LL"'},
934 {'type': 'long int', 'tag': 'LONG', 'strc': '"l"', 'conc': '"L"'},
935 {'type': 'int', 'tag': 'INT', 'strc': '""', 'conc': '""'},
936 {'type': 'short int', 'tag': 'SHORT', 'strc': '"h"', 'conc': '"@"'},
937 {'type': 'char', 'tag': 'CHAR', 'strc': '"hh"', 'conc': '"@@"'}
938 ],
939 [
940 {'type': 'long double', 'tag': 'LONG_DOUBLE'},
941 {'type': 'double', 'tag': 'DOUBLE'},
942 {'type': 'float', 'tag': 'FLOAT'}
943 ]
944 )
945
946 int128 = probe_int128(common)
947
948 maps = detect_sizes(probe, [1, 2, 4, 8], ['CHAR', 'SHORT', 'INT', 'LONG', 'LLONG'], ['LONG_DOUBLE', 'DOUBLE', 'FLOAT'])
949
950 finally:
951 sandbox_leave(owd)
952
953 common['AUTOGEN'] = "%s/autogen.py" % os.path.dirname(os.path.abspath(sys.argv[0]))
954
955 create_makefile(MAKEFILE, common)
956 create_header(HEADER, maps, int128)
957
958 return 0
959
960if __name__ == '__main__':
961 sys.exit(main())
Note: See TracBrowser for help on using the repository browser.