forked from coin-or-tools/BuildTools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
run_autotools
executable file
·575 lines (484 loc) · 18.9 KB
/
run_autotools
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
#!/bin/bash
#
# Copyright (C) 2020 COIN-OR Foundation
# All Rights Reserved.
#
# This file is distributed under the Eclipse Public License 2.0.
# See LICENSE for details.
#
# Author: Andreas Waechter IBM 2006-04-14
# Modified: Lou Hafer SFU 2010-06-11
# Mods to allow variations from standard package structure. Decision to
# process a configure.ac file is based on presence of COIN macros.
# Directories specified on the command line are recursively searched
# for configure.ac files. Install-sh signals an independent unit.
# Modified: Lou Hafer SFU 2010-07-08
# More mods to maintain flexibility but be a bit less aggressive about
# forcing installation of autotools auxilliary scripts. Also add some
# command line options and restore ability to specify individual
# directories on the command line.
# Modified: Lou Hafer retired 2017-05-17
# Allow that we can use bash. Make sure help always works.
# run_autotools takes care of running the autotools (automake, autoconf,
# and helpers) and also makes a few arrangements for when configure and
# libtool execute at configuration, build, and installation.
# Run_autotools can be given a set of directories on the command line; if none
# are specified, it assumes the current directory (`.'). Subdirectories are
# searched for configure.ac files unless suppressed with the -nr option.
# Autotools will consider a directory for processing if any AC_COIN_ macro is
# present in the configure.ac file. Should it be necessary to fool this script
# into processing a file that otherwise contains no COIN macros, just add a
# line with AC_COIN_. The resulting list is winnowed to remove directories
# specified in COIN_SKIP_PROJECTS.
# Each directory processed gets a temporary link to BuildTools, unless a
# BuildTools subdirectory is already present. Mostly this is a convenience, but
# one thing makes it mandatory: Many Makefile.am files in COIN-OR use an include
# directive to pull in BuildTools/Makemain.inc. There's no way I (lh) can see
# to alter the path that's hardcoded in the include directive. Just to make it
# more interesting, COIN-OR projects are generally constructed with the assumption
# that BuildTools will be one or two directories up, so you'll see things like
# `include ../BuildTools/Makemain.inc'. run_autotools doesn't understand this
# hierarchy, so it keeps all those temporary BuildTools links until the very
# end. That way, it works with the old-style COIN-OR organisation where a
# BuildTools directory is pulled in as an external in the top directory of a
# package, and with the new-style independent organisation, where there may be
# only a single copy of BuildTools out there somewhere.
# If any subdirectory queued for processing is found to contain an install-sh
# script, it is treated as an independent unit (i.e., you can run `make
# install' from this directory) and the set of auxilliary scripts is refreshed.
# You can suppress installation of install-sh and associated
# scripts with the -ni option. It's good to read the autoconf documentation for
# AC_CONFIG_AUX_DIR if this doesn't make sense to you.
# Find out the location for autotools executables, macros, etc.
# This can be overidden if the user sets COIN_AUTOTOOLS_DIR in the environment.
# If COIN_AUTOTOOLS_DIR is set, make sure that is at the beginning of PATH.
if test -z "$COIN_AUTOTOOLS_DIR" ; then
# assume that autotools directory is given by location of autoconf
COIN_AUTOTOOLS_DIR=`dirname $(which autoconf)`/..
else
# prefix PATH with COIN_AUTOTOOLS_DIR/bin
PATH="${COIN_AUTOTOOLS_DIR}/bin:$PATH"
fi
echo "Using COIN_AUTOTOOLS_DIR=$COIN_AUTOTOOLS_DIR"
repoDir='.git'
ver_autoconf='2.71'
ver_automake='1.16.5'
ver_libtool='2.4.7'
ltfile=$COIN_AUTOTOOLS_DIR/share/libtool/build-aux/ltmain.sh
autotoolsFiles="config.guess config.sub depcomp install-sh ltmain.sh missing compile ar-lib"
# Define a cleanup function. We'll set a trap below, just before we start to
# do actual work.
cleanupOnErrorExit ()
{ for link in $buildtoolsLinks; do
echo Trap: removing $link
rm -rf $link
done
cd $startDir
}
# Subroutine to print the help message.
printHelp () {
cat <<EOF
usage: run_autotools [-h] [-[n]r] [-ni] [-f] [ directory directory ... ]
-h | --help print help message and exit
-r | --recursion do recursive search for configure.ac files
-nr | --no-recursion do not do recursive search for configure.ac files
-ni | --dependent do not install scripts necessary for an independent unit
-f | --foreign process foreign configuration files (configure.ac
does not contain COIN-OR configuration macros).
-d | --dryrun exit immediately after determining the list of
directories to be processed
Default is no recursion, install scripts for an independent unit.
If no directories and -r are specified, the tree rooted at the current
directory is searched recursively for directories with configure.ac
files containing COIN-OR configuration macros (AC_COIN_*) and autotools
is run in those directories. Directories listed in COIN_SKIP_PROJECTS
are skipped. If directories are specified on the command line, the
search for configure.ac files is restricted to the specified directories.
In each directory where a configure.ac file is found, this script will
refresh a set of autotools scripts (listed below) necessary for a unit that
will be installed independently.
The -ni (--dependent) option will suppress refresh of the autotools scripts
(but will not delete existing scripts). This will be suppressed in *all*
directories processed.
The most common scenario for run_autotools is to process a project with a
configure.ac file in the top-level directory of the project and no nested
configure.ac files. Hence the default of no recursion and install autotools
scripts. The -r option is useful if you have multiple COIN-OR projects in
sibling directories and want to do a batch run of autotools on all of them.
The -f (--foreign) option causes run_autotools to process any configure.ac,
even if it contains no COIN-OR macros. Occasionally useful for adapting
ThirdParty native configuration for COIN-OR. Be sure you know what you're
doing.
The environment variable COIN_AUTOTOOLS_DIR can be used to point to an alternate
installation of the autotools (current location $COIN_AUTOTOOLS_DIR)
Default autotools versions:
autoconf: $ver_autoconf
automake: $ver_automake
libtool: $ver_libtool
Autotools scripts: ${autotoolsFiles}
EOF
}
# Subroutine to check that a given autotools command is present, has the
# correct version, and is being sourced from the correct directory.
checkAutotoolVersion () {
local toolName=$1
local requiredVer=$2
local escapedVer=`echo $requiredVer | sed -e 's/\./\\\./g'`
if ! command -v $toolName &>/dev/null ; then
echo "$toolName not available!"
return 1
fi
local toolVer=`$toolName --version`
if ! expr "$toolVer" : '.*'"$escapedVer"'.*' &>/dev/null ; then
echo "You are not using the required version $requiredVer of $toolName (" `which $toolName` ")"
return 2
fi
local toolDir=`command -v $toolName | sed -e "s,/$toolName,,"`
toolDir=`cd $toolDir ; pwd`
local autoDir=`cd $COIN_AUTOTOOLS_DIR/bin ; pwd`
if [[ "$toolDir" != "$autoDir" ]] ; then
echo "$toolName is not picked up from the correct location."
return 3
fi
}
# A couple of subroutines to decide if a directory is a project, and to find
# projects under a given directory. Pulled out as subroutines in anticipation
# that I'll want to expand the test when git comes into the picture.
# Subroutine to decide if a directory is a project. The test is presence
# of a $repoDir (.git or .svn are the known types). There's no protection
# against specifying an interior directory. The loop allows for mixed git and
# svn project directories.
isAProject () {
for lcldir in $repoDir ; do
if [[ -d $1/${lcldir} ]] ; then
return 0
fi
done
return 1
}
# Subroutine to find the project directories under a given directory. The test
# is presence of a $repoDir directory.
findProjects () {
local dirs
local tmp
for dir in $repoDir ; do
tmp=$( find $1 -type d -name ${dir} -print -prune )
tmp=`echo $tmp | sed -e "s,/${dir},,g"`
dirs="$dirs $tmp"
done
echo $dirs
}
# See if the user just wants help, before we get into the thick if it.
for arg in "$@" ; do
case $arg in
-h | -help | --h | --help )
printHelp
exit
;;
esac
done
# Make sure we bail out if there is an error
set -e
# Determine the source of run_autotools and confirm that it is a BuildTools
# directory with a copy of coin.m4.
# If there are no '/' chars in the command name, then run_autotools lives
# in some directory of PATH --- look there. Otherwise grab the prefix off
# the command name. Then, if we have a relative path, convert it to absolute
# using the current directory as a prefix. Clean up the result by compressing
# `XXX/../', '/./', '//' sequences and removing trailing '/.' and 'XXX/..'.
startDir=`pwd`
myName=${0##*/}
if expr "$0" : '.*/.*' &>/dev/null ; then
runautotoolDir=`echo $0 | sed -e 's,\(.*\)/[^/]*,\1,'`
else
for dir in $( echo $PATH | sed 's/:/ /' ) ; do
if test -x "${dir}/${myName}" ; then
runautotoolDir=$dir
break
fi
done
fi
if expr "$runautotoolDir" : '/.*' >/dev/null 2>&1 ; then
:
else
runautotoolDir=$startDir/$runautotoolDir
fi
while expr "$runautotoolDir" : '.*/\.\.' >/dev/null 2>&1 ; do
runautotoolDir=`echo $runautotoolDir | \
sed -e 's,/[^/][^/]*/\.\./,/,' -e 's,/[^/][^/]*/\.\.$,,'`
done
runautotoolDir=`echo $runautotoolDir | sed -e 's,/\./,/,g' -e 's,//,/,g' -e 's,/.$,,'`
if [[ ! -f ${runautotoolDir}/coin.m4 ]] ; then
echo "Found $myName in $runautotoolDir but coin.m4 is not present."
exit
fi
# Make sure we're using the correct versions of autoconf and automake. Failure
# to satisfy this requirement is a fatal error.
if ! checkAutotoolVersion autoconf $ver_autoconf ; then
exit 2
fi
if ! checkAutotoolVersion automake $ver_automake ; then
exit 2
fi
# Failure to find the correct version of ltmain.sh isn't fatal here, but the
# user should be warned.
if [[ ! -r $ltfile ]] ; then
echo "WARNING: Cannot find libtool shell $ltfile"
fi
if ! grep -F $ver_libtool $ltfile &>/dev/null ; then
echo "WARNING: You are not using the correct version of libtool"
fi
# Set up to process parameters. No parameters is the default.
doRecurse=0
suppressScripts=0
userSpecifiedDirs=0
dryRun=0
# Process the parameters. A parameter without an opening `-' is assumed to be
# a spec for a directory to be processed. We really shouldn't see -h here, but
# it's easy to deal with it.
while [[ $# -gt 0 ]] ; do
case "$1" in
-h* | --h* )
printHelp
exit
;;
-r* | --recursion )
doRecurse=1
;;
-nr | --no-recursion )
doRecurse=0
;;
-ni | --dependent )
suppressScripts=1
;;
-d | --dryrun )
dryRun=1
;;
-f | --foreign )
doForeign=1
;;
-* ) echo "$0: unrecognised command line switch '"$1"'."
printHelp=1
;;
* ) userDirs+=($1)
userSpecifiedDirs=1
;;
esac
shift
done
# If the user has specified project directories, assume those directories
# are not subject to COIN_SKIP_PROJECTS. On the other hand, directories
# that are not projects (but presumably contain projects) will be subject
# to COIN_SKIP_PROJECTS. If the user didn't specify anything, the default
# is the projects under the current directory.
if [[ $userSpecifiedDirs -eq 1 ]] ; then
for dir in ${userDirs[@]} ; do
if isAProject $dir ; then
# echo " $dir will be immune to COIN_SKIP_PROJECTS"
noSkipDirs+=($dir)
else
if [[ doRecurse -eq 1 ]] ; then
dirsToProcess+=(`findProjects $dir`)
else
dirsToProcess+=($dir)
fi
fi
done
else
if [[ doRecurse -eq 1 ]] ; then
dirsToProcess+=(`findProjects .`)
else
dirsToProcess+=(".")
fi
fi
# echo "dirsToProcess (${#dirsToProcess[@]}): ${dirsToProcess[*]}"
# echo "noSkipDirs (${#noSkipDirs[@]}): ${noSkipDirs[*]}"
# Allow that there might be overlap and remove it from dirsToProcess.
if [[ ${#noSkipDirs[@]} -gt 0 && ${#dirsToProcess[@]} -gt 0 ]] ; then
for dir in ${noSkipDirs[@]} ; do
canonicalNoSkipDirs+=(`cd $dir ; pwd`)
done
for (( ndx=0 ; ndx < ${#dirsToProcess[@]} ; ndx++ )) ; do
canonicalDir=`cd ${dirsToProcess[$ndx]} ; pwd`
for dir in ${canonicalNoSkipDirs[@]} ; do
if [[ $canonicalDir != $dir ]] ; then
tmpDir+=(${dirsToProcess[$ndx]})
break
fi
done
done
dirsToProcess=(${tmpDir[@]})
unset tmpDir
fi
# echo "dirsToProcess (${#dirsToProcess[@]}): ${dirsToProcess[*]}"
# echo "noSkipDirs (${#noSkipDirs[@]}): ${noSkipDirs[*]}"
# Now consider if any of the projects in dirsToProcess are listed in
# COIN_SKIP_PROJECTS. Here, we want to check if a project in COIN_SKIP_PROJECTS
# is a suffix of the value from dirsToProcess.
if [[ -n "$COIN_SKIP_PROJECTS" && ${#dirsToProcess[@]} -gt 0 ]] ; then
skipProjects=($COIN_SKIP_PROJECTS)
for (( ndx=0 ; ndx < ${#dirsToProcess[@]} ; ndx++ )) ; do
drop=0
for dir in ${skipProjects[@]} ; do
# echo "comparing [$ndx] ${dirsToProcess[$ndx]} with $dir"
if expr "${dirsToProcess[$ndx]}" : '.*/'"$dir"'$' &>/dev/null ; then
# echo " dropping ${dirsToProcess[$ndx]}"
drop=1
break
fi
done
if [[ $drop -eq 0 ]] ; then
tmpDir+=(${dirsToProcess[$ndx]})
fi
done
dirsToProcess=(${tmpDir[@]})
unset tmpDir
fi
# echo "dirsToProcess (${#dirsToProcess[@]}): ${dirsToProcess[*]}"
# echo "noSkipDirs (${#noSkipDirs[@]}): ${noSkipDirs[*]}"
# Finally, we can join all the directories into one big happy list.
dirsToProcess+=(${noSkipDirs[@]})
# If recursion is permitted, find directories which contain a file
# configure.ac.
if [[ $doRecurse = 1 ]] ; then
for dir in ${dirsToProcess[@]} ; do
# echo " diving in $dir"
tmp=`find $dir -name configure.ac | sed -e s,/configure.ac,,g`
# echo " result: $tmp"
candDirs+=($tmp)
done
else
candDirs=(${dirsToProcess[@]})
fi
echo "candDirs (${#candDirs[@]}): ${candDirs[*]}"
# Winnow the candidates. Process a directory only if the configure.ac file
# contains at least one macro that starts with AC_COIN_.
for dir in ${candDirs[@]} ; do
if [[ -r $dir/configure.ac ]] ; then
if grep AC_COIN_ $dir/configure.ac &>/dev/null || \
test $doForeign -eq 1 ; then
dirs+=($dir)
else
echo " Skipping foreign configure.ac in '$dir'."
fi
fi
done
# Set a trap so that we'll clean up any links on exit, for whatever reason.
# Note that this executes on normal exit, too, so don't do anything rash.
topLink=
subLink=
trap 'exit_status=$?
cleanupOnErrorExit
exit $exit_status' 0
# And now the main event. Process each directory.
echo "Running autotools in ${dirs[*]}"
if [[ $dryRun -eq 1 ]] ; then
exit
fi
buildtoolsLinks=
for dir in ${dirs[@]} ; do
if test -r $dir/configure.ac; then
cd $dir
echo "Processing $dir ..."
# Do we need a BuildTools subdirectory here? The criteria is that install-sh
# already exists, or Makefile.am (which may include Makemain.inc), or we're
# forcing installation of the configure scripts. Assuming we need BuildTools,
# what BuildTools should we use? If a BuildTools is already present, that's
# it. Otherwise, assume that runautotooldDir is BuildTools. Allow that the
# user may have linked to a BuildTools.
needScripts=1
if test $suppressScripts = 1 ; then
needScripts=0
fi
if test -f Makefile.am || test $needScripts = 1 ; then
if test -d BuildTools || test -L BuildTools ; then
createLink=0
toolsDir=`pwd`/BuildTools
else
createLink=1
toolsDir=$runautotoolDir
fi
echo " BuildTools directory: $toolsDir"
# Test to be sure that run_autotools is coming from the BuildTools directory.
if test $createLink = 0 && test "$toolsDir" != "$runautotoolDir" ; then
echo "WARNING: using run_autotools from $runautotoolDir"
echo " but BuildTools is $toolsDir."
echo " Consider carefully if this is what you wanted to do."
fi
# coin.m4 should live in the same directory; failure is fatal.
if test ! -r $toolsDir/coin.m4 ; then
echo "Cannot find Coin autotools macro file $toolsDir/coin.m4."
echo "It should be in the BuildTools directory."
exit 1
fi
# Install a link, if needed.
if test $createLink = 1 ; then
ln -s $toolsDir BuildTools
buildtoolsLinks="$buildtoolsLinks `pwd`/BuildTools"
echo " creating temporary link for ./BuildTools -> $toolsDir"
fi
# And refresh the autotools scripts, if needed.
if test $needScripts = 1 ; then
echo " refreshing autotools scripts in this directory."
for file in $autotoolsFiles ; do
if test -e BuildTools/$file ; then
cp BuildTools/$file .
elif test -e $COIN_AUTOTOOLS_DIR/share/automake-${ver_automake:0:4}/$file ; then
cp $COIN_AUTOTOOLS_DIR/share/automake-${ver_automake:0:4}/$file .
elif test -e $COIN_AUTOTOOLS_DIR/share/libtool/build-aux/$file ; then
cp $COIN_AUTOTOOLS_DIR/share/libtool/build-aux/$file .
else
echo " Do not know where to take $file from."
exit 1
fi
if test -e BuildTools/${file}.patch ; then
patch -p0 < BuildTools/${file}.patch
fi
done
fi
fi
# Get on with running the autotools.
m4Dirs="-I $COIN_AUTOTOOLS_DIR/share/aclocal"
m4Dirs="$m4Dirs -I $toolsDir"
if test -d m4 ; then
m4Dirs="$m4Dirs -I m4"
fi
echo " running aclocal in $dir"
aclocal $m4Dirs
# Not all projects make use of libtool, so check before we try to apply the
# libtool patch.
if grep -q -F '[_LT_COPYING]' aclocal.m4 ; then
echo " apply libtool.m4 patch to support ICL"
patch -p1 < BuildTools/libtool-icl.patch
fi
if grep AC_CONFIG_HEADER configure.ac >/dev/null 2>&1; then
echo " running autoheader in $dir"
autoheader || exit 1
fi
echo " running automake in $dir"
automake || exit 1
echo " running autoconf in $dir"
autoconf || exit 1
# Copy headers from headers/ (carefully avoiding a descent into BuildTools)
for f in BuildTools/headers/* ; do
h=`basename $f`
echo " update $f, if existing"
find . -name BuildTools -prune -o -name $h -exec cp $f {} \;
done
cd $startDir
else
# Serious confusion! Should not reach here.
echo "*** No configure.ac file in $dir - SKIPPING! ***"
fi
done
# Remove the links. Yeah, the trap will do this, but it never hurts to clean
# up properly.
if test -n "$buildtoolsLinks" ; then
echo "Removing temporary links to BuildTools."
for link in $buildtoolsLinks ; do
# echo " removing temporary link for BuildTools: $link"
rm -rf $link
done
buildtoolsLinks=
fi
exit