trouble linking cpp/hpp from cmake - c++

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.

Related

undefined function during cmake linking local file

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?

Eclipse build errors are coming from out-of-date code

I'm running Eclipse 3.7.2 with CDT installed on Ubuntu 12.04.
I created a new C++ project, then added existing source/header files by drag and dropping them into the project explorer. I added the header include paths and source paths to the project settings. The source code I added had a few compiler errors that I fixed. Simple stuff.
My Problem:
For lack of a better explanation, the build error log is showing "ghost" errors; errors that used to exist, but just aren't there anymore. Here's a screenshot showing where it's claiming the errors are in my code. Note: Image is high-resolution. View in separate tab so you can read it!
As you can see, it's complaining about a multiple definition error on line 24. And the code on line 24 has nothing to do with such claims.
Running clean on the project does nothing to help this issue.
Here's the console output for the build.
**** Build of configuration Debug for project blitzAPI ****
make -k all
Building target: blitzAPI
Invoking: GCC C++ Linker
g++ -o "blitzAPI" ./src/blitzAPI.o ./src/function.o ./src/iohelper.o ./src/main.o ./src/strHelper.o
./src/main.o: In function `parseTree(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
/home/david/workspace/blitzAPI/Debug/../src/main.cpp:24: multiple definition of `verbose'
./src/blitzAPI.o:/home/david/workspace/blitzAPI/Debug/../src/blitzAPI.cpp:48: first defined here
./src/main.o: In function `parseTree(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
/home/david/workspace/blitzAPI/Debug/../src/main.cpp:24: multiple definition of `lineCount'
./src/blitzAPI.o:/home/david/workspace/blitzAPI/Debug/../src/blitzAPI.cpp:48: first defined here
./src/main.o: In function `parseTree(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
/home/david/workspace/blitzAPI/Debug/../src/main.cpp:24: multiple definition of `functionList'
./src/blitzAPI.o:/home/david/workspace/blitzAPI/Debug/../src/blitzAPI.cpp:51: first defined here
collect2: ld returned 1 exit status
make: *** [blitzAPI] Error 1
make: Target `all' not remade because of errors.
**** Build Finished ****

error about compiling c++ code with cmake and boost

I am trying to compile c++ software depending on boost with CMake. With the same source code and CMakeLists.txt files, I succeeded with my own laptop (ubuntu 11 with boost1.42), but I am getting the following error message with my workstation (RHEL6.2 with boost 1.41) in research group (btw, boost1.41 should be enough):
main/main.cpp: In function ‘path
make_path(const std::string&)’:
main/main.cpp:50: error: invalid
conversion from ‘bool (*)(const std::string&)’ to ‘void*’
main/main.cpp:50: error:
initializing argument 2 of ‘boost::filesystem3::path::path(const Source&,
typename
boost::enable_if<boost::filesystem3::path_traits::is_pathable<typename
boost::decay<Source>::type>, void>::type*) [with Source =
std::basic_string<char, std::char_traits<char>, std::allocator<char> >]’
main/main.cpp: In function ‘int
main(int, char**)’:
main/main.cpp:664: error: ‘class
path’ has no member named ‘native_file_string’
main/main.cpp:676: error: ‘class
path’ has no member named ‘native_file_string’
make[2]: *** [main/CMakeFiles/vina_main.dir/main.cpp.o] Error 1
make[1]: *** [main/CMakeFiles/vina_main.dir/all] Error 2
make: *** [all] Error 2
I don't quite understand the error message and don't know how to fix it. Can anyone help me?
======================= update =========================
The above error message is fixed thanks to your help, but I still get the error message indicating linking failure between my executable file and boost libraries. I did link it within CMakeLists.txt by 'target_link_libraries (vvv_main vvv ${Boost_LIBRARIES})'. The error message is like:
CMakeFiles/vvv_main.dir/main.cpp.o: In function '__static_initialization_and_destruction_0':
/usr/local/include/boost/system/error_code.hpp:214: undefined reference to `boost::system::generic_category()'
/usr/local/include/boost/system/error_code.hpp:215: undefined reference to `boost::system::generic_category()'
/usr/local/include/boost/system/error_code.hpp:216: undefined reference to `boost::system::system_category()'
.......
I read other related posts here, but still have no clue how to fix my problem. Thanks!
I would suggest, that you use the find_package routines of CMake together with the required flag and explicitly specifying the components you need. Then there is no need to manually set the libraries.
For your project
FIND_PACKAGE(Boost 1.41 COMPONENTS filesystem system REQUIRED)
MESSAGE(STATUS "** Boost Include: ${Boost_INCLUDE_DIR}")
MESSAGE(STATUS "** Boost Libraries: ${Boost_LIBRARIES}")
together with
TARGET_LINK_LIBRARIES(your_project ${Boost_LIBRARIES})
should do the trick. Specifying the version (here 1.41) makes CMake if only an older version of boost is available. Specifying the components (components = boost libraries that are not header-only) makes CMake complain if those are not available and also automatically adds those to the variable Boost_LIBRARIES. The Message statements are not necessary but I like to have some feedback...
In case you would like to manually download and install the newest version of boost (which I normally do since Linux distributions tend to be somewhat slow with respect to boost packaging) alongside the version provided by the system, then you can hint the find_package scripts for boost to the custom location via
SET(BOOST_ROOT "$ENV{HOME}/usr")
which of course goes before the find_package call (in this example boost would have been installed into the prefix $HOME/usr).
One last remark - I sometimes used to have problems with older versions of the FindBoost.cmake script (especially those from the old CMake 2.6) that does all the magic when find_package(Boost) is called. It should not be a problem for Boost 1.41, but in case there are problems finding (newer versions of) Boost even though you're absolutely sure it is correctly installed, you might want to try a more recent version of FindBoost.cmake. For example from the gitweb, it should be in the Modules tree.

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 )

