Compilation issues with Cmake and Intel IPP under Ubuntu - c++

The issue is that I have a source which includes ipps.h and this code I'm able to compile into a test.so file without issues.
The problem starts when I have a Qt example which requires this built test.so file, I get the following messages from the compiler:
/home/antti/test.so: undefined reference to 'ippsFilterMedianGetBufferSize'
/home/antti/test.so: undefined reference to 'ippsFilterMedian_32f'
In my CMakeLists.txt for compiling the test.so, I have the following lines in the end of the file:
add_library(libippcore SHARED IMPORTED)
set_property(TARGET libippcore PROPERTY IMPORTED_IMPLIB "/opt/intel/compilers_and_libraries_2018.3.222/linux/ipp/lib/ia32_lin/libippcode.so")
Is this a linker problem or what is causing the issue? And how to solve it properly? The strange thing is that the Qt example is built with its own CMakeLists.txt but I don't see any reference in it to the test.so file even though it clearly includes it somehow.

The 'ippsFilterMedian_32f' function is in 'libipps.so' library. That is signal processing library.
So, you need to add libipps (along with libippcore) to your cmake file.
Let's look what happens after you successfully built test.so.
Regards,
Sergey

Related

C++ - Why is a Static Library unusable without source files?

So from what I understand, a static compiled mylib.a file should just be usable as plug-and-play. But I can't use it without the source code, I'm trying to avoid that.
I adapted this tutorial to compile using CMake with the following directory structure:
/
lib
libmy_math.a
main.cpp
my_math.h
my_math.cpp
CMakeLists.txt
The contents of the files are exactly as in the tutorial. The only added file is CMakeLists.txt which basically just runs the library compiling part before building:
CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(Test)
### Uncomment this ONCE to compile a libmy_math.a file
# add_library(my_math STATIC my_math.cpp)
add_executable(Test main.cpp)
find_library(MY_MATH_LIB my_math HINTS ./lib)
target_link_libraries(Test PUBLIC ${MY_MATH_LIB})
As the CMake file says, uncommenting Line 5 compiles the library, which is then linked to my code when compiling.
I'm trying to package my code so that I don't show my client the source code for the compiled library (my_math), but if I delete the my_math.h and my_math.cpp files, I get a "file not found" error on import:
/Users/Joe/Desktop/Test/main.cpp:1:10: fatal error: 'my_math.h' file not found
#include "my_math.h"
^~~~~~~~~~~
I thought you could compile libraries without needing the source code. What am I missing here?
A static library does not contain each and every definition a header can contain - think of macros, etc. Thus you still need the header. However, you don't need the .cpp anymore to link the library.
Besides the problem stated in Iorro's answer the find_library call here will not work as expected.
find_library(MY_MATH_LIB my_math HINTS ./lib)
target_link_libraries(Test PUBLIC ${MY_MATH_LIB})
What this does is, while running CMake, look for the my_math.a file. However, at that point of the build process, my_math.a has not been built yet. You're just running CMake for the first time, so all you have is source files. Nothing has been compiled yet.
What you want to do instead is link to the library target directly, as CMake already knows about that and can resolve the dependency on its own. So you need to replace the two lines above with:
target_link_libraries(Test PUBLIC my_math)
This now introduces a curious asymmetry in how your test consumes the library (as it is part of the same build) vs. how your clients consume the same library (which are not part of the same build and thus need to do a find_package call before they can use it). Look at CMake's config-file packages for a mechanism that allows you to restore symmetry here, at the cost of a significant amount of boilerplate required in your CMake script.

CLion - cannot solve undefined reference to constructor in class

