1.1.
1.2. Scope
Establish a standard method for laying out the common libraries to be used by components in a workflow. The complexity lies in the fact that components may be compiled with different library versions and even different compilers and versions of them, so the library layout must enable dynamically loading the relevant library for each workflow component.
1.3. Background and decision status
- The previous method used by the “ITM” is judged too complicate to maintain in the long term, so some adaptation should be made at the occasion of the transition to IMAS.
- IO provides only a framework where local sysadmins add their own path extensions to the user environment, because of no control on how other dependencies will be resolved on future systems (see discussions with IO on this topic: IMAS-1188, IMAS-1484, IMAS-1072),
Taking these factors into consideration CPT proposes "EUROfusion flavor" of library modules and related layout.
1.4. Usage scenario:
- User defines compiler being used and loads all IMAS/EF DD not dependent libraries / tools
module load imaslibs[/<compiler_vendor>/<compiler_version>/<version of this module>]
- User load
imas module
plus all components dependent on IMAS/Data Dictionarymodule load imasenv[/<imas_ver>/ual/<engine_ver>/<version of this module>]
- User cherry-picks version of library
module switch <imas_lib>
Assumptions
imaslibs
andimasenv
modules have to be loaded prior to<imas_lib>
module <imas_lib>
can be only switched
1.5. Module names
The module name explicitly identifies the library’s name and version and the compiler’s name and version.
module switch <LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION> E.g.: module switch ggd/1.8.0[/intel/17/imas/3.21.0/ual/3.8.4]
- Each module is conflicting with the others (of the same library).
- Meta-modules allowing loading at once all modules in a coherent environment for a given workflow/application (if not conflicting) will be available.
- In case a complex workflow/application contains components using conflicting libraries (i.e. using different versions/compilers for the same library), the relevant module must be loaded (switched) prior to the component compilation, and then unloaded.
Naming convention for compilers
GNU Compiler Collection -> gcc Intel -> intel
1.6. Package names
pkg-config --cflags --libs <LIB_NAME> E.g.: pkg-config --cflags --libs ggd
- Please notice that there are no longer <LIB_NAME>-<COMPILER_NAME> (e.g. ggd-ifort packages), as given module could be loaded for one compiler only
1.7. RPATH - library discovery at runtime
One of the drawbacks of the module based layout is the problem of pointing to proper library (if we don't have symbolic links with fully qualified names).
This issue can be solved with rpath while compiling the code. Instead of having number of libraries, each with slightly different name, we can use rpath instead.
gcc -o $@ $< -Iinclude -Llib -lshared -Wl,-rpath,$(CURDIR)/lib
This way, each code will refer to version of library used for linking.
Pros | Cons |
---|---|
different codes can use different versions of libraries | with each release of new version of the library user's code must be recompiled |
each library is released as a separate installation (it's easy to maintain each version separately) | it's not possible to move libraries from their original location |
we are not forced to build log LD_LIBRARY_PATH variables | |
LD_LIBRARY_PATH has lower precedence than rpath | |
It is still possible to use LD_PRELOAD to enforce given library to be used (e.g. debugging purposes) |
1.7.1. Libraries layout
Examples are provided for a single library (XMLLIB) for the sake of clarity, to be generalised for all libraries.
In case the library depends on the Data Dictionary (DD) version, this DD version information shall be included in the <LIB_VERSION> string.
1.7.2. Libraries
The library layout explicitly identifies the library’s name and version and the compiler’s name and version and puts the various files of the library as follows:
<ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/include/*.h <ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/include/*.mod <ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/lib/*.a <ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/lib/*.so <ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/lib/pkgconfig/<LIB_NAME>.pc <ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/src <ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/example <ROOT_LIB_PATH>/<LIB_NAME>/<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/man
Note that all pc files have the same name, for the sake of simplicity (for the code developer).
In addition, a “central” repository
<ROOT_LIB_PATH>/<LIB_NAME>/lib
contains links to the *.so files (for all library versions and compiler names and versions), in order to keep $LD_LIBRARY_PATH length below the operating system limit.
<ROOT_LIB_PATH>/<LIB_NAME>/lib/lib<LIB_NAME>-<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>.so -> ../<LIB_VERSION>-<COMPILER_NAME>-<COMPILER_VERSION>/lib/lib<LIB_NAME>.s
1.7.3. Example
<ROOT_LIB_PATH>/xmllib/1.0-ifort-17/include/*.h *.mod <ROOT_LIB_PATH>/xmllib/1.0-ifort-17/lib/*.a *.so <ROOT_LIB_PATH>/xmllib/1.0-ifort-17/lib/pkgconfig/xmllib.pc <ROOT_LIB_PATH>/xmllib/1.0-ifort-17/src <ROOT_LIB_PATH>/xmllib/1.0-ifort-17/example <ROOT_LIB_PATH>/xmllib/1.0-ifort-17/man <ROOT_LIB_PATH>/xmllib/lib/libxmllib-1.0-ifort-17.so -> ../1.0-ifort-17/lib/libxmllib.so
1.7.4. Example of XMLLIB installation based on IMAS based release
swimas |-- etc | `-- modulefiles | `-- xmllib | |-- 4.0-gnu-6.1.0 | `-- 4.0-intel-17.0.4 `-- extra `-- xmllib |-- 4.0-gnu-4.8.5 | |-- include | | |-- f90_file_reader.mod | | |-- mod_f90_kind.mod | | |-- string_manipulation_tools.mod | | |-- xml2eg_mdl.mod | | |-- xml_file_reader.mod | | |-- xmllib_parser.mod | | |-- xmllib_pathquery.mod | | `-- xmllib_types.mod | `-- lib | |-- libxmllib.a | `-- pkgconfig | `-- xmllib.pc |-- 4.0-intel-17.0.4 | |-- include | | |-- f90_file_reader.mod | | |-- mod_f90_kind.mod | | |-- string_manipulation_tools.mod | | |-- xml2eg_mdl.mod | | |-- xml_file_reader.mod | | |-- xmllib_parser.mod | | |-- xmllib_pathquery.mod | | `-- xmllib_types.mod | `-- lib | |-- libxmllib.a | `-- pkgconfig | `-- xmllib.pc `-- lib # this can be completely removed if we start using -rpath |-- libxmllib-4.0-gnu-4.8.5.a -> ../4.0-gnu-4.8.5/lib/libxmllib.a # this can be completely removed if we start using -rpath `-- libxmllib-4.0-intel-17.0.4.a -> ../4.0-intel-17.0.4/lib/libxmllib.a # this can be completely removed if we start using -rpath
1.7.5. RPATH - compiling codes with fixed location of libraries
One of the drawbacks of the module based layout is the problem of pointing to proper library (if we don't have symbolic links with fully qualified names).
This issue can be solved with rpath while compiling the code. Instead of having number of libraries, each with slightly different name, we can use rpath instead.
gcc -o $@ $< -Iinclude -Llib -lshared -Wl,-rpath,$(CURDIR)/lib
This way, each code will refer to version of library used for linking.
Pros | Cons |
---|---|
different codes can use different versions of libraries | with each release of new version of the library user's code must be recompiled |
each library is released as a separate installation (it's easy to maintain each version separately) | it's not possible to move libraries from their original location |
we are not forced to build log LD_LIBRARY_PATH variables | |
LD_LIBRARY_PATH has lower precedence than rpath | |
It is still possible to use LD_PRELOAD to enforce given library to be used (e.g. debugging purposes) |
1.7.6. RPATH - slightly different layout of directories
In case of rpath based compilation we don't need centrally located lib directory at all. All files (paths) will be provided by pc files for each and every module.
swimas |-- etc | `-- modulefiles | `-- xmllib | |-- 4.0-gnu-6.1.0 | `-- 4.0-intel-17.0.4 `-- extra `-- xmllib |-- 4.0-gnu-4.8.5 | |-- include | | |-- f90_file_reader.mod | | |-- mod_f90_kind.mod | | |-- string_manipulation_tools.mod | | |-- xml2eg_mdl.mod | | |-- xml_file_reader.mod | | |-- xmllib_parser.mod | | |-- xmllib_pathquery.mod | | `-- xmllib_types.mod | `-- lib | |-- libxmllib.a | `-- pkgconfig | `-- xmllib.pc `-- 4.0-intel-17.0.4 |-- include | |-- f90_file_reader.mod | |-- mod_f90_kind.mod | |-- string_manipulation_tools.mod | |-- xml2eg_mdl.mod | |-- xml_file_reader.mod | |-- xmllib_parser.mod | |-- xmllib_pathquery.mod | `-- xmllib_types.mod `-- lib |-- libxmllib.a `-- pkgconfig `-- xmllib.pc