How do I set up gtest in Windows Netbeans?

I've looked at the Netbeans forums, gtest wiki & around here & I can't seem to find a way to get gtest working right in Netbeans (6.9.1, Windows 7x64). There's no problem with my #include of gtest.h or with the unittest file itself - ASSERT_LE is recognized etc. I'm using cygwin & the results are the same with gtest at c:\gtest-1.5.0 or cygwin/usr/local/gtest-1.5.0. I think it might be matter of getting a different makefile for the tests to use & based off the gtest included makefile, but that hasn't worked for me (maybe I'm doing it wrong). This is what I get when I hit ALT-F6 (Test Project):
g++.exe -o build/Debug/Cygwin-Windows/tests/TestFiles/f1 build/Debug/Cygwin-Windows/tests/tests/Armor_unittest.o build/Debug/Cygwin-Windows/tests/tests/newsimpletest.o build/Debug/Cygwin-Windows/main_nomain.o build/Debug/Cygwin-Windows/Character_nomain.o build/Debug/Cygwin-Windows/Map_nomain.o build/Debug/Cygwin-Windows/Armor_nomain.o build/Debug/Cygwin-Windows/Weapon_nomain.o build/Debug/Cygwin-Windows/Shop_nomain.o build/Debug/Cygwin-Windows/Enemy_nomain.o
build/Debug/Cygwin-Windows/tests/tests/Armor_unittest.o: In function `_ZN31ArmorTest_SetupAndGetWorks_Test8TestBodyEv':
/cygdrive/c/Users/.../winPro2Game/tests/Armor_unittest.cpp:9: undefined reference to `testing::internal::AssertHelper::AssertHelper(testing::TestPartResult::Type, char const*, int, char const*)'
/cygdrive/c/Users/.../winPro2Game/tests/Armor_unittest.cpp:9: undefined reference to `testing::internal::AssertHelper::operator=(testing::Message const&) const'
/cygdrive/c/Users/.../winPro2Game/tests/Armor_unittest.cpp:9: undefined reference to `testing::internal::AssertHelper::~AssertHelper()'
/cygdrive/c/Users/.../winPro2Game/tests/Armor_unittest.cpp:9: undefined reference to `testing::internal::AssertHelper::~AssertHelper()'
etc...
If I put a custom built makefile that is almost identical to the one included with gtest into the test folder & right click on it & Make I get:
Makefile:21: target `gtest-all.o' doesn't match the target pattern
Makefile:25: target `gtest_main.o' doesn't match the target pattern
Makefile:39: *** multiple target patterns. Stop.
If I do Test Project again I get:
rm -f build/Debug/Cygwin-Windows/tests/tests/Makefile.o.d
g++.exe -c -g -I../../../../../../../gtest-1.5.0/include -MMD -MP -MF build/Debug/Cygwin-Windows/tests/tests/Makefile.o.d -o build/Debug/Cygwin-Windows/tests/tests/Makefile.o tests/Makefile
g++: tests/Makefile: linker input file unused because linking not done
gcc.exe build/Debug/Cygwin-Windows/tests/tests/Makefile.o -o build/Debug/Cygwin-Windows/tests/tests/Makefile
gcc: build/Debug/Cygwin-Windows/tests/tests/Makefile.o: No such file or directory
gcc: no input files
make[1]: *** [build/Debug/Cygwin-Windows/tests/tests/Makefile] Error 1
make[1]: Leaving directory `/cygdrive/c/Users/.../winPro2Game'
make: *** [.build-tests-impl] Error 2
Thanks!
you were close in the first place - from the first snippet of "undefined reference", it's a linker configuration issue - you don't have gtest library added. as far as i remember, gtest doesn't ship binaries, so you'll have to compile library yourself (gtest.lib), then add that somewhere in linker properties as additional library - not a netbeans user myself, can't tell exactly where.