I've already looked at this SO answer but I cannot seem to find the solution for my case.
I just started working in C++ and CLion. I did a basic test project that includes a header file and the main function then executes a method from the included class - all working just fine, CLion compiler is MinGW.
Now the real project I need to work on integrates a SDK from a vendor written in C++. They do have examples as well. Every time I run them, CLion breaks the build and complains about undefined references... the include file paths are all correct and CMakeList.txt looks like this:
project(test_2)
include_directories("../libraries/bin/headers/")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXE_LINKER_FLAGS "")
set(PROJECT_HEADERS
"../libraries/bin/headers/SDK.h"
"test.h"
)
set(PROJECT_SOURCES
main.cpp
)
add_executable(test_2 ${PROJECT_SOURCES} ${PROJECT_HEADERS})
the first undefined reference that is listed is the constructor of the SDK class, which is written simply as:
class SDK{
...
SDK();
...
}
Any suggestions what the problem is ?
Because of the current situation I cannot reach anybody on their end, so I thought I ask here...
Thanks !
Solution:
the solution was to compile the libs from the .cpp file an make a clean CMakeList file referencing those libs, this then resolved the undefined reference errors.
I'm not fluent in CMake - but you probably have to also link libraries/directories using something like target_link_libraries()/target_link_directories() if using external SDK. Seems to me that you simply tell the compiler "hey, here is my SDK header, do something" but compiler doesn't know where are the symbols for this SDK defined. Here is a little bit of an explanation what is the basic difference between the two, but I recommend checking CMake documentation directly.
c̛̣o̢̥m̯͕̖̠̙͡p͕̭͚͓̮̲ḭ͓͇͔̟̫l̪͈i͉̟̜̺͖͓͉n̮̻̼g͎̩̳̯ ̻̯̹̦̱̠̀w͕̬̜i̖̭̣th̹̠̕ C̙M̩a̲̮̹͉̻̥̥ķ͕̤̭̠͚e̩̙̼ ̫̮is̻̗͈͓͟ f̧̮͓̦u͏̯ͅń̹̣
I have no clue how the library that you're using is designed, but if there is no definition of the constructor in the header file, it is clearly not header-only. So you either have to link to that library, or add its implementation file (if you have one) to your project so linker gets what you promised. I suggest to look at target_link_libraries to see how to link in CMake (there are more ways to do it though).
Undefined reference error generally means that linker did not find something that was advertised in a header.
the solution was to compile the libs from the .cpp file an make a clean CMakeList file referencing those libs, this then resolved the undefined reference errors.

Linking error with cmake

