Rename caps_apply_to_all to caps_apply_to_type
[helenos.git] / tools / autotool.py
bloba8cd8311cea9b016205bc6c75fb4874c1e02f938
1 #!/usr/bin/env python
3 # Copyright (c) 2010 Martin Decky
4 # All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
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.
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.
30 """
31 Detect important prerequisites and parameters for building HelenOS
32 """
34 import sys
35 import os
36 import shutil
37 import re
38 import time
39 import subprocess
41 SANDBOX = 'autotool'
42 CONFIG = 'Makefile.config'
43 MAKEFILE = 'Makefile.common'
44 HEADER = 'common.h'
45 GUARD = 'AUTOTOOL_COMMON_H_'
47 PROBE_SOURCE = 'probe.c'
48 PROBE_OUTPUT = 'probe.s'
50 PROBE_INT128_SOURCE = 'probe_int128.c'
51 PROBE_INT128_OUTPUT = 'probe_int128.s'
53 PACKAGE_BINUTILS = "usually part of binutils"
54 PACKAGE_GCC = "preferably version 4.7.0 or newer"
55 PACKAGE_CROSS = "use tools/toolchain.sh to build the cross-compiler toolchain"
57 COMPILER_FAIL = "The compiler is probably not capable to compile HelenOS."
58 COMPILER_WARNING = "The compilation of HelenOS might fail."
60 PROBE_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) \\
67 #define STRING(arg) STRING_ARG(arg)
68 #define STRING_ARG(arg) #arg
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));
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));
87 #define DECLARE_FLOATSIZE(tag, type) \\
88 AUTOTOOL_DECLARE("floatsize", "", tag, #type, "", "", sizeof(type));
90 extern int main(int, char *[]);
92 int main(int argc, char *argv[])
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
105 PROBE_TAIL = """}
108 PROBE_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) \\
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));
119 extern int main(int, char *[]);
121 int main(int argc, char *argv[])
125 PROBE_INT128_TAIL = """}
128 def read_config(fname, config):
129 "Read HelenOS build configuration"
131 inf = open(fname, 'r')
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)
138 inf.close()
140 def print_error(msg):
141 "Print a bold error message"
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")
151 sys.exit(1)
153 def print_warning(msg):
154 "Print a bold error message"
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")
164 time.sleep(5)
166 def sandbox_enter():
167 "Create a temporal sandbox directory for running tests"
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])
179 try:
180 os.mkdir(SANDBOX)
181 except:
182 print_error(["Unable to create sandbox directory \"%s\"." % SANDBOX])
184 owd = os.getcwd()
185 os.chdir(SANDBOX)
187 return owd
189 def sandbox_leave(owd):
190 "Leave the temporal sandbox directory"
192 os.chdir(owd)
194 def check_config(config, key):
195 "Check whether the configuration key exists"
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."])
202 def check_common(common, key):
203 "Check whether the common key exists"
205 if (not key in common):
206 print_error(["Failed to determine the value %s." % key,
207 "Please contact the developers of HelenOS."])
209 def get_target(config):
210 target = None
211 gnu_target = None
212 clang_target = None
213 helenos_target = None
214 cc_args = []
216 if (config['PLATFORM'] == "abs32le"):
217 check_config(config, "CROSS_TARGET")
218 target = config['CROSS_TARGET']
220 if (config['CROSS_TARGET'] == "arm32"):
221 gnu_target = "arm-linux-gnueabi"
222 clang_target = "arm-unknown-none"
223 helenos_target = "arm-helenos-gnueabi"
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"
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"
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"
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"
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"
254 if (config['PLATFORM'] == "ia64"):
255 target = config['PLATFORM']
256 gnu_target = "ia64-pc-linux-gnu"
257 helenos_target = "ia64-pc-helenos"
259 if (config['PLATFORM'] == "mips32"):
260 check_config(config, "MACHINE")
261 cc_args.append("-mabi=32")
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"
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"
275 if (config['PLATFORM'] == "mips64"):
276 check_config(config, "MACHINE")
277 cc_args.append("-mabi=64")
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"
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"
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"
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"
303 return (target, cc_args, gnu_target, clang_target, helenos_target)
305 def check_app(args, name, details):
306 "Check whether an application can be executed"
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,
315 "Execution of \"%s\" has failed. Please make sure that it" % " ".join(args),
316 "is installed in your system (%s)." % details])
318 sys.stderr.write("ok\n")
320 def check_app_alternatives(alts, args, name, details):
321 "Check whether an application can be executed (use several alternatives)"
323 tried = []
324 found = None
326 for alt in alts:
327 working = True
328 cmdline = [alt] + args
329 tried.append(" ".join(cmdline))
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
338 if (working):
339 sys.stderr.write("ok\n")
340 found = alt
341 break
343 if (found is None):
344 print_error(["%s is missing." % name,
346 "Please make sure that it is installed in your",
347 "system (%s)." % details,
349 "The following alternatives were tried:"] + tried)
351 return found
353 def check_gcc(path, prefix, common, details):
354 "Check for GCC"
356 common['GCC'] = "%sgcc" % prefix
358 if (not path is None):
359 common['GCC'] = "%s/%s" % (path, common['GCC'])
361 check_app([common['GCC'], "--version"], "GNU GCC", details)
363 def check_binutils(path, prefix, common, details):
364 "Check for binutils toolchain"
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
373 if (not path is None):
374 for key in ["AS", "LD", "AR", "OBJCOPY", "OBJDUMP", "STRIP"]:
375 common[key] = "%s/%s" % (path, common[key])
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)
384 def check_python():
385 "Check for Python dependencies"
387 try:
388 sys.stderr.write("Checking for PyYAML ... ")
389 import yaml
390 except ImportError:
391 print_error(["PyYAML is missing.",
393 "Please make sure that it is installed in your",
394 "system (usually part of PyYAML package)."])
396 sys.stderr.write("ok\n")
398 def decode_value(value):
399 "Decode integer value"
401 base = 10
403 if ((value.startswith('$')) or (value.startswith('#'))):
404 value = value[1:]
406 if (value.startswith('0x')):
407 value = value[2:]
408 base = 16
410 return int(value, base)
412 def probe_compiler(common, intsizes, floatsizes):
413 "Generate, compile and parse probing source"
415 check_common(common, "CC")
417 outf = open(PROBE_SOURCE, 'w')
418 outf.write(PROBE_HEAD)
420 for typedef in intsizes:
421 outf.write("\tDECLARE_INTSIZE(\"%s\", %s, %s, %s);\n" % (typedef['tag'], typedef['type'], typedef['strc'], typedef['conc']))
423 for typedef in floatsizes:
424 outf.write("\tDECLARE_FLOATSIZE(\"%s\", %s);\n" % (typedef['tag'], typedef['type']))
426 outf.write(PROBE_TAIL)
427 outf.close()
429 args = [common['CC']]
430 args.extend(common['CC_ARGS'])
431 args.extend(["-S", "-o", PROBE_OUTPUT, PROBE_SOURCE])
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."])
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,
447 output[0],
448 output[1]])
450 sys.stderr.write("ok\n")
452 inf = open(PROBE_OUTPUT, 'r')
453 lines = inf.readlines()
454 inf.close()
456 unsigned_sizes = {}
457 signed_sizes = {}
459 unsigned_tags = {}
460 signed_tags = {}
462 unsigned_strcs = {}
463 signed_strcs = {}
465 unsigned_concs = {}
466 signed_concs = {}
468 float_tags = {}
470 builtin_sizes = {}
471 builtin_signs = {}
473 for j in range(len(lines)):
474 tokens = lines[j].strip().split("\t")
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])
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]
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])
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])
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])
514 float_tags[tag] = value_int
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])
522 builtin_sizes[tag] = {'name': name, 'value': value_int}
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])
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])
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}
538 def probe_int128(common):
539 "Generate, compile and parse probing source for 128-bit integers"
541 check_common(common, "CC")
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()
549 args = [common['CC']]
550 args.extend(common['CC_ARGS'])
551 args.extend(["-S", "-o", PROBE_INT128_OUTPUT, PROBE_INT128_SOURCE])
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
560 if (not os.path.isfile(PROBE_INT128_OUTPUT)):
561 sys.stderr.write("no\n")
562 return False
564 inf = open(PROBE_INT128_OUTPUT, 'r')
565 lines = inf.readlines()
566 inf.close()
568 for j in range(len(lines)):
569 tokens = lines[j].strip().split("\t")
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])
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]
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])
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])
601 sys.stderr.write("yes\n")
602 return True
604 def detect_sizes(probe, bytes, inttags, floattags):
605 "Detect correct types for fixed-size types"
607 macros = []
608 typedefs = []
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])
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])
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])
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])
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])
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])
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)})
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)})
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)})
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)})
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)})
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])
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)})
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])
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)})
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])
685 macros.append({'oldmacro': "1", 'newmacro': '%s_SIZE_%s' % (tag, probe['float_tags'][tag] * 8)})
687 if (not 'size' in probe['builtin_signs']):
688 print_error(['Unable to determine whether size_t is signed or unsigned.',
689 COMPILER_FAIL])
691 if (probe['builtin_signs']['size'] != 'unsigned'):
692 print_error(['The type size_t is not unsigned.',
693 COMPILER_FAIL])
695 fnd = True
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
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
712 if (not fnd):
713 macros.append({'oldmacro': "int32_t", 'newmacro': "wchar_t"})
714 else:
715 macros.append({'oldmacro': "__WCHAR_TYPE__", 'newmacro': "wchar_t"})
717 if (not 'wchar' in probe['builtin_signs']):
718 print_error(['Unable to determine whether wchar_t is signed or unsigned.',
719 COMPILER_FAIL])
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'})
726 fnd = True
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
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
743 if (not fnd):
744 macros.append({'oldmacro': "int32_t", 'newmacro': "wint_t"})
745 else:
746 macros.append({'oldmacro': "__WINT_TYPE__", 'newmacro': "wint_t"})
748 if (not 'wint' in probe['builtin_signs']):
749 print_error(['Unable to determine whether wint_t is signed or unsigned.',
750 COMPILER_FAIL])
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'})
757 return {'macros': macros, 'typedefs': typedefs}
759 def create_makefile(mkname, common):
760 "Create makefile output"
762 outmk = open(mkname, 'w')
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')
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))
775 outmk.close()
777 def create_header(hdname, maps, int128):
778 "Create header output"
780 outhd = open(hdname, 'w')
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')
787 outhd.write('#ifndef %s\n' % GUARD)
788 outhd.write('#define %s\n\n' % GUARD)
790 for macro in maps['macros']:
791 outhd.write('#define %s %s\n' % (macro['newmacro'], macro['oldmacro']))
793 outhd.write('\n')
795 for typedef in maps['typedefs']:
796 outhd.write('typedef %s %s;\n' % (typedef['oldtype'], typedef['newtype']))
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')
802 outhd.write('\n#endif\n')
803 outhd.close()
805 def main():
806 config = {}
807 common = {}
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."])
817 check_config(config, "PLATFORM")
818 check_config(config, "COMPILER")
819 check_config(config, "BARCH")
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"
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"
833 # Prefix binutils tools on Solaris
834 if (os.uname()[0] == "SunOS"):
835 binutils_prefix = "g"
836 else:
837 binutils_prefix = ""
839 owd = sandbox_enter()
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 check_app(["unzip"], "unzip utility", "usually part of zip/unzip utilities")
853 # Compiler
854 common['CC_ARGS'] = []
855 if (config['COMPILER'] == "gcc_cross"):
856 target, cc_args, gnu_target, clang_target, helenos_target = get_target(config)
858 if (target is None) or (gnu_target is None):
859 print_error(["Unsupported compiler target for GNU GCC.",
860 "Please contact the developers of HelenOS."])
862 path = "%s/%s/bin" % (cross_prefix, target)
863 prefix = "%s-" % gnu_target
865 check_gcc(path, prefix, common, PACKAGE_CROSS)
866 check_binutils(path, prefix, common, PACKAGE_CROSS)
868 check_common(common, "GCC")
869 common['CC'] = common['GCC']
870 common['CC_ARGS'].extend(cc_args)
872 if (config['COMPILER'] == "gcc_helenos"):
873 target, cc_args, gnu_target, clang_target, helenos_target = get_target(config)
875 if (target is None) or (helenos_target is None):
876 print_error(["Unsupported compiler target for GNU GCC.",
877 "Please contact the developers of HelenOS."])
879 path = "%s/%s/bin" % (cross_helenos_prefix, target)
880 prefix = "%s-" % helenos_target
882 check_gcc(path, prefix, common, PACKAGE_CROSS)
883 check_binutils(path, prefix, common, PACKAGE_CROSS)
885 check_common(common, "GCC")
886 common['CC'] = common['GCC']
887 common['CC_ARGS'].extend(cc_args)
889 if (config['COMPILER'] == "gcc_native"):
890 check_gcc(None, "", common, PACKAGE_GCC)
891 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
893 check_common(common, "GCC")
894 common['CC'] = common['GCC']
896 if (config['COMPILER'] == "icc"):
897 check_app([common['CC'], "-V"], "Intel C++ Compiler", "support is experimental")
898 check_gcc(None, "", common, PACKAGE_GCC)
899 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
901 common['CC'] = "icc"
903 if (config['COMPILER'] == "clang"):
904 target, cc_args, gnu_target, clang_target, helenos_target = get_target(config)
906 if (target is None) or (gnu_target is None) or (clang_target is None):
907 print_error(["Unsupported compiler target for clang.",
908 "Please contact the developers of HelenOS."])
910 path = "%s/%s/bin" % (cross_prefix, target)
911 prefix = "%s-" % gnu_target
913 check_app(["clang", "--version"], "clang compiler", "preferably version 1.0 or newer")
914 check_gcc(path, prefix, common, PACKAGE_GCC)
915 check_binutils(path, prefix, common, PACKAGE_BINUTILS)
917 check_common(common, "GCC")
918 common['CC'] = "clang"
919 common['CC_ARGS'].extend(cc_args)
920 common['CC_ARGS'].append("-target")
921 common['CC_ARGS'].append(clang_target)
922 common['CLANG_TARGET'] = clang_target
924 check_python()
926 # Platform-specific utilities
927 if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
928 common['GENISOIMAGE'] = check_app_alternatives(["genisoimage", "mkisofs", "xorriso"], ["--version"], "ISO 9660 creation utility", "usually part of genisoimage")
929 if common['GENISOIMAGE'] == 'xorriso':
930 common['GENISOIMAGE'] += ' -as genisoimage'
932 probe = probe_compiler(common,
934 {'type': 'long long int', 'tag': 'LLONG', 'strc': '"ll"', 'conc': '"LL"'},
935 {'type': 'long int', 'tag': 'LONG', 'strc': '"l"', 'conc': '"L"'},
936 {'type': 'int', 'tag': 'INT', 'strc': '""', 'conc': '""'},
937 {'type': 'short int', 'tag': 'SHRT', 'strc': '"h"', 'conc': '"@"'},
938 {'type': 'char', 'tag': 'CHAR', 'strc': '"hh"', 'conc': '"@@"'}
941 {'type': 'long double', 'tag': 'LONG_DOUBLE'},
942 {'type': 'double', 'tag': 'DOUBLE'},
943 {'type': 'float', 'tag': 'FLOAT'}
947 int128 = probe_int128(common)
949 maps = detect_sizes(probe, [1, 2, 4, 8], ['CHAR', 'SHRT', 'INT', 'LONG', 'LLONG'], ['LONG_DOUBLE', 'DOUBLE', 'FLOAT'])
951 finally:
952 sandbox_leave(owd)
954 common['AUTOGEN'] = "%s/autogen.py" % os.path.dirname(os.path.abspath(sys.argv[0]))
956 create_makefile(MAKEFILE, common)
957 create_header(HEADER, maps, int128)
959 return 0
961 if __name__ == '__main__':
962 sys.exit(main())