From 685c44484fd157293797d5afa4dec375d0286169 Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Mon, 27 Jul 2015 15:28:50 +0200
Subject: [PATCH] Changed installation layout for objects

Instead of replicating the whole tree upon install,
now objects are copied to prefix/lib/plumed/obj
and assigned a number.

When possible, objects are grouped in a single kernel.o
with ld -r (tested in configure). This saves a lot
of disk space.

I also removed from the install directory some other
useless files.

The Plumed.inc/cmake files when installing
are generated in a different way from the ones
used prior to installation. Thus, to avoid too many
repetitions, I wrote a small awk script the transforms
Plumed.inc to Plumed.make
---
 Makefile.conf.in          |  1 +
 configure                 | 70 ++++++++++++++++++++++++++++++++++++---
 configure.ac              | 39 ++++++++++++++++++++++
 src/lib/Makefile          | 67 ++++++++++++++++++++++++-------------
 src/maketools/copyobjects | 19 +++++++++++
 src/maketools/inc2cmake   |  9 +++++
 src/maketools/listobjects | 13 ++++++++
 7 files changed, 191 insertions(+), 27 deletions(-)
 create mode 100755 src/maketools/copyobjects
 create mode 100755 src/maketools/inc2cmake
 create mode 100755 src/maketools/listobjects

diff --git a/Makefile.conf.in b/Makefile.conf.in
index 344524bdd..b70654c97 100644
--- a/Makefile.conf.in
+++ b/Makefile.conf.in
@@ -17,3 +17,4 @@ prefix=@prefix@
 program_transform_name=@program_transform_name@
 program_can_run_mpi=@program_can_run_mpi@
 program_can_run=@program_can_run@
+LD_RO=@LD_RO@
diff --git a/configure b/configure
index c2e5b3a8a..b5fccae4f 100755
--- a/configure
+++ b/configure
@@ -621,6 +621,7 @@ ac_includes_default="\
 ac_subst_vars='LTLIBOBJS
 LIBOBJS
 build_dir
+LD_RO
 program_can_run_mpi
 program_can_run
 xxd
@@ -695,6 +696,7 @@ enable_fussy
 enable_debug_glibcxx
 enable_shared
 enable_cxx_exceptions
+enable_ld_r
 enable_mpi
 enable_external_lapack
 enable_external_blas
@@ -1352,6 +1354,7 @@ Optional Features:
   --enable-debug-glibcxx  enable enable boundary check, default: no
   --enable-shared         enable shared libs, default: yes
   --enable-cxx-exceptions enable c++ exceptions, default: no
+  --enable-ld-r           enable group object files, default: yes
   --enable-mpi            enable search for mpi, default: yes
   --enable-external-lapack
                           enable search for external lapack, default: yes
@@ -2496,6 +2499,24 @@ fi
 
 
 
+ld_r=
+# Check whether --enable-ld-r was given.
+if test "${enable_ld_r+set}" = set; then :
+  enableval=$enable_ld_r; case "${enableval}" in
+             (yes) ld_r=true ;;
+             (no)  ld_r=false ;;
+             (*)   as_fn_error $? "wrong argument to --enable-ld-r" "$LINENO" 5 ;;
+  esac
+else
+  case "yes" in
+             (yes) ld_r=true ;;
+             (no)  ld_r=false ;;
+  esac
+
+fi
+
+
+
 mpi=
 # Check whether --enable-mpi was given.
 if test "${enable_mpi+set}" = set; then :
@@ -5435,9 +5456,9 @@ if test -z "$blas_found" ; then
 $as_echo "$as_me: WARNING: using internal lapack and blas, could be inefficient" >&2;}
 LIBS="$save_LIBS"
 
-$as_echo "#define __PLUMED_HAS_INTERNAL_BLAS 1" >>confdefs.h
+$as_echo "#define __PLUMED_INTERNAL_BLAS 1" >>confdefs.h
 
-$as_echo "#define __PLUMED_HAS_INTERNAL_LAPACK 1" >>confdefs.h
+$as_echo "#define __PLUMED_INTERNAL_LAPACK 1" >>confdefs.h
 
 fi
 
@@ -5512,7 +5533,7 @@ if test -z "$lapack_found" ; then
 $as_echo "$as_me: WARNING: using internal lapack, could be inefficient" >&2;}
 LIBS="$save_LIBS"
 
-$as_echo "#define __PLUMED_HAS_INTERNAL_LAPACK 1" >>confdefs.h
+$as_echo "#define __PLUMED_INTERNAL_LAPACK 1" >>confdefs.h
 
 fi
 
