undefined function during cmake linking local file - c++

I'm trying to compile a small Qt example to an executable (with the test.cpp containg main) and later add support for compiling the non-test.cpp code to its own library. I was using qmake, but now I'm trying to use cmake following the example here. Unfortunately, I'm getting a linking error. Looks like the constructors, which I define in the cpp files that are compiling aren't being found at link time.
$ make
Linking CXX executable test
CMakeFiles/test.dir/attribute_editor.cpp.o: In function `AttributeEditor::AttributeEditor(QWidget*)':
attribute_editor.cpp:(.text+0x2a): undefined reference to `vtable for AttributeEditor'
CMakeFiles/test.dir/bindable.cpp.o: In function `Bindable::Bindable(QObject*)':
bindable.cpp:(.text+0x50): undefined reference to `vtable for Bindable'
CMakeFiles/test.dir/bindable.cpp.o: In function `AttributeObject::AttributeObject()':
bindable.cpp:(.text._ZN15AttributeObjectC2Ev[_ZN15AttributeObjectC5Ev]+0x24): undefined reference to `vtable for AttributeObject'
collect2: error: ld returned 1 exit status
make[2]: *** [test] Error 1
make[1]: *** [CMakeFiles/test.dir/all] Error 2
make: *** [all] Error 2
This is my cmake file...
cmake_minimum_required(VERSION 2.8)
# http://qt-project.org/quarterly/view/using_cmake_to_build_qt_projects
PROJECT(qattrs)
FIND_PACKAGE(Qt4 REQUIRED)
SET(QT_USE_QTSCRIPT TRUE)
SET(qattrs_SOURCES test.cpp attribute_editor.cpp bindable.cpp)
SET(qattrs_HEADERS bindable.h attribute_editor.h)
QT4_WRAP_CPP(qattrs_HEADERS_MOC ${qattrs_HEADERS})
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
ADD_EXECUTABLE(test ${qattrs_SOURCES} ${qattrs_HEADER_MOC})
TARGET_LINK_LIBRARIES(test ${QT_LIBRARIES})
I know very little about cmake, but I assume it's not including the .o files during linking.
The entire code (five or six files) is on github.

It cannot find a vtable for something - this means it is looking for the entries a type would put in it's vtable if it existed, because it is a linker. (It is not talking about a type lacking a vtable at runtime because that'd make no sense at all, I don't even like that sentence)
Somewhere you have a pure-virtual method you have never defined.
That code is REALLY hard to read and reading it I couldn't see any virtuals even in bindable.h, this means there's a pure virtual function in the parent class and you never implement it, that is your error.
Well more specifically you never implement 3 of them.
I'd feel bad for not saying: wxWidgets FTW :P

I found the answer on another question. It wasn't in the example Qt doc, but I just needed to set another environment variable.
set(CMAKE_AUTOMOC ON)
Why am I getting "undefined reference to vtable..." errors when linking this Qt 5.0 application?

Related

CMake 'undefined reference' error with CERN-ROOT

