1# ===========================================================================
2#   https://www.gnu.org/software/autoconf-archive/ax_subdirs_configure.html
3# ===========================================================================
4#
5# SYNOPSIS
6#
7#   AX_SUBDIRS_CONFIGURE( [subdirs], [mandatory arguments], [possibly merged arguments], [replacement arguments], [forbidden arguments])
8#
9# DESCRIPTION
10#
11#   AX_SUBDIRS_CONFIGURE attempts to be the equivalent of AC_CONFIG_SUBDIRS
12#   with customizable options for configure scripts.
13#
14#   Run the configure script for each directory from the comma-separated m4
15#   list 'subdirs'. This macro can be used multiple times. All arguments of
16#   this macro must be comma-separated lists.
17#
18#   All command line arguments from the parent configure script will be
19#   given to the subdirectory configure script after the following
20#   modifications (in that order):
21#
22#   1. The arguments from the 'mandatory arguments' list shall always be
23#   appended to the argument list.
24#
25#   2. The arguments from the 'possibly merged arguments' list shall be
26#   added if not present in the arguments of the parent configure script or
27#   merged with the existing argument otherwise.
28#
29#   3. The arguments from the 'replacement arguments' list shall be added if
30#   not present in the arguments of the parent configure script or replace
31#   the existing argument otherwise.
32#
33#   4. The arguments from the 'forbidden arguments' list shall always be
34#   removed from the argument list.
35#
36#   The lists 'mandatory arguments' and 'forbidden arguments' can hold any
37#   kind of argument. The 'possibly merged arguments' and 'replacement
38#   arguments' expect their arguments to be of the form --option-name=value.
39#
40#   This macro aims to remain as close as possible to the AC_CONFIG_SUBDIRS
41#   macro. It corrects the paths for '--cache-file' and '--srcdir' and adds
42#   '--disable-option-checking' and '--silent' if necessary.
43#
44#   This macro also sets the output variable subdirs_extra to the list of
45#   directories recorded with AX_SUBDIRS_CONFIGURE. This variable can be
46#   used in Makefile rules or substituted in configured files.
47#
48#   This macro shall do nothing more than managing the arguments of the
49#   configure script. Just like when using AC_CONFIG_SUBDIRS, it is up to
50#   the user to check any requirements or define and substitute any required
51#   variable for the remainder of the project.
52#
53#   Configure scripts recorded with AX_SUBDIRS_CONFIGURE may be executed
54#   before configure scripts recorded with AC_CONFIG_SUBDIRS.
55#
56#   Without additional arguments, the behaviour of AX_SUBDIRS_CONFIGURE
57#   should be identical to the behaviour of AC_CONFIG_SUBDIRS, apart from
58#   the contents of the variables subdirs and subdirs_extra (except that
59#   AX_SUBDIRS_CONFIGURE expects a comma-separated m4 list):
60#
61#     AC_CONFIG_SUBDIRS([something])
62#     AX_SUBDIRS_CONFIGURE([something])
63#
64#   This macro may be called multiple times.
65#
66#   Usage example:
67#
68#   Let us assume our project has 4 dependencies, namely A, B, C and D. Here
69#   are some characteristics of our project and its dependencies:
70#
71#   - A does not require any special option.
72#
73#   - we want to build B with an optional feature which can be enabled with
74#   its configure script's option '--enable-special-feature'.
75#
76#   - B's configure script is strange and has an option '--with-B=build'.
77#   After close inspection of its documentation, we don't want B to receive
78#   this option.
79#
80#   - C and D both need B.
81#
82#   - Just like our project, C and D can build B themselves with the option
83#   '--with-B=build'.
84#
85#   - We want C and D to use the B we build instead of building it
86#   themselves.
87#
88#   Our top-level configure script will be called as follows:
89#
90#     $ <path/to/configure> --with-A=build --with-B=build --with-C=build \
91#       --with-D=build --some-option
92#
93#   Thus we have to make sure that:
94#
95#   - neither B, C or D receive the option '--with-B=build'
96#
97#   - C and D know where to find the headers and libraries of B.
98#
99#   Under those conditions, we can use the AC_CONFIG_SUBDIRS macro for A,
100#   but need to use AX_SUBDIRS_CONFIGURE for B, C and D:
101#
102#   - B must receive '--enable-special-feature' but cannot receive
103#   '--with-B=build'
104#
105#   - C and D cannot receive '--with-B=build' (or else it would be built
106#   thrice) and need to be told where to find B (since we are building it,
107#   it would probably not be available in standard paths).
108#
109#   Here is a configure.ac snippet that solves our problem:
110#
111#     AC_CONFIG_SUBDIRS([dependencies/A])
112#     AX_SUBDIRS_CONFIGURE(
113#         [dependencies/B], [--enable-special-feature], [], [],
114#         [--with-B=build])
115#     AX_SUBDIRS_CONFIGURE(
116#         [[dependencies/C],[dependencies/D]],
117#         [],
118#         [[CPPFLAGS=-I${ac_top_srcdir}/dependencies/B -I${ac_top_builddir}/dependencies/B],
119#          [LDFLAGS=-L${ac_abs_top_builddir}/dependencies/B/.libs]],
120#         [--with-B=system],
121#         [])
122#
123#   If using automake, the following can be added to the Makefile.am (we use
124#   both $(subdirs) and $(subdirs_extra) since our example above used both
125#   AC_CONFIG_SUBDIRS and AX_SUBDIRS_CONFIGURE):
126#
127#     SUBDIRS = $(subdirs) $(subdirs_extra)
128#
129# LICENSE
130#
131#   Copyright (c) 2017 Harenome Ranaivoarivony-Razanajato <ranaivoarivony-razanajato@hareno.me>
132#
133#   This program is free software; you can redistribute it and/or modify it
134#   under the terms of the GNU General Public License as published by the
135#   Free Software Foundation; either version 3 of the License, or (at your
136#   option) any later version.
137#
138#   This program is distributed in the hope that it will be useful, but
139#   WITHOUT ANY WARRANTY; without even the implied warranty of
140#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
141#   Public License for more details.
142#
143#   Under Section 7 of GPL version 3, you are granted additional permissions
144#   described in the Autoconf Configure Script Exception, version 3.0, as
145#   published by the Free Software Foundation.
146#
147#   You should have received a copy of the GNU General Public License along
148#   with this program. If not, see <https://www.gnu.org/licenses/>.
149
150#serial 5
151
152AC_DEFUN([AX_SUBDIRS_CONFIGURE],
153[
154  dnl Calls to AC_CONFIG_SUBDIRS perform preliminary steps and build a list
155  dnl '$subdirs' which is used later by _AC_OUTPUT_SUBDIRS (used by AC_OUTPUT)
156  dnl to actually run the configure scripts.
157  dnl This macro performs similar preliminary steps but uses
158  dnl AC_CONFIG_COMMANDS_PRE to delay the final tasks instead of building an
159  dnl intermediary list and relying on another macro.
160  dnl
161  dnl Since each configure script can get different options, a special variable
162  dnl named 'ax_sub_configure_args_<subdir>' is constructed for each
163  dnl subdirectory.
164
165  # Various preliminary checks.
166  AC_REQUIRE([AC_DISABLE_OPTION_CHECKING])
167  AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])
168  AS_LITERAL_IF([$1], [],
169      [AC_DIAGNOSE([syntax], [$0: you should use literals])])
170
171  m4_foreach(subdir_path, [$1],
172  [
173    ax_dir="subdir_path"
174
175    dnl Build the argument list in a similar fashion to AC_CONFIG_SUBDIRS.
176    dnl A few arguments found in the final call to the configure script are not
177    dnl added here because they rely on variables that may not yet be available
178    dnl (see below the part that is similar to _AC_OUTPUT_SUBDIRS).
179    # Do not complain, so a configure script can configure whichever parts of a
180    # large source tree are present.
181    if test -d "$srcdir/$ax_dir"; then
182      _AC_SRCDIRS(["$ax_dir"])
183      # Remove --cache-file, --srcdir, and --disable-option-checking arguments
184      # so they do not pile up.
185      ax_args=
186      ax_prev=
187      eval "set x $ac_configure_args"
188      shift
189      for ax_arg; do
190        if test -n "$ax_prev"; then
191          ax_prev=
192          continue
193        fi
194        case $ax_arg in
195          -cache-file | --cache-file | --cache-fil | --cache-fi | --cache-f \
196          | --cache- | --cache | --cach | --cac | --ca | --c)
197            ax_prev=cache_file ;;
198          -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
199          | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
200          | --c=*)
201            ;;
202          --config-cache | -C)
203            ;;
204          -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
205            ax_prev=srcdir ;;
206          -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
207            ;;
208          -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
209            ax_prev=prefix ;;
210          -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* \
211          | --p=*)
212            ;;
213          --disable-option-checking)
214            ;;
215          *) case $ax_arg in
216              *\'*) ax_arg=$(AS_ECHO(["$ax_arg"]) | sed "s/'/'\\\\\\\\''/g");;
217            esac
218            AS_VAR_APPEND([ax_args], [" '$ax_arg'"]) ;;
219        esac
220      done
221      # Always prepend --disable-option-checking to silence warnings, since
222      # different subdirs can have different --enable and --with options.
223      ax_args="--disable-option-checking $ax_args"
224      # Options that must be added as they are provided.
225      m4_ifnblank([$2], [m4_foreach(opt, [$2], [AS_VAR_APPEND(ax_args, " 'opt'")
226      ])])
227      # New options that may need to be merged with existing options.
228      m4_ifnblank([$3], [m4_foreach(opt, [$3],
229          [ax_candidate="opt"
230           ax_candidate_flag="${ax_candidate%%=*}"
231           ax_candidate_content="${ax_candidate#*=}"
232           if test "x$ax_candidate" != "x" -a "x$ax_candidate_flag" != "x"; then
233             if echo "$ax_args" | grep -- "${ax_candidate_flag}=" >/dev/null 2>&1; then
234               [ax_args=$(echo $ax_args | sed "s,\(${ax_candidate_flag}=[^']*\),\1 ${ax_candidate_content},")]
235             else
236               AS_VAR_APPEND(ax_args, " 'opt'")
237             fi
238           fi
239      ])])
240      # New options that must replace existing options.
241      m4_ifnblank([$4], [m4_foreach(opt, [$4],
242          [ax_candidate="opt"
243           ax_candidate_flag="${ax_candidate%%=*}"
244           ax_candidate_content="${ax_candidate#*=}"
245           if test "x$ax_candidate" != "x" -a "x$ax_candidate_flag" != "x"; then
246             if echo "$ax_args" | grep -- "${ax_candidate_flag}=" >/dev/null 2>&1; then
247               [ax_args=$(echo $ax_args | sed "s,${ax_candidate_flag}=[^']*,${ax_candidate},")]
248             else
249               AS_VAR_APPEND(ax_args, " 'opt'")
250             fi
251           fi
252      ])])
253      # Options that must be removed.
254      m4_ifnblank([$5], [m4_foreach(opt, [$5], [ax_args=$(echo $ax_args | sed "s,'opt',,")
255      ])])
256      AS_VAR_APPEND([ax_args], [" '--srcdir=$ac_srcdir'"])
257
258      # Add the subdirectory to the list of target subdirectories.
259      ax_subconfigures="$ax_subconfigures $ax_dir"
260      # Save the argument list for this subdirectory.
261      dnl $1 is a path to some subdirectory: m4_bpatsubsts() is used to convert
262      dnl $1 into a valid shell variable name.
263      dnl For instance, "ax_sub_configure_args_path/to/subdir" becomes
264      dnl "ax_sub_configure_args_path_to_subdir".
265      ax_var=$(printf "$ax_dir" | tr -c "0-9a-zA-Z_" "_")
266      eval "ax_sub_configure_args_$ax_var=\"$ax_args\""
267      eval "ax_sub_configure_$ax_var=\"yes\""
268    else
269      AC_MSG_WARN([could not find source tree for $ax_dir])
270    fi
271
272    dnl Add some more arguments to the argument list and then actually run the
273    dnl configure script. This is mostly what happens in _AC_OUTPUT_SUBDIRS
274    dnl except it does not iterate over an intermediary list.
275    AC_CONFIG_COMMANDS_PRE(
276      dnl This very line cannot be quoted! m4_foreach has some work here.
277      ax_dir="subdir_path"
278    [
279      # Convert the path to the subdirectory into a shell variable name.
280      ax_var=$(printf "$ax_dir" | tr -c "0-9a-zA-Z_" "_")
281      ax_configure_ax_var=$(eval "echo \"\$ax_sub_configure_$ax_var\"")
282      if test "$no_recursion" != "yes" -a "x$ax_configure_ax_var" = "xyes"; then
283        AC_SUBST([subdirs_extra], ["$subdirs_extra $ax_dir"])
284        ax_msg="=== configuring in $ax_dir ($(pwd)/$ax_dir)"
285        _AS_ECHO_LOG([$ax_msg])
286        _AS_ECHO([$ax_msg])
287        AS_MKDIR_P(["$ax_dir"])
288        _AC_SRCDIRS(["$ax_dir"])
289
290        ax_popdir=$(pwd)
291        cd "$ax_dir"
292
293        # Check for guested configure; otherwise get Cygnus style configure.
294        if test -f "$ac_srcdir/configure.gnu"; then
295          ax_sub_configure=$ac_srcdir/configure.gnu
296        elif test -f "$ac_srcdir/configure"; then
297          ax_sub_configure=$ac_srcdir/configure
298        elif test -f "$ac_srcdir/configure.in"; then
299          # This should be Cygnus configure.
300          ax_sub_configure=$ac_aux_dir/configure
301        else
302          AC_MSG_WARN([no configuration information is in $ax_dir])
303          ax_sub_configure=
304        fi
305
306        if test -n "$ax_sub_configure"; then
307          # Get the configure arguments for the current configure.
308          eval "ax_sub_configure_args=\"\$ax_sub_configure_args_${ax_var}\""
309
310          # Always prepend --prefix to ensure using the same prefix
311          # in subdir configurations.
312          ax_arg="--prefix=$prefix"
313          case $ax_arg in
314            *\'*) ax_arg=$(AS_ECHO(["$ax_arg"]) | sed "s/'/'\\\\\\\\''/g");;
315          esac
316          ax_sub_configure_args="'$ax_arg' $ax_sub_configure_args"
317          if test "$silent" = yes; then
318            ax_sub_configure_args="--silent $ax_sub_configure_args"
319          fi
320          # Make the cache file name correct relative to the subdirectory.
321          case $cache_file in
322            [[\\/]]* | ?:[[\\/]]* )
323              ax_sub_cache_file=$cache_file ;;
324            *) # Relative name.
325              ax_sub_cache_file=$ac_top_build_prefix$cache_file ;;
326          esac
327
328          AC_MSG_NOTICE([running $SHELL $ax_sub_configure $ax_sub_configure_args --cache-file=$ac_sub_cache_file])
329          eval "\$SHELL \"$ax_sub_configure\" $ax_sub_configure_args --cache-file=\"$ax_sub_cache_file\"" \
330              || AC_MSG_ERROR([$ax_sub_configure failed for $ax_dir])
331        fi
332
333        cd "$ax_popdir"
334      fi
335    ])
336  ])
337])
338