From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 208.118.235.0/24 X-Spam-Status: No, score=-3.9 required=3.0 tests=AWL,BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 1432A1F6A9 for ; Fri, 4 Jan 2019 18:43:08 +0000 (UTC) Received: from localhost ([127.0.0.1]:38128 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gfUR0-00042K-FE for normalperson@yhbt.net; Fri, 04 Jan 2019 13:43:06 -0500 Received: from eggs.gnu.org ([208.118.235.92]:36323) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gfUQw-000422-0I for bug-gnulib@gnu.org; Fri, 04 Jan 2019 13:43:03 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gfUQu-0005k8-C8 for bug-gnulib@gnu.org; Fri, 04 Jan 2019 13:43:01 -0500 Received: from mo6-p00-ob.smtp.rzone.de ([2a01:238:20a:202:5300::10]:31286) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gfUQt-0005hH-Iu for bug-gnulib@gnu.org; Fri, 04 Jan 2019 13:43:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1546627377; s=strato-dkim-0002; d=clisp.org; h=Message-ID:Date:Subject:To:From:X-RZG-CLASS-ID:X-RZG-AUTH:From: Subject:Sender; bh=LhjH2IWI5yxBAhrdsnXh/sDrnno2W/W9u/glYqfIFmM=; b=pxW2b44Ib6GEENubSX16Oz/KKH68+iTGvVo7gimfljI9fPiimsu5FanqyI5DinvBHS oC8xV81TMuL/vLlKt9Y1VfV8jbgYVZCQDe00bCMhM4b0xNniwDYyx5dk+HmrzSnjuTPt fGrZ6fofuPV0pesJUM18tiermUv6jS1ZBFy1IoxzdkMAa8ncBn74LCgql2It+fl7yvHC KQ/NBYrFf2s+b567rhRdbM3rLGf2QPYweyUWmNa2nnxxpzbWhsM5JYSSW5IGPpbIa4ff P9QYNZSnMVbsBLH3I+5Zr3F5+FAW7aPN/mk6FkZoCnjQZBbgfopx4VmGC13a1jMbzLHP n6Xg== X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH+AHjwLuWOGKf2y/s=" X-RZG-CLASS-ID: mo00 Received: from bruno.haible.de by smtp.strato.de (RZmta 44.9 DYNA|AUTH) with ESMTPSA id v0a34ev04Igv34a (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (curve secp521r1 with 521 ECDH bits, eq. 15360 bits RSA)) (Client did not present a certificate); Fri, 4 Jan 2019 19:42:57 +0100 (CET) From: Bruno Haible To: bug-gnulib@gnu.org Subject: gnulib-tool: new option --extract-recursive-link-directive Date: Fri, 04 Jan 2019 19:42:56 +0100 Message-ID: <1911876.FbAL48B4cG@omega> User-Agent: KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; ) MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a01:238:20a:202:5300::10 X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: "bug-gnulib" With the clarified meaning of the 'Link' filed in the module description, it is now clear that the user of a module should generally *not* look at the 'Link' field in this module description, because in 90% of the cases this field is missing although the module has link dependencies. So, we need a new gnulib-tool option that produces the desired information. While at it, I'm also adding a gnulib-tool option that computes the set of dependencies (recursively). Example: $ ./gnulib-tool --extract-recursive-link-directive dfa $(LTLIBINTL) when linking with libtool, $(LIBINTL) otherwise 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. diff --git a/doc/gnulib-tool.texi b/doc/gnulib-tool.texi index 50802a9..fecc5cb 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 97dd634..9545796 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