I will try to explain in detail the difficulties I encountered.
Recently I want to use boost libraries in Ubuntu Mint 18 x64. So I download the newest version of it which is 1.62.0. Sha256sum is fine. Then I started compiled it with "./bootstrap.sh" and "./b2". Finally copied then to "/usr/local" with "sudo ./b2 install". So far so good.
I am using Clion right now, so new job is to add libraries in Cmakelist.txt. Code below is what I have added.
set(BOOST_ROOT /usr/local)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.62.0)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(BoostTest main.cpp)
target_link_libraries(BoostTest ${Boost_LIBRARIES})
endif()
First thing I want to explain is that I know it is not good to set up a specific location in CMake, but without it Cmake cannot find it. So I just do that. And, at this moment, CMake did not post any error info. Here is my hello_world demo.
#include <iostream>
#include <boost/thread/testable_mutex.hpp>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
I just include a .hpp for test, nothing else. When I attemped to run it. I got these.
-- Boost version: 1.62.0
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vita-nove/ClionProjects/BoostTest/cmake-build-debug
[ 50%] Building CXX object CMakeFiles/BoostTest.dir/main.cpp.o
[100%] Linking CXX executable BoostTest
CMakeFiles/BoostTest.dir/main.cpp.o: In function `__static_initialization_and_destruction_0(int, int)':
/usr/local/include/boost/system/error_code.hpp:221: undefined reference to `boost::system::generic_category()'
/usr/local/include/boost/system/error_code.hpp:222: undefined reference to `boost::system::generic_category()'
/usr/local/include/boost/system/error_code.hpp:223: undefined reference to `boost::system::system_category()'
collect2: error: ld returned 1 exit status
CMakeFiles/BoostTest.dir/build.make:94: recipe for target 'BoostTest' failed
make[3]: *** [BoostTest] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/BoostTest.dir/all' failed
make[2]: *** [CMakeFiles/BoostTest.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/BoostTest.dir/rule' failed
make[1]: *** [CMakeFiles/BoostTest.dir/rule] Error 2
Makefile:118: recipe for target 'BoostTest' failed
make: *** [BoostTest] Error 2
Wired thing is that I do find some .hpp file in External Libraries. They are all located in /include/boost. In /usr/local/lib and /usr/local/include/boost everything shows up as I expect.
Sorry for my bad English. After spending nearly whole day searching and testing I cannot solve it. I don't know what dependencies I have missed or something else. Anyway, Thank you for reading this, hope someone will help.
You have to tell cmake that you need the thread library
set(BOOST_ROOT /usr/local)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.62.0 COMPONENTS thread system) # <-- here
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(BoostTest main.cpp)
target_link_libraries(BoostTest ${Boost_LIBRARIES})
endif()
Related
I'm trying to compile and execute a simple test program with curl lib.
#include <curl/curl.h>
using namespace std;
int main(){
curl_global_init(CURL_GLOBAL_DEFAULT);
curl_global_cleanup();
return 0;
}
I have a CMakeLists to generate MakeFile :
cmake_minimum_required(VERSION 3.17)
set(CMAKE_CXX_STANDARD 17)
project(ONLY25)
file(GLOB_RECURSE SRCS source/*.cpp)
file(GLOB_RECURSE HDRS source/*.h)
set(EXECUTABLE_NAME "ONLY25")
include_directories("C:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw/include")
set(CURL_DIR "C:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw")
set(CURL_LIBRARY "C:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw/lib/libcurl.dll.a" "C:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw/lib/libcurl.a")
set(CURL_INCLUDE_DIR "C:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw/include")
find_package(CURL REQUIRED)
add_executable(${EXECUTABLE_NAME} ${SRCS} ${HDRS})
target_link_libraries(${EXECUTABLE_NAME} ${CURL_LIBRARIES})
First, I use :
cmake -G "MinGW Makefiles" .
Everything works well
After that, I use :
C:\MinGW\bin\mingw32-make.exe
And I've got this linking error :
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: CMakeFiles\ONLY25.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x16): undefined reference to `_imp__curl_global_init'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: CMakeFiles\ONLY25.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x1d): undefined reference to `_imp__curl_global_cleanup'
collect2.exe: error: ld returned 1 exit status
CMakeFiles\ONLY25.dir\build.make:106: recipe for target 'ONLY25.exe' failed
mingw32-make[2]: *** [ONLY25.exe] Error 1
CMakeFiles\Makefile2:93: recipe for target 'CMakeFiles/ONLY25.dir/all' failed
mingw32-make[1]: *** [CMakeFiles/ONLY25.dir/all] Error 2
Makefile:101: recipe for target 'all' failed
mingw32-make: *** [all] Error 2
I searched a lot on internet, there are some other posts on this topics but I think I did like they said.
I tried with different version of curl, and I'm using MinGW on Windows 10.
I'm really sorry if it's a dumb mistake, I still have a little trouble with Cmake. I'm stuck here for the whole day...
I'd appreciate your help with some explaination to not reproduce this aberration :)
I tried some new things thanks to responses :
set up FindCURL.cmake by copying this one link
change the CMakeLists
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
message(${CMAKE_MODULE_PATH})
set(CURL_LIBRARY "-lcurl")
find_package(CURL)
message(${CURL_LIBRARIES})
message(${CURL_INCLUDE_DIRS})
include_directories(${CURL_INCLUDE_DIRS})
add_executable(${EXECUTABLE_NAME} ${SRCS} ${HDRS})
target_link_libraries(${EXECUTABLE_NAME} ${CURL_LIBRARIES})
Currently, the cmake command is working well and the variables seems legit:
CURL_LIBRARIES : C:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw/lib/libcurl.dll.aC:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw/lib/libcurl.a
CURL_INCLUDE_DIRS : C:/Users/natha/Desktop/work/myLibs/curl-7.71.1-win64-mingw/include
However, there is again the linking error with the make command...
I'm trying to write a GUI appication (under Ubuntu 18.04) using Qt5 and CMake. I failed to integrate the Qt multimedia module into my project.
My CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(Chess)
#set(CMAKE_PREFIX_PATH "/home/mashplant/Qt5.9.6/5.9.6/gcc_64")
#whether I comment it off or not doesn't have an effect on the result
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5 COMPONENTS Widgets Network Multimedia REQUIRED)
set(CMAKE_CXX_STANDARD 11)
include_directories(.)
add_executable(Main Main.cpp
MainWindow.cpp MainWindow.hpp ChessFrame.cpp ChessFrame.hpp resource.qrc)
target_link_libraries(Main Qt5::Widgets Qt5::Network Qt5::Multimedia)
And I get the following warning when I run CMake:
CMake Warning at CMakeLists.txt:18 (add_executable):
Cannot generate a safe runtime search path for target Main because files in
some directories may conflict with libraries in implicit directories:
runtime library [libQt5Widgets.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/mashplant/Qt5.9.6/5.9.6/gcc_64/lib
runtime library [libQt5Network.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/mashplant/Qt5.9.6/5.9.6/gcc_64/lib
runtime library [libQt5Gui.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/mashplant/Qt5.9.6/5.9.6/gcc_64/lib
runtime library [libQt5Core.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/mashplant/Qt5.9.6/5.9.6/gcc_64/lib
Some of these libraries may not be found correctly.
And when I compile, I get a link error.
/home/mashplant/Qt5.9.6/5.9.6/gcc_64/lib/libQt5Multimedia.so.5.9.6:undefined reference to ‘operator delete(void*, unsigned long)#Qt_5’
collect2: error: ld returned 1 exit status
CMakeFiles/Main.dir/build.make:203: recipe for target 'Main' failed
make[3]: *** [Main] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/Main.dir/all' failed
make[2]: *** [CMakeFiles/Main.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/Main.dir/rule' failed
make[1]: *** [CMakeFiles/Main.dir/rule] Error 2
Makefile:118: recipe for target 'Main' failed
make: *** [Main] Error 2
My best bet is that CMake find different components from different installations of Qt. If that's the case, it should be enough to correct all Qt-related CMake variables to point to correct paths (for example, variables like Qt5Widgets_DIR, Qt5Multimedia_DIR, etc.).
Let's consider the following trivial code for connecting C to python as follows
// main.cpp
#include <Python.h>
int main()
{
Py_Initialize();
return 0;
}
The following CMake code works fine for
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.9)
project (myapp)
find_package(Threads)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(Python_ADDITIONAL_VERSIONS 3.5)
find_package(Threads REQUIRED)
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
add_executable(myapp
main.cpp
)
target_link_libraries(myapp rt)
target_link_libraries(myapp ${CMAKE_DL_LIBS})
target_link_libraries(myapp "-L/usr/lib/python3.5/config-3.6m-x86_64-linux-gnu -L/usr/lib -lpython3.5m -Bsymbolic-functions")
#target_link_libraries(myapp ${PYTHON_LIBRARIES})
target_link_libraries(myapp ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(myapp ${PYTHON_LIBRARIES})
The problem is when I move the code to another computer, the linking fails as I have python 3.6 there instead of 3.5. Thus I should replace every 3.5 with 3.6. Is there any portable solution for linking python?
I have tried this instead of the lengthy line but it does not work:
target_link_libraries(myapp ${PYTHON_LIBRARIES})
With the following message:
/usr/local/lib/libpython3.5m.a(posixmodule.o): In function `os_forkpty_impl':
/usr/src/Python-3.5.2/./Modules/posixmodule.c:5972: undefined reference to `forkpty'
/usr/local/lib/libpython3.5m.a(posixmodule.o): In function `os_openpty_impl':
/usr/src/Python-3.5.2/./Modules/posixmodule.c:5878: undefined reference to `openpty'
/usr/local/lib/libpython3.5m.a(dynload_shlib.o): In function `_PyImport_FindSharedFuncptr':
/usr/src/Python-3.5.2/./Python/dynload_shlib.c:82: undefined reference to `dlsym'
/usr/src/Python-3.5.2/./Python/dynload_shlib.c:95: undefined reference to `dlopen'
/usr/src/Python-3.5.2/./Python/dynload_shlib.c:126: undefined reference to `dlsym'
/usr/src/Python-3.5.2/./Python/dynload_shlib.c:95: undefined reference to `dlopen'
/usr/src/Python-3.5.2/./Python/dynload_shlib.c:101: undefined reference to `dlerror'
collect2: error: ld returned 1 exit status
CMakeFiles/myapp.dir/build.make:96: recipe for target 'myapp' failed
make[2]: *** [myapp] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/myapp.dir/all' failed
make[1]: *** [CMakeFiles/myapp.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
Distributing standalone application dynamically linked against python
Generally speaking, since the API and ABI between minor version of python change, you would have to distribute one version of your executable for each python version you would like to support.
For example, your different application could be named myapp-cpython-34m-linux_x86_64, myapp-cpython-35m-linux_x86_64, ... or myapp-py34m, ...
The Stable Application Binary Interface
As described in Stable Application Binary Interface document, you could compile your program with Py_LIMITED_API definition (meaning only a subset of the API is used), that would allow you create a binary compatible with any version of python start with python 3.2.
That said, this only work well for cpython binary extension that are imported in the cpython interpreter. Indeed, in that case the python symbols are already available.
In your care, myapp would have to find any of the shared python 3.x library and I believe that is not supported by the operating system library loader.
Possible solutions
Redistribute your own python shared library
Statically link against CPython library
Note that if your project uses a compiler different from the one officially associated with a given version of CPython, you could easily compile CPython itself using https://github.com/python-cmake-buildsystem/python-cmake-buildsystem
Tweak and improvement to your project
Here is an improved version of your project specifying Usage requirements for the target.
cmake_minimum_required(VERSION 3.12)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(myapp)
# dependencies
set(Python_ADDITIONAL_VERSIONS 3.5)
find_package(PythonLibs REQUIRED)
find_package(Threads REQUIRED)
# executable
add_executable(myapp
main.cpp
)
target_compile_definitions(myapp
PRIVATE
Py_LIMITED_API
)
target_include_directories(myapp
PRIVATE
${PYTHON_INCLUDE_DIRS}
)
target_link_libraries(myapp
PRIVATE
${CMAKE_DL_LIBS}
Threads::Threads
${PYTHON_LIBRARIES}
rt
)
I'm trying to compile a c++ program that uses xlib with cmake. However, I'm having a problem including and linking xlib libraries in cmake file.
This is the error that I'm getting.
main.cpp:378: undefined reference to `XClearWindow'
collect2: error: ld returned 1 exit status
CMakeFiles/project1.dir/build.make:94: recipe for target 'project1' failed
make[2]: *** [project1] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/project1.dir/all' failed
make[1]: *** [CMakeFiles/project1.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
And when I use just the command line to compile, it works just fine.
I use this command (g++ main.cpp -L/usr/X11R6/lib -lX11)
and this is my cmake file.
cmake_minimum_required(VERSION 3.6)
project(project1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
link_directories(/usr/X11R6/lib)
include_directories(/usr/share/X11)
set(SOURCE_FILES main.cpp)
add_executable(project1 ${SOURCE_FILES})
In your case, you forgot to specify the libraries that cmake should use to link your application (target_link_libraries or link_libraries).
But, why not just let cmake find the required path, libraries and includes by itself? I suggest you to use find_package(X11). In your case, you can try:
cmake_minimum_required(VERSION 3.6)
project(project1)
set(CMAKE_CXX_STANDARD 11) # for c++11
find_package(X11 REQUIRED)
link_libraries(${X11_LIBRARIES})
include_directories(${X11_INCLUDE_DIR})
set(SOURCE_FILES main.cpp)
add_executable(project1 ${SOURCE_FILES})
I won't be able to explain why (if you have some idea, don't hesitate to comment my answer), but, in my case, I had to link X11 library using this command:
target_link_libraries( DisplayImage "-lX11" )
It works, at least, for the 3.5.1 version of cmake.
I have a project with the following structure
/cmake_modules/
FindSFML.cmake
/includes/
car.hpp
motor.hpp
tires.hpp
/sources/
car.cpp
motor.cpp
tires.cpp
/main.cpp
/main.hpp
I have the following CMakeFiles.txt file:
cmake_minimum_required(VERSION 2.8)
project (MYGAME)
set (MYGAME_VERSION_MAJOR 1)
set (MYGAME_VERSION_MINOR 0)
set (EXECUTABLE_NAME "mygame")
include_directories ("${MYGAME_BINARY_DIR}")
include_directories ("${MYGAME_BINARY_DIR}/includes")
link_directories ("${MYGAME_BINARY_DIR}/sources")
add_executable(${EXECUTABLE_NAME} main.cpp)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 2.0 REQUIRED system window graphics network audio)
target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
When I try to execute make I get this:
[100%] Building CXX object CMakeFiles/mygame.dir/main.cpp.o
Linking CXX executable mygame
CMakeFiles/mygame.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x11): undefined reference to `mynamespace::Car::Instance()'
main.cpp:(.text+0x21): undefined reference to `mynamespace::Car::start()'
collect2: error: ld returned 1 exit status
make[2]: *** [mygame] Error 1
make[1]: *** [CMakeFiles/mygame.dir/all] Error 2
make: *** [all] Error 2
How do I fix it?
You need to include the rest of your sources (car.cpp, motor.cpp and tires.cpp) in the build in some way.
You can either add them along with main.cpp in the executable directly:
set(MySources sources/car.cpp sources/motor.cpp sources/tires.cpp main.cpp)
add_executable(${EXECUTABLE_NAME} ${MySources})
or you can make these into a library and link that:
set(MyLibSources sources/car.cpp sources/motor.cpp sources/tires.cpp)
add_library(MyLib ${MyLibSources})
add_executable(${EXECUTABLE_NAME} main.cpp)
...
target_link_libraries(${EXECUTABLE_NAME} MyLib ${SFML_LIBRARIES})
A couple of other points to note:
You should avoid the use of link_directories if possible (its own documentation discourages its use), and it's often helpful to include the headers in the list of files added via add_executable or add_library since these then show up in IDEs like MS Visual Studio.