1.1.13
by Jonathan Riddell
Import upstream version 4.0.80 |
1 |
#!/usr/bin/perl
|
1.1.46
by Alessandro Ghersi
Import upstream version 4.4.92 |
2 |
# Copyright (C) 2006-2010 Thomas Zander <zander@kde.org>
|
1.1.13
by Jonathan Riddell
Import upstream version 4.0.80 |
3 |
$COMMAND = "unsercmake"; |
1.1.46
by Alessandro Ghersi
Import upstream version 4.4.92 |
4 |
$VERSION = "$COMMAND 0.32"; |
1.1.13
by Jonathan Riddell
Import upstream version 4.0.80 |
5 |
# This script allows you to build a target library including dependency checking, but it
|
6 |
# limits the dependency checking to the current dir and its subdirs meaning a lot of
|
|
7 |
# unwanted steps are skipped.
|
|
8 |
||
9 |
||
10 |
# user settings...
|
|
11 |
# if we assume the user has something like: /kde/project as a sourcedir and /kde/current/project
|
|
12 |
# as a build dir then we can auto-switch between those dirs
|
|
13 |
# Please alter the variable to set the basedir and the builddir. Like this:
|
|
14 |
# BASE=BUILD
|
|
15 |
# Examples:
|
|
16 |
# $buildDirType = "/kde=/kde/current";
|
|
17 |
# $buildDirType = "kde/{project}=kde/{project}/build";
|
|
18 |
$buildDirType = ""; |
|
19 |
||
20 |
##########################
|
|
1.1.46
by Alessandro Ghersi
Import upstream version 4.4.92 |
21 |
# Copyright (c) 2006-2010 Thomas Zander <zander@kde.org>
|
1.1.13
by Jonathan Riddell
Import upstream version 4.0.80 |
22 |
#
|
23 |
# This program is free software; you can redistribute it and/or modify
|
|
24 |
# it under the terms of the GNU General Public License as published by
|
|
25 |
# the Free Software Foundation; either version 2 of the License,
|
|
26 |
# or (at your option) any later version.
|
|
27 |
#
|
|
28 |
# This program is distributed in the hope that it will be useful,
|
|
29 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
30 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
31 |
# GNU General Public License for more details.
|
|
32 |
#
|
|
33 |
# You should have received a copy of the GNU General Public License
|
|
34 |
# along with this program; if not, write to the Free Software
|
|
35 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
36 |
||
37 |
if ($buildDirType eq "") { |
|
38 |
print "Not setup!\n"; |
|
39 |
print " This tool can automatically switch from your source dir to the builddir.\n"; |
|
40 |
print " To do this correctly you have to alter the $COMMAND using your editor\n"; |
|
41 |
print " and alter the buildDirType variable according to the comments.\n"; |
|
42 |
exit; |
|
43 |
}
|
|
44 |
||
45 |
#argument options
|
|
46 |
$argMap{"C"}="directory"; |
|
47 |
$argMap{"j"}="jobs"; |
|
48 |
$argMap{"n"}="just-print"; |
|
49 |
$argMap{"v"}="verbose"; |
|
50 |
$argMap{"k"}="keep-going"; |
|
51 |
$argMap{"p"}="projecthelp"; |
|
52 |
$argMap{"h"}="help"; |
|
53 |
$argMap{"e"}="exclude"; |
|
54 |
$argMap{"q"}="quiet"; |
|
55 |
@options=split(" ", "help directory jobs just-print verbose keep-going version projecthelp exclude quiet"); |
|
56 |
@argCommands=split(" ","directory jobs exclude"); |
|
57 |
||
58 |
&parseArguments(@ARGV); |
|
59 |
if(defined $help) { |
|
60 |
print "Usage: $COMMAND [OPTION] ...\n"; |
|
61 |
print "Available options:\n\n"; |
|
62 |
print " -h, --help This help.\n"; |
|
63 |
print " -p --projecthelp print project help information\n"; |
|
64 |
print " -j, --jobs=N Allow N parallel jobs.\n"; |
|
65 |
print " -k, --keep-going Keep going when some targets can't be made.\n"; |
|
66 |
print " -C, --directory=dir Change to directory dir before doing anything.\n"; |
|
67 |
print " -v, --verbose Show verbose output.\n"; |
|
68 |
print " --version Show version information and copyright notice.\n"; |
|
69 |
print " -n --just-print Only print out the commands to call.\n"; |
|
70 |
print " -q --quiet Don't print details\n"; |
|
71 |
print " -e --exclude=RegEx Exclude libraries and subdirs based on a regular expression\n"; |
|
72 |
exit; |
|
73 |
}
|
|
74 |
||
75 |
if(defined $version) { |
|
76 |
print "$VERSION\nWritten by Thomas Zander\n\nThis is free software see the source for copying conditions. There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; |
|
77 |
exit; |
|
78 |
}
|
|
79 |
||
80 |
if(defined $directory) { |
|
81 |
chdir $directory || die "Failed to change directory to '$directory'\n"; |
|
82 |
}
|
|
83 |
||
84 |
while(! -f "CMakeFiles" && ! -f "CMakeLists.txt") { |
|
85 |
# for the case where there is a subdir but that subdir does not have a cmakefile
|
|
86 |
chdir ".." || die "Error: Can not find a cmake based basedir\nPlease start from the source dir\n"; |
|
87 |
if(`pwd` eq "/\n") { |
|
88 |
die "Error: Can not find a cmake based basedir\nPlease start from the source dir\n"; |
|
89 |
}
|
|
90 |
}
|
|
91 |
||
92 |
$dir=`pwd`; |
|
93 |
chomp($dir); |
|
94 |
$builddir = "$dir/"; |
|
95 |
||
96 |
# find the build-dir where the Makefile lives
|
|
97 |
@bd = split("=", $buildDirType); |
|
98 |
if($#bd > 0) { |
|
99 |
# make sure slashes are all round
|
|
100 |
$bd[0]="/$bd[0]/"; |
|
101 |
$bd[1]="/$bd[1]/"; |
|
102 |
$bd[0]=~s/\/\//\//g; |
|
103 |
$bd[1]=~s/\/\//\//g; |
|
104 |
my $wildcard=""; |
|
105 |
if($bd[0]=~/(\{.*\})/) { # used {project} wildcard |
|
106 |
$wildcard=$1; |
|
107 |
if($bd[1]=~/$wildcard/) { |
|
108 |
$bd[0]=~s/$wildcard/(.*?)/; |
|
109 |
}
|
|
110 |
}
|
|
111 |
if($builddir=~/$bd[0]/ && $builddir=~/$bd[1]/ == false) { |
|
112 |
my $project=$wildcard; |
|
113 |
$builddir=~/$bd[0]/; |
|
114 |
if($builddir=~m/$bd[0]/) { |
|
115 |
$project=$1; |
|
116 |
}
|
|
117 |
$builddir=~s/$bd[0]/$bd[1]/; |
|
118 |
if($wildcard ne "" && $project ne "") { |
|
119 |
$builddir=~s/$wildcard/$project/; |
|
120 |
}
|
|
121 |
#print "$dir => $builddir\n";
|
|
122 |
}
|
|
123 |
}
|
|
124 |
||
125 |
$makeDependNeeded = 0; |
|
126 |
&readCmakeFile("."); |
|
127 |
||
128 |
if(defined $projecthelp) { |
|
129 |
print "\nLibraries:\n\n"; |
|
130 |
foreach $key (sort {uc($a) cmp uc($b)} @libraries) { |
|
131 |
print " $key"; |
|
132 |
if(defined $exclude && $key=~/$exclude/) { |
|
133 |
print " [excluded]"; |
|
134 |
}
|
|
135 |
print "\n"; |
|
136 |
}
|
|
137 |
exit; |
|
138 |
}
|
|
139 |
||
140 |
$doInstall = 0; |
|
141 |
if($#userArgs >= 0) { # limit to user request |
|
142 |
foreach $lib (@userArgs) { |
|
143 |
if($lib eq "install") { |
|
144 |
$doInstall = 1; |
|
145 |
if($#userArgs == 0) { |
|
146 |
@targets = @libraries; |
|
147 |
}
|
|
148 |
next; |
|
149 |
}
|
|
150 |
||
151 |
my $pureLib = $lib; |
|
152 |
$pureLib=~s/^[\/ \\]*//; |
|
153 |
$pureLib=~s/[\/ \\]*$//; |
|
154 |
if(&contains($pureLib, @libraries)) { |
|
155 |
push @targets, $pureLib; |
|
156 |
}
|
|
157 |
else { |
|
158 |
push @nonLibTargets, $lib; |
|
159 |
}
|
|
160 |
}
|
|
161 |
}
|
|
162 |
else { |
|
163 |
@targets=@libraries; |
|
164 |
}
|
|
165 |
||
166 |
foreach $lib (@targets) { # add dependencies |
|
167 |
@deps = &dependencies(0, $lib); |
|
168 |
LIB: foreach $l (@deps) { |
|
169 |
if($l eq "ERROR") { |
|
170 |
exit 1; |
|
171 |
}
|
|
172 |
if(defined $exclude && $l=~/$exclude/) { |
|
173 |
next; |
|
174 |
}
|
|
175 |
foreach $x (@maketargets) { |
|
176 |
if($l eq $x) { |
|
177 |
next LIB; |
|
178 |
}
|
|
179 |
}
|
|
180 |
push @maketargets, $l; |
|
181 |
}
|
|
182 |
}
|
|
183 |
||
184 |
# cd to builddir
|
|
185 |
chdir $builddir || die "Can't find builddir '$builddir'\n"; |
|
186 |
if($makeDependNeeded) { |
|
187 |
system ("make depend") == 0 or exit 1; |
|
188 |
}
|
|
189 |
||
190 |
@actualTargets=`make help`; |
|
191 |
foreach $target (@nonLibTargets) { |
|
192 |
foreach $h (@actualTargets) { |
|
193 |
if($h=~/\b$target\b/) { |
|
194 |
push @maketargets, $target; |
|
195 |
}
|
|
196 |
}
|
|
197 |
}
|
|
198 |
||
199 |
if($doInstall == 0 && $#maketargets < 0) { |
|
200 |
print "No targets\n"; |
|
201 |
exit; |
|
202 |
}
|
|
203 |
||
204 |
if(defined $jobs) { |
|
205 |
$jobs="-j $jobs"; |
|
206 |
}
|
|
207 |
if(defined $verbose) { |
|
208 |
$verbose="VERBOSE=0"; |
|
209 |
}
|
|
210 |
foreach $lib (@maketargets) { |
|
211 |
chdir "$builddir/$locations{$lib}"; |
|
212 |
$dir = $locations{$lib}; |
|
213 |
$dir=~s/^\.\///; |
|
214 |
if(&checkTargetAvail($lib) == 1) { |
|
215 |
if(! defined $quiet) { |
|
216 |
print "Building lib: $lib (in $dir)\n"; |
|
217 |
}
|
|
218 |
if(defined $just_print) { |
|
219 |
next; |
|
220 |
}
|
|
1.1.46
by Alessandro Ghersi
Import upstream version 4.4.92 |
221 |
foreach $h (@actualTargets) { |
222 |
if($h=~/(\b$lib\_automoc)/) { |
|
223 |
system ("make $jobs $verbose $1"); |
|
224 |
last; |
|
225 |
}
|
|
226 |
}
|
|
227 |
||
1.1.13
by Jonathan Riddell
Import upstream version 4.0.80 |
228 |
my $rc = system ("make $jobs $verbose $lib/fast"); |
229 |
if(!(defined $keep_going) && $rc != 0) { |
|
230 |
exit 1; |
|
231 |
}
|
|
232 |
}
|
|
233 |
elsif(! defined $quiet) { |
|
234 |
print "Skipping lib: $lib (in $dir)\n"; |
|
235 |
}
|
|
236 |
}
|
|
237 |
||
238 |
# install!
|
|
239 |
if($doInstall == 1) { |
|
240 |
if(! defined $quiet) { |
|
241 |
print "Installing changed files"; |
|
242 |
#if($dir ne ".") { print " in '$dir'"; }
|
|
243 |
print "\n"; |
|
244 |
}
|
|
245 |
if(! defined $just_print) { |
|
1.1.46
by Alessandro Ghersi
Import upstream version 4.4.92 |
246 |
@output=`(cd $builddir && make install/fast)`; |
247 |
my $line; |
|
248 |
foreach $line (@output) { |
|
249 |
if ($line=~/^-- (Installing: .*)$/) { |
|
250 |
print "$1\n"; |
|
251 |
}
|
|
252 |
}
|
|
1.1.13
by Jonathan Riddell
Import upstream version 4.0.80 |
253 |
}
|
254 |
}
|
|
255 |
||
256 |
###############
|
|
257 |
sub readCmakeFile { |
|
258 |
my $dir=shift(@_); |
|
259 |
my $file="CMakeLists.txt"; |
|
260 |
||
261 |
if($makeDependNeeded == 0) { |
|
262 |
my $buildAge = (stat("$builddir/$dir/CMakeFiles/CMakeDirectoryInformation.cmake"))[9]; |
|
263 |
my $fileAge = (stat("$dir/$file"))[9]; |
|
264 |
if($fileAge > $buildAge) { |
|
265 |
$makeDependNeeded = 1; |
|
266 |
print "makeDepend needed due to $dir\n"; |
|
267 |
}
|
|
268 |
}
|
|
269 |
||
270 |
my @subdirs; |
|
271 |
open FILE, "$dir/$file"; |
|
272 |
my $inLink=0; |
|
273 |
my $lib = ""; |
|
274 |
foreach $line (<FILE>) { |
|
275 |
if($inLink == 0 && $line=~/^\s*add_subdirectory\s*\((.*)\)/i) { |
|
276 |
my $d=$1; |
|
277 |
$d=~s/^\s*//; #chomp |
|
278 |
$d=~s/\s*$//; |
|
279 |
push @subdirs, $d; |
|
280 |
}
|
|
281 |
||
282 |
my $libs = ""; |
|
283 |
if($inLink == 1) { |
|
284 |
$libs = $line; |
|
285 |
}
|
|
286 |
if($line=~/^\s*target_link_libraries\s*\((.*)/) { |
|
287 |
$libs = $1; |
|
288 |
$inLink=1; |
|
289 |
}
|
|
290 |
if($inLink == 1 && $libs ne "") { |
|
291 |
foreach $i (split(" ", $libs)) { |
|
292 |
if($i=~/\)$/) { # incase no space was used |
|
293 |
$i=~s/\)$//; |
|
294 |
$inLink = 0; |
|
295 |
}
|
|
296 |
if($i eq ")") { #incase a space was used |
|
297 |
$inLink = 0; |
|
298 |
}
|
|
299 |
elsif($inLink==1 && $lib eq "") { # a library is defined in this file |
|
300 |
$lib = $i; |
|
301 |
push @libraries, $lib; |
|
302 |
#print "found lib: $lib\n";
|
|
303 |
$locations{$lib} = "$dir"; |
|
304 |
}
|
|
305 |
else { # and that libraries dependencies |
|
306 |
$$lib .= "$i "; |
|
307 |
#print " supportlib $i\n";
|
|
308 |
}
|
|
309 |
}
|
|
310 |
$libs =""; |
|
311 |
}
|
|
312 |
if($inLink == 0) { |
|
313 |
$lib = ""; |
|
314 |
}
|
|
315 |
}
|
|
316 |
close FILE; |
|
317 |
||
318 |
# only go into subdir when the DartTestfile lists the subdir.
|
|
319 |
open FILE, "$builddir/$dir/DartTestfile.txt"; |
|
320 |
foreach $line (<FILE>) { |
|
321 |
if($line=~/^SUBDIRS\s*\((.*)\)/) { |
|
322 |
my $subdir; |
|
323 |
foreach $subdir (@subdirs) { |
|
324 |
if(defined $exclude && "/$subdir/"=~/$exclude/) { |
|
325 |
next; |
|
326 |
}
|
|
327 |
if($line=~/\b$subdir\b/) { |
|
328 |
&readCmakeFile("$dir/$subdir"); |
|
329 |
}
|
|
330 |
}
|
|
331 |
last; |
|
332 |
}
|
|
333 |
}
|
|
334 |
close FILE; |
|
335 |
}
|
|
336 |
||
337 |
sub dependencies() { |
|
338 |
my $level=shift(@_); |
|
339 |
my $target=shift(@_); |
|
340 |
if($level > 12) { |
|
341 |
print "ERROR; dependency checking hit 12 levels deep, probably a circular dependency, baling out\n"; |
|
342 |
print " dependencies traceback (bottom depends on top):\n"; |
|
343 |
print " $target\n"; |
|
344 |
return "ERROR"; |
|
345 |
}
|
|
346 |
#my $inset ="";
|
|
347 |
#for($i=0; $i < $level; $i++) { $inset .=" "; }
|
|
348 |
#print "$inset |dependencies of '$target'\n";
|
|
349 |
||
350 |
my @depend; |
|
351 |
my $lib; |
|
352 |
#print "$inset depsLine='$$target'\n";
|
|
353 |
foreach $lib (split(" ", $$target)) { |
|
354 |
my $found=0; |
|
355 |
my $l; |
|
356 |
# if not in our libraries, skip it.
|
|
357 |
foreach $l (@libraries) { |
|
358 |
if($l eq $lib) { |
|
359 |
$found=1; |
|
360 |
last; |
|
361 |
}
|
|
362 |
}
|
|
363 |
if($found == 0) { |
|
364 |
next; |
|
365 |
}
|
|
366 |
#print "$inset has dependency $lib\n";
|
|
367 |
||
368 |
if(&contains($lib, @depend) == 0) { |
|
369 |
#print "$inset $lib not yet present in: \"";
|
|
370 |
#foreach $dslf (@depend) {
|
|
371 |
# print " $dslf";
|
|
372 |
#}
|
|
373 |
#print "\"\n";
|
|
374 |
# before we add it, lets find the dependencies of that library
|
|
375 |
foreach $l (&dependencies($level+1, $lib)) { |
|
376 |
if($l eq "ERROR") { |
|
377 |
print " $target\n"; |
|
378 |
return "ERROR"; |
|
379 |
}
|
|
380 |
if(&contains($l, @depend) == 0) { |
|
381 |
push @depend, $l; |
|
382 |
}
|
|
383 |
}
|
|
384 |
push @depend, $lib; |
|
385 |
}
|
|
386 |
}
|
|
387 |
if(&contains($target, @depend) == 0) { |
|
388 |
push @depend, $target; |
|
389 |
}
|
|
390 |
||
391 |
#foreach $dslf (@depend) {
|
|
392 |
# print "$inset += '$dslf'\n";
|
|
393 |
#}
|
|
394 |
||
395 |
return @depend; |
|
396 |
}
|
|
397 |
||
398 |
## Returns 1 if the first arg is already present in the rest of the array, 0 otherwise
|
|
399 |
sub contains() { |
|
400 |
my $new=shift(@_); |
|
401 |
@array = @_; |
|
402 |
my $item; |
|
403 |
foreach $item (@array) { |
|
404 |
if($item eq $new) { |
|
405 |
return 1; |
|
406 |
}
|
|
407 |
}
|
|
408 |
return 0; |
|
409 |
}
|
|
410 |
||
411 |
sub parseArguments() { |
|
412 |
@arguments=@_; |
|
413 |
for($i=0; $i<=$#arguments; $i++) { |
|
414 |
if($arguments[$i]=~/(-{1,2}\S+?)(=\S+|)$/) { |
|
415 |
$command=$1; |
|
416 |
$param=$2; |
|
417 |
if($command=~/^-\b(.)(.*)/) { |
|
418 |
my $char=$1; |
|
419 |
$param=$2; |
|
420 |
$command=$argMap{$char}; |
|
421 |
}
|
|
422 |
$command=~s/^--//; |
|
423 |
if(&contains($command, @options) == 0) { |
|
424 |
print "unrecognized option '$arguments[$i]'\n"; |
|
425 |
print "Try `$COMMAND --help' for more information.\n"; |
|
426 |
exit 1; |
|
427 |
}
|
|
428 |
if($param eq "" && &contains($command, @argCommands) == 1) { |
|
429 |
$i++; |
|
430 |
if($arguments[$i]=~/^-/ || $#arguments < $i) { |
|
431 |
print "Missing argument: $arguments[$i-1]\n"; |
|
432 |
exit 1; |
|
433 |
}
|
|
434 |
$param = $arguments[$i]; |
|
435 |
}
|
|
436 |
if($param eq "") { |
|
437 |
$param =1; |
|
438 |
}
|
|
439 |
$command=~s/\W/_/g; |
|
440 |
# print "setting param $command\n";
|
|
441 |
$$command=$param; |
|
442 |
}
|
|
443 |
else { |
|
444 |
push @userArgs, $arguments[$i]; |
|
445 |
}
|
|
446 |
}
|
|
447 |
}
|
|
448 |
||
449 |
sub checkTargetAvail() { |
|
450 |
my $target=shift(@_); |
|
451 |
open FILE, "Makefile"; |
|
452 |
foreach $line (<FILE>) { |
|
453 |
if($line=~/^$target:/) { |
|
454 |
close FILE; |
|
455 |
return 1; |
|
456 |
}
|
|
457 |
}
|
|
458 |
close FILE; |
|
459 |
return 0; |
|
460 |
}
|
|
461 |