Linking static fortran libraries with inter-dependencies - linker

I am developing a Fortran program prog1 and two Fortran libraries, lib1 and lib2. prog1 depends on lib1 and lib2, and lib1 also depends on lib2. The directory structure might look like:
prog1
|- lib2
|- lib1
|- lib2
In some cases, I would like prog1 to use a different version of lib2 than what lib1 uses. However, if the static library lib1.a includes the object files from lib2, the linker gives me errors like
./lib1/lib1.a(lib2_module.o): In function `__lib2_module_MOD_function1':
./lib2/src/lib2_module.f90:12: multiple definition of `__lib2_module_MOD_function1'
./lib2/lib2.a(lib2_module.o):./lib2/src/lib2_module.f90:12: first defined here
In other words, the linker is confused since both libraries contain the same object file lib2_module.o, but with different versions.
So my question is: How can two Fortran libraries contain (and use) different versions of the same object files?

I do not think it is possible to do it by usage of static libraries. It is because from prog1 prespective, function1 from lib2's module is simple defined 2 times.
On Wikipedia you can see that
...external functions and variables which are resolved in a caller at
compile-time and copied into a target application...
And you would probably not be suprised that this code would generate similar errors you see in your question:
prog1.f90
some code here...
function funtion1(x) ...
...first version of function1 ...
end function
function funtion1(x) ...
...second version of function1 ...
end function
some code here...
One possibility would be to compile at least lib1 as shared library and make sure (compiler/platform dependent) that the symbols from lib2 are not exported from shared lib1.

Related

Override weak symbols in static library

I want to make a static .a library for my project from multiple sources, some of them define weak functions and others implements them. Let's say as example I have :
lib1.c :
void defaultHandler()
{
for(;;);
}
void myHandler() __attribute__((weak, alias ("defaultHandler")));
lib2.c :
void myHandler()
{
/* do my stuff here */
}
Then I want to put them into one single library, so that it seems transparent for the end application
$ ar -r libhandlers.a lib1.o lib2.o
But there is now 2 symbols myHandler in libhandlers :
$ nm libhandlers.a | grep "myHandler"
00000001 W myHandler
00000581 T myHandler
And then when using the lib, the weak reference is linked. The only solution I have for the moment is to not include in the library lib2.c but to add it as source in the application's Makefile… that's not satisfying since I would like to provide only a few libraries to use and not a whole bunch of files.
The --whole-archive option is also not satisfying since I work on embedded system and I don't want to include all things I don't need.
Is there a way to compile the library so that the weak symbol disappear if a strong one is provided?
NOTE : I'm using arm-none-eabi-gcc v4.8
This is a byproduct of the way that .a libraries work - they're simply a collection of .o files.
What happens at compile link time is that the first reference to the name gets resolved to the weak reference and the strong name never gets a look in.
You can test this yourself by actually making both the identical name and strong and you'll see exactly the same behaviour.
If you want the strong references resolved first, then put them earlier in the archive, or create a separate strong archive and link that first in the link-line.
While not directly applicable to your case, as you're using an embedded environment, weak vs. strong references come into force properly when creating/consuming .so dynamic libraries rather than .a archives. When you create a .so, all the weak references that make up the library will not generate an error, and only one of them will be used for the final product; and if there is a strong definition anywhere then it gets used rather than any of the weak ones (this only works properly if, when you're creating a .so, you link all the .o files that make it up separately, or use the --whole-archive when creating the .so if linking to a .a).

gcc nested libraries and linker dependencies

Situation:
i have a static library "lib1.a" ;
a second static library "lib2.a" that uses the functions of "lib1.a";
an application that directly uses just the functions of "lib2.a".
When i link the application i have to pass to the application dependencies also "lib1.a" even if the application do not calls directly none of lib1 functions. Lib2 is a sort of more high level wrapper library.
Is there a way to link lib1 inside lib2 (a sort of intermediate linking) so that the "app" does not even know about the existence of lib1?
I know that i can scompact lib1.a and include the objects files inside lib2.a but is there another way so that is done automatically and JUST the USED object files are included inside lib2? Linke when you link the final app.
{app} -uses-> {lib2} -uses-> {[lib1]}
Cheers,
Davide
is there another way
No, there is not (on any UNIX-like system I know of).
The best you can do, when using GNU-ld or gold, is to write a libcombined.a as a linker script, containing -l2 -l1, and point the application to it.

Linking a Shared Library Autotools

