7 #use Data::Dump qw(dump);
9 my $this_path = abs_path
();
12 die "syntax: $0 [--new --force --verbose --step --ignore-errors] mainfile.c [-lc -lm -lncurses]\n" .
13 "--new will ignore an existing .rcb file and rescan the deps\n" .
14 "--force will force a complete rebuild despite object file presence.\n" .
15 "--verbose will print the complete linker output and other info\n" .
16 "--step will add one dependency after another, to help finding hidden deps\n";
42 $l-- while($l && substr($x, $l, 1) ne ".");
43 return substr($x, 0, $l + 1) if($l);
59 my $colstr = "\033[%dm";
66 printf $colstr, $colors->{$color};
70 printf $colstr, $colors->{"end"};
75 my $np = dirname
($nf);
76 my $nb = basename
($nf);
77 if(!defined($hdep{$nf})) {
79 printc
("red", "failed to find dependency $nf referenced from $self!\n");
80 die unless $nf =~ /\.h$/;
88 my ($basepath, $relpath) = @_;
89 #print "$basepath ::: $relpath\n";
90 die "both path's must start with /" if(substr($basepath, 0, 1) ne "/" || substr($relpath, 0, 1) ne "/");
91 $basepath .= "/" if($basepath !~ /\
/$/ && -d
$basepath);
92 $relpath .= "/" if($relpath !~ /\
/$/ && -d
$relpath);
96 $l++ while(substr($basepath, $l, 1) eq substr($relpath, $l, 1));
98 $l-- while(substr($basepath, $l, 1) ne "/");
100 $l++ if substr($relpath, $l, 1) eq "/";
101 my $res = substr($relpath, $l);
103 while($l2 < length($basepath)) {
104 $sl++ if substr($basepath, $l2, 1) eq "/";
108 for ($i = 0; $i < $sl; $i++) {
116 my ($self, $path, $tf) = @_;
117 my $absolute = substr($tf, 0, 1) eq "/";
119 my $nf = $absolute ?
$tf : abs_path
($path) . "/" . $tf;
120 printc
("red", "[RcB] warning: $tf not found, continuing...\n"), return if !defined($nf);
123 if ($nf =~ /^\// && $nf !~ /\
.h
$/) {
124 $nf = make_relative
($this_path, $nf);
126 die "problem processing $self, $path, $tf" if(!defined($nf));
128 my @deps = glob($nf);
130 scandep_doit
($self, $d);
133 scandep_doit
($self, $nf);
138 my $forcerebuild = 0;
142 my $mainfile = undef;
143 my $ignore_errors = 0;
144 my $debug_cflags = 0;
147 my ($path, $file) = @_;
149 my $self = $path . "/" . $file;
153 open($fp, "<", $self) or die "could not open file $self: $!";
156 if ($line =~ /^\/\
/RcB: (\w{3,6}) \"(.+?)\"/) {
159 if($command eq "DEP") {
161 print "found RcB DEP $tf : $self\n" if $verbose;
162 scandep
($self, $path, $tf);
163 } elsif ($command eq "LINK") {
164 print "found RcB LINK $arg\n" if $verbose;
167 } elsif($line =~ /^\s*#\s*include\s+\"([\w\.\/_\
-]+?
)\"/) {
169 scandep
($self, $path, $tf);
176 push @adep, $self if $file =~ /[\w_-]+\.[c]{1}$/; #only add .c files to deps...
180 my $arg1 = shift @ARGV or syntax
;
181 if($arg1 eq "--force") {
184 } elsif($arg1 eq "--verbose") {
187 } elsif($arg1 eq "--new") {
190 } elsif($arg1 eq "--step") {
193 } elsif($arg1 eq "--ignore-errors") {
196 } elsif($arg1 eq "--debug") {
203 $mainfile = shift unless defined($mainfile);
204 syntax
unless defined($mainfile);
207 if (defined($ENV{CC
})) {
211 printc
"blue", "[RcB] \$CC not set, defaulting to cc\n";
214 my $cflags = defined($ENV{CFLAGS
}) ?
$ENV{CFLAGS
} : "";
215 $cflags .= $debug_cflags ?
"-O0 -g" : "";
218 if (defined($ENV{NM
})) {
222 printc
"blue", "[RcB] \$NM not set, defaulting to nm\n";
227 printc
"magenta", "[CC] ", $cmdline, "\n";
228 my $reslt = `$cmdline 2>&1`;
230 printc
"red", "ERROR ", $!, "\n";
237 $link = expandarr
(@ARGV) . " ";
239 my $cnd = name_wo_ext
($mainfile);
240 my $cndo = $cnd . "o";
241 my $bin = $cnd . "out";
243 my $cfgn = name_wo_ext
($mainfile) . "rcb";
244 my $haveconfig = (-e
$cfgn);
245 if($haveconfig && !$ignore_rcb) {
246 printc
"blue", "[RcB] config file found. trying single compile.\n";
247 @adep = `cat $cfgn | grep "^DEP " | cut -b 5-`;
248 my @rcb_links = `cat $cfgn | grep "^LINK" | cut -b 6-`;
249 my $cs = expandarr
(@adep);
250 my $ls = expandarr
(@rcb_links);
251 $link = $ls if (defined($ls) && $ls ne "");
252 my $res = compile
("$cc $cflags $cs $link -o $bin");
253 if($res =~ /undefined reference to/) {
254 printc
"red", "[RcB] undefined reference[s] found, switching to scan mode\n";
257 printc
"red", "[RcB] error. exiting.\n";
259 printc
"green", "[RcB] success. $bin created.\n";
265 printc
"blue", "[RcB] scanning deps...";
267 scanfile dirname
(abs_path
($mainfile)), basename
($mainfile);
269 printc
"green", "done\n";
272 printc
"blue", "[RcB] compiling main file...\n";
273 my $op = compile
("$cc $cflags -c $mainfile -o $cndo");
274 exit 1 if($op =~ /error:/g);
288 printc
"blue", "[RcB] resolving linker deps...\n";
291 if($i + 1 >= @adep) { #last element of the array is the already build mainfile
296 %glob_missym = %missym, last unless $relink;
298 my %missym_old = %missym;
300 my $ex = expandhash
(\
%obj);
301 printc
"blue", "[RcB] trying to link ...\n";
302 my $cmd = "$cc $cflags $ex $link -o $bin";
303 printc
"cyan", "[LD] ", $cmd, "\n";
306 if(/undefined reference to [\'\`\"]{1}([\w\._]+)[\'\`\"]{1}/) {
311 /([\/\w\
._\
-]+): file
not recognized
: File format
not recognized
/ ||
312 /architecture of input file [\'\`\"]{1}([\/\w\
._\
-]+)[\'\
`\"]{1} is incompatible with/ ||
313 /fatal error: ([\/\w\._\-]+): unsupported ELF machine number/ ||
314 /ld: ([\/\w\._\-]+): Relocations in generic ELF/
317 $i = delete $obj{$cnd};
318 printc "red", "[RcB] incompatible object file $cnd, rebuilding...\n";
323 %missym = %missym_old;
326 /collect2: ld returned 1 exit status/ ||
327 /In function [\'\`\"]{1}[\w_
]+[\'\
`\"]{1}:/ ||
328 /more undefined references to/
331 printc "red", "[RcB] FATAL: unexpected linker output!\n";
336 if(!scalar(keys %missym)) {
344 goto skip unless defined $cnd;
348 $cndo = name_wo_ext($cnd) . "o";
349 if(($forcerebuild || $rebuildflag || ! -e $cndo) && !defined($rebuilt{$cndo})) {
350 my $op = compile("$cc $cflags -c $cnd -o $cndo");
351 if($op =~ /error:/) {
352 exit 1 unless($ignore_errors);
357 @opa = `$nm -g
$cndo 2>&1`;
361 if(/[\da-fA-F]{8,16}\s+[TWRBCD]{1}\s+([\w_]+)/) {
363 $symhash{$symname} = 1;
365 } elsif (/File format not recognized/) {
366 printc "red", "[RcB] nm doesn't recognize the format of $cndo, rebuilding...\n";
372 $sym{$cndo} = \%symhash;
375 if(defined($symhash{$_})) {
379 if($objfail || $step) {
382 printc "red", "[RcB] adding $cndo to the bunch...\n" if $step;
393 printc "red", "[RcB] failed to resolve the following symbols, check your DEP tags\n";
394 for(keys %glob_missym) {
398 printc "green", "[RcB] success. $bin created.\n";
399 printc "blue", "saving required dependencies to $cfgn\n";
401 open($fh, ">", $cfgn);
403 print { $fh } "DEP ", name_wo_ext($_), "c\n";
405 print { $fh } "LINK ", $link, "\n" if($link);