From: Bruno Haible Date: Fri, 4 Jan 2019 18:34:19 +0000 (+0100) Subject: gnulib-tool: New option --extract-recursive-link-directive. X-Git-Tag: v1.0~5189 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=ce8a5edbc49dea0cb859207c2d063dbd3be0f96c;p=gnulib.git gnulib-tool: New option --extract-recursive-link-directive. * gnulib-tool (func_usage): Document the new options --extract-recursive-dependencies, --extract-recursive-link-directive. (func_verify_module): Document output variables. (func_get_dependencies_recursively): New function. (func_get_link_directive_recursively): New function. Use them to implement the new options --extract-recursive-dependencies, --extract-recursive-link-directive. * doc/gnulib-tool.texi (Link-time requirements): New section. --- diff --git a/ChangeLog b/ChangeLog index 6b3dcdf44c..4b8df0ad4b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2019-01-04 Bruno Haible + + gnulib-tool: New option --extract-recursive-link-directive. + * gnulib-tool (func_usage): Document the new options + --extract-recursive-dependencies, --extract-recursive-link-directive. + (func_verify_module): Document output variables. + (func_get_dependencies_recursively): New function. + (func_get_link_directive_recursively): New function. + Use them to implement the new options + --extract-recursive-dependencies, --extract-recursive-link-directive. + * doc/gnulib-tool.texi (Link-time requirements): New section. + 2019-01-04 Bruno Haible Clarify meaning of 'Link' section in module description. diff --git a/doc/gnulib-tool.texi b/doc/gnulib-tool.texi index 50802a9eee..c3adf57f1a 100644 --- a/doc/gnulib-tool.texi +++ b/doc/gnulib-tool.texi @@ -44,6 +44,7 @@ a real run without changing anything. * Modified imports:: Changing the import specification. * Simple update:: Tracking Gnulib development. * Source changes:: Impact of Gnulib on your source files. +* Link-time requirements:: Which libraries to link against * Finding POSIX substitutes:: Determining additional suitable Gnulib modules * Modified build rules:: Modifying the build rules of a Gnulib import * Multiple instances:: Using Gnulib for both a library and a program @@ -465,6 +466,43 @@ used to set system dependent flags (such as @code{_GNU_SOURCE} on GNU systems), and these flags have no effect after any system header file has been included. +@node Link-time requirements +@section Changing your link commands for use with Gnulib + +When you use Gnulib, you need to augment the set of libraries against which +your programs and libraries are linked. This is done by augmenting the +Automake variable @code{LDADD} (for all programs) or +@code{@var{prog}_LDADD} (for a single program @code{@var{prog}}) or +@code{@var{library}_la_LIBADD} (for a single library @code{@var{library}.la}). + +What do you need to add to this Automake variable? +@enumerate +@item +The reference to the Gnulib library. In the example of section +@ref{Initial import}, this would be @code{lib/libgnu.a} for source in the +top-level directory, or @code{../lib/libgnu.a} for source in a sibling +directory of @code{lib/}. + +@item +References to additional libraries, brought in by some of the Gnulib +modules that you use (directly or indirectly). The complete list of such +libraries is printed when you invoke @code{gnulib-tool}. Alternatively, +you can retrieve the set of additional libraries required by a specific +Gnulib module by running +@smallexample +./gnulib-tool --extract-recursive-link-directive @var{module} +@end smallexample +@noindent +Beware: By looking into the module description file @code{modules/@var{module}} +or by running +@smallexample +./gnulib-tool --extract-link-directive @var{module} +@end smallexample +@noindent +you would miss the link dependencies of indirectly used modules. +@end enumerate + + @node Finding POSIX substitutes @section Finding recommended ISO C and POSIX function substitutes diff --git a/gnulib-tool b/gnulib-tool index 97dd634173..9545796fd4 100755 --- a/gnulib-tool +++ b/gnulib-tool @@ -141,10 +141,12 @@ Usage: gnulib-tool --list gnulib-tool --extract-applicability module gnulib-tool --extract-filelist module gnulib-tool --extract-dependencies module + gnulib-tool --extract-recursive-dependencies module gnulib-tool --extract-autoconf-snippet module gnulib-tool --extract-automake-snippet module gnulib-tool --extract-include-directive module gnulib-tool --extract-link-directive module + gnulib-tool --extract-recursive-link-directive module gnulib-tool --extract-license module gnulib-tool --extract-maintainer module gnulib-tool --extract-tests-module module @@ -177,10 +179,16 @@ Operation modes: --extract-applicability extract the applicability --extract-filelist extract the list of files --extract-dependencies extract the dependencies + --extract-recursive-dependencies extract the dependencies of the module + and its dependencies, recursively, all + together, but without the conditions --extract-autoconf-snippet extract the snippet for configure.ac --extract-automake-snippet extract the snippet for library makefile --extract-include-directive extract the #include directive --extract-link-directive extract the linker directive + --extract-recursive-link-directive extract the linker directive of the + module and its dependencies, + recursively, all together --extract-license report the license terms of the source files under lib/ --extract-maintainer report the maintainer(s) inside gnulib @@ -1748,6 +1756,10 @@ func_exists_module () # Input: # - local_gnulib_path from --local-dir # - module module name argument +# Output: +# - module unchanged if OK, empty if not OK +# - lookedup_file if OK: name of the merged (combined) module description file +# - lookedup_tmp if OK: true if it is located in the tmp directory, blank otherwise func_verify_module () { if func_exists_module "$module"; then @@ -2328,6 +2340,8 @@ func_get_dependencies () | sed -e '/^#/d' } +sed_dependencies_without_conditions='s/ *\[.*//' + # func_get_autoconf_early_snippet module # Input: # - local_gnulib_path from --local-dir @@ -2669,6 +2683,83 @@ func_get_tests_module () fi } +# func_get_dependencies_recursively module +# Input: +# - local_gnulib_path from --local-dir +# - modcache true or false, from --cache-modules/--no-cache-modules +func_get_dependencies_recursively () +{ + # In order to process every module only once (for speed), process an "input + # list" of modules, producing an "output list" of modules. During each round, + # more modules can be queued in the input list. Once a module on the input + # list has been processed, it is added to the "handled list", so we can avoid + # to process it again. + handledmodules= + inmodules="$1" + outmodules= + while test -n "$inmodules"; do + inmodules_this_round="$inmodules" + inmodules= # Accumulator, queue for next round + for module in $inmodules_this_round; do + func_verify_module + if test -n "$module"; then + func_append outmodules " $module" + deps=`func_get_dependencies $module | sed -e "$sed_dependencies_without_conditions"` + for dep in $deps; do + func_append inmodules " $dep" + done + fi + done + handledmodules=`for m in $handledmodules $inmodules_this_round; do echo $m; done | LC_ALL=C sort -u` + # Remove $handledmodules from $inmodules. + for m in $inmodules; do echo $m; done | LC_ALL=C sort -u > "$tmp"/queued-modules + inmodules=`echo "$handledmodules" | LC_ALL=C join -v 2 - "$tmp"/queued-modules` + done + rm -f "$tmp"/queued-modules + for m in $outmodules; do echo $m; done | LC_ALL=C sort -u +} + +# func_get_link_directive_recursively module +# Input: +# - local_gnulib_path from --local-dir +# - modcache true or false, from --cache-modules/--no-cache-modules +func_get_link_directive_recursively () +{ + # In order to process every module only once (for speed), process an "input + # list" of modules, producing an "output list" of modules. During each round, + # more modules can be queued in the input list. Once a module on the input + # list has been processed, it is added to the "handled list", so we can avoid + # to process it again. + handledmodules= + inmodules="$1" + outmodules= + while test -n "$inmodules"; do + inmodules_this_round="$inmodules" + inmodules= # Accumulator, queue for next round + for module in $inmodules_this_round; do + func_verify_module + if test -n "$module"; then + if grep '^Link:[ ]*$' "$lookedup_file" >/dev/null; then + # The module description has a 'Link:' field. Ignore the dependencies. + func_append outmodules " $module" + else + # The module description has no 'Link:' field. Recurse through the dependencies. + deps=`func_get_dependencies $module | sed -e "$sed_dependencies_without_conditions"` + for dep in $deps; do + func_append inmodules " $dep" + done + fi + fi + done + handledmodules=`for m in $handledmodules $inmodules_this_round; do echo $m; done | LC_ALL=C sort -u` + # Remove $handledmodules from $inmodules. + for m in $inmodules; do echo $m; done | LC_ALL=C sort -u > "$tmp"/queued-modules + inmodules=`echo "$handledmodules" | LC_ALL=C join -v 2 - "$tmp"/queued-modules` + done + rm -f "$tmp"/queued-modules + for m in $outmodules; do func_get_link_directive "$m"; done | LC_ALL=C sort -u | sed -e '/^$/d' +} + # func_acceptable module # tests whether a module is acceptable. # Input: @@ -2818,8 +2909,6 @@ else } fi -sed_dependencies_without_conditions='s/ *\[.*//' - # func_modules_transitive_closure # Input: # - local_gnulib_path from --local-dir @@ -7018,6 +7107,19 @@ s/\([.*$]\)/[\1]/g' done ;; + extract-recursive-dependencies ) + if test -n "$avoidlist"; then + func_fatal_error "cannot combine --avoid and --extract-recursive-dependencies" + fi + for module + do + func_verify_module + if test -n "$module"; then + func_get_dependencies_recursively "$module" + fi + done + ;; + extract-autoconf-snippet ) for module do @@ -7058,6 +7160,19 @@ s/\([.*$]\)/[\1]/g' done ;; + extract-recursive-link-directive ) + if test -n "$avoidlist"; then + func_fatal_error "cannot combine --avoid and --extract-recursive-link-directive" + fi + for module + do + func_verify_module + if test -n "$module"; then + func_get_link_directive_recursively "$module" + fi + done + ;; + extract-license ) for module do