I'm trying to understand why I get a linking error while compiling a project generated with CMake.
The CMakeFiles.txt builds a static library for each folder of the project and then link all of them together in the following way:
# root CMakeLists.txt
add_subdirectory(subfolder1)
add_subdirectory(subfolder2)
add_subdirectory(...)
add_executable(target ${SOURCES})
set(LIBRARIES
LIB_FOO
LIB_BAR
...
)
target_link_libraries(target
${LIBRARIES}
)
then in each subfolder I have a simple CMakeLists.txt like
file(GLOB FOO_SOURCE *.cpp)
add_library(LIB_FOO ${FOO_SOURCE})
Now this works and compiles everything fine but I get an undefined reference while linking, so I tried to investigate if everything was available at the end and it looks like so. The actual error is the following:
libLIB_WORLD.a(World.cpp.o): In function `World::generate(WorldGenOptions)':
World.cpp:(.text+0x803): undefined reference to `MapGenerator::MapGenerator(BlockMap*)'
World.cpp:(.text+0x837): undefined reference to `MapGenerator::generate(bool, WorldGenOptions)'
Now, MapGenerator.cpp is part of LIB_MAP, so I checked if the file exists and contains the symbols:
:~$ nm libLIB_MAP.a | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions
:~$ nm CMakeFiles/LIB_MAP.dir/MapGenerator.cpp.o | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions
So the symbol is present, at this point I checked if it was correctly linked by ld:
:~$ make VERBOSE=1
/usr/bin/g++ ... libLIB_MAP.a libLIB_WORLD.a ...
So it is actually present in linking phase together with the other library that is not able to find the symbol.
Is there something trivial I'm missing? I'm quite new to CMake so I'm out of ideas.
This is a problem of a library dependency that was not modeled correctly in CMake.
Your LIB_WORLD references methods from LIB_MAP. This dependency is not modeled in your CMake scripts. As both of those are static libraries, they will still build fine on their own. (Remember that static libraries are essentially a bunch of object files packed together, but they never pass through the linker.)
However, as soon as you link them to an executable or a shared library, you will get the problem. Even though your executable links against both LIB_WORLD and LIB_MAP, it does so in the wrong order. So when the linker is trying to resolve the missing symbols for LIB_WORLD, it does not know yet about the symbols exported by LIB_MAP, hence the error message you experienced.
The proper fix is to introduce the dependency on LIB_WORLD:
add_library(LIB_WORLD [...])
target_link_libraries(LIB_WORLD LIB_MAP)
Now whenever you link something against LIB_WORLD you will always also link against LIB_MAP and CMake will take care that the order is right. (In particular, if your executable does not make direct use of methods from LIB_MAP you might want to remove it from its target_link_libraries altogether.)
As an additional benefit, it now allows you to build LIB_WORLD as a shared library, which would have failed with a linker error before.

Undefined reference when linking one dynamic library into the other using CMake and Cygwin

I've looked around, and it doesn't seem that the solution to my problem has been discussed anywhere. So, I write here.
I create a CMake project for generation of several Python libraries. I use Boost.Python to wrap my C++ code, CMake to build dynamic libraries. Everything is on Cygwin platform. The topmost level of the project is pretty standard- eventually it leads to the source directory via:
ADD_SUBDIRECTORY("src")
The /src directory contains two sub-folders - mmath and ann - each is intended for its own library. The CMake file at this level is:
MESSAGE("Going into subdirectory mmath...")
ADD_SUBDIRECTORY("mmath")
MESSAGE("Going into subdirectory ann...")
ADD_SUBDIRECTORY("ann")
So we build the mmath library first:
file(GLOB MMATH_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
file(GLOB MMATH_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${MMATH_HEADERS})
SET( ext_libs
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}/libpython2.6.dll
)
ADD_LIBRARY(mmath SHARED ${MMATH_SRC})
TARGET_LINK_LIBRARIES(mmath ${ext_libs})
and it works perfectly. The resulting dynamic library can then be imported in Python as a module (in cygwin the library is prepended with "cyg" prefix, instead of "lib"). Among other things, the library defines a class DATA, which is essentially a customized container (a collection of variables of standard types), so very simple.
Now, when CMake proceeds into the /src/ann directory, it tries to build the corresponding cygann.dll (cygwin convention) library, which depends on the mmath library we have built already. The CMake script is:
file(GLOB ANN_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
file(GLOB ANN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${ANN_HEADERS})
SET( ext_libs1
mmath
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}/libpython2.6.dll
)
ADD_LIBRARY(ann SHARED ${ANN_SRC})
TARGET_LINK_LIBRARIES(ann ${ext_libs1})
In the src/ann directory we have a file defining the class Ann, which has the members of type std::vector. It is here where linking problem revels itself: the DATA class causes some problems on the linking stage - the "undefined reference" error. The errors indicate that neither constructor nor destructor for the DATA class are defined:
CMakeFiles/ann.dir/libann.cpp.o: In function `Destroy<libmmath::DATA>':
/usr/lib/gcc/i686-pc-cygwin/4.8.3/include/c++/bits/stl_construct.h:93: undefined reference to `libmmath::DATA::~DATA()'
CMakeFiles/ann.dir/libann.cpp.o: In function `Construct<libmmath::DATA, libmmath::DATA>':
/usr/lib/gcc/i686-pc-cygwin/4.8.3/include/c++/bits/stl_construct.h:83: undefined reference to `libmmath::DATA::DATA(libmmath::DATA const&)'
So I'm wondering what could be the problem. Is this related to CMake features, cygwin tricks or is it something regarding the code itself? Well, i feel that the problem is less likely related to the code itself, since it works in standard utilization (static exe or just a single dynamic library). It is more likely that it is something about CMake or cygwin that I'm missing. But what? Please, help. Thank you in advance.

Linking errors on library built using cmake

I guess I just made a simple mistake but I'm not getting which..
Anyways I'm working on a library, also I'm using cmake to build the Makefiles for the project: https://github.com/immapoint/NaNO3/blob/master/CMakeLists.txt
Everything works just fine when compiling the library; it builds the following Files:
bin/libNaNO3.dll
lib/libNaNO3.dll.a (I don't like that name as well)
To test the whole thing, I got another project set up, also using cmake. https://github.com/immapoint/NaNO3TestApp/blob/master/CMakeLists.txt
The main file to test the library looks like this:
https://github.com/immapoint/NaNO3TestApp/blob/master/src/main.cpp
But when it comes to compiling the main file, I'm getting following errors:
CMakeFiles/NaNO3TestApp.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xbf): undefined reference to `nano::Event<int>::attach(std::function<void(int)> *)`
CMakeFiles/NaNO3TestApp.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xd3): undefined reference to `nano::Event<int>::notify(int)`
[...]ld.exe: CMakeFiles/NaNO3TestApp.dir/objects.a(main.cpp.obj): bad reloc address 0x8 in section `.rdata'
This error occures whether I'm building the project using make/cmake or compiling the source file directly using
g++ -Wall -pedantic -ansi -std=c++0x main.cpp [-L./lib -I./include] -lNaNO3
So the problem seems not to lie in cmake but in ld.
I'm working with CMake version 2.8 and MinGW containing GCC version 4.7.2.
Additional information:
Compiler output with -fPIC:
This has nothing to do with CMake or the linker. You need to include the definitions for the nano::Event member functions in the header, not in a separate source file, since templates are instantiated at compile time. By the time the linker gets there, it's too late.
For a fuller explanation, see Why should the implementation and the declaration of a template class be in the same header file? and http://www.parashift.com/c++-faq-lite/templates-defn-vs-decl.html