source: mainline/tools/autotool.py@ a0a273e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a0a273e was a0a273e, checked in by jzr <zarevucky.jiri@…>, 8 years ago

Unify compiler handling a bit.

Most compiler flags have been changed from GCC-specific to "common",
since code might build but not work properly without them.
Clang still rejects some of the flags, but at least we can see
the incompatibilities now.

Explicit —target flag was removed from clang, in favor of using clang
through a target-specific symlink. This allows clang to automatically
find correct assembler and linker, if it needs to.

Additionally, assembly language files are now compiled using $(CC)
whether or not they need the preprocessor. This allows clang to build
.s files using its integrated assembler.

  • Property mode set to 100755
File size: 32.2 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 helenos_target = None
213 cc_args = []
214
215 if (config['PLATFORM'] == "abs32le"):
216 check_config(config, "CROSS_TARGET")
217 target = config['CROSS_TARGET']
218
219 if (config['CROSS_TARGET'] == "arm32"):
220 gnu_target = "arm-linux-gnueabi"
221 helenos_target = "arm-helenos-gnueabi"
222
223 if (config['CROSS_TARGET'] == "ia32"):
224 gnu_target = "i686-pc-linux-gnu"
225 helenos_target = "i686-pc-helenos"
226
227 if (config['CROSS_TARGET'] == "mips32"):
228 cc_args.append("-mabi=32")
229 gnu_target = "mipsel-linux-gnu"
230 helenos_target = "mipsel-helenos"
231
232 if (config['PLATFORM'] == "amd64"):
233 target = config['PLATFORM']
234 gnu_target = "amd64-linux-gnu"
235 helenos_target = "amd64-helenos"
236
237 if (config['PLATFORM'] == "arm32"):
238 target = config['PLATFORM']
239 gnu_target = "arm-linux-gnueabi"
240 helenos_target = "arm-helenos-gnueabi"
241
242 if (config['PLATFORM'] == "ia32"):
243 target = config['PLATFORM']
244 gnu_target = "i686-pc-linux-gnu"
245 helenos_target = "i686-pc-helenos"
246
247 if (config['PLATFORM'] == "ia64"):
248 target = config['PLATFORM']
249 gnu_target = "ia64-pc-linux-gnu"
250 helenos_target = "ia64-pc-helenos"
251
252 if (config['PLATFORM'] == "mips32"):
253 check_config(config, "MACHINE")
254 cc_args.append("-mabi=32")
255
256 if ((config['MACHINE'] == "msim") or (config['MACHINE'] == "lmalta")):
257 target = config['PLATFORM']
258 gnu_target = "mipsel-linux-gnu"
259 helenos_target = "mipsel-helenos"
260
261 if ((config['MACHINE'] == "bmalta")):
262 target = "mips32eb"
263 gnu_target = "mips-linux-gnu"
264 helenos_target = "mips-helenos"
265
266 if (config['PLATFORM'] == "mips64"):
267 check_config(config, "MACHINE")
268 cc_args.append("-mabi=64")
269
270 if (config['MACHINE'] == "msim"):
271 target = config['PLATFORM']
272 gnu_target = "mips64el-linux-gnu"
273 helenos_target = "mips64el-helenos"
274
275 if (config['PLATFORM'] == "ppc32"):
276 target = config['PLATFORM']
277 gnu_target = "ppc-linux-gnu"
278 helenos_target = "ppc-helenos"
279
280 if (config['PLATFORM'] == "riscv64"):
281 target = config['PLATFORM']
282 gnu_target = "riscv64-unknown-linux-gnu"
283 helenos_target = "riscv64-helenos"
284
285 if (config['PLATFORM'] == "sparc64"):
286 target = config['PLATFORM']
287 gnu_target = "sparc64-linux-gnu"
288 helenos_target = "sparc64-helenos"
289
290 return (target, cc_args, gnu_target, helenos_target)
291
292def check_app(args, name, details):
293 "Check whether an application can be executed"
294
295 try:
296 sys.stderr.write("Checking for %s ... " % args[0])
297 subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
298 except:
299 sys.stderr.write("failed\n")
300 print_error(["%s is missing." % name,
301 "",
302 "Execution of \"%s\" has failed. Please make sure that it" % " ".join(args),
303 "is installed in your system (%s)." % details])
304
305 sys.stderr.write("ok\n")
306
307def check_app_alternatives(alts, args, name, details):
308 "Check whether an application can be executed (use several alternatives)"
309
310 tried = []
311 found = None
312
313 for alt in alts:
314 working = True
315 cmdline = [alt] + args
316 tried.append(" ".join(cmdline))
317
318 try:
319 sys.stderr.write("Checking for %s ... " % alt)
320 subprocess.Popen(cmdline, stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
321 except:
322 sys.stderr.write("failed\n")
323 working = False
324
325 if (working):
326 sys.stderr.write("ok\n")
327 found = alt
328 break
329
330 if (found is None):
331 print_error(["%s is missing." % name,
332 "",
333 "Please make sure that it is installed in your",
334 "system (%s)." % details,
335 "",
336 "The following alternatives were tried:"] + tried)
337
338 return found
339
340def check_clang(path, prefix, common, details):
341 "Check for clang"
342
343 common['CLANG'] = "%sclang" % prefix
344
345 if (not path is None):
346 common['CLANG'] = "%s/%s" % (path, common['CLANG'])
347
348 check_app([common['CLANG'], "--version"], "clang", details)
349
350def check_gcc(path, prefix, common, details):
351 "Check for GCC"
352
353 common['GCC'] = "%sgcc" % prefix
354
355 if (not path is None):
356 common['GCC'] = "%s/%s" % (path, common['GCC'])
357
358 check_app([common['GCC'], "--version"], "GNU GCC", details)
359
360def check_binutils(path, prefix, common, details):
361 "Check for binutils toolchain"
362
363 common['AS'] = "%sas" % prefix
364 common['LD'] = "%sld" % prefix
365 common['AR'] = "%sar" % prefix
366 common['OBJCOPY'] = "%sobjcopy" % prefix
367 common['OBJDUMP'] = "%sobjdump" % prefix
368 common['STRIP'] = "%sstrip" % prefix
369
370 if (not path is None):
371 for key in ["AS", "LD", "AR", "OBJCOPY", "OBJDUMP", "STRIP"]:
372 common[key] = "%s/%s" % (path, common[key])
373
374 check_app([common['AS'], "--version"], "GNU Assembler", details)
375 check_app([common['LD'], "--version"], "GNU Linker", details)
376 check_app([common['AR'], "--version"], "GNU Archiver", details)
377 check_app([common['OBJCOPY'], "--version"], "GNU Objcopy utility", details)
378 check_app([common['OBJDUMP'], "--version"], "GNU Objdump utility", details)
379 check_app([common['STRIP'], "--version"], "GNU strip", details)
380
381def check_python():
382 "Check for Python dependencies"
383
384 try:
385 sys.stderr.write("Checking for PyYAML ... ")
386 import yaml
387 except ImportError:
388 print_error(["PyYAML is missing.",
389 "",
390 "Please make sure that it is installed in your",
391 "system (usually part of PyYAML package)."])
392
393 sys.stderr.write("ok\n")
394
395def decode_value(value):
396 "Decode integer value"
397
398 base = 10
399
400 if ((value.startswith('$')) or (value.startswith('#'))):
401 value = value[1:]
402
403 if (value.startswith('0x')):
404 value = value[2:]
405 base = 16
406
407 return int(value, base)
408
409def probe_compiler(common, intsizes, floatsizes):
410 "Generate, compile and parse probing source"
411
412 check_common(common, "CC")
413
414 outf = open(PROBE_SOURCE, 'w')
415 outf.write(PROBE_HEAD)
416
417 for typedef in intsizes:
418 outf.write("\tDECLARE_INTSIZE(\"%s\", %s, %s, %s);\n" % (typedef['tag'], typedef['type'], typedef['strc'], typedef['conc']))
419
420 for typedef in floatsizes:
421 outf.write("\tDECLARE_FLOATSIZE(\"%s\", %s);\n" % (typedef['tag'], typedef['type']))
422
423 outf.write(PROBE_TAIL)
424 outf.close()
425
426 args = common['CC_AUTOGEN'].split(' ')
427 args.extend(["-S", "-o", PROBE_OUTPUT, PROBE_SOURCE])
428
429 try:
430 sys.stderr.write("Checking compiler properties ... ")
431 output = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
432 except:
433 sys.stderr.write("failed\n")
434 print_error(["Error executing \"%s\"." % " ".join(args),
435 "Make sure that the compiler works properly."])
436
437 if (not os.path.isfile(PROBE_OUTPUT)):
438 sys.stderr.write("failed\n")
439 print(output[1])
440 print_error(["Error executing \"%s\"." % " ".join(args),
441 "The compiler did not produce the output file \"%s\"." % PROBE_OUTPUT,
442 "",
443 output[0],
444 output[1]])
445
446 sys.stderr.write("ok\n")
447
448 inf = open(PROBE_OUTPUT, 'r')
449 lines = inf.readlines()
450 inf.close()
451
452 unsigned_sizes = {}
453 signed_sizes = {}
454
455 unsigned_tags = {}
456 signed_tags = {}
457
458 unsigned_strcs = {}
459 signed_strcs = {}
460
461 unsigned_concs = {}
462 signed_concs = {}
463
464 float_tags = {}
465
466 builtin_sizes = {}
467 builtin_signs = {}
468
469 for j in range(len(lines)):
470 tokens = lines[j].strip().split("\t")
471
472 if (len(tokens) > 0):
473 if (tokens[0] == "AUTOTOOL_DECLARE"):
474 if (len(tokens) < 7):
475 print_error(["Malformed declaration in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
476
477 category = tokens[1]
478 subcategory = tokens[2]
479 tag = tokens[3]
480 name = tokens[4]
481 strc = tokens[5]
482 conc = tokens[6]
483 value = tokens[7]
484
485 if (category == "intsize"):
486 try:
487 value_int = decode_value(value)
488 except:
489 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
490
491 if (subcategory == "unsigned"):
492 unsigned_sizes[value_int] = name
493 unsigned_tags[tag] = value_int
494 unsigned_strcs[value_int] = strc
495 unsigned_concs[value_int] = conc
496 elif (subcategory == "signed"):
497 signed_sizes[value_int] = name
498 signed_tags[tag] = value_int
499 signed_strcs[value_int] = strc
500 signed_concs[value_int] = conc
501 else:
502 print_error(["Unexpected keyword \"%s\" in \"%s\" on line %s." % (subcategory, PROBE_OUTPUT, j), COMPILER_FAIL])
503
504 if (category == "floatsize"):
505 try:
506 value_int = decode_value(value)
507 except:
508 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
509
510 float_tags[tag] = value_int
511
512 if (category == "builtin_size"):
513 try:
514 value_int = decode_value(value)
515 except:
516 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
517
518 builtin_sizes[tag] = {'name': name, 'value': value_int}
519
520 if (category == "builtin_sign"):
521 try:
522 value_int = decode_value(value)
523 except:
524 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
525
526 if (value_int == 1):
527 if (not tag in builtin_signs):
528 builtin_signs[tag] = strc;
529 elif (builtin_signs[tag] != strc):
530 print_error(["Inconsistent builtin type detection in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
531
532 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}
533
534def probe_int128(common):
535 "Generate, compile and parse probing source for 128-bit integers"
536
537 check_common(common, "CC")
538
539 outf = open(PROBE_INT128_SOURCE, 'w')
540 outf.write(PROBE_INT128_HEAD)
541 outf.write("\tDECLARE_INTSIZE(\"INT128\", int __attribute((mode(TI))));\n")
542 outf.write(PROBE_INT128_TAIL)
543 outf.close()
544
545 args = common['CC_AUTOGEN'].split(' ')
546 args.extend(["-S", "-o", PROBE_INT128_OUTPUT, PROBE_INT128_SOURCE])
547
548 try:
549 sys.stderr.write("Checking whether the compiler has intrinsic support for 128-bit integers ... ")
550 output = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
551 except:
552 sys.stderr.write("no\n")
553 return False
554
555 if (not os.path.isfile(PROBE_INT128_OUTPUT)):
556 sys.stderr.write("no\n")
557 return False
558
559 inf = open(PROBE_INT128_OUTPUT, 'r')
560 lines = inf.readlines()
561 inf.close()
562
563 for j in range(len(lines)):
564 tokens = lines[j].strip().split("\t")
565
566 if (len(tokens) > 0):
567 if (tokens[0] == "AUTOTOOL_DECLARE"):
568 if (len(tokens) < 7):
569 print_error(["Malformed declaration in \"%s\" on line %s." % (PROBE_INT128_OUTPUT, j), COMPILER_FAIL])
570
571 category = tokens[1]
572 subcategory = tokens[2]
573 tag = tokens[3]
574 name = tokens[4]
575 strc = tokens[5]
576 conc = tokens[6]
577 value = tokens[7]
578
579 if (category == "intsize"):
580 try:
581 value_int = decode_value(value)
582 except:
583 print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_INT128_OUTPUT, j), COMPILER_FAIL])
584
585 if (subcategory == "unsigned"):
586 if (value_int != 16):
587 sys.stderr.write("no\n")
588 return False
589 elif (subcategory == "signed"):
590 if (value_int != 16):
591 sys.stderr.write("no\n")
592 return False
593 else:
594 print_error(["Unexpected keyword \"%s\" in \"%s\" on line %s." % (subcategory, PROBE_INT128_OUTPUT, j), COMPILER_FAIL])
595
596 sys.stderr.write("yes\n")
597 return True
598
599def detect_sizes(probe, bytes, inttags, floattags):
600 "Detect correct types for fixed-size types"
601
602 macros = []
603 typedefs = []
604
605 for b in bytes:
606 if (not b in probe['unsigned_sizes']):
607 print_error(['Unable to find appropriate unsigned integer type for %u bytes.' % b,
608 COMPILER_FAIL])
609
610 if (not b in probe['signed_sizes']):
611 print_error(['Unable to find appropriate signed integer type for %u bytes.' % b,
612 COMPILER_FAIL])
613
614 if (not b in probe['unsigned_strcs']):
615 print_error(['Unable to find appropriate unsigned printf formatter for %u bytes.' % b,
616 COMPILER_FAIL])
617
618 if (not b in probe['signed_strcs']):
619 print_error(['Unable to find appropriate signed printf formatter for %u bytes.' % b,
620 COMPILER_FAIL])
621
622 if (not b in probe['unsigned_concs']):
623 print_error(['Unable to find appropriate unsigned literal macro for %u bytes.' % b,
624 COMPILER_FAIL])
625
626 if (not b in probe['signed_concs']):
627 print_error(['Unable to find appropriate signed literal macro for %u bytes.' % b,
628 COMPILER_FAIL])
629
630 typedefs.append({'oldtype': "unsigned %s" % probe['unsigned_sizes'][b], 'newtype': "uint%u_t" % (b * 8)})
631 typedefs.append({'oldtype': "signed %s" % probe['signed_sizes'][b], 'newtype': "int%u_t" % (b * 8)})
632
633 macros.append({'oldmacro': "unsigned %s" % probe['unsigned_sizes'][b], 'newmacro': "UINT%u_T" % (b * 8)})
634 macros.append({'oldmacro': "signed %s" % probe['signed_sizes'][b], 'newmacro': "INT%u_T" % (b * 8)})
635
636 macros.append({'oldmacro': "\"%so\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIo%u" % (b * 8)})
637 macros.append({'oldmacro': "\"%su\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIu%u" % (b * 8)})
638 macros.append({'oldmacro': "\"%sx\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIx%u" % (b * 8)})
639 macros.append({'oldmacro': "\"%sX\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIX%u" % (b * 8)})
640 macros.append({'oldmacro': "\"%sd\"" % probe['signed_strcs'][b], 'newmacro': "PRId%u" % (b * 8)})
641
642 name = probe['unsigned_concs'][b]
643 if ((name.startswith('@')) or (name == "")):
644 macros.append({'oldmacro': "c ## U", 'newmacro': "UINT%u_C(c)" % (b * 8)})
645 else:
646 macros.append({'oldmacro': "c ## U%s" % name, 'newmacro': "UINT%u_C(c)" % (b * 8)})
647
648 name = probe['unsigned_concs'][b]
649 if ((name.startswith('@')) or (name == "")):
650 macros.append({'oldmacro': "c", 'newmacro': "INT%u_C(c)" % (b * 8)})
651 else:
652 macros.append({'oldmacro': "c ## %s" % name, 'newmacro': "INT%u_C(c)" % (b * 8)})
653
654 for tag in inttags:
655 newmacro = "U%s" % tag
656 if (not tag in probe['unsigned_tags']):
657 print_error(['Unable to find appropriate size macro for %s.' % newmacro,
658 COMPILER_FAIL])
659
660 oldmacro = "UINT%s" % (probe['unsigned_tags'][tag] * 8)
661 macros.append({'oldmacro': "%s_MIN" % oldmacro, 'newmacro': "%s_MIN" % newmacro})
662 macros.append({'oldmacro': "%s_MAX" % oldmacro, 'newmacro': "%s_MAX" % newmacro})
663 macros.append({'oldmacro': "1", 'newmacro': 'U%s_SIZE_%s' % (tag, probe['unsigned_tags'][tag] * 8)})
664
665 newmacro = tag
666 if (not tag in probe['signed_tags']):
667 print_error(['Unable to find appropriate size macro for %s' % newmacro,
668 COMPILER_FAIL])
669
670 oldmacro = "INT%s" % (probe['signed_tags'][tag] * 8)
671 macros.append({'oldmacro': "%s_MIN" % oldmacro, 'newmacro': "%s_MIN" % newmacro})
672 macros.append({'oldmacro': "%s_MAX" % oldmacro, 'newmacro': "%s_MAX" % newmacro})
673 macros.append({'oldmacro': "1", 'newmacro': '%s_SIZE_%s' % (tag, probe['signed_tags'][tag] * 8)})
674
675 for tag in floattags:
676 if (not tag in probe['float_tags']):
677 print_error(['Unable to find appropriate size macro for %s' % tag,
678 COMPILER_FAIL])
679
680 macros.append({'oldmacro': "1", 'newmacro': '%s_SIZE_%s' % (tag, probe['float_tags'][tag] * 8)})
681
682 if (not 'size' in probe['builtin_signs']):
683 print_error(['Unable to determine whether size_t is signed or unsigned.',
684 COMPILER_FAIL])
685
686 if (probe['builtin_signs']['size'] != 'unsigned'):
687 print_error(['The type size_t is not unsigned.',
688 COMPILER_FAIL])
689
690 fnd = True
691
692 if (not 'wchar' in probe['builtin_sizes']):
693 print_warning(['The compiler does not provide the macro __WCHAR_TYPE__',
694 'for defining the compiler-native type wchar_t. We are',
695 'forced to define wchar_t as a hardwired type int32_t.',
696 COMPILER_WARNING])
697 fnd = False
698
699 if (probe['builtin_sizes']['wchar']['value'] != 4):
700 print_warning(['The compiler provided macro __WCHAR_TYPE__ for defining',
701 'the compiler-native type wchar_t is not compliant with',
702 'HelenOS. We are forced to define wchar_t as a hardwired',
703 'type int32_t.',
704 COMPILER_WARNING])
705 fnd = False
706
707 if (not fnd):
708 macros.append({'oldmacro': "int32_t", 'newmacro': "wchar_t"})
709 else:
710 macros.append({'oldmacro': "__WCHAR_TYPE__", 'newmacro': "wchar_t"})
711
712 if (not 'wchar' in probe['builtin_signs']):
713 print_error(['Unable to determine whether wchar_t is signed or unsigned.',
714 COMPILER_FAIL])
715
716 if (probe['builtin_signs']['wchar'] == 'unsigned'):
717 macros.append({'oldmacro': "1", 'newmacro': 'WCHAR_IS_UNSIGNED'})
718 if (probe['builtin_signs']['wchar'] == 'signed'):
719 macros.append({'oldmacro': "1", 'newmacro': 'WCHAR_IS_SIGNED'})
720
721 fnd = True
722
723 if (not 'wint' in probe['builtin_sizes']):
724 print_warning(['The compiler does not provide the macro __WINT_TYPE__',
725 'for defining the compiler-native type wint_t. We are',
726 'forced to define wint_t as a hardwired type int32_t.',
727 COMPILER_WARNING])
728 fnd = False
729
730 if (probe['builtin_sizes']['wint']['value'] != 4):
731 print_warning(['The compiler provided macro __WINT_TYPE__ for defining',
732 'the compiler-native type wint_t is not compliant with',
733 'HelenOS. We are forced to define wint_t as a hardwired',
734 'type int32_t.',
735 COMPILER_WARNING])
736 fnd = False
737
738 if (not fnd):
739 macros.append({'oldmacro': "int32_t", 'newmacro': "wint_t"})
740 else:
741 macros.append({'oldmacro': "__WINT_TYPE__", 'newmacro': "wint_t"})
742
743 if (not 'wint' in probe['builtin_signs']):
744 print_error(['Unable to determine whether wint_t is signed or unsigned.',
745 COMPILER_FAIL])
746
747 if (probe['builtin_signs']['wint'] == 'unsigned'):
748 macros.append({'oldmacro': "1", 'newmacro': 'WINT_IS_UNSIGNED'})
749 if (probe['builtin_signs']['wint'] == 'signed'):
750 macros.append({'oldmacro': "1", 'newmacro': 'WINT_IS_SIGNED'})
751
752 return {'macros': macros, 'typedefs': typedefs}
753
754def create_makefile(mkname, common):
755 "Create makefile output"
756
757 outmk = open(mkname, 'w')
758
759 outmk.write('#########################################\n')
760 outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
761 outmk.write('## Generated by: tools/autotool.py ##\n')
762 outmk.write('#########################################\n\n')
763
764 for key, value in common.items():
765 if (type(value) is list):
766 outmk.write('%s = %s\n' % (key, " ".join(value)))
767 else:
768 outmk.write('%s = %s\n' % (key, value))
769
770 outmk.close()
771
772def create_header(hdname, maps, int128):
773 "Create header output"
774
775 outhd = open(hdname, 'w')
776
777 outhd.write('/***************************************\n')
778 outhd.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
779 outhd.write(' * Generated by: tools/autotool.py *\n')
780 outhd.write(' ***************************************/\n\n')
781
782 outhd.write('#ifndef %s\n' % GUARD)
783 outhd.write('#define %s\n\n' % GUARD)
784
785 for macro in maps['macros']:
786 outhd.write('#define %s %s\n' % (macro['newmacro'], macro['oldmacro']))
787
788 outhd.write('\n')
789
790 for typedef in maps['typedefs']:
791 outhd.write('typedef %s %s;\n' % (typedef['oldtype'], typedef['newtype']))
792
793 if (int128):
794 outhd.write('typedef unsigned int __attribute((mode(TI))) uint128_t;\n')
795 outhd.write('typedef signed int __attribute((mode(TI))) int128_t;\n')
796
797 outhd.write('\n#endif\n')
798 outhd.close()
799
800def main():
801 config = {}
802 common = {}
803
804 # Read and check configuration
805 if os.path.exists(CONFIG):
806 read_config(CONFIG, config)
807 else:
808 print_error(["Configuration file %s not found! Make sure that the" % CONFIG,
809 "configuration phase of HelenOS build went OK. Try running",
810 "\"make config\" again."])
811
812 check_config(config, "PLATFORM")
813 check_config(config, "COMPILER")
814 check_config(config, "BARCH")
815
816 # Cross-compiler prefix
817 if ('CROSS_PREFIX' in os.environ):
818 cross_prefix = os.environ['CROSS_PREFIX']
819 else:
820 cross_prefix = "/usr/local/cross"
821
822 # HelenOS cross-compiler prefix
823 if ('CROSS_HELENOS_PREFIX' in os.environ):
824 cross_helenos_prefix = os.environ['CROSS_HELENOS_PREFIX']
825 else:
826 cross_helenos_prefix = "/usr/local/cross-helenos"
827
828 # Prefix binutils tools on Solaris
829 if (os.uname()[0] == "SunOS"):
830 binutils_prefix = "g"
831 else:
832 binutils_prefix = ""
833
834 owd = sandbox_enter()
835
836 try:
837 # Common utilities
838 check_app(["ln", "--version"], "Symlink utility", "usually part of coreutils")
839 check_app(["rm", "--version"], "File remove utility", "usually part of coreutils")
840 check_app(["mkdir", "--version"], "Directory creation utility", "usually part of coreutils")
841 check_app(["cp", "--version"], "Copy utility", "usually part of coreutils")
842 check_app(["find", "--version"], "Find utility", "usually part of findutils")
843 check_app(["diff", "--version"], "Diff utility", "usually part of diffutils")
844 check_app(["make", "--version"], "Make utility", "preferably GNU Make")
845 check_app(["makedepend", "-f", "-"], "Makedepend utility", "usually part of imake or xutils")
846 check_app(["unzip"], "unzip utility", "usually part of zip/unzip utilities")
847
848 # Compiler
849 if (config['COMPILER'] == "gcc_cross"):
850 target, cc_args, gnu_target, helenos_target = get_target(config)
851
852 if (target is None) or (gnu_target is None):
853 print_error(["Unsupported compiler target for GNU GCC.",
854 "Please contact the developers of HelenOS."])
855
856 path = "%s/%s/bin" % (cross_prefix, target)
857 prefix = "%s-" % gnu_target
858
859 check_gcc(path, prefix, common, PACKAGE_CROSS)
860 check_binutils(path, prefix, common, PACKAGE_CROSS)
861
862 check_common(common, "GCC")
863 common['CC'] = " ".join([common['GCC']] + cc_args)
864 common['CC_AUTOGEN'] = common['CC']
865
866 if (config['COMPILER'] == "gcc_helenos"):
867 target, cc_args, gnu_target, helenos_target = get_target(config)
868
869 if (target is None) or (helenos_target is None):
870 print_error(["Unsupported compiler target for GNU GCC.",
871 "Please contact the developers of HelenOS."])
872
873 path = "%s/%s/bin" % (cross_helenos_prefix, target)
874 prefix = "%s-" % helenos_target
875
876 check_gcc(path, prefix, common, PACKAGE_CROSS)
877 check_binutils(path, prefix, common, PACKAGE_CROSS)
878
879 check_common(common, "GCC")
880 common['CC'] = " ".join([common['GCC']] + cc_args)
881 common['CC_AUTOGEN'] = common['CC']
882
883 if (config['COMPILER'] == "gcc_native"):
884 check_gcc(None, "", common, PACKAGE_GCC)
885 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
886
887 check_common(common, "GCC")
888 common['CC'] = common['GCC']
889 common['CC_AUTOGEN'] = common['CC']
890
891 if (config['COMPILER'] == "icc"):
892 check_app([common['CC'], "-V"], "Intel C++ Compiler", "support is experimental")
893 check_gcc(None, "", common, PACKAGE_GCC)
894 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
895
896 common['CC'] = "icc"
897 common['CC_AUTOGEN'] = common['CC']
898
899 if (config['COMPILER'] == "clang"):
900 target, cc_args, gnu_target, helenos_target = get_target(config)
901
902 if (target is None) or (gnu_target is None):
903 print_error(["Unsupported compiler target.",
904 "Please contact the developers of HelenOS."])
905
906 path = "%s/%s/bin" % (cross_prefix, target)
907 prefix = "%s-" % gnu_target
908
909 check_clang(path, prefix, common, "")
910 check_gcc(path, prefix, common, PACKAGE_GCC)
911 check_binutils(path, prefix, common, PACKAGE_BINUTILS)
912
913 check_common(common, "GCC")
914 check_common(common, "CLANG")
915 common['CC'] = " ".join([common['CLANG']] + cc_args)
916 common['CC_AUTOGEN'] = common['CC'] + " -no-integrated-as"
917
918 if (config['INTEGRATED_AS'] == "yes"):
919 common['CC'] += " -integrated-as"
920
921 if (config['INTEGRATED_AS'] == "no"):
922 common['CC'] += " -no-integrated-as"
923
924 check_python()
925
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'
931
932 probe = probe_compiler(common,
933 [
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': '"@@"'}
939 ],
940 [
941 {'type': 'long double', 'tag': 'LONG_DOUBLE'},
942 {'type': 'double', 'tag': 'DOUBLE'},
943 {'type': 'float', 'tag': 'FLOAT'}
944 ]
945 )
946
947 int128 = probe_int128(common)
948
949 maps = detect_sizes(probe, [1, 2, 4, 8], ['CHAR', 'SHRT', 'INT', 'LONG', 'LLONG'], ['LONG_DOUBLE', 'DOUBLE', 'FLOAT'])
950
951 finally:
952 sandbox_leave(owd)
953
954 common['AUTOGEN'] = "%s/autogen.py" % os.path.dirname(os.path.abspath(sys.argv[0]))
955
956 create_makefile(MAKEFILE, common)
957 create_header(HEADER, maps, int128)
958
959 return 0
960
961if __name__ == '__main__':
962 sys.exit(main())
Note: See TracBrowser for help on using the repository browser.