I ran into an interesting problem today. I am trying to compile and link a test executable to the Boost unit test framework and I tried it in two different ways.
The classic approach of linking directly to the "boost_unit_test_framework" library using -lboost_unit_test_framework
The modern CMake approach of linking to the Boost::unit_test_framework CMake target.
Interestingly when I link to the library directly my code compiles and links fine; however when I link to the CMake target my code fails to compile before it even gets to the linking stage!
The errors I get are related to a header file that it suddenly can't seem to find anymore. This suggests that linking to the Boost::unit_test_framework somehow messed with my include path.
I know linking to a CMake target is supposed to be the more modern and preferred approach, but if it can have such unexpected and unexplainable side effects, it seems worse than just linking straight to the library...
Why would linking the CMake target cause header files to not be found anymore? Also what other kinds of things can linking to a CMake target instead of linking directly to a library impact?
In both scenarios I am using target_link_libraries to link to the boost library. For example
target_link_libraries(mytest_exe
testlib
-lboost_unit_test_framework
)
or
target_link_libraries(mytest_exe
testlib
Boost::unit_test_framework
)
The fact that it is failing before linking means that the target_link_libraries command in CMake actually effects more than just linking. It is effecting the compilation as well.
Yes, it is true that new include directories are added when you link with a library target instead of the library file. This is why the approach is called "modern" - a single target_link_libraries call does all things which are needed to use the library (Boost in your case).
Reason of failing with "modern" approach could be that "true" Boost headers conflict with other headers you use. You may detect that via inspecting chain of include files in the error message.
Related
I have a custom build cmake v3.10.0 which was compiled with a gcc_4.8.3. I am using this custom build cmake to compile a cmake project that must use gcc _4.1.2 because of legacy code.
Executing cmake promted me with an error because it needs to use the libstdc++-IFX.so.6 provided by gcc_4.8.3 which I fixed by adding the path to the correct library in my LD_LIBRARY_PATH before the path to the libraries provided by gcc_4.1.2.
Compiling my project and linking an executable (which is done by c++) results in the linker taking the gcc_4.8.3 stdlibs over the gcc_4.1.2 libs. Is there any way to tell cmake to not use the libraries it needs for himself for my cmake project preferably without touching LD_LIBRARY_PATH?
Edits:
#squareskittles comment: I did read and try everything this post suggest but without any changes. The libstdc++-IFX.so.6 is still taken from gcc_4.8.3
So I am running into a pretty large headache building my software with CMake.
I am building a third party library statically (dlib) which requires zlib and libpng (both also static, I prebuilt these) libraries to support PNG functionality. The CMakeFile provided by the COTS dlib library is doing a basic:
target_link_libraries( dlib ${dlib_required_libs})
This is making all of its libraries configured as "general" libraries, which end up being used for both Release and Debug builds.
This isn't an issue in Linux, but Windows has a lovely "feature" of specifying the runtime library (/MT or /MD or /MTd or /MDd). Any mismatches between these flags cause multiple symbol definition errors at link time. i.e. If libpng was built with /MT and my software is using /MTd, they will be incompatible.
To alleviate this, I have two built versions of zlib and libpng. One set using the /MT flag for Release builds and the other /MTd for Debug builds. These happily link into my own software using optimized/debug flags on target_link_libraries where they are used. HOWEVER, dlib (3rd party) is only linking the Release set of the zlib and libpng libs by the way it's CMakeFile has been written.
My main question is, is there a way I can 'override' what dlib is linking without modifying it's provided CMakeFile?
I attempted overwriting dlib_LIB_DEPENDS and forcing it into the cache out of desperation, to no avail.
FindPNG.cmake script, like many other Find*.cmake scripts used by find_package(), does not care about multiconfig builds. So it just searched single library, while multiconfig builds naturally want library-per-config.
For make searched PNG library to be per-config, one can to write own FindPNG.cmake script (and set CMAKE_MODULE_PATH to point to the directory with this script).
But for concrete usage it is simpler to just rewrite output of the original script, that is set PNG_LIBRARY cache variable pointed to library-per-config:
optimized png-lib-release debug png-lib-debug
or, using generator expressions,
$<$<CONFIG:Release>:png-lib-release>$<$<CONFIG:Debug>:png-lib-debug>`
(instead of png-lib-release and png-lib-debug should be paths to the release and debug version of the library conrrespondingly).
Both these values are expected to be used with target_link_libraries command,
producing per-config linkage.
Dlib comes with copies of libpng and zlib in dlib/external. By default, dlib's CMakeLists.txt will build them the correct way and statically link them into your program. So the solution is to let it do that. Don't try to create a separate static library because, as you noted, that causes a lot of trouble on windows.
I am using boost::property_tree to read and write json files from a CMake C++ project. On machines I can install libjsoncpp and boost to the system, everything compiles, links, and works properly/as expected. However, I am now working on a machine I do not have root access to. Therefore I am compiling boost from source, and linking against it via CMake.
I am running into a problem where, it would seem, FindBoost.cmake is putting in a hard dependancy upon libjsoncpp.so
make[2]: *** No rule to make target /usr/lib64/libjsoncpp.so', needed bybin/myApp'. Stop.
I've tried building jsoncpp from source, and have tried adding the .a and .so to my cmake target_link_libraries command, but to no avail.
I'm not sure if this is related (or causing the issue somehow), but I am using
ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK) as boost::log requires it for linking from module modules.
I absolutely cannot have lipjsoncpp.so installed in /usr/lib64. What should I do?
I am trying to build a large Java/c++ project involving JNI and ANT in Eclipse, under Linux. One of the source c++ files calls the log10() function for mathematical calculations. The project compiles fine, but fails at linking, where it complains that it cannot find the libm.so library necessary to link log10().
My problem is that I am unable to properly tell Eclipse to link that file, even after the following steps:
Added the correct library path in the linker options,
Added a reference to libm in the linker include list,
Added -lm to the full compile options list,
Set LD_LIBRARY_PATH to point to the library's location,
Copied the library to the current directory.
What am I doing wrong/has anyone had such experiences with correctly linking libs in Eclipse? Any suggestions?
This is a bit confusing.
If you fail to find your library at runtime inside your java environment :
Try loading your .so library inside the java environment before making any calls to log10.
System.LoadLibrary("m");
Notice how I left "lib" and ".so" out.
However, you are complaining of a Linker problem from C++, you cannot link to a dynamic file. You can only link to a static library, or a static export library (so you need a libm.a file to which to link at compile time, and then your program will require libm.so at runtime).
Could you post the exact message you are receiving and when you are receiving it ?
I am using target_link_libraries to link external libraries to my application. But when one of the linked libraries changes, the make command does not detect and link the changed libraries again. Is there anything I have to include in the CMakeLists.txt file to observe and detect library changes?
CMake doesn't have this feature. Nor does it have a feature to detect changes in system-level header files (in /usr/include). It's probably not a good idea to add such features either, as it would slow down the common case. I suggest you just do a clean build after you have updated your system libraries.