93fe859ef0a67755f78870db08d019a04d17e894
[pspp] / build-aux / bootstrap
1 #! /bin/sh
2
3 # Bootstrap this package from checked-out sources.
4
5 # Copyright (C) 2003-2008 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 3 of the License, or
10 # (at your option) 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, see <http://www.gnu.org/licenses/>.
19
20 # Written by Paul Eggert.
21
22 nl='
23 '
24
25 # Ensure file names are sorted consistently across platforms.
26 LC_ALL=C
27 export LC_ALL
28
29 local_gl_dir=gl
30
31 # Temporary directory names.
32 bt='._bootmp'
33 bt_regex=`echo "$bt"| sed 's/\./[.]/g'`
34 bt2=${bt}2
35
36 usage() {
37   echo >&2 "\
38 Usage: $0 [OPTION]...
39 Bootstrap this package from the checked-out sources.
40
41 Options:
42  --gnulib-srcdir=DIRNAME  Specify the local directory where gnulib
43                           sources reside.  Use this if you already
44                           have gnulib sources on your machine, and
45                           do not want to waste your bandwidth downloading
46                           them again.
47  --copy                   Copy files instead of creating symbolic links.
48  --force                  Attempt to bootstrap even if the sources seem
49                           not to have been checked out.
50  --skip-po                Do not download po files.
51
52 If the file bootstrap.conf exists in the current working directory, its
53 contents are read as shell variables to configure the bootstrap.
54
55 Running without arguments will suffice in most cases.
56 "
57 }
58
59 # Configuration.
60
61 # Name of the Makefile.am
62 gnulib_mk=gnulib.mk
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 # The command to download all .po files for a specified domain into
71 # a specified directory.  Fill in the first %s is the domain name, and
72 # the second with the destination directory.  Use rsync's -L and -r
73 # options because the latest/%s directory and the .po files within are
74 # all symlinks.
75 po_download_command_format=\
76 "rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
77
78 extract_package_name='
79   /^AC_INIT(/{
80      /.*,.*,.*, */{
81        s///
82        s/[][]//g
83        s/)$//
84        p
85        q
86      }
87      s/AC_INIT(\[*//
88      s/]*,.*//
89      s/^GNU //
90      y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
91      s/[^A-Za-z0-9_]/-/g
92      p
93   }
94 '
95 package=`sed -n "$extract_package_name" configure.ac` || exit
96 gnulib_name=lib$package
97
98 build_aux=build-aux
99 source_base=lib
100 m4_base=m4
101 doc_base=doc
102 tests_base=tests
103
104 # Extra files from gnulib, which override files from other sources.
105 gnulib_extra_files="
106         $build_aux/install-sh
107         $build_aux/missing
108         $build_aux/mdate-sh
109         $build_aux/texinfo.tex
110         $build_aux/depcomp
111         $build_aux/config.guess
112         $build_aux/config.sub
113         doc/INSTALL
114 "
115
116 # Additional gnulib-tool options to use.  Use "\newline" to break lines.
117 gnulib_tool_option_extras=
118
119 # Other locale categories that need message catalogs.
120 EXTRA_LOCALE_CATEGORIES=
121
122 # Additional xgettext options to use.  Use "\\\newline" to break lines.
123 XGETTEXT_OPTIONS='\\\
124  --flag=_:1:pass-c-format\\\
125  --flag=N_:1:pass-c-format\\\
126  --flag=error:3:c-format --flag=error_at_line:5:c-format\\\
127 '
128
129 # Package bug report address for gettext files
130 MSGID_BUGS_ADDRESS=bug-$package@gnu.org
131
132 # Files we don't want to import.
133 excluded_files=
134
135 # File that should exist in the top directory of a checked out hierarchy,
136 # but not in a distribution tarball.
137 checkout_only_file=README-hacking
138
139 # Whether to use copies instead of symlinks.
140 copy=false
141
142 # Set this to '.cvsignore .gitignore' in bootstrap.conf if you want
143 # those files to be generated in directories like lib/, m4/, and po/.
144 # Or set it to 'auto' to make this script select which to use based
145 # on which version control system (if any) is used in the source directory.
146 vc_ignore=auto
147
148 # Override the default configuration, if necessary.
149 test -r bootstrap.conf && . ./bootstrap.conf
150
151 if test "$vc_ignore" = auto; then
152   vc_ignore=
153   test -d .git && vc_ignore=.gitignore
154   test -d CVS && vc_ignore="$vc_ignore .cvsignore"
155 fi
156
157 # Translate configuration into internal form.
158
159 # Parse options.
160
161 for option
162 do
163   case $option in
164   --help)
165     usage
166     exit;;
167   --gnulib-srcdir=*)
168     GNULIB_SRCDIR=`expr "X$option" : 'X--gnulib-srcdir=\(.*\)'`;;
169   --skip-po)
170     SKIP_PO=t;;
171   --force)
172     checkout_only_file=;;
173   --copy)
174     copy=true;;
175   *)
176     echo >&2 "$0: $option: unknown option"
177     exit 1;;
178   esac
179 done
180
181 if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
182   echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
183   exit 1
184 fi
185
186 # If $STR is not already on a line by itself in $FILE, insert it,
187 # sorting the new contents of the file and replacing $FILE with the result.
188 insert_sorted_if_absent() {
189   file=$1
190   str=$2
191   test -f $file || touch $file
192   echo "$str" | sort -u - $file | cmp -s - $file \
193     || echo "$str" | sort -u - $file -o $file \
194     || exit 1
195 }
196
197 # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
198 found_aux_dir=no
199 grep '^[         ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \
200     >/dev/null && found_aux_dir=yes
201 grep '^[         ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \
202     >/dev/null && found_aux_dir=yes
203 if test $found_aux_dir = no; then
204   echo "$0: expected line not found in configure.ac. Add the following:" >&2
205   echo "  AC_CONFIG_AUX_DIR([$build_aux])" >&2
206   exit 1
207 fi
208
209 # If $build_aux doesn't exist, create it now, otherwise some bits
210 # below will malfunction.  If creating it, also mark it as ignored.
211 if test ! -d $build_aux; then
212   mkdir $build_aux
213   for dot_ig in x $vc_ignore; do
214     test $dot_ig = x && continue
215     insert_sorted_if_absent $dot_ig $build_aux
216   done
217 fi
218
219 echo "$0: Bootstrapping from checked-out $package sources..."
220
221 # See if we can use gnulib's git-merge-changelog merge driver.
222 if test -d .git && (git --version) >/dev/null 2>/dev/null ; then
223   if git config merge.merge-changelog.driver >/dev/null ; then
224     :
225   elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then
226     echo "initializing git-merge-changelog driver"
227     git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'
228     git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B'
229   else
230     echo "consider installing git-merge-changelog from gnulib"
231   fi
232 fi
233
234
235 cleanup_gnulib() {
236   status=$?
237   rm -fr gnulib
238   exit $status
239 }
240
241 git_modules_config () {
242   GIT_CONFIG_LOCAL=.gitmodules git config "$@"
243 }
244
245 # Get gnulib files.
246
247 case ${GNULIB_SRCDIR--} in
248 -)
249   if git_modules_config submodule.gnulib.url >/dev/null; then
250     echo "$0: getting gnulib files..."
251     git submodule init || exit $?
252     git submodule update || exit $?
253
254   elif [ ! -d gnulib ]; then
255     echo "$0: getting gnulib files..."
256
257     trap cleanup_gnulib 1 2 13 15
258
259     git clone --depth 2 git://git.sv.gnu.org/gnulib ||
260       cleanup_gnulib
261
262     trap - 1 2 13 15
263   fi
264   GNULIB_SRCDIR=gnulib
265   ;;
266 *)
267   # Redirect the gnulib submodule to the directory on the command line
268   # if possible.
269   if test -d "$GNULIB_SRCDIR"/.git && \
270         git_modules_config submodule.gnulib.url >/dev/null; then
271     git submodule init
272     GNULIB_SRCDIR=`cd $GNULIB_SRCDIR && pwd`
273     git config --replace-all submodule.gnulib.url $GNULIB_SRCDIR
274     echo "$0: getting gnulib files..."
275     git submodule update || exit $?
276     GNULIB_SRCDIR=gnulib
277   fi
278   ;;
279 esac
280
281 gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
282 <$gnulib_tool || exit
283
284 # Get translations.
285
286 download_po_files() {
287   subdir=$1
288   domain=$2
289   echo "$0: getting translations into $subdir for $domain..."
290   cmd=`printf "$po_download_command_format" "$domain" "$subdir"`
291   eval "$cmd"
292 }
293
294 # Download .po files to $po_dir/.reference and copy only the new
295 # or modified ones into $po_dir.  Also update $po_dir/LINGUAS.
296 update_po_files() {
297   # Directory containing primary .po files.
298   # Overwrite them only when we're sure a .po file is new.
299   po_dir=$1
300   domain=$2
301
302   # Download *.po files into this dir.
303   # Usually contains *.s1 checksum files.
304   ref_po_dir="$po_dir/.reference"
305
306   test -d $ref_po_dir || mkdir $ref_po_dir || return
307   download_po_files $ref_po_dir $domain \
308     && ls "$ref_po_dir"/*.po 2>/dev/null |
309       sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
310
311   langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
312   test "$langs" = '*' && langs=x
313   for po in $langs; do
314     case $po in x) continue;; esac
315     new_po="$ref_po_dir/$po.po"
316     cksum_file="$ref_po_dir/$po.s1"
317     if ! test -f "$cksum_file" ||
318         ! test -f "$po_dir/$po.po" ||
319         ! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
320       echo "updated $po_dir/$po.po..."
321       cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
322     fi
323   done
324 }
325
326 case $SKIP_PO in
327 '')
328   if test -d po; then
329     update_po_files po $package || exit
330   fi
331
332   if test -d runtime-po; then
333     update_po_files runtime-po $package-runtime || exit
334   fi;;
335 esac
336
337 symlink_to_dir()
338 {
339   src=$1/$2
340   dst=${3-$2}
341
342   test -f "$src" && {
343
344     # If the destination directory doesn't exist, create it.
345     # This is required at least for "lib/uniwidth/cjk.h".
346     dst_dir=`dirname "$dst"`
347     if ! test -d "$dst_dir"; then
348       mkdir -p "$dst_dir"
349
350       # If we've just created a directory like lib/uniwidth,
351       # tell version control system(s) it's ignorable.
352       # FIXME: for now, this does only one level
353       parent=`dirname "$dst_dir"`
354       for dot_ig in x $vc_ignore; do
355         test $dot_ig = x && continue
356         ig=$parent/$dot_ig
357         insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'`
358       done
359     fi
360
361     if $copy; then
362       {
363         test ! -h "$dst" || {
364           echo "$0: rm -f $dst" &&
365           rm -f "$dst"
366         }
367       } &&
368       test -f "$dst" &&
369       cmp -s "$src" "$dst" || {
370         echo "$0: cp -fp $src $dst" &&
371         cp -fp "$src" "$dst"
372       }
373     else
374       test -h "$dst" &&
375       src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
376       dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
377       test "$src_i" = "$dst_i" || {
378         dot_dots=
379         case $src in
380         /*) ;;
381         *)
382           case /$dst/ in
383           *//* | */../* | */./* | /*/*/*/*/*/)
384              echo >&2 "$0: invalid symlink calculation: $src -> $dst"
385              exit 1;;
386           /*/*/*/*/)    dot_dots=../../../;;
387           /*/*/*/)      dot_dots=../../;;
388           /*/*/)        dot_dots=../;;
389           esac;;
390         esac
391
392         echo "$0: ln -fs $dot_dots$src $dst" &&
393         ln -fs "$dot_dots$src" "$dst"
394       }
395     fi
396   }
397 }
398
399 cp_mark_as_generated()
400 {
401   cp_src=$1
402   cp_dst=$2
403
404   if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
405     symlink_to_dir "$GNULIB_SRCDIR" "$cp_dst"
406   elif cmp -s "$cp_src" "$local_gl_dir/$cp_dst"; then
407     symlink_to_dir $local_gl_dir "$cp_dst"
408   else
409     case $cp_dst in
410       *.[ch])             c1='/* '; c2=' */';;
411       *.texi)             c1='@c '; c2=     ;;
412       *.m4|*/Make*|Make*) c1='# ' ; c2=     ;;
413       *)                  c1=     ; c2=     ;;
414     esac
415
416     # If the destination directory doesn't exist, create it.
417     # This is required at least for "lib/uniwidth/cjk.h".
418     dst_dir=`dirname "$cp_dst"`
419     test -d "$dst_dir" || mkdir -p "$dst_dir"
420
421     if test -z "$c1"; then
422       cmp -s "$cp_src" "$cp_dst" || {
423         # Copy the file first to get proper permissions if it
424         # doesn't already exist.  Then overwrite the copy.
425         echo "$0: cp -f $cp_src $cp_dst" &&
426         rm -f "$cp_dst" &&
427         cp "$cp_src" "$cp_dst-t" &&
428         sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst-t" &&
429         mv -f "$cp_dst-t" "$cp_dst"
430       }
431     else
432       # Copy the file first to get proper permissions if it
433       # doesn't already exist.  Then overwrite the copy.
434       cp "$cp_src" "$cp_dst-t" &&
435       (
436         echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
437         echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
438         sed "s!$bt_regex/!!g" "$cp_src"
439       ) > $cp_dst-t &&
440       if cmp -s "$cp_dst-t" "$cp_dst"; then
441         rm -f "$cp_dst-t"
442       else
443         echo "$0: cp $cp_src $cp_dst # with edits" &&
444         mv -f "$cp_dst-t" "$cp_dst"
445       fi
446     fi
447   fi
448 }
449
450 version_controlled_file() {
451   dir=$1
452   file=$2
453   found=no
454   if test -d CVS; then
455     grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
456              grep '^/[^/]*/[0-9]' > /dev/null && found=yes
457   elif test -d .git; then
458     git rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
459   elif test -d .svn; then
460     svn log -r HEAD "$dir/$file" > /dev/null 2>&1 && found=yes
461   else
462     echo "$0: no version control for $dir/$file?" >&2
463   fi
464   test $found = yes
465 }
466
467 slurp() {
468   for dir in . `(cd $1 && find * -type d -print)`; do
469     copied=
470     sep=
471     for file in `ls -a $1/$dir`; do
472       case $file in
473       .|..) continue;;
474       .*) continue;; # FIXME: should all file names starting with "." be ignored?
475       esac
476       test -d $1/$dir/$file && continue
477       for excluded_file in $excluded_files; do
478         test "$dir/$file" = "$excluded_file" && continue 2
479       done
480       if test $file = Makefile.am; then
481         copied=$copied${sep}$gnulib_mk; sep=$nl
482         remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
483         sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/$gnulib_mk || {
484           echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
485           rm -f $dir/$gnulib_mk &&
486           sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk
487         }
488       elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
489            version_controlled_file $dir $file; then
490         echo "$0: $dir/$file overrides $1/$dir/$file"
491       else
492         copied=$copied$sep$file; sep=$nl
493         if test $file = gettext.m4; then
494           echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
495           rm -f $dir/$file
496           sed '
497             /^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
498               AC_DEFUN([AM_INTL_SUBDIR], [
499             /^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
500               AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
501             $a\
502               AC_DEFUN([gl_LOCK_EARLY], [])
503           ' $1/$dir/$file >$dir/$file
504         else
505           cp_mark_as_generated $1/$dir/$file $dir/$file
506         fi
507       fi || exit
508     done
509
510     for dot_ig in x $vc_ignore; do
511       test $dot_ig = x && continue
512       ig=$dir/$dot_ig
513       if test -n "$copied"; then
514         insert_sorted_if_absent $ig "$copied"
515         # If an ignored file name ends with .in.h, then also add
516         # the name with just ".h".  Many gnulib headers are generated,
517         # e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc.
518         # Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed
519         f=`echo "$copied"|sed 's/\.in\.h$/.h/;s/\.sin$/.sed/;s/\.y$/.c/;s/\.gperf$/.h/'`
520         insert_sorted_if_absent $ig "$f"
521
522         # For files like sys_stat.in.h and sys_time.in.h, record as
523         # ignorable the directory we might eventually create: sys/.
524         f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'`
525         insert_sorted_if_absent $ig "$f"
526       fi
527     done
528   done
529 }
530
531
532 # Create boot temporary directories to import from gnulib and gettext.
533 rm -fr $bt $bt2 &&
534 mkdir $bt $bt2 || exit
535
536 # Import from gnulib.
537
538 gnulib_tool_options="\
539  --import\
540  --no-changelog\
541  --aux-dir $bt/$build_aux\
542  --doc-base $bt/$doc_base\
543  --lib $gnulib_name\
544  --m4-base $bt/$m4_base/\
545  --source-base $bt/$source_base/\
546  --tests-base $bt/$tests_base\
547  --local-dir $local_gl_dir\
548  $gnulib_tool_option_extras\
549 "
550 echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
551 $gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
552 slurp $bt || exit
553
554 for file in $gnulib_files; do
555   symlink_to_dir "$GNULIB_SRCDIR" $file || exit
556 done
557
558
559 # Import from gettext.
560 with_gettext=yes
561 grep '^[         ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
562     with_gettext=no
563
564 if test $with_gettext = yes; then
565   echo "$0: (cd $bt2; autopoint) ..."
566   cp configure.ac $bt2 &&
567   (cd $bt2 && autopoint && rm configure.ac) &&
568   slurp $bt2 $bt || exit
569 fi
570 rm -fr $bt $bt2 || exit
571
572 # Remove any dangling symlink matching "*.m4" or "*.[ch]" in some
573 # gnulib-populated directories.  Such .m4 files would cause aclocal to fail.
574 # The following requires GNU find 4.2.3 or newer.  Considering the usual
575 # portability constraints of this script, that may seem a very demanding
576 # requirement, but it should be ok.  Ignore any failure, which is fine,
577 # since this is only a convenience to help developers avoid the relatively
578 # unusual case in which a symlinked-to .m4 file is git-removed from gnulib
579 # between successive runs of this script.
580 find "$m4_base" "$source_base" \
581   -depth \( -name '*.m4' -o -name '*.[ch]' \) \
582   -type l -xtype l -delete > /dev/null 2>&1
583
584 # Reconfigure, getting other files.
585
586 for command in \
587   libtool \
588   'aclocal --force -I m4' \
589   'autoconf --force' \
590   'autoheader --force' \
591   'automake --add-missing --copy --force-missing';
592 do
593   if test "$command" = libtool; then
594     grep '^[     ]*AM_PROG_LIBTOOL\>' configure.ac >/dev/null ||
595       continue
596     command='libtoolize -c -f'
597   fi
598   echo "$0: $command ..."
599   $command || exit
600 done
601
602
603 # Get some extra files from gnulib, overriding existing files.
604 for file in $gnulib_extra_files; do
605   case $file in
606   */INSTALL) dst=INSTALL;;
607   build-aux/*) dst=$build_aux/`expr "$file" : 'build-aux/\(.*\)'`;;
608   *) dst=$file;;
609   esac
610   symlink_to_dir "$GNULIB_SRCDIR" $file $dst || exit
611 done
612
613 if test $with_gettext = yes; then
614   # Create gettext configuration.
615   echo "$0: Creating po/Makevars from po/Makevars.template ..."
616   rm -f po/Makevars
617   sed '
618     /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
619     /^MSGID_BUGS_ADDRESS *=/s/=.*/= '"$MSGID_BUGS_ADDRESS"'/
620     /^XGETTEXT_OPTIONS *=/{
621       s/$/ \\/
622       a\
623           '"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
624     }
625   ' po/Makevars.template >po/Makevars
626
627   if test -d runtime-po; then
628     # Similarly for runtime-po/Makevars, but not quite the same.
629     rm -f runtime-po/Makevars
630     sed '
631       /^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
632       /^subdir *=.*/s/=.*/= runtime-po/
633       /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
634       /^XGETTEXT_OPTIONS *=/{
635         s/$/ \\/
636         a\
637             '"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
638       }
639     ' <po/Makevars.template >runtime-po/Makevars
640
641     # Copy identical files from po to runtime-po.
642     (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
643   fi
644 fi
645
646 echo "$0: done.  Now you can run './configure'."