I'm an autotools beginner, and I can't seem to figure out how to use an external library correctly with autotools.
Here is my directory hierarchy.
.
├── configure.ac
├── Makefile.am
├── README
└── src
(source files)
└── Makefile.am
The library's name is acml_mp and is, by default, installed in /opt/acml5.3.1/gfortran64/lib. There is also a directory called /opt/acml5.3.1/gfortran64/include to include. When I compile without autotools, including the usual compiler flags works fine:
g++ ... -L/opt/acml5.3.1/gfortran64_mp/lib -I/opt/acml5.3.1/gfortran64_mp/include -lacml_mp ...
In configure.ac, I put the command AC_LIB_LINKFLAGS([acml_mp]) which I think only deals with the -lacml_mp flag.
Basically, the end goal is to have autoconf search for this library, and have the makefile generated by automake include the correct link/include paths when compiling. Finally, when compiling by hand, I always need to modify the environment variable LD_LIBRARY_PATH using the command
Export LD_LIBRARY_PATH=/opt/acml5.3.1/gfortran64_mp/lib:$LD_LIBRARY_PATH
which, ideally, I would like to avoid having the user do. Apologies if this information exists already, I looked through SO and Google for a few hours to no avail.
The problem with searching is that /opt/acml5.3.1/gfortran is never going to be a standard (search) location for libraries (and headers) like /usr/lib, /usr/local/lib etc. Probably the best bet is to supply this location explicitly via --with-acml to configure.
The AC_ARG_WITH macro is described here. Assuming test "x$with_acml" != xno, you can try linking a program with AC_LINK_IFELSE.
AC_LANG_PUSH([C]) # or [Fortran]
ac_save_acml_CPPFLAGS="$CPPFLAGS" # or FCFLAGS instead of CPPFLAGS.
ac_save_acml_LIBS="$LIBS"
ac_acml_CPPFLAGS="-I${with_acml}/include"
ac_acml_LIBS="-L${with_acml}/libs -lacml_mp"
CPPFLAGS+="$ac_acml_CPPFLAGS"
LIBS+="$ac_acml_LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM( ... some C or Fortran program ... )],,
AC_MSG_FAILURE([couldn't link with acml]))
AC_LANG_POP
# we *could* stop here... but we might need the original values later.
CPPFLAGS="$ac_save_acml_CPPFLAGS"
LIBS="$ac_save_acml_LIBS"
AC_SUBST(ACML_CPPFLAGS, $ac_acml_CPPFLAGS)
AC_SUBST(ACML_LIBFLAGS, $ac_acml_LIBS)
Assuming you've initialized libtool support with LT_INIT, you can add the acml library with $(ACML_LIBFLAGS) to your own libraries in src/Makefile.am via the LIBADD variable, or to executables with the LDADD variable. or <lib>_la_LIBADD, <prog>_LDADD respectively.
To compile sources with the $(ACML_CPPFLAGS) include path, add it to the AM_CPPFLAGS variable. Or the <prog>_CPPFLAGS variable.
It's difficult to be specific without knowing how your Makefile.am is already set up. I know it looks complicated - but it's better to get the infrastructure right the first time. I'll add to the answer if you have further questions.

UNIX: Static library linked to a static library [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to pack multiple library archives (.a) into one archive file?
I have a situation where I must provide only a single static library (.a file) to an executable file to build it.
However, I split this lib in 2 parts because one part is common to other executable files and the other is needed only by one.
So now I have lib1 (for exe1) and lib2 (for all exes)
The problem is that I can't provide two libs, so I must merge for exe1, lib2 into lib1
I tried my compiling the lib1.o with -llib2 but even if it works, it looks like if nothing happened
Are there any other way? I'm can only think about using raw object files but I don't like this idea
There's no need for two static libraries; when a static library is used, only the functions (or variables) that are needed are copied to the executable - unlike a shared library where everything in the library is accessible to the executable.
Mechanically, the other question referenced describes what you need to do:
Extract all the object files from one library
Add them to the other library
Or:
files=$(ar t lib1.a)
ar x lib1.a
ar r lib2.a $files
rm -f $files lib1.a
You can even compile each source file, produce all .o and create two different libs by using ar.
The whole library will be produced using all .o (the ones you put in lib1.a and lib2.a together), the smaller one will use just a reduced set of .o files.
Than... a single Makefile, .o files produced once, two libraryes coming out from this job: the complete one (libaplus2.a) and the reduced one (lib1.a).

Is it possible to get CMake to build both a static and shared library at the same time?

Same source, all that, just want a static and shared version both. Easy to do?
Yes, it's moderately easy. Just use two "add_library" commands:
add_library(MyLib SHARED source1.c source2.c)
add_library(MyLibStatic STATIC source1.c source2.c)
Even if you have many source files, you can place the list of sources in a Cmake variable, so it's still easy to do.
On Windows you should probably give each library a different name, since there is a ".lib" file for both shared and static. But on Linux and Mac you can even give both libraries the same name (e.g. libMyLib.a and libMyLib.so):
set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
But I don't recommend giving both the static and dynamic versions of the library the same name. I prefer to use different names because that makes it easier to choose static vs. dynamic linkage on the compile line for tools that link to the library. Usually I choose names like libMyLib.so (shared) and libMyLib_static.a (static). (Those would be the names on linux.)
Since CMake version 2.8.8, you can use "object libraries" to avoid the duplicated compilation of the object files. Using Christopher Bruns' example of a library with two source files:
# list of source files
set(libsrc source1.c source2.c)
# this is the "object library" target: compiles the sources only once
add_library(objlib OBJECT ${libsrc})
# shared libraries need PIC
set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)
# shared and static libraries built from the same object files
add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>)
add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>)
From the CMake docs:
An object library compiles source files but does not archive or link
their object files into a library. Instead other targets created by
add_library() or add_executable() may reference the objects using an
expression of the form $<TARGET_OBJECTS:objlib> as a source, where
objlib is the object library name.
Simply put, the add_library(objlib OBJECT ${libsrc}) command instructs CMake to compile the source files to *.o object files. This collection of *.o files is then referred to as $<TARGET_OBJECT:objlib> in the two add_library(...) commands that invoke the appropriate library creation commands that build the shared and static libraries from the same set of object files. If you have lots of source files, then compiling the *.o files can take quite long; with object libraries you compile them only once.
The price you pay is that the object files must be built as position-independent code because shared libraries need this (static libs don't care). Note that position-independent code may be less efficient, so if you aim for maximal performance then you'd go for static libraries. Furthermore, it is easier to distribute statically linked executables.
There is generally no need to duplicate ADD_LIBRARY calls for your purpose. Just make use of
$> man cmake | grep -A6 '^ *BUILD_SHARED_LIBS$'
BUILD_SHARED_LIBS
Global flag to cause add_library to create shared libraries if on.
If present and true, this will cause all libraries to be built shared unless the library was
explicitly added as a static library. This variable is often added to projects as an OPTION
so that each user of a project can decide if they want to build the project using shared or
static libraries.
while building, first (in one out-of-source directory) with -DBUILD_SHARED_LIBS:BOOL=ON, and with OFF in the other.
Please be aware that previous answers won't work with MSVC:
add_library(test SHARED ${SOURCES})
add_library(testStatic STATIC ${SOURCES})
set_target_properties(testStatic PROPERTIES OUTPUT_NAME test)
CMake will create test.dll together with test.lib and test.exp for shared target. Than it will create test.lib in the same directory for static target and replace previous one. If you will try to link some executable with shared target it will fail with error like:
error LNK2001: unresolved external symbol __impl_*.`.
Please use ARCHIVE_OUTPUT_DIRECTORY and use some unique output directory for static target:
add_library(test SHARED ${SOURCES})
add_library(testStatic STATIC ${SOURCES})
set_target_properties(
testStatic PROPERTIES
OUTPUT_NAME test
ARCHIVE_OUTPUT_DIRECTORY testStatic
)
test.lib will be created in testStatic directory and won't override test.lib from test target. It works perfect with MSVC.
It's possible to pack eveything in the same compilation breath, as suggested in the previous answers, but I would advise against it, because in the end it's a hack that works only for simple projects. For example, you may need at some point different flags for different versions of the library (esp. on Windows where flags are typically used to switch between exporting symbols or not). Or as mentionned above, you may want to put .lib files into different directories depending on whether they correspond to static or shared libraries. Each of those hurdles will require a new hack.
It may be obvious, but one alternative that has not been mentionned previously is to make the type of the library a parameter:
set( ${PROJECT_NAME}_LIBTYPE CACHE STRING "library type" )
set_property( CACHE ${PROJECT_NAME}_LIBTYPE PROPERTY STRINGS "SHARED;STATIC" )
add_library( ${PROJECT_NAME} ${PROJECT_NAME}_LIBTYPE ${SOURCE_FILES} )
Having shared and static versions of the library in two different binary trees makes it easier to handle different compilation options. I don't see any serious drawback in keeping compilation trees distinct, especially if your compilations are automated.
Note that even if you intend to mutualize compilations using an intermediate OBJECT library (with the caveats mentionned above, so you need a compelling reason to do so), you could still have end libraries put in two different projects.

Resources