undefined reference to boost::iostreams::mapped_file_source::init() using CMake - c++

Linking error on minimal example with Boost Iostreams. Looks like I have not linked with libboost_iostream, however CMake reports that library is found and other applications with Boost compile and link without any problems.
Using Cmake for build:
cmake_minimum_required(VERSION 3.0)
project(mmap_example CXX)
set(TARGET mmap_example)
set(BOOST_MIN_VERSION "1.61.0")
set(Boost_ADDITIONAL_VERSIONS "1.61.0" "1.61")
set(Boost_USE_STATIC_LIBS ON)
set(BOOST_ROOT ${MY_BOOST_DIR})
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS iostreams REQUIRED)
set(CMAKE_CXX_FLAGS "-std=c++11 -std=gnu++1y -pthread")
set(CMAKE_EXE_LINKER_FLAGS "-std=c++11 -std=gnu++1y -pthread")
file(GLOB SOURCES *.cpp)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(${TARGET} ${SOURCES})
target_link_libraries(${TARGET} ${Boost_IOSTREAMS})
C++ itself:
#include <boost/iostreams/device/mapped_file.hpp>
namespace boost_io = boost::iostreams;
int main(int argc, char** argv) {
boost_io::mapped_file_source file(argv[1]);
return 0;
}
GCC output:
Linking CXX executable mmap_example
CMakeFiles/mmap_example.dir/mmap.cpp.o: In function boost::iostreams::mapped_file_source::mapped_file_source<char*>(char* const&, unsigned int, long long):
mmap.cpp:(.text._ZN5boost9iostreams18mapped_file_sourceC2IPcEERKT_jx[_ZN5boost9iostreams18mapped_file_sourceC5IPcEERKT_jx]+0x43): undefined reference to boost::iostreams::mapped_file_source::init()
gcc (Debian 4.9.2-10) 4.9.2
Cmake 3.0.2
Boost 1.61

I'm not sure that ${Boost_IOSTREAMS} is the correct variable to use, AFAIK it should be ${Boost_LIBRARIES} (at least that is what I always use).
You can check if the variable is really set by using
message(STATUS "Boost_IOSTREAMS: ${Boost_IOSTREAMS}")
in your cmake file.
You can also use
make all VERBOSE=1
to list all the commands, to check what libraries are present on the linker command line.

Related

Compiling boost::log with static linking doesn't work when including init_from_settings.hpp

