From f060c4464605e4f016b0eae476cb4dd3f47a9b40 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi <giovanni.bussi@gmail.com> Date: Sun, 4 Feb 2018 11:37:03 +0100 Subject: [PATCH] Added static library libplumed.a I found out that by using the pre-linked kernel.o file it is possible to make a static library libplumed.a that is correctly linked, including static constructors. When available, this library is used for plumed patch --static --- Makefile.conf.in | 1 + configure | 76 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 53 +++++++++++++++++++++++++++++- src/lib/Makefile | 31 ++++++++++++++++-- src/lib/pkgconfig.in | 1 + 5 files changed, 158 insertions(+), 4 deletions(-) diff --git a/Makefile.conf.in b/Makefile.conf.in index 9d9e38dff..43fffaee0 100644 --- a/Makefile.conf.in +++ b/Makefile.conf.in @@ -34,3 +34,4 @@ docdir=@docdir@ htmldir=@htmldir@ python_bin=@PYTHON_BIN@ mpiexec=@MPIEXEC@ +make_static_archive=@make_static_archive@ diff --git a/configure b/configure index 9214a5ccf..60db89bf8 100755 --- a/configure +++ b/configure @@ -622,6 +622,7 @@ ac_subst_vars='LTLIBOBJS LIBOBJS build_dir program_name +make_static_archive AR_CR LD_RO program_can_run_mpi @@ -712,6 +713,7 @@ enable_dependency_tracking enable_rpath enable_ld_r enable_ar_cr +enable_static_archive enable_mpi enable_external_lapack enable_external_blas @@ -1381,6 +1383,8 @@ Optional Features: --enable-ld-r enable group object files, default: yes --enable-ar-cr enable use ar to build libplumedWrapper.a, default: yes + --enable-static-archive enable try to build libplumed.a for static linking, + default: yes --enable-mpi enable search for mpi, default: yes --enable-external-lapack enable search for external lapack, default: yes @@ -2705,6 +2709,24 @@ fi +static_archive= +# Check whether --enable-static-archive was given. +if test "${enable_static_archive+set}" = set; then : + enableval=$enable_static_archive; case "${enableval}" in + (yes) static_archive=true ;; + (no) static_archive=false ;; + (*) as_fn_error $? "wrong argument to --enable-static-archive" "$LINENO" 5 ;; + esac +else + case "yes" in + (yes) static_archive=true ;; + (no) static_archive=false ;; + esac + +fi + + + mpi= # Check whether --enable-mpi was given. if test "${enable_mpi+set}" = set; then : @@ -8794,6 +8816,60 @@ done fi +make_static_archive=no + + +if test "${static_archive}" == true ; then + if test -z "$LD_RO" || test -z "$AR_CR" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no way to create a static archive if ld -ro or ar cr do not work" >&5 +$as_echo "$as_me: WARNING: no way to create a static archive if ld -ro or ar cr do not work" >&2;} + static_archive=false + fi +fi + +if test "${static_archive}" == true ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether static-object constructors can be linked from a static archive" >&5 +$as_echo_n "checking whether static-object constructors can be linked from a static archive... " >&6; } + + magic_token=c1bc476d093a3a5c67b4530e6c54c633593fe9aa + rm -f conftest-* + + cat << EOF > conftest-main.cpp + void f(void); + int main(int argc,char**argv){ f(); return 0; } +EOF + cat << EOF > conftest-f.cpp + void f(void){ return; } +EOF + cat << EOF > conftest-g.cpp +#include <iostream> + class g{ + public: + g(){ std::cout<<"$magic_token\n"; } + } init; +EOF + + $CXX $CXXFLAGS -c conftest-main.cpp 1> /dev/null 2> /dev/null + $CXX $CXXFLAGS -c conftest-f.cpp 1> /dev/null 2> /dev/null + $CXX $CXXFLAGS -c conftest-g.cpp 1> /dev/null 2> /dev/null + + $LD_RO conftest-both.o conftest-f.o conftest-g.o 1> /dev/null 2> /dev/null +# linking the previously merged objects should work: + $AR_CR conftest-both.a conftest-both.o 1> /dev/null 2> /dev/null +# something like the following, instead, should not work: +# $AR_CR conftest-both.a conftest-f.o conftest-g.o 1> /dev/null 2> /dev/null +# + $CXX $CXXFLAGS -o conftest.exe conftest-main.o conftest-both.a 1> /dev/null 2> /dev/null + if grep -q $magic_token ./conftest.exe ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + make_static_archive=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi +fi + if test "${static_patch}" == true ; then { $as_echo "$as_me:${as_lineno-$LINENO}: I will now check if C++ objects can be linked by C/Fortran compilers" >&5 diff --git a/configure.ac b/configure.ac index 6d37a79aa..81b794cdd 100644 --- a/configure.ac +++ b/configure.ac @@ -239,6 +239,7 @@ PLUMED_CONFIG_ENABLE([dependency-tracking],[dependency tracking],[yes]) PLUMED_CONFIG_ENABLE([rpath],[store rpath],[no]) PLUMED_CONFIG_ENABLE([ld-r],[group object files],[yes]) PLUMED_CONFIG_ENABLE([ar-cr],[use ar to build libplumedWrapper.a],[yes]) +PLUMED_CONFIG_ENABLE([static-archive],[try to build libplumed.a for static linking],[yes]) PLUMED_CONFIG_ENABLE([mpi],[search for mpi],[yes]) PLUMED_CONFIG_ENABLE([external-lapack],[search for external lapack],[yes]) PLUMED_CONFIG_ENABLE([external-blas],[search for external blas],[yes]) @@ -923,7 +924,7 @@ EOF AC_MSG_RESULT([no]) fi done - + fi AC_SUBST(AR_CR) @@ -967,6 +968,56 @@ done fi +make_static_archive=no +AC_SUBST(make_static_archive) + +if test "${static_archive}" == true ; then + if test -z "$LD_RO" || test -z "$AR_CR" ; then + AC_MSG_WARN([no way to create a static archive if ld -ro or ar cr do not work]) + static_archive=false + fi +fi + +if test "${static_archive}" == true ; then + AC_MSG_CHECKING([whether static-object constructors can be linked from a static archive]) + + magic_token=c1bc476d093a3a5c67b4530e6c54c633593fe9aa + rm -f conftest-* + + cat << EOF > conftest-main.cpp + void f(void); + int main(int argc,char**argv){ f(); return 0; } +EOF + cat << EOF > conftest-f.cpp + void f(void){ return; } +EOF + cat << EOF > conftest-g.cpp +#include <iostream> + class g{ + public: + g(){ std::cout<<"$magic_token\n"; } + } init; +EOF + + $CXX $CXXFLAGS -c conftest-main.cpp 1> /dev/null 2> /dev/null + $CXX $CXXFLAGS -c conftest-f.cpp 1> /dev/null 2> /dev/null + $CXX $CXXFLAGS -c conftest-g.cpp 1> /dev/null 2> /dev/null + + $LD_RO conftest-both.o conftest-f.o conftest-g.o 1> /dev/null 2> /dev/null +# linking the previously merged objects should work: + $AR_CR conftest-both.a conftest-both.o 1> /dev/null 2> /dev/null +# something like the following, instead, should not work: +# $AR_CR conftest-both.a conftest-f.o conftest-g.o 1> /dev/null 2> /dev/null +# + $CXX $CXXFLAGS -o conftest.exe conftest-main.o conftest-both.a 1> /dev/null 2> /dev/null + if grep -q $magic_token ./conftest.exe ; then + AC_MSG_RESULT([yes]) + make_static_archive=yes + else + AC_MSG_RESULT([no]) + fi +fi + if test "${static_patch}" == true ; then AC_MSG_NOTICE([I will now check if C++ objects can be linked by C/Fortran compilers]) diff --git a/src/lib/Makefile b/src/lib/Makefile index 340ef0b81..3f1b7c7be 100644 --- a/src/lib/Makefile +++ b/src/lib/Makefile @@ -96,6 +96,9 @@ install-build: ifdef LD_RO $(MAKE) PLUMED_INSTALL=Install install/kernel.o endif +ifeq ($(make_static_archive),yes) + $(MAKE) PLUMED_INSTALL=Install install/libplumed.a +endif # modulefile @cat modulefile.in | \ sed "s|@_SOEXT_@|$(SOEXT)|" | \ @@ -108,7 +111,8 @@ endif sed "s|@_SOEXT_@|$(SOEXT)|" | \ sed "s|@_program_name_@|$(program_name)|" | \ sed "s|@_libdir_@|$(libdir)|" | \ - sed "s|@_libs_@||" | \ + sed "s|@_libs_@|$(LIBS) $(DYNAMIC_LIBS)|" | \ + sed "s|@_private_libs_@||" | \ sed "s|@_bindir_@|$(bindir)|" | \ sed "s|@_includedir_@|$(includedir)|" | \ sed "s|@_prefix_@|$(prefix)|" | \ @@ -123,6 +127,7 @@ endif sed "s|@_program_name_@|$(program_name)|" | \ sed "s|@_libdir_@|$(libdir)|" | \ sed "s|@_libs_@||" | \ + sed "s|@_private_libs_@|$(LIBS) $(DYNAMIC_LIBS)|" | \ sed "s|@_bindir_@|$(bindir)|" | \ sed "s|@_includedir_@|$(includedir)|" | \ sed "s|@_prefix_@|$(prefix)|" | \ @@ -137,6 +142,7 @@ endif sed "s|@_program_name_@|$(program_name)Wrapper|" | \ sed "s|@_libdir_@|$(libdir)|" | \ sed "s|@_libs_@|$(LIBS)|" | \ + sed "s|@_private_libs_@||" | \ sed "s|@_bindir_@|$(bindir)|" | \ sed "s|@_includedir_@|$(includedir)|" | \ sed "s|@_prefix_@|$(prefix)|" | \ @@ -152,6 +158,12 @@ install/kernel.o: $(OBJ_KERNEL) $(LD_RO) install/kernel.o $(OBJ_KERNEL) endif +ifeq ($(make_static_archive),yes) +install/libplumed.a: install/kernel.o $(OBJ_WRAPPER) + rm -f $@ + $(AR_CR) $@ $^ +endif + # standard target (according to GNU doc) install-html: if test -d ../../user-doc/html ; then mkdir -p "$(DESTDIR)$(htmldir)" && cd ../../ && tar cf - user-doc/html | tar xf - -C "$(DESTDIR)$(htmldir)/" ; fi @@ -219,13 +231,16 @@ endif cp ../config/compile_options.sh "$(DESTDIR)$(libdir)/$(program_name)/src/config/compile_options.sh" # copy config.txt file (we leave it in src/colvar/ for backward compatibility) cp ../config/config.txt "$(DESTDIR)$(libdir)/$(program_name)/src/config/config.txt" +ifeq ($(make_static_archive),yes) + cp install/libplumed.a "$(DESTDIR)$(libdir)/lib$(program_name).a" +else + cp $(OBJ_WRAPPER) "$(DESTDIR)$(libdir)/$(program_name)/obj/PlumedStatic.o" ifdef LD_RO cp install/kernel.o "$(DESTDIR)$(libdir)/$(program_name)/obj/kernel.o" else ../maketools/copyobjects "$(DESTDIR)$(libdir)/$(program_name)/obj/k" $(subst ../config/Config.o,../config/ConfigInstall.o,$(OBJ_KERNEL)) endif - cp $(OBJ_WRAPPER) "$(DESTDIR)$(libdir)/$(program_name)/obj/PlumedStatic.o" - cp $(OBJ_DYNAMIC_WRAPPER) "$(DESTDIR)$(libdir)/$(program_name)/obj/Plumed.o" +endif # also copy .h files into include/ dir cd ../../src ; tar cf - */*.h */*/*.h | tar xf - -C "$(DESTDIR)$(includedir)/$(program_name)/" # install executable @@ -251,6 +266,8 @@ ifdef SOEXT endif ifdef AR_CR cp install/libplumedWrapper.a "$(DESTDIR)$(libdir)/lib$(program_name)Wrapper.a" +else + cp $(OBJ_DYNAMIC_WRAPPER) "$(DESTDIR)$(libdir)/$(program_name)/obj/Plumed.o" endif # modulefile cp install/modulefile "$(DESTDIR)$(libdir)/$(program_name)/modulefile" @@ -463,22 +480,30 @@ ifdef AR_CR else @echo "PLUMED_RUNTIME_LOAD= \"$(libdir)/$(program_name)/obj/Plumed.o\" $(LIBS) $(LDFLAGS)" > $@ endif +ifeq ($(make_static_archive),yes) + @echo "PLUMED_STATIC_LOAD= \"$(libdir)/lib$(program_name).a\" $(LIBS) $(DYNAMIC_LIBS) $(LDFLAGS)" >> $@ +else ifdef LD_RO @echo "PLUMED_STATIC_LOAD= \"$(libdir)/$(program_name)/obj/kernel.o\" \"$(libdir)/$(program_name)/obj/PlumedStatic.o\" $(LIBS) $(DYNAMIC_LIBS) $(LDFLAGS)" >> $@ else # single quote required to preserve double quote in resulting file @echo "PLUMED_STATIC_LOAD= '$(shell ../maketools/listobjects "$(libdir)/$(program_name)/obj/k" $(OBJ_KERNEL))' \"$(libdir)/$(program_name)/obj/PlumedStatic.o\" $(LIBS) $(DYNAMIC_LIBS) $(LDFLAGS)" >> $@ +endif endif @echo "PLUMED_SHARED_LOAD= \"$(libdir)/lib$(program_name).$(SOEXT)\" $(LIBS) $(LDFLAGS)" >> $@ @echo "PLUMED_RUNTIME_DEPENDENCIES=" >> $@ # in principle all objects are replaced at the same time # however, to keep compatibility with the include files generated in plumed 2.0 and 2.1, # I put all the objects (or shared objects) here +ifeq ($(make_static_archive),yes) + @echo "PLUMED_STATIC_DEPENDENCIES= \"$(libdir)/lib$(program_name).a\"" >> $@ +else ifdef LD_RO @echo "PLUMED_STATIC_DEPENDENCIES= \"$(libdir)/$(program_name)/obj/kernel.o\" \"$(libdir)/$(program_name)/obj/PlumedStatic.o\"" >> $@ else # single quote required to preserve double quote in resulting file @echo "PLUMED_STATIC_DEPENDENCIES= '$(shell ../maketools/listobjects "$(libdir)/$(program_name)/obj/k" $(OBJ_KERNEL))' \"$(libdir)/$(program_name)/obj/PlumedStatic.o\"" >> $@ +endif endif @echo "PLUMED_SHARED_DEPENDENCIES= \"$(libdir)/lib$(program_name).$(SOEXT)\"" >> $@ else diff --git a/src/lib/pkgconfig.in b/src/lib/pkgconfig.in index 98f2c493b..d715c1a92 100644 --- a/src/lib/pkgconfig.in +++ b/src/lib/pkgconfig.in @@ -9,4 +9,5 @@ URL: http://www.plumed.org Version: @_VERSION_@ Cflags: -I${includedir} @_cppflags_@ Libs: -L${libdir} -l@_program_name_@ @_libs_@ +Libs.private: @_private_libs_@ Conflicts: @_conflicts_@ -- GitLab