chiark / gitweb /
5629f24f1c02e7a15c8bd3f504f58d008f6fcbe8
[elogind.git] / klcc.in
1 # -*- perl -*-
2
3 use IPC::Open3;
4
5 # Standard includes
6 @includes = ("-I${prefix}/${KCROSS}include/arch/${ARCH}",
7              "-I${prefix}/${KCROSS}include/bits${BITSIZE}",
8              "-I${prefix}/${KCROSS}include");
9
10 # Default optimization options (for compiles without -g)
11 @optopt =  @OPTFLAGS;
12 @goptopt = ('-O');
13
14 # Standard library directories
15 @stdlibpath = ("-L${prefix}/${KCROSS}lib");
16
17 # Options and libraries to pass to ld; shared versus static
18 @staticopt = ("${prefix}/${KCROSS}lib/crt0.o");
19 @staticlib = ("${prefix}/${KCROSS}lib/libc.a");
20 @sharedopt = (@EMAIN, "${prefix}/${KCROSS}lib/interp.o");
21 @sharedlib = ('-R', "${prefix}/${KCROSS}lib/libc.so");
22
23 # Returns the language (-x option string) for a specific extension.
24 sub filename2lang($) {
25     my ($file) = @_;
26
27     return 'c' if ( $file =~ /\.c$/ );
28     return 'c-header' if ( $file =~ /\.h$/ );
29     return 'cpp-output' if ( $file =~ /\.i$/ );
30     return 'c++-cpp-output' if ( $file =~ /\.ii$/ );
31     return 'objective-c' if ( $file =~ /\.m$/ );
32     return 'objc-cpp-output' if ( $file =~ /\.mi$/ );
33     return 'c++' if ( $file =~/\.(cc|cp|cxx|cpp|CPP|c\+\+|C)$/ );
34     return 'c++-header' if ( $file =~ /\.(hh|H)$/ );
35     return 'f77' if ( $file =~ /\.(f|for|FOR)$/ );
36     return 'f77-cpp-input' if ( $file =~ /\.(F|fpp|FPP)$/ );
37     return 'ratfor' if ( $file =~ /\.r$/ );
38
39     # Is this correct?
40     return 'ada' if ( $file =~ /\.(ads|adb)$/ );
41
42     return 'assembler' if ( $file =~ /\.s$/ );
43     return 'assembler-with-cpp' if ( $file =~/ \.S$/ );
44
45     # Linker file; there is no option to gcc to assume something
46     # is a linker file, so we make up our own...
47     return 'obj';
48 }
49
50 # Produces a series of -x options and files
51 sub files_with_lang($$) {
52     my($files, $flang) = @_;
53     my(@as) = ();
54     my($xopt) = 'none';
55     my($need);
56
57     foreach $f ( @{$files} ) {
58         $need = ${$flang}{$f};
59
60         # Skip object files
61         if ( $need ne 'obj' ) {
62             unless ( $xopt eq $need || $need eq 'stdin') {
63                 push(@as, '-x', $need);
64                 $xopt = $need;
65             }
66             push(@as, $f);
67         }
68     }
69
70     return @as;
71 }
72
73 # Convert a return value from system() to an exit() code
74 sub syserr($) {
75     my($e) = @_;
76
77     return ($e & 0x7f) | 0x80 if ( $e & 0xff );
78     return $e >> 8;
79 }
80
81 # Run a program; printing out the command line if $verbose is set
82 sub mysystem(@) {
83     print STDERR join(' ', @_), "\n" if ( $verbose );
84     my $cmd = shift;
85     open(INPUT, "<&STDIN");     # dup STDIN filehandle to INPUT
86     my $childpid = open3("<&INPUT", ">&STDOUT", ">&STDERR", $cmd, @_);
87     waitpid ($childpid, 0);
88     return $?;
89 }
90
91 #
92 # Initialization
93
94 open(NULL, '+<', '/dev/null') or die "$0: cannot open /dev/null\n";
95
96 #
97 # Begin parsing options.
98 #
99
100 @ccopt = ();
101 @ldopt = ();
102 @libs  = ();
103
104 @files = ();                    # List of files
105 %flang = ();                    # Languages for files
106
107 # This is 'c' for compile only, 'E' for preprocess only,
108 # 'S' for compile to assembly.
109 $operation = '';                # Compile and link
110
111 # Current -x option.  If undefined, it means autodetect.
112 undef $lang;
113
114 $save_temps = 0;                # The -save-temps option
115 $verbose = 0;                   # The -v option
116 $shared = 0;                    # Are we compiling shared?
117 $debugging = 0;                 # -g or -p option present?
118 $strip = 0;                     # -s option present?
119 undef $output;                  # -o option present?
120
121 while ( defined($a = shift(@ARGV)) ) {
122     if ( $a !~ /^\-/ ) {
123         # Not an option.  Must be a filename then.
124         push(@files, $a);
125         $flang{$a} = $lang || filename2lang($a);
126     } elsif ( $a eq '-' ) {
127         # gcc gets its input from stdin
128         push(@files, $a);
129         # prevent setting -x
130         $flang{$a} = 'stdin'
131     } elsif ( $a =~ /^-print-klibc-(.*)$/ ) {
132         # This test must precede -print
133         if ( defined($conf{$1}) ) {
134             print ${$conf{$1}}, "\n";
135             exit 0;
136         } else {
137             die "$0: unknown option: $a\n";
138         }
139     } elsif ( $a =~ /^(-print|-dump|--help|--version)/ ) {
140         # These share prefixes with some other options, so put this test early!
141         # Pseudo-operations; just pass to gcc and don't do anything else
142         push(@ccopt, $a);
143         $operation = 'c' if ( $operation eq '' );
144     } elsif ( $a =~ /^-Wl,(.*)$/ ) {
145         # -Wl used to pass options to the linker
146         push(@ldopt, split(/,/, $1));
147     } elsif ( $a =~ /^-([fmwWQdO]|std=|ansi|pedantic|M[GPD]|MMD)/ ) {
148         # Options to gcc
149         push(@ccopt, $a);
150     } elsif ( $a =~ /^-([DUI]|M[FQT])(.*)$/ ) {
151         # Options to gcc, which can take either a conjoined argument
152         # (-DFOO) or a disjoint argument (-D FOO)
153         push(@ccopt, $a);
154         push(@ccopt, shift(@ARGV)) if ( $2 eq '' );
155     } elsif ( $a eq '-include' ) {
156         # Options to gcc which always take a disjoint argument
157         push(@ccopt, $a, shift(@ARGV));
158     } elsif ( $a eq '-M' || $a eq '-MM' ) {
159         # gcc options, that force preprocessing mode
160         push(@ccopt, $a);
161         $operation = 'E';
162     } elsif ( $a =~ /^-[gp]/ || $a eq '-p' ) {
163         # Debugging options to gcc
164         push(@ccopt, $a);
165         $debugging = 1;
166     } elsif ( $a eq '-v' ) {
167         push(@ccopt, $a);
168         $verbose = 1;
169     } elsif ( $a eq '-save-temps' ) {
170         push(@ccopt, $a);
171         $save_temps = 1;
172     } elsif ( $a =~ '^-([cSE])$' ) {
173         push(@ccopt, $a);
174         $operation = $1;
175     } elsif ( $a eq '-shared' ) {
176         $shared = 1;
177     } elsif ( $a eq '-static' ) {
178         $shared = 0;
179     } elsif ( $a eq '-s' ) {
180         $strip = 1;
181     } elsif ( $a eq '-o' ) {
182         $output = shift(@ARGV);
183     } elsif ( $a eq '-x' ) {
184         $lang = shift(@ARGV);
185     } elsif ( $a eq '-nostdinc' ) {
186         push(@ccopt, $a);
187         @includes = ();
188     } elsif ( $a =~ /^-([lL])(.*)$/ ) {
189         # Libraries
190         push(@libs, $a);
191         push(@libs, shift(@ARGV)) if ( $2 eq '' );
192     } else {
193         die "$0: unknown option: $a\n";
194     }
195 }
196
197 if ( $debugging ) {
198     @ccopt = (@REQFLAGS, @includes, @goptopt, @ccopt);
199 } else {
200     @ccopt = (@REQFLAGS, @includes, @optopt, @ccopt);
201 }
202
203 if ( $operation ne '' ) {
204     # Just run gcc with the appropriate options
205     @outopt = ('-o', $output) if ( defined($output) );
206     $rv = mysystem($CC, @ccopt, @outopt, files_with_lang(\@files, \%flang));
207 } else {
208     if ( scalar(@files) == 0 ) {
209         die "$0: No input files!\n";
210     }
211
212     @outopt = ('-o', $output || 'a.out');
213
214     @objs = ();
215     @rmobjs = ();
216
217     foreach $f ( @files ) {
218         if ( $flang{$f} eq 'obj' ) {
219             push(@objs, $f);
220         } else {
221             $fo = $f;
222             $fo =~ s/\.[^\/.]+$/\.o/;
223
224             die if ( $f eq $fo ); # safety check
225
226             push(@objs, $fo);
227             push(@rmobjs, $fo) unless ( $save_temps );
228
229             $rv = mysystem($CC, @ccopt, '-c', '-o', $fo, '-x', $flang{$f}, $f);
230
231             if ( $rv ) {
232                 unlink(@rmobjs);
233                 exit syserr($rv);
234             }
235         }
236     }
237
238     # Get the libgcc pathname for the *current* gcc
239     open(LIBGCC, '-|', $CC, @ccopt, '-print-libgcc-file-name')
240         or die "$0: cannot get libgcc filename\n";
241     $libgcc = <LIBGCC>;
242     chomp $libgcc;
243     close(LIBGCC);
244
245     if ( $shared ) {
246         $rv = mysystem($LD, @LDFLAGS, @sharedopt, @ldopt, @outopt, @objs, @libs, @stdlibpath, @sharedlib, $libgcc);
247     } else {
248         $rv = mysystem($LD, @LDFLAGS, @staticopt, @ldopt, @outopt, @objs, @libs, @stdlibpath, @staticlib, $libgcc);
249     }
250
251     unlink(@rmobjs);
252
253     if ( $strip && !$rv ) {
254         $rv = mysystem($STRIP, @STRIPFLAGS, $output);
255     }
256 }
257
258 exit syserr($rv);