Handling header dependencies with cmake - gcc

Let's say I have main.cpp, a.h and b.h in the same folder. main.cpp includes a.h, and a.h includes b.h.
Checking the generated depends.make file, main.cpp.o depends both on a.h and b.h, as expected.
If b.h is moved to a folder B, and used the -iquote B flag, main.cpp.o does not depend any more on b.h.
I can put back the dependency by adding include_directories(${CMAKE_SOURCE_DIR}/B) to the CMakeLists.txt file. This however has a side effect: when compiling main.cpp, cmake uses the flag -I/pathTo/B. I prefer using -iquote instead of -I.
Is there a way in this second case to let cmake to detect the dependencies automatically without introducing the -I compiler flag?

You might find this SO answer helpful: https://stackoverflow.com/a/9899919/5820799
It boils down to not use include_directories(${CMAKE_SOURCE_DIR}/B), but to manually add the -iquote directive instead:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -iquote ${CMAKE_SOURCE_DIR}/B")
This will generate -iquote <path> instead of -I <path>.
It is not pretty, but does the job. :-)

Related

Why is CMake putting "std=gnu++14" in Clang invocations when I don't specify GCC?

I have a pretty simple CMake-based project that builds one lib and a small executable that uses it. It builds fine on Linux with GCC, but fails on Mac OS with loads of errors of the following kind. The inciting line of code in main.cpp is the second one here:
#include <cstdlib>
#include <memory>
The first of many similar errors:
[build] In file included from /Users/me/data/series2server/main.cpp:2:
[build] In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/memory:671:
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/__algorithm/search.h:34:19: error: no member named 'make_pair' in namespace 'std::__1'
[build] return _VSTD::make_pair(__first1, __first1); // Everything matches an empty sequence
This appears to be a mismatch between Clang and GCC uses of std. But I can't figure out why CMake is configuring things to call clang++ but putting "std=gnu++14" in the compiler invocation. I did a full-text search for "std=gnu" in the whole source tree and didn't find it. I do see this in various CMakeLists.txt files:
set( CMAKE_CXX_STANDARD 14 )
A compiler invocation is below. Where might I look for where this gnu option is specified? Thanks!
[build] cd /Users/me/data/series2server/build/restbed && /usr/bin/clang++ -DBUILD_SSL -I/Users/me/data/series2server/restbed/source -isystem /Users/me/data/series2server/restbed/dependency/asio/asio/include -isystem /Users/me/data/series2server/restbed/dependency/openssl/include -Wall -Wextra -Weffc++ -pedantic -Wno-unknown-pragmas -Wno-deprecated-declarations -Wno-non-virtual-dtor -DASIO_STANDALONE=YES -Wno-deprecated-declarations -g -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk -std=gnu++14 -MD -MT restbed/CMakeFiles/restbed-static.dir/source/corvusoft/restbed/detail/service_impl.cpp.o -MF CMakeFiles/restbed-static.dir/source/corvusoft/restbed/detail/service_impl.cpp.o.d -o CMakeFiles/restbed-static.dir/source/corvusoft/restbed/detail/service_impl.cpp.o -c /Users/me/data/series2server/restbed/source/corvusoft/restbed/detail/service_impl.cpp
From n.m.'s comment 10 years ago, for clarity:
set( CMAKE_CXX_STANDARD 14 ) sets gcc or clang flag to -std=gnu++14, unless CXX_EXTENSIONS property (or CMAKE_CXX_EXTENSIONS variable) is set to OFF.

CMake: correctly linking system library using gcc