I'm writing a small addition to CERN ROOT and now can't get rid of 'undefined reference' errors on every function from ROOT that I use (and my classes too). Can't find a way to fix this, so looking for help here.
My OS is Linux Mint 19. I use g++ as my c++ compiler, however, I tried clang++ and there was no difference.
I downloaded sources of ROOT from their github and built it now on my computer. Output of root --version is this:
ROOT Version: 6.19/01
Built for linuxx8664gcc on Sep 29 2019, 14:25:35
From heads/master#v6-19-01-1167-gbec9f2d1f7
This is the structure of my project:
ParentFolder
--CMakeLists.txt
--General
----include/...
----source/...
----CMakeLists.txt
----LinkDef.h
--Test
----include/...
----source/...
----CMakeLists.txt
Important lines from top level CMakeLists.txt are:
find_package(ROOT REQUIRED)
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
include(${ROOT_USE_FILE})
add_subdirectory("./General")
add_subdirectory("./Test")
From Test/CmakeLists.txt:
add_executable(Test source/test_main.cpp)
target_include_directories(Test PUBLIC "./include")
target_link_libraries(Test PUBLIC General GTest::GTest GTest::Main ${ROOT_LIBRARIES})
From General/CmakeLists.txt:
file(GLOB_RECURSE SOURCES . source/*.cpp)
ROOT_GENERATE_DICTIONARY(GeoManagerExtractor LINKDEF LinkDef.h)
add_library(General SHARED ${SOURCES} GeoManagerExtractor.cxx)
target_link_libraries(General ${ROOT_LIBRARIES})
target_include_directories(General PUBLIC "./include")
Here are first few lines produced by CMake (while using clang++)
CMakeFiles/Test.dir/source/test_main.cpp.o: In function `main':
test_main.cpp:(.text+0x37): undefined reference to `TGeoManager::Import(char const*, char const*, char const*)'
test_main.cpp:(.text+0x3f): undefined reference to `gGeoManager'
test_main.cpp:(.text+0x8c): undefined reference to `gGeoManager'
CMakeFiles/Test.dir/source/test_main.cpp.o: In function `TGeoManagerExporter::~TGeoManagerExporter()':
test_main.cpp:(.text._ZN19TGeoManagerExporterD2Ev[_ZN19TGeoManagerExporterD2Ev]+0xa): undefined reference to `vtable for TGeoManagerExporter'
../General/libGeneral.so: undefined reference to `ROOT::GenerateInitInstance(TGeoManagerExporter const*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Here are a few lines from test_main.cpp:
TGeoManager::Import("../root_tests/geofile_full.root");
if (gGeoManager == nullptr) {
std::cerr << "Can't find TGeoManager in file" << std::endl;
return 0;
}
UPD: Forgot to mention, that in order to create my CMakeLists.txt files I used these two sources:
https://root.cern.ch/how/integrate-root-my-project-cmake
https://cliutils.gitlab.io/modern-cmake/chapters/packages/ROOT.html
I have managed to compile my project.
As it turned out, .so file that contains TGeoManager implementation was not included in ROOT_LIBRARIES(thanks, Kamil Cuk for bringing my attention to this variable) by the script provided by ROOT developers. It was hard to find as this class was working properly in Cling(c++ interpreter included with ROOT) and this class is almost the only one from ROOT that I use in the project, so I assumed, that the whole ROOT library was not linking properly. After I found this issue, I fixed my CMake files like this (this is from General/CmakeLists.txt):
file(GLOB_RECURSE SOURCES2 . $ENV{ROOTSYS}/lib/*.so)
add_library(General SHARED ${SOURCES} ${SOURCES2} GeoManagerExtractor.cxx)
This eliminates all of the "undefined reference to 'gGeoManager'" and alike, but "undefined reference to `vtable for TGeoManagerExporter'" (TGeoManagerExporter is my own class) stays. However, I figured out that this error is caused by a reflection feature, so as a temporary solution I just don't activate it. I'll post a comment here if I solve this problem.

C++ undefined reference for libtins library

I installed the libtins package for C++, by building it as described and adding #include <tins/tins.h> to the header of the example file. I ran ldconfig but building always throws a Undefined reference error:
CMakeFiles/lts.dir/main.cpp.o: In function `main':
/home/patrick/ClionProjects/lts/main.cpp:6: undefined reference to `Tins::EthernetII::EthernetII(Tins::HWAddress<6ul, unsigned char> const&, Tins::HWAddress<6ul, unsigned char> const&)'
/home/patrick/ClionProjects/lts/main.cpp:7: undefined reference to `Tins::IPv4Address::IPv4Address(char const*)'
/home/patrick/ClionProjects/lts/main.cpp:7: undefined reference to `Tins::IPv4Address::IPv4Address(char const*)'
/home/patrick/ClionProjects/lts/main.cpp:7: undefined reference to `Tins::IP::IP(Tins::IPv4Address, Tins::IPv4Address)'
/home/patrick/ClionProjects/lts/main.cpp:8: undefined reference to `Tins::TCP::TCP(unsigned short, unsigned short)'
/home/patrick/ClionProjects/lts/main.cpp:10: undefined reference to `Tins::PDU::inner_pdu(Tins::PDU*)'
/home/patrick/ClionProjects/lts/main.cpp:12: undefined reference to `Tins::PDU::inner_pdu(Tins::PDU*)'
CMakeFiles/lts.dir/main.cpp.o: In function `Tins::EthernetII::~EthernetII()':
/usr/local/include/tins/ethernetII.h:46: undefined reference to `vtable for Tins::EthernetII'
/usr/local/include/tins/ethernetII.h:46: undefined reference to `Tins::PDU::~PDU()'
collect2: error: ld returned 1 exit status
make[3]: *** [lts] Error 1
I am using CLion as IDE and the following cmake file:
cmake_minimum_required(VERSION 3.5)
project(lts)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -ltins")
set(SOURCE_FILES main.cpp)
add_executable(lts ${SOURCE_FILES})
Any Idea what could be the problem?
There's a couple of things to address in your question. First, let CMake find the location of the libtins library for you, then use target_link_libraries() to add it to your lts executable. In the CMake sample in your question, you are specifying library options in the compiler flags variable (CMAKE_CXX_FLAGS). The other thing is to also let CMake handle setting the appropriate compiler flags for C++11 instead of manually adding them to CMAKE_CXX_FLAGS (which would only take care of the compiler part but not the linker). The following should do what you want in a robust, platform independent way:
cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(lts)
find_library(TINS_LIBRARY tins)
set(SOURCE_FILES main.cpp)
add_executable(lts ${SOURCE_FILES})
target_link_libraries(lts "${TINS_LIBRARY}")
I recommend you read the CMake docs for find_library() and target_link_libraries() to understand what those commands do. For the C++11 stuff, I recommend this blog article for a more cohesive explanation than what the CMake docs give you (disclosure: I wrote the article).
The CMake variable CMAKE_CXX_FLAGS is for the compiler flags, not for libraries.
To add a library you should use target_link_libraries:
target_link_libraries(lts tins)
If you want all targets to link to the same library, you should add it to the list CMAKE_STANDARD_LIBRARIES.
A small tip on debugging these kind of things: Either set CMAKE_VERBOSE_MAKEFILE or use make VERBOSE=1 to inhibit the normal CMake build output, and instead display the normal make output, which will show you all commands make runs, and all flags and options used for each and every program. That way you will be able to see the -ltins flag being passed as a compiler flag, but not as a linker flag or library.
The compiler should -ltins. Refer to CMake manual on how to add library dependencies.
From the Download page of libtins:
In order to link your application with libtins on GCC or clang, use the -ltins flag
Simply add the following line in your CMake file:
target_link_libraries(PROJECT_NAME -ltins)

trouble linking cpp/hpp from cmake

There's zillions of questions on this, but nothing I have read has helped me to resolve my problem.
I am working on unit testing on a large project, so there are multiple CMakeLists.txt files. I created a "utilities.cpp" file which grew quickly, so I decided to split it into test_utilities.cpp and test_utilities.hpp. When I #include test_utilities.cpp there is joy, but if I #include test_utilities.hpp the build fails:
Linking CXX executable foo
CMakeFiles/foo.dir/src/foo.cpp.o: In function `foo::bar()':
/mydir/trunk/tests/src/foo.cpp:57: undefined reference to `exit_on_invalid_config(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)'
collect2: ld returned 1 exit status
make[2]: *** [tests/foo] Error 1
make[1]: *** [tests/CMakeFiles/foo.dir/all] Error 2
make: *** [all] Error 2
I think this is because the hpp and cpp are not being linked.
I have tried adding this to CMakeLists.txt:
ADD_EXECUTABLE(utilities src/test_utilities.cpp src/test_utilities.hpp)
TARGET_LINK_LIBRARIES(utilities
some_project
test_main
boost_program_options)
(actually this was here before, minus the hpp part, when I was including utilities.cpp, before I added the header file). This change does not help, so I tried adding
ADD_LIBRARY(test_utilities src/test_utilities.cpp src/test_utilities.hpp)
and included test_utilities into TARGET_LINK_LIBRARIES:
ADD_EXECUTABLE(foo src/foo.cpp)
TARGET_LINK_LIBRARIES(foo
some_project
test_main
test_utilities
boost_program_options)
But when I try this, I get errors about boost crap being redefined. When I remove boost imports from foo.cpp, test_utilities.cpp/hpp I either get the same output or complaints that it can't find boost definitions.
What I would like CMake to do is compile the test_utilities executable (cpp + hpp) so that I don't get undefined reference when I try to import test_utilities.hpp from foo.cpp.
Thanks in advance for your help.
Edit: another issue I am having is, I'll add the executable test_utilities, but it doesn't get built before foo. I feel like this is part of my problem and I haven't figured out how to get test_utilities to build first.
Edit: Resolved thanks to wojciii! My issue boiled down to, I was importing boost unit test in test_utilities.cpp, test_main.cpp, and foo.cpp. I needed to stop doing that, fix dependency issues in my hpp, and tweak CMakeLists.txt a little.

Using Cuda Object Linking with Cmake

Right now I am working on a project that uses the object linking capabilities of Cuda 5. Since the project is starting to get complex, I wanted to switch to using cmake to compile the code. However I can't seem to get object linking to work correctly for me.
I ended up creating a toy version of the project which gets the same kind of errors as the original project. The toy project consists of a main file (TextureMain.cu) that calls a kernel function to run on the GPU. In each GPU thread an instance of a user-defined class (TextureFunc) is referenced, where the class exists in a separate folder from the main file. The class consists of a TextureFunc.cu and TextureFunc.h file in that folder.
Here are the CMakeList.txt files I am using:
In the project directory (contains src directory):
project(TextureMain)
cmake_minimum_required(VERSION 2.8)
find_package(CUDA REQUIRED)
#-------------------------------------------------------------------------------
set(CUDA_NVCC_FLAGS "-arch=compute_20; -code=sm_20; -rdc=true; -lcudadevrt")
include_directories(src/TextureFunc)
#-------------------------------------------------------------------------------
add_subdirectory(src/TextureFunc)
add_subdirectory(src)
In the src directory (contains TextureMain.cu and TextureFunc directory):
cuda_add_executable(TextureMain TextureMain.cu)
target_link_libraries(TextureMain TextureFunc)
install(TARGETS TextureMain DESTINATION bin)
In TextureFunc directory (contains TextureFunc.h and TextureFunc.cu):
cuda_add_library(TextureFunc TextureFunc.cu )
target_link_libraries(TextureFunc)
When I try to compile this code using the above CMakeList.txt files, I get the following error.
Linking CXX executable TextureMain
CMakeFiles/TextureMain.dir/./TextureMain_generated_TextureMain.cu.o: In function `__sti____cudaRegisterAll_46_tmpxft_00004c15_00000000_6_TextureMain_cpp1_ii_texRef':
/tmp/tmpxft_00004c15_00000000-3_TextureMain.cudafe1.stub.c:2: undefined reference to `__cudaRegisterLinkedBinary_46_tmpxft_00004c15_00000000_6_TextureMain_cpp1_ii_texRef'
TextureFunc/libTextureFunc.a(TextureFunc_generated_TextureFunc.cu.o): In function `__sti____cudaRegisterAll_46_tmpxft_00004bd8_00000000_6_TextureFunc_cpp1_ii_421ca072':
/tmp/tmpxft_00004bd8_00000000-3_TextureFunc.cudafe1.stub.c:8: undefined reference to `__cudaRegisterLinkedBinary_46_tmpxft_00004bd8_00000000_6_TextureFunc_cpp1_ii_421ca072'
collect2: ld returned 1 exit status
make[2]: *** [src/TextureMain] Error 1
make[1]: *** [src/CMakeFiles/TextureMain.dir/all] Error 2
This is obviously a linking error, and it probably has to do with the way that I compile the code using cmake. I think the flags for nvcc are right since I was able to compile this project using a Makefile with the same flags. However, I'm not really sure what else I could be doing wrong. I did notice that the error message references some non-existent .cpp files, but I don't know what to do with that.
Any advice that can be given would be greatly appreciated. I'm using cmake version 2.8.8.
How about linking${CUDA_LIBRARIES} to whatever targets using `.cu files?
For example in your src directory you could try:
cuda_add_executable(TextureMain TextureMain.cu)
target_link_libraries(TextureMain TextureFunc ${CUDA_LIBRARIES})
install(TARGETS TextureMain DESTINATION bin)

How do I solve these libcurl linking errors?

[Administrator#windows ~]$ g++ client.cpp -lcurl -o client.exe
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0x23): undefined reference to `_imp__curl_global_init'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0x5f): undefined reference to `_imp__curl_formadd'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0x9b): undefined reference to `_imp__curl_formadd'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0xa2): undefined reference to `_imp__curl_easy_init'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0xc8): undefined reference to `_imp__curl_easy_setopt'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0xe4): undefined reference to `_imp__curl_easy_setopt'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0xf1): undefined reference to `_imp__curl_easy_perform'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0x101): undefined reference to `_imp__curl_easy_cleanup'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0x10e): undefined reference to `_imp__curl_formfree'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccKXFUtC.o:client.cpp:(.text+0x11b): undefined reference to `_imp__curl_slist_free_all'
collect2: ld returned 1 exit status
I don't have this problem on linux so I don't know why this happens on windows. I googled it already and didn't find anything except mailing list archives with the same question and reply saying "google it".
I'm using mingw. I did get some linker warnings when I built libcurl but they seemed to be ssl related and I don't know if it's a big deal because it built without errors.
*** Warning: linker path does not have real file for library -lssl.
*** I have the capability to make that library automatically link in when
*** you link to this library. But I can only do this if you have a
*** shared version of the library, which you do not appear to have
*** because I did check the linker path looking for a file starting
*** with libssl and none of the candidates passed a file format test
*** using a file magic. Last file checked: /ssl/lib/libssl.a
*** Warning: linker path does not have real file for library -lcrypto.
*** I have the capability to make that library automatically link in when
*** you link to this library. But I can only do this if you have a
*** shared version of the library, which you do not appear to have
*** because I did check the linker path looking for a file starting
*** with libcrypto and none of the candidates passed a file format test
*** using a file magic. Last file checked: /ssl/lib/libcrypto.a
*** Warning: linker path does not have real file for library -lz.
*** I have the capability to make that library automatically link in when
*** you link to this library. But I can only do this if you have a
*** shared version of the library, which you do not appear to have
*** because I did check the linker path looking for a file starting
*** with libz and none of the candidates passed a file format test
*** using a file magic. Last file checked: /mingw/lib//libz.a
*** The inter-library dependencies that have been dropped here will be
*** automatically added whenever a program is linked with this library
*** or is declared to -dlopen it.
*** Since this library must not contain undefined symbols,
*** because either the platform does not support them or
*** it was explicitly requested with -no-undefined,
*** libtool will only create a static version of it.
I was able to avoid these curl linking errors on windows (mingw win32) by adding option -lcurl.dll. -DCURL_STATICLIB was not needed in my case.
My build has two libcurl files in mingw/lib folder: libcurl.a and libcurl.dll.a
Libtool only built a static libcurl and not a dynamic library. Your headers are looking for a dynamic libcurl. It's probably not libcurl's fault, because I can see code in the headers that supports __declspec(dllimport) and __declspec(dllexport) (that's a good sign the package author knows what's what.
Technical details: see this answer regarding libssh.
Solution: Compile with -DCURL_STATICLIB.
Was having the same issue using netbeans 7.1 with mingw. From properties, linker adding library libcurl.dll.a solved the issue for me.
This file was located under curl-7.28.1\lib.libs after I ran the mingw make.
I had similar error (with libz and libsqlite) in different projects.
It is produced by GNU libtool script.
The reason in my case was lack of some files for these libraries (.la ?) or maybe libz.dll.a variants of the libraries.
To have all necessary files for automake/autoconf build ./configure --prefix=... ; make, you'll have to build zlib, crypto and ssl with configure and make to under the same MSYS.
cmake or custom makefile builds will usually not work as dependencies for shared-library autotool build.
Another and the most simple option is to build dynamic curl with cmake ( https://github.com/bagder/curl.git )