A user of my project reported this error to me. I cannot reproduce it on my computer or my lab's server, so I ask it here.
The project uses CMake to generate build environment. It uses the FindBoost utility (provided with CMake) to find Boost resources.
On the beginning, my user said while linking the final programs, the compiler was provided with "/usr/lib64/lib64/libboost_XXX.so", instead of the correct "/usr/lib64/libboost_XXX.so". I failed to find why CMake generated such weird library location, and asked him to manually set the variable Boost_LIBRARIES, and print them:
Boost libraries are: /usr/lib64/libboost_thread-mt.so;/usr/lib64/libboost_program_options-mt.so;/usr/lib64/libboost_filesystem-mt.so
Things seem to be correct. The compilation was successful. But when it goes to linking, the program cries about many undefined symbols:
CMakeFiles/ht-filter.dir/ht-filter.cpp.o: In function `parse_options(int, char**)':
/public/home/yli/Downloads/htqc-0.15.0-Source/ht-filter.cpp:43: undefined reference to `boost::program_options::options_description::options_description(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int, unsigned int)'
......
/usr/local/include/boost/program_options/errors.hpp:372: undefined reference to `boost::program_options::validation_error::get_template(boost::program_options::validation_error::kind_t)'
This is the two typical of the so-many errors: one locates from my source code, the other locates from boost's header. In the corresponding line of my source code, I just created the options_description object
// I renamed boost::program_options to opt
opt::options_description opt_main("Options:");
The OS of my user is CentOS 6.2, and his Boost version is 1.50.0 which is similiar with the one in my computer. The version of CMake of my user is 2.8.11 which is also same with mine.
While using CMake's find_package for Boost, you can give a few hints to CMake which may help it find the correct library, such as:
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(BOOST_ROOT "/usr")
find_package(Boost 1.50.0)
message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARY_DIRS: ${Boost_LIBRARY_DIRS}")
Also if you are linking with dynamic libs make sure to let Boost headers know about it (I think you shouldn't mess with the order in here):
link_directories(${Boost_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
add_definitions( -DBOOST_ALL_DYN_LINK )
Related
I spend whole day trying to link the data_time library to my c++ cmake project.
So I am using cmake 3.4 and boost 1.61.0.
I have the class where is a function which is taking local time:
void TestClass::getTime() {
this->endDate = boost::posix_time::second_clock::local_time();
}
Then I want to return the value of endDate by function returning string:
string testCalss::Info() {
return to_simple_string(this->beginningDate);
}
I need to convert the type of endDate variable to string, because function is string type.
I am getting error messages while program is linking:
In function boost::date_time::month_formatter<boost::gregorian::greg_month, boost::date_time::simple_format<char>, char>::format_month(boost::gregorian::greg_month const&, std::ostream&)':
/usr/include/boost/date_time/date_formatting.hpp:44: undefined reference to `boost::gregorian::greg_month::as_short_string() const'
/usr/include/boost/date_time/date_formatting.hpp:49: undefined reference to `boost::gregorian::greg_month::as_long_string() const'
I have read that data_time is not only header-only library and I should build and add it to my project.
I have tried this command gcc myapp.cpp -omyapp -lboost_date_time, and it's does not work because I am using g++ in cmake project and I haven't find nothing for g++.
I also tried this:
c++ -I path/to/boost_1_61_0 example.cpp -o example \
~/boost/stage/lib/libboost_regex-gcc34-mt-d-1_36.a
Its example from official boost docs how to link libraries.
In cmake project I have few cpp files. Should I run this command using file where is my converting command?
Is there any easier way to fix this error?
I found out how to solve the problem. The way I choose is simple. First of all I have used the locate */boost/date_time* command to find where is my boost and date_time libraries installed. I did not know what version of boost library I am using, so I used locate command again to find boost/version.hpp file. After that I added few lines to my CmakeLists.txt:
find_package( Boost 1.60.0 COMPONENTS date_time)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries( Program ${Boost_DATE_TIME_LIBRARY} )
endif()
Thats all.
cmake_minimum_required(VERSION 3.17)
project(boost_ptime)
set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES main.cpp)
add_executable(boost_ptime ${SOURCE_FILES})
find_package( Boost 1.73 COMPONENTS date_time)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries( boost_ptime ${Boost_DATE_TIME_LIBRARY} )
endif()
Thanks to Warszawski Koks, I was able to compile my program in this way. Above is the full CMakeLists.txt file.
I'm trying to build a C++ executable that uses a Boost library. Building with CMake.
CMake snippet:
find_package(Boost REQUIRED system)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(main src/cpp/main.cpp)
target_link_libraries(main ${BOOST_LIBRARIES})
Getting following CMake build error message:
Undefined symbols for architecture x86_64:
"boost::system::system_category()", referenced from:
...
Why am I getting the error and how can I fix it?
The variables created by the find_package(Boost ...) call you are using are case sensitive, i.e.
${BOOST_LIBRARIES}
will be empty and you need to make sure you are using it like this:
${Boost_LIBRARIES}
The same goes for Boost_INCLUDES which you have used (read: copy-pasted) correctly here:
include_directories(${Boost_INCLUDE_DIRS})
To complete seeekr's answer, you should consider using imported target instead of Boost_ variables:
find_package(Boost REQUIRED system)
add_executable(main ...)
target_link_libraries(main Boost::system)
The imported target will handle linkage, include directories, compile definitions, and all needed stuff with a single call.
I am developing a library (let's say mylibrary) to be used by some third-party applications. My library is build and compiled by cmake (on CentOS 7 and g++ 4.8) and uses some boost libraries, such as thread, log, system, filesystem and date_time (version 1.61.0). To test my lib, I've developed a very simple tester (let's call it tester). The point is that my library can by successfully built and linked, but the tester cannot. Let me show the contents of cmake files below:
In the main cmake file that is dedicated to building mylibrary, I have added boost in this way:
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
SET(Boost_ADDITIONAL_VERSIONS "1.51.0" "1.52.0"
"1.53.0" "1.54.0" "1.55.0" "1.56.0" "1.57.0" "1.58.0"
"1.60.0" "1.61.0" "1.61.0" "1.62.0" "1.63.0" "1.64.0")
find_package(Threads)
find_package(Boost REQUIRED)
find_package(Boost 1.61.0 COMPONENTS thread log log_setup filesystem system date_time)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
To add the library, I have used these lines of code:
set(MYLIBRARY_SRC
${MYLIBRARY_SOURCE_DIR}/src/folder1/File1.cpp
${MYLIBRARY_SOURCE_DIR}/src/folder2/File2.cpp
${MYLIBRARY_SOURCE_DIR}/src/folder3/File3.cpp)
add_library (mylibrary ${MYLIBRARY_SRC})
In the last lines of this cmake files, I have added the tester directory in this way:
if(ENABLE_TESTER)
message(STATUS "tester is enabled and will be built")
add_subdirectory (tester)
endif(ENABLE_TESTER)
and for the tester, I have a very simple cmake file like this:
add_executable(tester tester.cpp)
message(STATUS , "Boost_libraries are ${Boost_LIBRARIES}")
target_link_libraries(tester mylibrary ${Boost_LIBRARIES})
Now, whenever I build my project, my library is built successfully, but when the tester is going to be linked, I face lots of linker errors like this:
../../lib/mylibrary.a (Logger.cpp.o): In function `void boost::log::v2s_mt_posix::basic_formatting_ostream<char, std::char_traits<char>, std::allocator<char> >::aligned_write<wchar_t>(wchar_t const*, long)':
/home/john/local/include/boost/log/utility/formatting_ostream.hpp:702: undefined reference to `boost::log::v2s_mt_posix::aux::code_convert(wchar_t const*, unsigned long, std::string&, std::locale const&)'
/home/john/local/include/boost/log/utility/formatting_ostream.hpp:696: undefined reference to `boost::log::v2s_mt_posix::aux::code_convert(wchar_t const*, unsigned long, std::string&, std::locale const&)'
The point is that I have printed the Boost_LIBRARIES variable before linking the tester and everything seems fine.
Well, the root cause of this issue was exactly the same asked in this question.
p.s. J.J.Hakala answered this question in the comments. I asked him to write his reply as an answer, so I can accept it. But he has not replied yet and I decided to write the answer myself. If this action is wrong form S.O.'s point of view or if I should ask moderators to make my Q duplicate, please let me know.
I'm trying to use glbinding in my own project. I'm using cmake to build everything. The problem is linker cannot find this library. Probably I don't build library thus it cannot be linked, but I don't know how to achive that.
I've written linking code according to https://github.com/hpicgs/glbinding#linking-binaries.
Cmake:
set(SOURCE_FILES main.cpp)
add_executable(AKOpenGLEngine ${SOURCE_FILES})
set(CMAKE_PREFIX_PATH ${CMAKE_MODULE_PATH} glbinding )
find_package(glbinding REQUIRED)
include_directories(${GLBINDING_INCLUDES})
target_link_libraries(AKOpenGLEngine glbinding ${GLBINDING_LIBRARIES})
Error:
Linking CXX executable AKOpenGLEngine
ld: library not found for -lglbinding
main.cpp:
#include <glbinding/gl/gl.h>
int main(void) {
glbinding::Binding::initialize();
exit(EXIT_SUCCESS);
}
My current project structure:
Have you tried to remove the glbinding from target_link_libraries? ${GLBINDING_LIBRARIES} should be sufficient; it passes <your_specific_file_path_to_glbinding_library> to the linker. With -lglbinding the linker searches for a library within some default directories, your glbinding or build directory not included, thus throwing a library not found. To verify the content of ${GLBINDING_LIBRARIES} you can print it to cmake output, e.g., via message(STATUS ${GLBINDING_LIBRARIES}). However, i also suggest to integrate glbinding as external project as suggested by #janisz.
EDIT: sorry, didn't see the valid, but collapsed answer of #jet47
I'm new to this forum, but I've seen it a few times while trying to search for a solution to this problem. I'm trying to generate KML files to use in Google Earth using a C++ API library I found for Ubuntu (libkml-dev_1.2.0-1ubuntu6_amd64). I installed the package using the command sudo apt-get install libkml-dev, came back successful. Afterwards, I used the command line terminal to navigate to the examples folder to try and execute the program 'helloworld.cc' with the command g++ helloworld.cc -o helloworld, but then got a slew of errors (mainly claiming that kmldom is an undefined reference). Sorry, I wanted to attach the text file, but don't know how so I included a sample of the error below. I've searched high and low all week, made sure the header files were indeed included in the download, and even contacted the Google Earth developers about the problem (and they responded that they have nothing to do with this and to redirect all questions regarding this issue to StackOverflow).
Does anyone know what is causing this problem(s) and what I can do to resolve this so I can move on please?
/tmp/cc5u2JyV.o: In function HelloKml(bool)': helloworld.cc:(.text+0x17): undefined reference to kmldom::KmlFactory::GetFactory()'
helloworld.cc:(.text+0x27): undefined reference to kmldom::KmlFactory::CreateCoordinates() const' helloworld.cc:(.text+0x328): undefined reference to kmldom::AsPoint(boost::intrusive_ptrkmldom::Element)'
/tmp/cc5u2JyV.o: In function boost::intrusive_ptr<kmldom::Coordinates>::intrusive_ptr(kmldom::Coordinates*, bool)': helloworld.cc:(.text._ZN5boost13intrusive_ptrIN6kmldom11CoordinatesEEC2EPS2_b[_ZN5boost13intrusive_ptrIN6kmldom11CoordinatesEEC5EPS2_b]+0x3d): undefined reference to kmlbase::intrusive_ptr_add_ref(kmlbase::Referent*)'
/tmp/cc5u2JyV.o: In function boost::intrusive_ptr<kmldom::Coordinates>::~intrusive_ptr()': helloworld.cc:(.text._ZN5boost13intrusive_ptrIN6kmldom11CoordinatesEED2Ev[_ZN5boost13intrusive_ptrIN6kmldom11CoordinatesEED5Ev]+0x23): undefined reference to kmlbase::intrusive_ptr_release(kmlbase::Referent*)'
/tmp/cc5u2JyV.o: In function boost::intrusive_ptr<kmldom::Geometry>::intrusive_ptr(boost::intrusive_ptr<kmldom::Geometry> const&)': helloworld.cc:(.text._ZN5boost13intrusive_ptrIN6kmldom8GeometryEEC2ERKS3_[_ZN5boost13intrusive_ptrIN6kmldom8GeometryEEC5ERKS3_]+0x35): undefined reference to kmlbase::intrusive_ptr_add_ref(kmlbase::Referent*)'
collect2: ld returned 1 exit status
When you compile application that uses library, you need to link it when your application compiles. So, try using this parameters:
To specify a directory to search for your libs, use -L:
-L/data[...]/lib
To specify the actual library name, use -l:
-labc (links abc.a or abc.so)
To specify a directory to search for include files, use -I:
-I/data[...]/lib
I've found the solution. The problem is that you are linking libkml incrorrectly. You should find the paths to the header files and to the library files (*.so). I found them here:
/usr/include/kml/ (include dit with headers),
/usr/lib/x86_64-linux-gnu/ (library dir).
I use CMake and CMakeLists.txt for a project. Using libkml may look like this:
`cmake_minimum_required (VERSION 3.2)
# Set language standard
set(CMAKE_CXX_STANDARD "11")
project (test_proj)
add_definitions(-std=c++11)
# Set default build type to RelWithDebInfo if not specified
if (NOT CMAKE_BUILD_TYPE)
message (STATUS "Default CMAKE_BUILD_TYPE not set using Release with Debug Info")
set (CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE
STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel"
FORCE)
endif()
# linking boost library
find_package(Boost COMPONENTS system filesystem thread REQUIRED)
if(NOT Boost_FOUND)
message(SEND_ERROR "Failed to find boost.")
return()
else()
include_directories(${Boost_INCLUDE_DIRS})
endif()
add_executable(test_proj main.cpp)
set (LibKML_INCLUDE_DIRS /usr/include/kml/)
set (LibKML_LIBRARIES /usr/lib/x86_64-linux-gnu/libkmlbase.so /usr/lib/x86_64-linux-gnu/libkmlconvenience.so /usr/lib/x86_64-linux-gnu/libkmldom.so /usr/lib/x86_64-linux-gnu/libkmlengine.so /usr/lib/x86_64-linux-gnu/libkmlregionator.so /usr/lib/x86_64-linux-gnu/libkmlxsd.so)
message("LibKML is at: ${LibKML_INCLUDE_DIRS} and ${LibKML_LIBRARIES}")
message("Boost is at: ${Boost_INCLUDE_DIRS} and ${Boost_LIBRARIES}")
target_include_directories(test_proj
PUBLIC
${LibKML_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS} )
target_link_libraries(test_proj
PUBLIC
${LibKML_LIBRARIES} ${Boost_LIBRARIES})
install(TARGETS test_proj EXPORT test_proj_export)
export(EXPORT test_proj_export FILE cmake/test_proj-targets.cmake)`