I have a static libary mylib that depends on the math library.
If I first link mylib with math and then to my executable it works:
add_executable(myapp main.c)
target_link_libraries(mylib m)
target_link_libraries(myapp mylib)
But if I do the linking directly with the executable it fails when using gcc (with clang it works!)
add_executable(myapp main.c)
target_link_libraries(myapp m mylib)
Why does this make any difference?
I thought that it is anyway not possible to link libraries together?
When using cmake's target_link_libraries it does not mean you will link anything. It rather will create a dependency between a target and a library of type/action link.
I guess that the actually build line of the first example will result in something like that:
gcc -o myapp myapp.o -lmylib -lm
and the second one
gcc -o myapp myapp.o -lm -lmylib
. If mylib has references to m the second example (might) not link.
Try to run make VERBOSE=1 and study the command-line of the link-process to really understand what's happening. The linker of clang is maybe intelligent and waits for all calls to be linked before actually dropping a library during the link-process.
When using target_link_libraries it matters in which order you specify linked libraries.
This does not work when using gcc (at least in v4.6.3):
target_link_libraries(myapp m mylib)
while this works:
target_link_libraries(myapp mylib m)
So all libraries mylib depends on have to come after mylib.
If you track down the actual linker invocation with make VERBOSE=1 you will find this for the broken example:
gcc main.c.o -o luatest -rdynamic -lm mylib.a
and this for the working one:
gcc main.c.o -o luatest -rdynamic mylib.a -lm
Invoking clang with the exact same parameters works in both cases!
So #PatrickB seems to be right:
The linker of clang is maybe intelligent and waits for all calls to be
linked before actually dropping a library during the link-process.

Linking with dynamic library with dependencies

Consider the following scenario:
Shared Library libA.so ,with no dependencies.
Shared Library libB.so, with libA.so as its dependency.
I want to compile a binary file that links with the libB.
Should I link the binary with libB only or with libA either?
Is there any way to link only with the direct dependencies, letting the resolution of unresolved symbols from the dependencies for runtime?
I'm worried about the fact that the library libB implementation may change in the future, introducing other dependencies (libC, libD, libE for instance). Am I going to have problems with that?
In other words:
libA files: a.cpp a.h
libB files: b.cpp b.h
main program files: main.cpp
Of course, b.cpp includes a.h and main.cpp includes b.h.
Compilation commands:
g++ -fPIC a.cpp -c
g++ -shared -o libA.so a.o
g++ -fPIC b.cpp -c -I.
g++ -shared -o libB.so b.o -L. -lA
Which of the bellow options should I use?
g++ main.cpp -o main -I. -L. -lB
or
g++ main.cpp -o main -I. -L. -lB -lA
I couldn't use the first option. The linker complains about the unresolved symbols from the library libA. But it sound a little strange to me.
Thanks very much.
-- Updated comments:
When I link the binary, the linker will try to resolve all symbols from the main and the libB. However, libB has undefined symbols from the libA. That's why the linker complains about that.
That's why I need to link with the libA too.
However I found a way to ignore unresolved symbols from shared libraries.
Looks like I should use the following command line to do that:
g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs
Looks like it is still possible to use the -rpath option.
However I need to understand it a little better.
Does anyone knows any possible pitfalls when using the -Wl,-unresolved-symbols=ignore-in-shared-libs option?
-- Updated comments 2:
-rpath should not be used for this purpose. It is useful to force a library to be found in a given directory. The -unresolved-symbol approach looks much better.
Thanks again.
It looks like you are most of the way there already. Well done with your investigation. Let's see if I can help clear up the 'why' behind it.
Here's what the linker is doing. When you link your executable ('main' above) it has some symbols (functions and other things) that are unresolved. It will look down the list of libraries that follow, trying to resolve unresolved symbols. Along the way, it finds that some of the symbols are provided by libB.so, so it notes that they are now resolved by this library.
However, it also discovers that some of those symbols use other symbols that are not yet resolved in your executable, so it now needs to resolve those as well. Without linking against libA.so, your application would be incomplete. Once it links against libA.so, all symbols are resolved and linking is complete.
As you saw, the use of -unresolved-symbols-in-shared-libs, doesn't fix the problem. It just defers it so that those symbols are resolved at run time. That's what -rpath is for: to specify the libraries to be searched at run time. If those symbols can't be resolved then, your app will fail to start.
It's not an easy thing to figure out library dependencies because a symbol could be provided by more than one library and be satisfied by linking against any one of them.
There is another description of this process here: Why does the order in which libraries are linked sometimes cause errors in GCC?
For dynamic linking only with direct dependencies you can use -Wl,--as-needed with adding the libs after -Wl,--as-needed:
gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA
For checking the direct dependencies you should use readelf instead of ldd because ldd also shows the indirect dependencies.
$ readelf -d main | grep library
0x0000000000000001 (NEEDED) Shared library: [libB.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
ldd also shows the indirect dependencies:
$ LD_LIBRARY_PATH=. ldd ./main
linux-vdso.so.1 (0x00007fff13717000)
libB.so => ./libB.so (0x00007fb6738ed000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb6734ea000)
libA.so => ./libA.so (0x00007fb6732e8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb673af0000)
If you use cmake, you can add the following lines to include only direct dependencies:
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}")
Another option is to use libtool
If you change the g++ call to libtool --mode=compile g++ to compile the source code and then libtool --mode=link g++ to create the application off of libB, then libA will be linked automatically.
This is an interesting post - I was banging my head with this as well, but I think you miss a point here..
The idea is as follows, right ?
main.cpp =(depends)=> libB.so =(depends)=> libA.so
Let's further consider that ..
In a.cpp (and only there) you define a class / variable, let's call it "symA"
In b.cpp (and only there) you define a class / variable, let's call it "symB".
symB uses symA
main.cpp uses symB
Now, libB.so and libA.so have been compiled as you described above. After that, your first option should work, i.e.:
g++ main.cpp -o main -I. -L. -lB
I guess that your problem originates from the fact that
in main.cpp you also refer to symA
Am I correct?
If you use a symbol in your code, then that symbol must be found in an .so file
The whole idea of inter-referencing shared libraries (i.e. creating APIs), is that the symbols in the deeper layers are hidden (think of peeling onions) and not used.
.. i.e. don't refer to symA in your main.cpp, but only to symB instead (and let symB to refer symA only).

