On Thu, Dec 19, 2019 at 02:54:16PM +0100, Pino Toscano wrote:
 Move the interal static libraries as the last items in the list of
 libraries of guestfsd, to make sure their symbols are used for all the
 other libraries.  This is because GCC resolves the symbols looking at
 the arguments from the beginning to the end of the command line.
 This currently does not cause failures, however it "just works" because
 of the tricky situation set up.
 
 The situation is the following:
 
 1) common/utils contains few utility sources: one of them is utils.c,
 which contains various functions -- for example
 guestfs_int_free_string_list and guestfs_int_drive_name --, it is built
 as utils.o, and bundled in the static library libutils.a
 
 2) common/mlutils builds a OCaml library with bindings for some utility
 functions in libutils.a, in particular guestfs_int_drive_name (but not
 guestfs_int_free_string_list); there are two versions of this library,
 one OCaml library (dllmlcutils.so) that links with libutils.a, and one
 static library (libmlcutils.a), which cannot specify the libraries it
 links to (as it is static)
 
 3) when the daemon is linked, the command line was the following
 (simplified):
   $ gcc [...] -o guestfsd guestfsd-9p.o other_daemon_object.o [...] \
       ../common/utils/.libs/libutils.a [...] -lmlcutils [...]
 Some of the objects of the daemon itself use
 guestfs_int_free_string_list, and thus the compiler opens libutils.a
 (it is after the objects in the command line) and picks utils.o, which
 contains also guestfs_int_drive_name (not used directly in the daemon);
 when linking later on with libmlcutils.a, the symbols for this static
 library (like guestfs_int_drive_name) are already resolved, and thus
 all the symbols are resolved, and the linking succeeds
 
 This fragile situation can be easily broken by moving e.g.
 guestfs_int_drive_name out of common/utils/utils.c to a new source (say
 utils2.c) still built as part of libutils.a: since nothing before
 -lmlcutils actually needs to pick utils2.o from libutils.a for symbols,
 then GCC will not be able to resolve all the symbols in libmlcutils.a.
 
 As solution, move libutils.a (and other internal static libraries) as
 last libraries to link guestfsd to: this way, GCC knows where to find
 all the symbols needed by all the objects and libraries specified in
 the command line.
 ---
  daemon/Makefile.am | 8 ++++----
  1 file changed, 4 insertions(+), 4 deletions(-)
 
 diff --git a/daemon/Makefile.am b/daemon/Makefile.am
 index ab3019cc1..25948dbe9 100644
 --- a/daemon/Makefile.am
 +++ b/daemon/Makefile.am
 @@ -217,9 +217,6 @@ guestfsd_LDFLAGS = \
  	-L../bundled/ocaml-augeas \
  	-L../common/mlpcre
  guestfsd_LDADD = \
 -	../common/errnostring/liberrnostring.la \
 -	../common/protocol/libprotocol.la \
 -	../common/utils/libutils.la \
  	camldaemon.o \
  	$(ACL_LIBS) \
  	$(CAP_LIBS) \
 @@ -236,7 +233,10 @@ guestfsd_LDADD = \
  	$(TSK_LIBS) \
  	$(RPC_LIBS) \
  	$(YARA_LIBS) \
 -	$(OCAML_LIBS)
 +	$(OCAML_LIBS) \
 +	../common/errnostring/liberrnostring.la \
 +	../common/protocol/libprotocol.la \
 +	../common/utils/libutils.la 
Good find, ACK.
Rich.
-- 
Richard Jones, Virtualization Group, Red Hat 
http://people.redhat.com/~rjones
Read my programming and virtualization blog: 
http://rwmj.wordpress.com
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  
http://libguestfs.org