I am able to successfully compile the below program.
#include <iostream>
#include "boost/log/trivial.hpp"
int main(int, char**)
{
BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
return EXIT_SUCCESS;
}
With the following CMakeFile.
cmake_minimum_required(VERSION 2.8)
project(boost_log CXX)
# we will use static libs
set(Boost_USE_STATIC_LIBS ON)
# Boost::log required Boost version >= 1.54.0
find_package(Boost 1.54.0 REQUIRED COMPONENTS log)
find_package(Threads)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
set(SRC_FILES
src/main.cpp)
add_executable(boost_log ${SRC_FILES})
target_link_libraries(boost_log ${Boost_LIBRARIES} Threads::Threads)
However, if I edit main.cpp and add the following snippet:
#include "boost/log/utility/setup.hpp"
#include "boost/log/utility/setup/from_settings.hpp"
void blah(void)
{
boost::log::settings setts;
boost::log::init_from_settings(setts);
}
Then I get linking errors:
/usr/bin/c++ -rdynamic CMakeFiles/boost_log.dir/src/main.cpp.o -o boost_log -Wl,-Bstatic -lboost_log -lboost_date_time -lboost_log_setup -lboost_system -lboost_filesystem -lboost_thread -lboost_regex -lboost_chrono -lboost_atomic -Wl,-Bdynamic -lpthread -lpthread
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libboost_log_setup.a(init_from_settings.o): In function `boost::log::v2s_mt_posix::(anonymous namespace)::default_syslog_sink_factory<char>::create_sink(boost::log::v2s_mt_posix::basic_settings_section<char> const&)':
(.text+0x27fa): undefined reference to `boost::log::v2s_mt_posix::sinks::syslog_backend::set_severity_mapper(boost::log::v2s_mt_posix::aux::light_function<boost::log::v2s_mt_posix::sinks::syslog::level (boost::log::v2s_mt_posix::record_view const&)> const&)'
(snipped, but the errors continue)
Why does including from_settings.hpp cause linking to fail? Is this not avaliable to link statically?
I have tried both on Fedora and Ubuntu with the same result.
You are missing the log_setup library!
Do:
find_package(Boost 1.54.0 REQUIRED COMPONENTS log_setup log)
I encountered the same link error these days and it turned out to be a static linking order issue which is a topic I'm not familiar enough to explain here but I found an article that may help: Library order in static linking.
I used the same C++ source code as you posted in the question but my CMakeLists.txt looks like the following:
cmake_minimum_required(VERSION 3.10)
include(CMakePrintHelpers)
project(boost_log CXX)
# Compile as C++17.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# we will use static libs
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost REQUIRED COMPONENTS
filesystem
log
log_setup
regex
system
)
find_package(Threads)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
set(SRC_FILES main.cpp)
message(STATUS "==========")
message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARIES}")
message(STATUS "==========")
add_executable(boost_log_exec ${SRC_FILES}
)
target_link_libraries(boost_log_exec
# Unfortunately, in ${Boost_LIBRARIES}, `boost_log_setup` follows
# `boost_log` rather than precedes it, hence the link errors.
# ${Boost_LIBRARIES}
Boost::log_setup
Boost::log
Threads::Threads
)
The key point is the explicit use of Boost::log_setup and Boost::log in this particular order (i.e., Boost::log_setup must precede Boost::log) which are CMake targets that are explained here. With these two targets explicitly specified in target_link_libraries, you don't need the variable Boost_LIBRARIES at all.
The order of these two is important due to the static linking order issue I mentioned at the very beginning: one must put before the other in order to link correctly.
The reason that ${Boost_LIBRARIES} alone doesn't work is that the static libraries that Boost_LIBRARIES represents are listed in the following order (which is printed out by the message call in my CMakeLists.txt):
Boost_LIBRARIES: /usr/lib/x86_64-linux-gnu/libboost_filesystem.a;/usr/lib/x86_64-linux-gnu/libboost_log.a;/usr/lib/x86_64-linux-gnu/libboost_log_setup.a;/usr/lib/x86_64-linux-gnu/libboost_regex.a;/usr/lib/x86_64-linux-gnu/libboost_system.a;/usr/lib/x86_64-linux-gnu/libboost_date_time.a;/usr/lib/x86_64-linux-gnu/libboost_thread.a;-lpthread;/usr/lib/x86_64-linux-gnu/libboost_chrono.a;/usr/lib/x86_64-linux-gnu/libboost_atomic.a
(I'm not sure why -lpthread is also in the listing, by the way.)
The GCC command line that CMake generates uses the same order of the static libraries when ${Boost_LIBRARIES} was used. Therefore, the actual command was (see note [1] at the end):
/usr/bin/c++ CMakeFiles/boost_log_exec.dir/main.cpp.o -o boost_log_exec /usr/lib/x86_64-linux-gnu/libboost_filesystem.a /usr/lib/x86_64-linux-gnu/libboost_log.a /usr/lib/x86_64-linux-gnu/libboost_log_setup.a /usr/lib/x86_64-linux-gnu/libboost_regex.a /usr/lib/x86_64-linux-gnu/libboost_system.a /usr/lib/x86_64-linux-gnu/libboost_date_time.a /usr/lib/x86_64-linux-gnu/libboost_thread.a -lpthread /usr/lib/x86_64-linux-gnu/libboost_chrono.a /usr/lib/x86_64-linux-gnu/libboost_atomic.a -lpthread
The libboost_log.a and libboost_log_setup.a are listed in the inverse order that they should be, hence the link errors.
In addition, using the CMake target Boost::log itself doesn't solve the problem. In other words, the following code snippet doesn't work:
target_link_libraries(boost_log_exec
Boost::log
Threads::Threads
)
It doesn't work because the target Boost::log also lists libboost_log.a first and then libboost_log_setup.a, which is not the desired order. I found this by showing the underlying GCC command line as I mentioned in note [1].
Note [1]: FYI: After I ran cmake . to configure the build, I ran make VERBOSE=1 to build but also show the underlying GCC command line. New versions of CMake seem to support --verbose command line option directly. See this answer.

CMake unable to link libxml2 in CLion

tl;dr add set(CMAKE_CXX_STANDARD_LIBRARIES "-lxml2" ) to CMakeLists.txt (more infos below).
I want to run a very simple application within CLion. This application uses libxml2.
I use CLion 2018.1.2 on Ubuntu 18.04 LTS, libxml2-dev is properly installed.
My project does compile with:
g++ -I /usr/include/libxml2 xmlTest.cpp -o xmlTest.exe -lxml2
it does not compile in CLion though, using this CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(xmlTest)
set(CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -I/usr/include/libxml2 -lxml2 -lz -lm")
include_directories( /usr/local/include/libxml2 )
add_executable (xmlTest.exe xmlTest.cpp)
the compiler throws me:
/home/xxxx/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/181.4668.70/bin/cmake/bin/cmake --build /home/xxxx/src/cmake-build-debug --target xmlTest.exe -- -I /usr/include/libxml2 -lxml2
Scanning dependencies of target xmlTest.exe
[ 50%] Building CXX object CMakeFiles/xmlTest.exe.dir/xmlTest.cpp.o
[100%] Linking CXX executable xmlTest.exe
CMakeFiles/xmlTest.exe.dir/xmlTest.cpp.o: In function `main':
/home/xxxx/src/xmlTest.cpp:10: undefined reference to `xmlReadFile'
/home/xxxx/src/xmlTest.cpp:17: undefined reference to `xmlDocGetRootElement'
/home/xxxx/src/xmlTest.cpp:21: undefined reference to `xmlFreeDoc'
/home/xxxx/src/xmlTest.cpp:25: undefined reference to `xmlStrcmp'
/home/xxxx/src/xmlTest.cpp:27: undefined reference to `xmlFreeDoc'
my application (xmlTest.cpp):
#include <stdlib.h>
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
int main(int argc, char const *argv[]) {
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlReadFile(argv[1], NULL, 0);
if (doc == NULL ) {
fprintf(stderr,"Document not parsed successfully. \n");
return 1;
}
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return 1;
}
if (xmlStrcmp(cur->name, (const xmlChar *) "users")) {
fprintf(stderr,"document of the wrong type, root node != story");
xmlFreeDoc(doc);
return 1;
}
return 0;
}
after fiddling with libxml2 and CMake for hours now without success, I am open to any idea what to do to tell CMake libxml2 actually exists...
Update #1:
thanks to #vre's suggestion I updated my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.10)
project(xmlTest)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -I/usr/include/libxml2 -lxml2 -lz -lm")
set(CMAKE_CXX "/usr/local/include/libxml2")
find_library(libxml2 libxml2)
link_directories(/usr/local/include/libxml2)
add_compile_options("-I/usr/include/libxml2 -lxml2 -lz -lm")
find_package(LibXml2 REQUIRED)
add_executable (xmlTest.exe xmlTest.cpp)
target_compile_definitions(xmlTest.exe PUBLIC ${LibXml2_DEFINITIONS})
target_include_directories(xmlTest.exe PUBLIC ${LibXml2_INCLUDE_DIRS})
target_link_libraries(xmlTest.exe ${LibXml2_LIBRARIES})
This did not change or resolve the error though.
Update #2 (solution):
this is how to build projects with libxml2 in CLion:
cmake_minimum_required(VERSION 3.10)
project(xmlTest)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -I/usr/include/libxml2")
set(CMAKE_CXX_STANDARD_LIBRARIES "-lxml2" )
add_executable (xmlTest.exe xmlTest.cpp)
My issue was that I had the wrong order of arguments in my CMAKE_CXX_FLAGS. This article points this out. Using set(CMAKE_CXX_STANDARD_LIBRARIES "-lxml2" ) was the key (see this)
I hope this helps some future timetravelers:
The solution you came up with works but the intention of CMake is to provide means to express a platform, compiler, and build tool independent way of describing projects. All the magic happens in the FindLibXml2.cmake module. And a huge number of modules are delivered ready to use with your CMake installation. See the modules directory under /usr/share/cmake-3.10/Modules on Ubuntu 18.04.
If you reformulate your CMakeLists.txt the following way:
cmake_minimum_required(VERSION 3.10)
project(xmlTest)
set(CMAKE_CXX_STANDARD 11)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
elseif(MSVC)
# add options for Visual C/C++ Compiler here
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
find_package(LibXml2 REQUIRED)
add_executable(xmlTest.exe xmlTest.cpp)
target_compile_definitions(xmlTest.exe PUBLIC ${LIBXML2_DEFINITIONS})
target_include_directories(xmlTest.exe PUBLIC ${LIBXML2_INCLUDE_DIRS})
target_link_libraries(xmlTest.exe ${LIBXML2_LIBRARIES})
you are able to work on a wide range of platforms and combinations of compilers and IDEs. This was tested on Ubuntu 18.04 with GCC 7.3 and Windows 10 with MSVC 15. You need some more steps to build on Windows (i.e. installing and setup libxml2 and all of its dependencies). And this should work with CLion too out of the box.

Non-default compilers (GCC or Vanilla-Clang) on macOS High Sierra linking issue

I am working on a currently mac based hobby project that involves some parallelization, for which I'd like to use OpenMP since this seems quite portable and relatively easy to implement in my case. After some online reading, I found out that gcc and clang can both compile with -fopenmp in their current versions. The default macOS compiler included with Xcode is stripped of this functionality, though. So, I installed both gcc 7 and clang 5 on my macOS. Since my project is built via CMake, I have written the following makefile.
cmake_minimum_required(VERSION 3.0)
project(Project C CXX)
#SET(CMAKE_C_COMPILER /usr/local/bin/gcc-7)
#SET(CMAKE_CXX_COMPILER /usr/local/bin/gcc-7)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -mavx2 -march=haswell -flto=thin -g0")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread")
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost 1.65 COMPONENTS filesystem system thread atomic chrono regex)
FIND_PACKAGE(OpenCV REQUIRED core imgproc imgcodecs calib3d)
set(HDF5_USE_STATIC_LIBRARIES ON)
set(HDF5_ROOT /usr/local/HDF_GROUP/HDF5/1.10.0/)
FIND_PACKAGE(HDF5 REQUIRED)
include_directories(${CMAKE_SOURCE_DIR}/include ${Boost_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${HDF5_INCLUDE_DIRS})
add_executable(Project /path/to/many/files..)
TARGET_LINK_LIBRARIES(Project ${Boost_LIBRARIES})
TARGET_LINK_LIBRARIES(Project ${OpenCV_LIBS})
TARGET_LINK_LIBRARIES(Project ${HDF5_LIBRARIES})
In this version with the CMAKE_CXX_COMPILER setting disabled, the code compiles, links, and runs without a hitch. As soon as I set CMake to use gcc or vanilla-clang for the exact same project without any further changes, compiling finishes without any trouble but linking fails. The linker reports hundreds of missing symbols ranging from a few OpenCV symbols to mostly libc++ things like
"std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)", referenced from:
_main in main.cpp.o
Therefore, I am obviously missing something fundamental. With vanilla-clang, I tried adding -L/usr/local/opt/llvm/lib to point the linker to the libs that came with clang. Unfortunately, this changed nothing.
I'd appreciate any hints on the matter. Thank you
I had the same problem and it took one complete day to find the solution. I am using Mac-Sierra 10.13.4. I want to use Opencv3 (I think the same problem also appears for opencv2) and openMP. I was actually using Clion as the IDE (CLion uses cmake to configure the project unlike other IDE), so I have to write the CMakeLists.txt file.
There was a conflict of using gcc as the compiler for openCV and openMP. If you use gcc as the compiler then it gives error for opencv as :
imwrite() on OS X error: Undefined symbols
You need to specifically use llvm compiler on OS X to resolve this issue. Following, I am giving the correct code for using OpenCV and OpenMP on Mac-Sierra:
cmake_minimum_required(VERSION 3.10)
project(MyOpenCVTest)
set(CMAKE_CXX_STANDARD 11)
add_executable(MyOpenCVTest main.cpp)
# set("OpenCV_DIR" "/modules/opencv/3.4.1/share/OpenCV/")
set(CMAKE_PREFIX_PATH "/usr/local/Cellar/opencv#3/")
set(OpenCV_INCLUDE_DIRS "/usr/local/Cellar/opencv#3/include/")
set(OpenCV_LIBS "/usr/local/Cellar/opencv#3/lib/")
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
if(UNIX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=gnu++0x")
endif()
set(CMAKE_C_COMPILER "/usr/local/Cellar/llvm/6.0.0/bin/clang")
set(CMAKE_CXX_COMPILER "/usr/local/Cellar/llvm/6.0.0/bin/clang++")
set(OPENMP_LIBRARIES "/usr/local/Cellar/llvm/6.0.0/lib")
set(OPENMP_INCLUDES "/usr/local/Cellar/llvm/6.0.0/include")
OPTION (USE_OpenMP "Use OpenMP to enamble <omp.h>" ON)
# Find OpenMP
if(APPLE AND USE_OpenMP)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(OpenMP_C "${CMAKE_C_COMPILER}")
set(OpenMP_C_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument")
set(OpenMP_C_LIB_NAMES "libomp" "libgomp" "libiomp5")
set(OpenMP_libomp_LIBRARY ${OpenMP_C_LIB_NAMES})
set(OpenMP_libgomp_LIBRARY ${OpenMP_C_LIB_NAMES})
set(OpenMP_libiomp5_LIBRARY ${OpenMP_C_LIB_NAMES})
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(OpenMP_CXX "${CMAKE_CXX_COMPILER}")
set(OpenMP_CXX_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument")
set(OpenMP_CXX_LIB_NAMES "libomp" "libgomp" "libiomp5")
set(OpenMP_libomp_LIBRARY ${OpenMP_CXX_LIB_NAMES})
set(OpenMP_libgomp_LIBRARY ${OpenMP_CXX_LIB_NAMES})
set(OpenMP_libiomp5_LIBRARY ${OpenMP_CXX_LIB_NAMES})
endif()
endif()
if(USE_OpenMP)
find_package(OpenMP REQUIRED)
endif(USE_OpenMP)
if (OPENMP_FOUND)
include_directories("${OPENMP_INCLUDES}")
link_directories("${OPENMP_LIBRARIES}")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
# set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif(OPENMP_FOUND)
include_directories( ${OpenCV_INCLUDE_DIRS} )
target_link_libraries( MyOpenCVTest ${OpenCV_LIBS})
TARGET_LINK_LIBRARIES(MyOpenCVTest opencv_core opencv_highgui opencv_imgproc opencv_imgcodecs)
You might want to set e.g. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread") such that the linker automatically detects the appropriate pthread library
Do
brew reinstall llvm
to install llvm compiler.
Please note that, you can't use gcc compiler on Mac-Sierra for your project which needs openMP and also openCV. You need to use llvm compiler.
Verify the correct locations of llvm and opencv installation directory.
If using the gcc compiler driver to perform the link change the compiler to 'g++' from 'gcc', g++ automatically brings in the standard c++ library where gcc does not, or add -lstdc++, there may be others required but using g++ as the compiler driver is usually easier.

cmake does not consider -pthread

I am trying to make a testbench to my program using gmock/gtest; Linux/Ubuntu; KDevelop/CMake. From the link error message I conclude that part of the gtest package is missing pthread support.
/home/projects/cpp/gmock/gtest/libgtest.a(gtest-all.cc.o): In function `testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::~ThreadLocal()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED2Ev[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED5Ev]+0x16): undefined reference to `pthread_getspecific'
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED2Ev[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED5Ev]+0x2b): undefined reference to `pthread_key_delete'
I also read
googletest: how to setup?
Using g++ directly, everything works. So, since I am usinc KDevelop/CMake, I suspect either my code or CMake.
In my CMakeLists.txt I do use
add_definitions( -pthread -m64)
However, I do not see any effect in the Makefile.
Am I missing something from my CMakeLists.txt, or CMake does not consider the line above?
My CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_definitions( -Dpthread )
project(ThreadTest)
INCLUDE_DIRECTORIES(gmock/gtest/include)
set ( GTEST_LIBS libgtest.a )
link_directories( ~/projects/cpp/gmock/gtest)
add_executable(ThreadTest main_test.cpp)
target_link_libraries(ThreadTest ${GTEST_LIBS})
Do I misunderstand, that add_definitions should work in this situation?
After reading
How do I force cmake to include "-pthread" option during compilation?
my question really looks like duplicate. However,
cmake_minimum_required(VERSION 2.8)
add_definitions( -Dpthread )
project(ThreadTest)
INCLUDE_DIRECTORIES(gmock/gtest/include)
find_package( Threads )
set ( GTEST_LIBS libgtest.a )
link_directories( ~/projects/cpp/gmock/gtest)
add_executable(ThreadTest main_test.cpp)
target_link_libraries(ThreadTest ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT})
still gives the warning 'Could NOT find Threads'. I tried to search Ubuntu software center for "threads", with no result. After that, I installed libghc-threads-dev. However, when using
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
I keep receiving 'Could NOT find Threads', as error. What shall I do to satisfy find_package, and why do I have this problem, when the simple Makefile produces what I expect?
PS: my main file:
#include "gmock/gtest/include/gtest/gtest.h"
TEST(blahTest, blah1) {
EXPECT_EQ(1, 1);
}
int main (int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
int returnValue;
returnValue = RUN_ALL_TESTS();
return returnValue;
}
After busy hours, I succeeded to compile my supercomplex test program, using KDevelop/CMake/gtest
#include "gtest-1.7.0/include/gtest/gtest.h"
TEST(blahTest, blah1) {
EXPECT_EQ(1, 1);
}
int main (int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
The CMakeLists.txt file that could do the task is
# http://stackoverflow.com/questions/13513905/how-to-properly-setup-googletest-on-linux/13513907#13513907
# http://stackoverflow.com/questions/15193785/how-to-get-cmake-to-recognize-pthread-on-ubuntu
# http://stackoverflow.com/questions/21116622/undefined-reference-to-pthread-key-create-linker-error
# http://stackoverflow.com/questions/1620918/cmake-and-libpthread
# https://meekrosoft.wordpress.com/2009/10/04/testing-c-code-with-the-googletest-framework/
# http://stackoverflow.com/questions/30106608/googletest-cmake-and-make-tests-not-running
# http://stackoverflow.com/questions/13521618/c-project-organisation-with-gtest-cmake-and-doxygen
# http://www.kaizou.org/2014/11/gtest-cmake/
cmake_minimum_required(VERSION 2.8)
project(ThreadTest C CXX)
ADD_SUBDIRECTORY (gtest-1.7.0)
enable_testing()
#set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(GTest REQUIRED)
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
if(NOT MSVC)
set(PThreadLib -pthread)
endif()
add_executable(ThreadTest main_test.cpp)
target_link_libraries(ThreadTest ${PThreadLib} ${GTEST_LIBRARIES})
#add_test(ThreadTest ThreadTest)
I want to highlight some things: a few valuable links and
project(ThreadTest C CXX) rather than project(ThreadTest)
and
set(PThreadLib -pthread) rather than set(PThreadLib pthread)
I guess the rest can be managed. It could be a good starting point.
I integrated Google Test framework in my own project and this CMake file is working.
# Google C++ Testing Framework
# https://code.google.com/p/googletest/
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
if(WIN32)
# GTest is static compiled by default
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
endif()
enable_testing()
add_executable(ThreadTest main_test.cpp)
target_link_libraries(ThreadTest ${GTEST_BOTH_LIBRARIES})
CMake warning "Could NOT find Threads" is related to a bug:
CMake failing to detect pthreads due to warnings
All you need to do is link with pthread:
target_link_libraries(BUILD_ARTIFACT pthread)
BUILD_ARTIFACT can be your project, or library name. You should add this line after defining your artifact.
For example, if your build artifact is ThreadTest:
add_executable(ThreadTest main_test.cpp)
target_link_libraries(ThreadTest pthread)

Linking freetype with cmake

I'm having troubles with linking freetype 2 under linux using cmake when building a C++11 project with an extern C library.
With cmake and freetype 2 I basically have 2 options :
use the utility freetype-config like freetype-config --libs
use the FindFreetype cmake module
Now I'm trying to implement the second option and I'm not very skilled with cmake nor I understand the logic of it.
My problem is the linking phase, I have no idea how to do that properly plus this module is not as complete as the result of freetype-config --libs which really includes all the libraries and flags that I need, and not just the path of a file; so I'm assuming that I have to do the same for zlib and libpng.
CMakeLists.txt
cmake_minimum_required (VERSION 2.6)
project (FreetypeTutorials1)
include(FindFreetype)
include_directories(${FREETYPE_INCLUDE_DIRS})
SET(CMAKE_CXX_FLAGS "-O2 -std=c++11")
SET(CMAKE_EXE_LINKER_FLAGS "-v -lfreetype")
add_executable( demo "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp")
./src/main.cpp ( just some random code so I have something to feed to the compiler )
extern "C" {
#include <ft2build.h>
#include FT_FREETYPE_H
}
#include <iostream>
int main()
{
FT_Library library;
auto error = FT_Init_FreeType(&library);
if (error)
{
std::cout << "An error !\n";
}
}
To load a module like FindFreetype.cmake you need to use it in cmake with the find_package-command. The first argument is the package name. The "Find" of its corresponding filename is added automatically by cmake.
While include might work with find_package you can add some flags. For example, as shown below, REQUIRED, to make cmake fail when freetype wasn't found.
Additionally linking with cmake should be done with the command target_link_libraries.
This is how I would write you CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (FreetypeTutorials1)
find_package(Freetype REQUIRED)
SET(CMAKE_CXX_FLAGS "-O2 -std=c++11")
SET(CMAKE_EXE_LINKER_FLAGS "-v")
add_executable( demo src/main.cpp) # CMAKE_CURRENT_SOURCE_DIR is implicit here
target_link_libraries(demo ${FREETYPE_LIBRARIES})
target_include_directories(demo PRIVATE ${FREETYPE_INCLUDE_DIRS})
target_link_libraries is platform independent whereas '-lfreetype in CMAKE_EXE_LINKER_FLAGS is not.
The CMakeLists.txt will work on other platforms where freetype is available.
(Edit 2019: use target_include_directories() instead of include_directories()