Flags for g++ static link when using -nostartfiles -nodefaultlibs -nostdlib

I've been trying to find the proper .a's and related flags for statically linking an app or SO under Linux. I know -static exists, but I can't use it as there's one specific SO I must link to.
To put it another way, I'm looking for the appropriate flags to statically link everything, except for a specific SO.
Thanks.
At my workplace we use -Bstatic and -Bdynamic but they are options to the linker ld. You can specify them with gcc using the -Wl option.
g++ -o app -Wl,-Bstatic -llib1 -llib2 -llib3 -Wl,-Bdynamic -llib4 app.o
Above shows command line for linking with lib1, lib2, and lib3 as static libraries and lib4 as a shared object library.

how to link static library into dynamic library in gcc

Under gcc (g++), I have compiled a static .a (call it some_static_lib.a) library. I want to link (is that the right phrase?) this .a file into another dynamic library (call it libsomeDyn.so) that I'm building. Though the .so compiles, I don't see content of .a under .so using nm command:
/usr/bin/g++ -fPIC -g -O2 -Wall -Werror -pipe -march=pentium3
-mtune=prescott -MD -D_FILE_OFFSET_BITS=64 -DLINUX -D_GNU_SOURCE -D_THREAD_SAFE -I../../../../../../../../ -I../../../../../../../..//libraries -Wl,-rpath,/usr/lib -o libsomeDyn.so some.o another.o some_static_lib.a -shared -Wl -x
-Wl,-soname,libsomeDyn.so
I do not see functions under some_static_lib.a under libsomeDyn.so. What am I doing wrong?
Static libraries have special rules when it comes to linking. An object from the static library will only be added to the binary if the object provides an unresolved symbol.
On Linux, you can change that behavior with the --whole-archive linker option:
g++ -Wl,--whole-archive some_static_lib.a -Wl,--no-whole-archive
For every one that comes across that problem like me (and has not understand the answer properly): here is a short howto generate a dynamic library (libmylib.so) from a static one (mylib.a):
1.) create a mylib.c file that only imports the mylib.h file
2.) compile this mylib.c to mylib.o with
gcc -c -fPIC mylib.c -o mylib.o
3.) generate a dynamic library with the following command:
gcc --whole-archive -shared -Wl,-soname,libmylib.so -o libmylib.so mylib.o mylib.a
That worked at least for me, turning a static library (compiled with -fPIC) to
a dynamic library. I'm not sure wether this will work for other libraries too.

Resources