====== Shared Libraries with FESA ====== This documents provides a straightforward recipe how to use shared libs with FESA and FECs\\ \\ CSCO encourages to link statically as this significantly eases deployment.\\ However, there are cases where vendors neither supply source code nor static libraries.\\ \\ CAEN's HVWrapper, for instance, was only optionally available static for a short period of time on request.\\ They don't ship static libs anymore - for technical reasons, whatever that actually means.\\ ==== Shared Lib Directories on ASL73x and FECs ==== When developing FESA classes on the ASL73x cluster, the directory\\ /common/fesa/fec/arch/L866_{32,64}/lib is available to place the shared libraries.\\ More specifically, ''/common/fesa'' is the mount point of ''fsl00c:/fesa''.\\ On the **FEC** fsl00c:/common/fesa/fec/arch/L866_{32,64} is mounted at /fec/arch i.e. the libraries are available at\\ /fec/arch/lib It is encouraged to create a subdirectory for each lib, e.g. HVWrapper resides in /common/fesa/fec/arch/L866_{32,64}/lib/caen with libcaenhvwrapper.so -> libcaenhvwrapper.so.5.77 libcaenhvwrapper.so.5.22 libcaenhvwrapper.so.5.56 libcaenhvwrapper.so.5.61 libcaenhvwrapper.so.5.62 libcaenhvwrapper.so.5.77 to make testing against different library versions simple.\\ However, since this affects all FECs globally,\\ make sure, that no operational system relying on that \\ lib boots or reloads the FESA binary while pointing\\ to an unwanted version and hooks it up - as this might \\ lead to unexpected behaviour! ==== Search Paths ==== The //required// linker flag -L only provides resolution of symbols and, thus, the specified\\ path **is not** the look-up path for the binary runtime.\\ \\ This is still provided by the system libs\\ and/or the LD_LIBRARY_PATH env variable.\\ However, a third option exists which does not require adminstration of the diskless system.\\ The linker flag -Wl,-rpath=[,-rpath=] includes hard-coded search paths for the shared lib into the binary.\\ This RPATH segment in the binary looks like the PATH variable string.\\ \\ Here is an example for the 64-bit CaenHvSYx527 FESA binary : Dynamic section at offset 0xf38d68 contains 31 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libetherbone.so.1] 0x0000000000000001 (NEEDED) Shared library: [libxml2.so.2] 0x0000000000000001 (NEEDED) Shared library: [librt.so.1] 0x0000000000000001 (NEEDED) Shared library: [libdl.so.2] 0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0] 0x0000000000000001 (NEEDED) Shared library: [libcaenhvwrapper.so] 0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6] 0x0000000000000001 (NEEDED) Shared library: [libm.so.6] 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2] 0x000000000000000f (RPATH) Library rpath: [/common/fesa/fec/arch/L866_64/lib/caen:/fec/arch/L866_64/lib/caen] ... The search order for shared libraries is as follows: LD_LIBRARY_PATH (env var) -> RPATH (via linker flag) -> system libs (e.g. via ldconfig for custom libs) ==== Boilerplate Code ==== When building FESA for a target architecture, the variable ''CPU'' is set to either //i686// or //x86_64//\\ and accessible from the Makefile. Depending on where linking to the custom vendor shared library happens,\\ this can be leveraged to define the directory name regarding bitness in the appropriate Makefile.specific: ifeq "$(CPU)" "i686" ARCH_DIR=L866_32 else ARCH_DIR=L866_64 endif (Currently, that's actually more connected to the distribution instead of the architecture - see RFC)\\ Next create to directory variables that reference the mount point on the ASL73x and the path as seen on the FEC.\\ Mind again that 'caen' is specific to this example. LIB_PREFIX_LOCAL=/common/fesa LIB_FEC_PATH_LOCAL=/fec/arch/$(ARCH_DIR)/lib/caen LIB_FEC_PATH=/fec/arch/lib/caen Two LIB_FEC* paths are required to make the binary run on the FEC and locally on the ASL73* cluster.\\ We can now append all appropriate paths to linker and rpath flags. LINKER_FLAGS += -L$(LIB_PREFIX_LOCAL)$(LIB_FEC_PATH_LOCAL) -lcaenhvwrapper LINKER_FLAGS += -Wl,-rpath=$(LIB_PREFIX_LOCAL)$(LIB_FEC_PATH_LOCAL),-rpath=$(LIB_FEC_PATH) There must be no whitespace around the commas!\\ Otherwise, the linker will complain.\\ \\ This allows to test the binary on the ASL73x cluster and run it on the FEC. ==== Proposal ==== I suggest changing the directory structure for shared libs from fec/arch/L866_{32,64}/lib// to fec/lib//{i686,x86_64}/ or fec/lib/{i686,x86_64}// for two reasons. (Where is your directory, e.g. //caen//, in this example)\\ \\ First, we will have other distributions soon, i.e. instead of differentiating only\\ between L866_32 and L866_64, there will be more (CentOS7, Systems with X, etc...)\\ However, only the architecture really matters. Second, we can directly leverage the ''CPU'' variable set during build time to \\ generate the appropriate target directories.