@@ -5601,7 +5622,7 @@ fi
 if test $found == ko ; then
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using internal molfile_plugins, which only support dcd/xtc/trr/trj/crd files" >&5
 $as_echo "$as_me: WARNING: using internal molfile_plugins, which only support dcd/xtc/trr/trj/crd files" >&2;}
-	$as_echo "#define __PLUMED_HAS_INTERNAL_MOLFILE_PLUGINS 1" >>confdefs.h
+	$as_echo "#define __PLUMED_INTERNAL_MOLFILE_PLUGINS 1" >>confdefs.h
 
 fi
 
@@ -6726,6 +6747,47 @@ fi
 $as_echo "$as_me: PLUMED seems to be configured properly!" >&6;}
 { $as_echo "$as_me:${as_lineno-$LINENO}: **************************" >&5
 $as_echo "$as_me: **************************" >&6;}
+
+LD_RO=
+if test "$ld_r" == true ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ objects can be grouped with ld -r" >&5
+$as_echo_n "checking whether C++ objects can be grouped with ld -r... " >&6; }
+
+  LD_RO="ld -r -o"
+
+  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 g(void);
+  void f(void){ g(); }
+EOF
+  cat << EOF > conftest-g.cpp
+  void g(void){ return; }
+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
+
+  $CXX $CXXFLAGS -o conftest.exe conftest-main.o conftest-both.o 1> /dev/null 2> /dev/null
+
+  if test -f conftest.exe
+  then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    LD_RO=""
+  fi
+fi
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: I will now check if C++ objects can be linked by C/Fortran compilers" >&5
 $as_echo "$as_me: I will now check if C++ objects can be linked by C/Fortran compilers" >&6;}
 { $as_echo "$as_me:${as_lineno-$LINENO}: This is relevant if you want to use plumed patch --static on a non-C++ code" >&5
diff --git a/configure.ac b/configure.ac
index fdf57fa68..1f81d66db 100644
--- a/configure.ac
+++ b/configure.ac
@@ -162,6 +162,7 @@ PLUMED_CONFIG_ENABLE([fussy],[fussy],[fussy warnings],[no])
 PLUMED_CONFIG_ENABLE([debug_glibcxx],[debug-glibcxx],[enable boundary check],[no])
 PLUMED_CONFIG_ENABLE([shared],[shared],[shared libs],[yes])
 PLUMED_CONFIG_ENABLE([cxx_exceptions],[cxx-exceptions],[c++ exceptions],[no])
+PLUMED_CONFIG_ENABLE([ld_r],[ld-r],[group object files],[yes])
 PLUMED_CONFIG_ENABLE([mpi],[mpi],[search for mpi],[yes])
 PLUMED_CONFIG_ENABLE([external_lapack],[external-lapack],[search for external lapack],[yes])
 PLUMED_CONFIG_ENABLE([external_blas],[external-blas],[search for external blas],[yes])
@@ -603,6 +604,44 @@ fi
 #### This further tests are required to allow linking with non c++ compiler
 AC_MSG_NOTICE([PLUMED seems to be configured properly!])
 AC_MSG_NOTICE([**************************])
+AC_SUBST(LD_RO)
+LD_RO=
+if test "$ld_r" == true ; then
+  AC_MSG_CHECKING([whether C++ objects can be grouped with ld -r])
+  
+  LD_RO="ld -r -o"
+  
+  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 g(void);
+  void f(void){ g(); }
+EOF
+  cat << EOF > conftest-g.cpp
+  void g(void){ return; }
+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
+  
+  $CXX $CXXFLAGS -o conftest.exe conftest-main.o conftest-both.o 1> /dev/null 2> /dev/null
+  
+  if test -f conftest.exe
+  then
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+    LD_RO=""
+  fi
+fi
+
 AC_MSG_NOTICE([I will now check if C++ objects can be linked by C/Fortran compilers])
 AC_MSG_NOTICE([This is relevant if you want to use plumed patch --static on a non-C++ code])
 
diff --git a/src/lib/Makefile b/src/lib/Makefile
index b3faf2556..dc6cd7301 100644
--- a/src/lib/Makefile
+++ b/src/lib/Makefile
@@ -61,7 +61,7 @@ else
 endif
 
 
-.PHONY: all links $(DIRS) $(DIRSLINKS) all-static Plumed.cmake Plumed.inc
+.PHONY: all links $(DIRS) $(DIRSLINKS) all-static $(PLUMED_LIBDIR)Plumed.cmake $(PLUMED_LIBDIR)Plumed.inc
 ifdef SOEXT
 all:
 	$(MAKE) dirslinks
@@ -92,14 +92,22 @@ install-do:
 	mkdir -p $(DESTDIR)$(PLUMED_INSTALL_PREFIX)/bin
 	mkdir -p $(DESTDIR)$(PLUMED_INSTALL_ROOT)/src/lib
 	mkdir -p $(DESTDIR)$(PLUMED_INSTALL_PREFIX)/include/$(PLUMED_PROGRAM_NAME)
+	mkdir -p $(DESTDIR)$(PLUMED_INSTALL_ROOT)/obj
 # rebuild libraries and main using new target dir
 	$(MAKE) PLUMED_LIBDIR=$(DESTDIR)$(PLUMED_INSTALL_ROOT)/src/lib/ PLUMED_LIBDIR_NODEST=$(PLUMED_INSTALL_ROOT)/src/lib/ PLUMED_INSTALL=Install all
-# copy .h, .cpp .o compile_options.sh and documentation:
-	cd ../../ ; tar cf - patches scripts src/*/*.h src/*/*.cpp src/*/*.o src/config/compile_options.sh *-doc/html *-doc/regtests *-doc/manual.pdf | tar xf - -C $(DESTDIR)$(PLUMED_INSTALL_ROOT)/
+# copy scripts, required .h, .cpp, compile_options.sh and documentation:
+	cd ../../ ; tar cf - patches scripts src/wrapper/Plumed.h src/colvar/Template.cpp *-doc/html *-doc/regtests *-doc/manual.pdf | tar xf - -C $(DESTDIR)$(PLUMED_INSTALL_ROOT)/
+	mkdir -p $(DESTDIR)$(PLUMED_INSTALL_ROOT)/src/config/
+	sed 's|-I"$$PLUMED_ROOT"/src|-I"$$PLUMED_ROOT"/../../include/$(PLUMED_PROGRAM_NAME)|' ../config/compile_options.sh > $(DESTDIR)$(PLUMED_INSTALL_ROOT)/src/config/compile_options.sh
+ifdef LD_RO
+	$(LD_RO) $(DESTDIR)$(PLUMED_INSTALL_ROOT)/obj/kernel.o $(OBJ_KERNEL)
+else
+	../maketools/copyobjects $(DESTDIR)$(PLUMED_INSTALL_ROOT)/obj/k $(OBJ_KERNEL)
+endif
+	cp $(OBJ_WRAPPER) $(DESTDIR)$(PLUMED_INSTALL_ROOT)/obj/PlumedStatic.o
+	cp $(OBJ_DYNAMIC_WRAPPER) $(DESTDIR)$(PLUMED_INSTALL_ROOT)/obj/Plumed.o
 # also copy .h files into include/ dir
 	cd ../../src ; tar cf - */*.h */*/*.h | tar xf - -C $(DESTDIR)$(PLUMED_INSTALL_PREFIX)/include/$(PLUMED_PROGRAM_NAME)/
-# copy inc files changing the path
-	for file in Plumed.inc* Plumed.cmake* ; do sed "s| $(realpath ../..)| $(PLUMED_INSTALL_ROOT)|g" $$file > $(DESTDIR)$(PLUMED_INSTALL_ROOT)/src/lib/$$file ; done
 # modulefile
 	@sed "s|@_PREFIX_@|$(PLUMED_INSTALL_PREFIX)|" modulefile.in | sed "s|@_SOEXT_@|$(SOEXT)|" | sed "s|@_PROGNAME_@|$(PLUMED_PROGRAM_NAME)|" > $(DESTDIR)$(PLUMED_INSTALL_ROOT)/src/lib/modulefile
 # install links
@@ -173,11 +181,11 @@ $(DIRS):
 
 lib: lib-static lib-shared
 
-lib-static: $(PLUMED_MAIN_STATIC) $(OBJ_WRAPPER) Plumed.inc.static Plumed.cmake.static $(PLUMED_SCRIPTS_EXE)
+lib-static: $(PLUMED_MAIN_STATIC) $(OBJ_WRAPPER) $(PLUMED_LIBDIR)Plumed.inc.static $(PLUMED_LIBDIR)Plumed.cmake.static $(PLUMED_SCRIPTS_EXE)
 
 lib-shared: $(PLUMED_KERNEL) $(PLUMED_SHARED_OBJ) $(PLUMED_MAIN_SHARED) $(PLUMED_MAIN_RUNTIME) \
-           Plumed.inc Plumed.inc.runtime Plumed.inc.shared \
-           Plumed.cmake Plumed.cmake.runtime Plumed.cmake.shared
+           $(PLUMED_LIBDIR)Plumed.inc $(PLUMED_LIBDIR)Plumed.inc.runtime $(PLUMED_LIBDIR)Plumed.inc.shared \
+           $(PLUMED_LIBDIR)Plumed.cmake $(PLUMED_LIBDIR)Plumed.cmake.runtime $(PLUMED_LIBDIR)Plumed.cmake.shared
 
 $(PLUMED_SCRIPTS_EXE):
 	@echo "#! /bin/bash" > $@
@@ -225,6 +233,23 @@ $(PLUMED_MAIN_SHARED): $(OBJ_MAIN) $(PLUMED_SHARED_OBJ)
 $(PLUMED_MAIN_RUNTIME): $(OBJ_MAIN) $(OBJ_DYNAMIC_WRAPPER)
 	$(LD) $(LDFLAGS) $^ -o $@ $(LIBS)
 
+ifeq ($(PLUMED_INSTALL),Install)
+
+$(PLUMED_LIBDIR)Plumed.inc:
+	@echo Building Plumed.inc
+	@echo "PLUMED_RUNTIME_LOAD=" $(PLUMED_INSTALL_ROOT)/obj/Plumed.o $(LIBS) $(LDFLAGS) > $@
+ifdef LD_RO
+	@echo "PLUMED_STATIC_LOAD=" $(PLUMED_INSTALL_ROOT)/obj/kernel.o $(PLUMED_INSTALL_ROOT)/obj/PlumedStatic.o $(LIBS) $(DYNAMIC_LIBS) $(LDFLAGS) >> $@
+else
+	@echo "PLUMED_STATIC_LOAD=" $(shell ../maketools/listobjects $(PLUMED_INSTALL_ROOT)/obj/k $(OBJ_KERNEL)) $(PLUMED_INSTALL_ROOT)/obj/PlumedStatic.o $(LIBS) $(DYNAMIC_LIBS) $(LDFLAGS) >> $@
+endif
+	@echo "PLUMED_SHARED_LOAD=" $(PLUMED_INSTALL_PREFIX)/lib/lib$(PLUMED_PROGRAM_NAME).$(SOEXT) $(LIBS) $(LDFLAGS) >> $@
+	@echo "PLUMED_RUNTIME_DEPENDENCIES="   >> $@
+# when installing, it is sufficient to include dependence wrt a single object
+# indeed, the object are replaced all at the same time
+	@echo "PLUMED_STATIC_DEPENDENCIES=" $(PLUMED_INSTALL_ROOT)/obj/PlumedStatic.o  >> $@
+	@echo "PLUMED_SHARED_DEPENDENCIES=" $(PLUMED_INSTALL_PREFIX)/lib/lib$(PLUMED_PROGRAM_NAME).$(SOEXT)  >> $@
+else
 Plumed.inc:
 	@echo Building Plumed.inc
 	@echo "PLUMED_RUNTIME_LOAD=" $(realpath $(OBJ_DYNAMIC_WRAPPER)) $(LIBS) $(LDFLAGS) > $@
@@ -233,42 +258,38 @@ Plumed.inc:
 	@echo "PLUMED_RUNTIME_DEPENDENCIES="   >> $@
 	@echo "PLUMED_STATIC_DEPENDENCIES=" $(realpath $(OBJ_KERNEL)) $(realpath $(OBJ_WRAPPER))  >> $@
 	@echo "PLUMED_SHARED_DEPENDENCIES=" $(realpath .)/libplumed.$(SOEXT)  >> $@
+endif
 
-Plumed.inc.runtime: Plumed.inc
+$(PLUMED_LIBDIR)Plumed.cmake: $(PLUMED_LIBDIR)Plumed.inc
+	@echo Building Plumed.cmake
+	@../maketools/inc2cmake < $(PLUMED_LIBDIR)Plumed.inc > $@
+
+$(PLUMED_LIBDIR)Plumed.inc.runtime: $(PLUMED_LIBDIR)Plumed.inc
 	@echo Building Plumed.inc, runtime-linking version
 	@echo "# PLUMED: runtime installation" > $@
 	@grep PLUMED_RUNTIME $< | sed 's/PLUMED_RUNTIME_/PLUMED_/' >> $@
 
-Plumed.inc.static: Plumed.inc
+$(PLUMED_LIBDIR)Plumed.inc.static: $(PLUMED_LIBDIR)Plumed.inc
 	@echo Building Plumed.inc, static version
 	@echo "# PLUMED: static installation" > $@
 	@grep PLUMED_STATIC $< | sed 's/PLUMED_STATIC_/PLUMED_/' >> $@
 
-Plumed.inc.shared: Plumed.inc
+$(PLUMED_LIBDIR)Plumed.inc.shared: $(PLUMED_LIBDIR)Plumed.inc
 	@echo Building Plumed.inc, shared version
 	@echo "# PLUMED: shared installation" > $@
 	@grep PLUMED_SHARED $< | sed 's/PLUMED_SHARED_/PLUMED_/' >> $@
 
-Plumed.cmake:
-	@echo Building Plumed.cmake
-	@echo "set(PLUMED_RUNTIME_LOAD " $(realpath $(OBJ_DYNAMIC_WRAPPER)) $(LIBS) $(LDFLAGS)")" > $@
-	@echo "set(PLUMED_STATIC_LOAD " $(realpath $(OBJ_KERNEL)) $(realpath $(OBJ_WRAPPER)) $(LIBS) $(DYNAMIC_LIBS) $(LDFLAGS)")" >> $@
-	@echo "set(PLUMED_SHARED_LOAD " $(realpath ./)/libplumed.$(SOEXT) $(LIBS) $(LDFLAGS)")" >> $@
-	@echo "set(PLUMED_RUNTIME_DEPENDENCIES) "   >> $@
-	@echo "set(PLUMED_STATIC_DEPENDENCIES " $(realpath $(OBJ_KERNEL)) $(realpath $(OBJ_WRAPPER))")"  >> $@
-	@echo "set(PLUMED_SHARED_DEPENDENCIES " $(realpath ./)/libplumed.$(SOEXT)")"  >> $@
-
-Plumed.cmake.runtime: Plumed.cmake
+$(PLUMED_LIBDIR)Plumed.cmake.runtime: $(PLUMED_LIBDIR)Plumed.cmake
 	@echo Building Plumed.cmake, runtime-linking version
 	@echo "# PLUMED: runtime installation" > $@
 	@grep PLUMED_RUNTIME $< | sed 's/PLUMED_RUNTIME_/PLUMED_/' >> $@
 
-Plumed.cmake.static: Plumed.cmake
+$(PLUMED_LIBDIR)Plumed.cmake.static: $(PLUMED_LIBDIR)Plumed.cmake
 	@echo Building Plumed.cmake, static version
 	@echo "# PLUMED: static installation" > $@
 	@grep PLUMED_STATIC $< | sed 's/PLUMED_STATIC_/PLUMED_/' >> $@
 
-Plumed.cmake.shared: Plumed.cmake
+$(PLUMED_LIBDIR)Plumed.cmake.shared: $(PLUMED_LIBDIR)Plumed.cmake
 	@echo Building Plumed.cmake, shared version
 	@echo "# PLUMED: shared installation" > $@
 	@grep PLUMED_SHARED $< | sed 's/PLUMED_SHARED_/PLUMED_/' >> $@
diff --git a/src/maketools/copyobjects b/src/maketools/copyobjects
new file mode 100755
index 000000000..f01357bda
--- /dev/null
+++ b/src/maketools/copyobjects
@@ -0,0 +1,19 @@
+#! /bin/bash
+# copy the listed objects to prefix giving them a progressive number
+# e.g.
+# copyobjects pippo/k a/a.o b/b.o c/c.o
+# becomes
+# cp a/a.o pippo/k0.o
+# cp b/b.o pippo/k1.o
+# cp c/c.o pippo/k2.o
+
+prefix=$1
+
+shift
+
+i=0
+for file in "$@"
+do
+  cp $file $prefix$i.o
+  i=$((i+1))
+done
diff --git a/src/maketools/inc2cmake b/src/maketools/inc2cmake
new file mode 100755
index 000000000..a5d350237
--- /dev/null
+++ b/src/maketools/inc2cmake
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+awk '{
+  if(match($1,"[A-Z_]=")){
+    sub("="," ")
+    $0="set("$0")"
+  }
+  print 
+}'
diff --git a/src/maketools/listobjects b/src/maketools/listobjects
new file mode 100755
index 000000000..1a587e375
--- /dev/null
+++ b/src/maketools/listobjects
@@ -0,0 +1,13 @@
+#! /bin/bash
+# same as copyobjects but just print the names
+
+prefix=$1
+
+shift
+
+i=0
+for file in "$@"
+do
+  echo -n " $prefix$i.o"
+  i=$((i+1))
+done
-- 
GitLab