Allow the use of a destructor for the values stored in the list.
[gnulib.git] / build-aux / bootstrap
1 #! /bin/sh
2
3 # Bootstrap this package from checked-out sources.
4
5 # Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2, or (at your option)
10 # any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 # 02110-1301, USA.
21
22 # Written by Paul Eggert.
23
24 nl='
25 '
26
27 # Ensure file names are sorted consistently across platforms.
28 # Also, ensure diagnostics are in English, e.g., "wget --help" below.
29 LC_ALL=C
30 export LC_ALL
31
32 # Temporary directory names.
33 bt='._bootmp'
34 bt_regex=`echo "$bt"| sed 's/\./[.]/g'`
35 bt2=${bt}2
36
37 usage() {
38   echo >&2 "\
39 Usage: $0 [OPTION]...
40 Bootstrap this package from the checked-out sources.
41
42 Options:
43  --gnulib-srcdir=DIRNAME  Specify the local directory where gnulib
44                           sources reside.  Use this if you already
45                           have gnulib sources on your machine, and
46                           do not want to waste your bandwidth downloading
47                           them again.
48  --copy                   Copy files instead of creating symbolic links.
49  --force                  Attempt to bootstrap even if the sources seem
50                           not to have been checked out.
51  --skip-po                Do not download po files.
52  --cvs-user=USERNAME      Set the username to use when checking out
53                           sources from the gnulib repository.
54
55 If the file .bootstrap.conf exists in the current working directory, its
56 contents are read as shell variables to configure the bootstrap.
57
58 Running without arguments will suffice in most cases.
59 "
60 }
61
62 # Configuration.
63
64 # List of gnulib modules needed.
65 gnulib_modules=
66
67 # Any gnulib files needed that are not in modules.
68 gnulib_files=
69
70 # Translation Project URL, for the registry of all projects
71 # and for the translation-team master directory.
72 TP_URL='http://www.iro.umontreal.ca/translation/registry.cgi?domain='
73 TP_PO_URL='http://www.iro.umontreal.ca/translation/teams/PO/'
74
75 extract_package_name='
76   /^AC_INIT(/{
77      /.*,.*,.*,/{
78        s///
79        s/[][]//g
80        p
81        q
82      }
83      s/AC_INIT(\[*//
84      s/]*,.*//
85      s/^GNU //
86      y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
87      s/[^A-Za-z0-9_]/-/g
88      p
89   }
90 '
91 package=`sed -n "$extract_package_name" configure.ac` || exit
92
93 build_aux=build-aux
94 # Extra files from gnulib, which override files from other sources.
95 gnulib_extra_files="
96         $build_aux/install-sh
97         $build_aux/missing
98         $build_aux/mdate-sh
99         $build_aux/texinfo.tex
100         $build_aux/depcomp
101         $build_aux/config.guess
102         $build_aux/config.sub
103         doc/INSTALL
104 "
105
106 # Other locale categories that need message catalogs.
107 EXTRA_LOCALE_CATEGORIES=
108
109 # Additional xgettext options to use.  Use "\\\newline" to break lines.
110 XGETTEXT_OPTIONS='\\\
111  --flag=_:1:pass-c-format\\\
112  --flag=N_:1:pass-c-format\\\
113  --flag=error:3:c-format --flag=error_at_line:5:c-format\\\
114 '
115
116 # Files we don't want to import.
117 excluded_files=
118
119 # File that should exist in the top directory of a checked out hierarchy,
120 # but not in a distribution tarball.
121 checkout_only_file=README-hacking
122
123 # Whether to use copies instead of symlinks.
124 copy=false
125
126 # Override the default configuration, if necessary.
127 test -r bootstrap.conf && . ./bootstrap.conf
128
129 # Translate configuration into internal form.
130
131 # Parse options.
132
133 for option
134 do
135   case $option in
136   --help)
137     usage
138     exit;;
139   --gnulib-srcdir=*)
140     GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
141   --cvs-user=*)
142     CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
143   --skip-po)
144     SKIP_PO=t;;
145   --force)
146     checkout_only_file=;;
147   --copy)
148     copy=true;;
149   *)
150     echo >&2 "$0: $option: unknown option"
151     exit 1;;
152   esac
153 done
154
155 if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
156   echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
157   exit 1
158 fi
159
160 # If $STR is not already on a line by itself in $FILE, insert it,
161 # sorting the new contents of the file and replacing $FILE with the result.
162 insert_sorted_if_absent() {
163   file=$1
164   str=$2
165   echo "$str" | sort -u - $file | cmp -s - $file \
166     || echo "$str" | sort -u - $file -o $file \
167     || exit 1
168 }
169
170 # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
171 grep '^[         ]*AC_CONFIG_AUX_DIR('$build_aux')' configure.ac >/dev/null ||
172   {
173     echo "$0: expected line not found in configure.ac. Add the following:" >&2
174     echo "  AC_CONFIG_AUX_DIR($build_aux)" >&2.
175   }
176
177 # If $build_aux doesn't exist, create it now, otherwise some bits
178 # below will malfunction.  If creating it, also mark it as ignored.
179 if test ! -d $build_aux; then
180   mkdir $build_aux
181   for ig in .cvsignore .gitignore; do
182     test -f $ig && insert_sorted_if_absent $ig $build_aux
183   done
184 fi
185
186 echo "$0: Bootstrapping from checked-out $package sources..."
187
188 cleanup_gnulib() {
189   status=$?
190   rm -fr gnulib
191   exit $status
192 }
193
194 # Get gnulib files.
195
196 case ${GNULIB_SRCDIR--} in
197 -)
198   if [ ! -d gnulib ]; then
199     echo "$0: getting gnulib files..."
200
201     case ${CVS_AUTH-pserver} in
202     pserver)
203       CVS_PREFIX=':pserver:anonymous@';;
204     ssh)
205       CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
206     *)
207       echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
208       exit 1;;
209     esac
210
211     case $CVS_RSH in
212     '') CVS_RSH=ssh; export CVS_RSH;;
213     esac
214
215     trap cleanup_gnulib 1 2 13 15
216
217     cvs -z3 -q -d ${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/gnulib co gnulib ||
218       cleanup_gnulib
219
220     trap - 1 2 13 15
221   fi
222   GNULIB_SRCDIR=gnulib
223 esac
224
225 gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
226 <$gnulib_tool || exit
227
228 # Get translations.
229
230 get_translations() {
231   subdir=$1
232   domain=$2
233
234   case $WGET_COMMAND in
235   '')
236     echo "$0: wget not available; skipping translations";;
237   ?*)
238     echo "$0: getting translations into $subdir for $domain..." &&
239
240     (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'`) &&
241     $WGET_COMMAND -O "$subdir/$domain.html" "$TP_URL$domain" &&
242
243     sed -n 's|.*"http://[^"]*/translation/teams/PO/\([^/"]*\)/'"$domain"'-\([^/"]*\)\.[^."]*\.po".*|\1.\2|p' <"$subdir/$domain.html" |
244     sort -k 1,1 -k 2,2n -k2,2 -k3,3n -k3,3 -k4,4n -k4,4 -k5,5n -k5.5 |
245     awk -F. '
246       { if (lang && $1 != lang) print lang, ver }
247       { lang = $1; ver = substr($0, index($0, ".") + 1) }
248       END { if (lang) print lang, ver }
249     ' | awk -v domain="$domain" -v subdir="$subdir" '
250       {
251         lang = $1
252         ver = $2
253         urlfmt = ""
254         printf "{ $WGET_COMMAND -O %s/%s.po '\'"$TP_PO_URL"'/%s/%s-%s.%s.po'\'' &&\n", subdir, lang, lang, domain, ver, lang
255         printf "  msgfmt -c -o /dev/null %s/%s.po || {\n", subdir, lang
256         printf "    echo >&2 '\'"$0"': omitting translation for %s'\''\n", lang
257         printf "    rm -f %s/%s.po; }; } &&\n", subdir, lang
258       }
259       END { print ":" }
260     ' | WGET_COMMAND="$WGET_COMMAND" sh;;
261   esac &&
262   ls "$subdir"/*.po 2>/dev/null |
263     sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS" &&
264   rm -f "$subdir/$domain.html"
265 }
266
267 case $SKIP_PO in
268 '')
269   case `wget --help` in
270   *'--no-cache'*)
271     WGET_COMMAND='wget -nv --no-cache';;
272   *'--cache=on/off'*)
273     WGET_COMMAND='wget -nv --cache=off';;
274   *'--non-verbose'*)
275     WGET_COMMAND='wget -nv';;
276   *)
277     WGET_COMMAND='';;
278   esac
279
280   if test -d po; then
281     get_translations po $package || exit
282   fi
283
284   if test -d runtime-po; then
285     get_translations runtime-po $package-runtime || exit
286   fi;;
287 esac
288
289 symlink_to_gnulib()
290 {
291   src=$GNULIB_SRCDIR/$1
292   dst=${2-$1}
293
294   test -f "$src" && {
295     if $copy; then
296       {
297         test ! -h "$dst" || {
298           echo "$0: rm -f $dst" &&
299           rm -f "$dst"
300         }
301       } &&
302       test -f "$dst" &&
303       cmp -s "$src" "$dst" || {
304         echo "$0: cp -fp $src $dst" &&
305         cp -fp "$src" "$dst"
306       }
307     else
308       test -h "$dst" &&
309       src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
310       dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
311       test "$src_i" = "$dst_i" || {
312         dot_dots=
313         case $src in
314         /*) ;;
315         *)
316           case /$dst/ in
317           *//* | */../* | */./* | /*/*/*/*/*/)
318              echo >&2 "$0: invalid symlink calculation: $src -> $dst"
319              exit 1;;
320           /*/*/*/*/)    dot_dots=../../../;;
321           /*/*/*/)      dot_dots=../../;;
322           /*/*/)        dot_dots=../;;
323           esac;;
324         esac
325
326         echo "$0: ln -fs $dot_dots$src $dst" &&
327         ln -fs "$dot_dots$src" "$dst"
328       }
329     fi
330   }
331 }
332
333 cp_mark_as_generated()
334 {
335   cp_src=$1
336   cp_dst=$2
337
338   if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
339     symlink_to_gnulib "$cp_dst"
340   else
341     case $cp_dst in
342       *.[ch])             c1='/* '; c2=' */';;
343       *.texi)             c1='@c '; c2=     ;;
344       *.m4|*/Make*|Make*) c1='# ' ; c2=     ;;
345       *)                  c1=     ; c2=     ;;
346     esac
347
348     if test -z "$c1"; then
349       cmp -s "$cp_src" "$cp_dst" || {
350         echo "$0: cp -f $cp_src $cp_dst" &&
351         rm -f "$cp_dst" &&
352         sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst"
353       }
354     else
355       # Copy the file first to get proper permissions if it
356       # doesn't already exist.  Then overwrite the copy.
357       cp "$cp_src" "$cp_dst-t" &&
358       (
359         echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
360         echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
361         sed "s!$bt_regex/!!g" "$cp_src"
362       ) > $cp_dst-t &&
363       if cmp -s "$cp_dst-t" "$cp_dst"; then
364         rm -f "$cp_dst-t"
365       else
366         echo "$0: cp $cp_src $cp_dst # with edits" &&
367         mv -f "$cp_dst-t" "$cp_dst"
368       fi
369     fi
370   fi
371 }
372
373 version_controlled_file() {
374   dir=$1
375   file=$2
376   found=no
377   if test -d CVS; then
378     grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
379              grep '^/[^/]*/[0-9]' > /dev/null && found=yes
380   elif test -d .git; then
381     git-rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
382   else
383     echo "$0: no version control for $dir/$file?" >&2
384   fi
385   test $found = yes
386 }
387
388 slurp() {
389   for dir in . `(cd $1 && find * -type d -print)`; do
390     copied=
391     sep=
392     for file in `ls $1/$dir`; do
393       test -d $1/$dir/$file && continue
394       for excluded_file in $excluded_files; do
395         test "$dir/$file" = "$excluded_file" && continue 2
396       done
397       if test $file = Makefile.am; then
398         copied=$copied${sep}gnulib.mk; sep=$nl
399         remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
400         sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/gnulib.mk || {
401           echo "$0: Copying $1/$dir/$file to $dir/gnulib.mk ..." &&
402           rm -f $dir/gnulib.mk &&
403           sed "$remove_intl" $1/$dir/$file >$dir/gnulib.mk
404         }
405       elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
406            version_controlled_file $dir $file; then
407         echo "$0: $dir/$file overrides $1/$dir/$file"
408       else
409         copied=$copied$sep$file; sep=$nl
410         if test $file = gettext.m4; then
411           echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
412           rm -f $dir/$file
413           sed '
414             /^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
415               AC_DEFUN([AM_INTL_SUBDIR], [
416             /^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
417               AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
418             $a\
419               AC_DEFUN([gl_LOCK_EARLY], [])
420           ' $1/$dir/$file >$dir/$file
421         else
422           cp_mark_as_generated $1/$dir/$file $dir/$file
423         fi
424       fi || exit
425     done
426
427     for dot_ig in .cvsignore .gitignore; do
428       ig=$dir/$dot_ig
429       if test -n "$copied" && test -f $ig; then
430         insert_sorted_if_absent $ig "$copied"
431         # If an ignored file name ends with _.h, then also add
432         # the name with just ".h".  Many gnulib headers are generated,
433         # e.g., stdint_.h -> stdint.h, dirent_.h ->..., etc.
434         f=`echo "$copied"|sed 's/_\.h$/.h/'`
435         insert_sorted_if_absent $ig "$f"
436       fi
437     done
438   done
439 }
440
441
442 # Create boot temporary directories to import from gnulib and gettext.
443 rm -fr $bt $bt2 &&
444 mkdir $bt $bt2 || exit
445
446 # Import from gnulib.
447
448 gnulib_tool_options="\
449  --import\
450  --no-changelog\
451  --aux-dir $bt/$build_aux\
452  --doc-base $bt/doc\
453  --lib lib$package\
454  --m4-base $bt/m4/\
455  --source-base $bt/lib/\
456  --tests-base $bt/tests\
457  --local-dir gl\
458 "
459 echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
460 $gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
461 slurp $bt || exit
462
463 for file in $gnulib_files; do
464   symlink_to_gnulib $file || exit
465 done
466
467
468 # Import from gettext.
469
470 echo "$0: (cd $bt2; autopoint) ..."
471 cp configure.ac $bt2 &&
472 (cd $bt2 && autopoint && rm configure.ac) &&
473 slurp $bt2 $bt || exit
474
475 rm -fr $bt $bt2 || exit
476
477
478 # Reconfigure, getting other files.
479
480 for command in \
481   libtool \
482   'aclocal --force -I m4' \
483   'autoconf --force' \
484   'autoheader --force' \
485   'automake --add-missing --copy --force-missing';
486 do
487   if test "$command" = libtool; then
488     grep '^[     ]*AM_PROG_LIBTOOL\>' configure.ac >/dev/null ||
489       continue
490     command='libtoolize -c -f'
491   fi
492   echo "$0: $command ..."
493   $command || exit
494 done
495
496
497 # Get some extra files from gnulib, overriding existing files.
498
499 for file in $gnulib_extra_files; do
500   case $file in
501   */INSTALL) dst=INSTALL;;
502   *) dst=$file;;
503   esac
504   symlink_to_gnulib $file $dst || exit
505 done
506
507
508 # Create gettext configuration.
509 echo "$0: Creating po/Makevars from po/Makevars.template ..."
510 rm -f po/Makevars
511 sed '
512   /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
513   /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
514   /^XGETTEXT_OPTIONS *=/{
515     s/$/ \\/
516     a\
517         '"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
518   }
519 ' po/Makevars.template >po/Makevars
520
521 if test -d runtime-po; then
522   # Similarly for runtime-po/Makevars, but not quite the same.
523   rm -f runtime-po/Makevars
524   sed '
525     /^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
526     /^subdir *=.*/s/=.*/= runtime-po/
527     /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
528     /^XGETTEXT_OPTIONS *=/{
529       s/$/ \\/
530       a\
531           '"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
532     }
533   ' <po/Makevars.template >runtime-po/Makevars
534
535   # Copy identical files from po to runtime-po.
536   (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
537 fi
538
539 echo "$0: done.  Now you can run './configure'."