I would like to compile my own project. I have error with **make**. cmake .. works properly.
I tried to compile the example in /Onboard-SDK/sample/platform/telemetry.
I did mkdir build and cd build in telemetry directory.
This is my CMakeList.txt
cmake_minimum_required(VERSION 2.8)
project(djiosdk-telemetry-sample)
# Compiler flags: link with pthread and enable C++11 support
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -g -O0")
# Tell the project where osdk-core is located
if(NOT ONBOARDSDK_SOURCE)
set(ONBOARDSDK_SOURCE "/home/pi/Onboard-SDK/osdk-core")
#set(ONBOARDSDK_SOURCE "/usr/local/include")
endif()
# Specify locations for osdk-core headers
include_directories(${ONBOARDSDK_SOURCE}/api/inc)
include_directories(${ONBOARDSDK_SOURCE}/utility/inc)
include_directories(${ONBOARDSDK_SOURCE}/hal/inc)
include_directories(${ONBOARDSDK_SOURCE}/protocol/inc)
include_directories(${ONBOARDSDK_SOURCE}/platform/linux/inc)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../hal)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../osal)
include_directories(include /usr/local/include)
include_directories(${ONBOARDSDK_SOURCE}/../sample/core/inc)
# User-code related project files
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common)
FILE(GLOB SOURCE_FILES *.hpp *.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../common/dji_linux_environment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../common/dji_linux_helpers.cpp
main.cpp
telemetry_sample.cpp
)
if (OSDK_HOTPLUG)
FILE(GLOB SOURCE_FILES ${SOURCE_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/../hal/hotplug/*.c)
endif ()
# Target and linking
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} djiosdk-core)
This is the result after make
[ 20%] Linking CXX executable djiosdk-telemetry-sample
/usr/bin/ld: //usr/local/lib/libdjiosdk-core.a(dji_legacy_linker.cpp.o): in function `DJI::OSDK::LegacyLinker::legacyX5SEnableTask(void*)':
/home/pi/Onboard-SDK/osdk-core/api/src/dji_legacy_linker.cpp:69: **undefined reference to `DJI::OSDK**::Linker::getLocalSenderId()'
/usr/bin/ld: /home/pi/Onboard-SDK/osdk-core/api/src/dji_legacy_linker.cpp:71: **undefined reference** to `OsdkOsal_TaskSleepMs'
/usr/bin/ld: /home/pi/Onboard-SDK/osdk-core/api/src/dji_legacy_linker.cpp:72: **undefined reference** to `**DJI::OSDK**::Linker::isUSBPlugged()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/djiosdk-telemetry-sample.dir/build.make:129: djiosdk-telemetry-sample] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/djiosdk-telemetry-sample.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I often have [100%] Linking CXX executable djiosdk-telemetry-sample.
The main problem is with "undefined reference".
I create CMakeList.txt according to: https://developer.dji.com/onboard-sdk/documentation/development-workflow/integrate-sdk.html
What I should do?
The proper CMakeList.txt for creating your own project (example based on telemetry sample):
cmake_minimum_required(VERSION 2.8)
project(djiosdk-telemetry-sample)
set(ARCH armv7)
# Compiler flags: link with pthread and enable C++11 support
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -g -O0")
# Tell the project where osdk-core is located
if(NOT ONBOARDSDK_SOURCE)
set(ONBOARDSDK_SOURCE "/home/pi/Onboard-SDK/osdk-core")
endif()
set(CURRENT_CMAKE_MODULE_PATH ${ONBOARDSDK_SOURCE}/cmake-modules)
# Specify locations for osdk-core headers
include_directories(${ONBOARDSDK_SOURCE}/api/inc)
include_directories(${ONBOARDSDK_SOURCE}/utility/inc)
include_directories(${ONBOARDSDK_SOURCE}/hal/inc)
include_directories(${ONBOARDSDK_SOURCE}/protocol/inc)
include_directories(${ONBOARDSDK_SOURCE}/platform/linux/inc)
include_directories(${ONBOARDSDK_SOURCE}/linker/${ARCH}/inc)
include_directories(${ONBOARDSDK_SOURCE}/../sample/platform/linux/hal)
include_directories(${ONBOARDSDK_SOURCE}/../sample/platform/linux/hal/hotplug)
include_directories(${ONBOARDSDK_SOURCE}/../sample/platform/linux/osal)
include_directories(include /usr/local/include)
include_directories(include /usr/local/lib)
include_directories(${ONBOARDSDK_SOURCE}/../sample/core/inc)
# User-code related project files
include_directories(${ONBOARDSDK_SOURCE}/../sample/platform/linux/common)
FILE(GLOB SOURCE_FILES *.hpp *.cpp
${ONBOARDSDK_SOURCE}/../sample/platform/linux/common/dji_linux_environment.cpp
${ONBOARDSDK_SOURCE}/../sample/platform/linux/common/dji_linux_helpers.cpp
${ONBOARDSDK_SOURCE}/../sample/platform/linux/hal/osdkhal_linux.c
${ONBOARDSDK_SOURCE}/../sample/platform/linux/osal/osdkosal_linux.c
)
if (OSDK_HOTPLUG)
FILE(GLOB SOURCE_FILES ${SOURCE_FILES} ${ONBOARDSDK_SOURCE}/../sample/platform/linux/hal/hotplug/*.c)
endif ()
link_libraries(dji-linker)
link_directories(/usr/local/include /usr/local/lib)
link_libraries(${ONBOARDSDK_SOURCE}/linker/${ARCH}/lib/libdji-linker.a)
set(CMAKE_MODULE_PATH ${CURRENT_CMAKE_MODULE_PATH})
find_package(LibUSB REQUIRED)
find_package(FFMPEG REQUIRED)
include_directories(${ADVANCED_SENSING_HEADERS_DIR})
# Target and linking
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} PUBLIC djiosdk-core)
target_link_libraries(${PROJECT_NAME} PUBLIC dji-linker)
target_link_libraries(${PROJECT_NAME} PUBLIC ${ONBOARDSDK_SOURCE}/linker/${ARCH}/lib/libdji-linker.a)
target_include_directories(${PROJECT_NAME} PUBLIC ${LIBUSB_1_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PUBLIC ${LIBUSB_1_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PUBLIC ${FFMPEG_LIBRARIES})
target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${ADVANCED_SENSING_HEADERS_DIR}>)
target_link_libraries(${PROJECT_NAME} PRIVATE advanced-sensing)
target_include_directories(${PROJECT_NAME} PUBLIC ${FFMPEG_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC ${FFMPEG_LIBRARIES})
I try to compile some protocol-buffer files and I am getting the following errors.
[ 99%] Building CXX object CMakeFiles/lattice_planner.dir/modules/control/proto/lat_controller_conf.pb.cc.o
[100%] Linking CXX executable lattice_planner
CMakeFiles/lattice_planner.dir/modules/localization/proto/pose.pb.cc.o:(.bss+0x0): multiple definition of `apollo::localization::_Pose_default_instance_'
CMakeFiles/lattice_planner.dir/modules/common/localization/proto/pose.pb.cc.o:(.bss+0x0): first defined here
CMakeFiles/lattice_planner.dir/modules/localization/proto/pose.pb.cc.o: In function `apollo::localization::Pose::Pose()':
pose.pb.cc:(.text+0x4e8): multiple definition of `apollo::localization::Pose::Pose()'
CMakeFiles/lattice_planner.dir/modules/common/localization/proto/pose.pb.cc.o:pose.pb.cc:(.text+0x4e8): first defined here
The files are in different folders. Can I trick the compiler GCC 5.4.0 so that there are not multiple definitions?
The CMakeLists.txt is quite huge because I added all source files by hand. Here are some code snippets:
cmake_minimum_required(VERSION 3.5)
project(lattice_planner_src)
set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -pthread")
find_package(Protobuf 3.7.1 REQUIRED)
if(PROTOBUF_FOUND)
message ("log: protobuf found")
else()
message (FATAL_ERROR "Cannot find Protobuf")
endif()
add_executable(lattice_planner apollo-planner-test-main.cpp ${SOURCE_FILES} ${HEADER_FILES} ${PTB_SRC} ${PTB_HDR})
target_include_directories (
lattice_planner
PUBLIC
${Boost_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}
${PROTOBUF_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
/usr/local/include/qpOASES
${TinyXML2_INCLUDE_DIR}
${IPOPT_INCLUDE_DIRS}
${GLOG_INCLUDE_DIR}
ctpl
)
target_link_libraries(lattice_planner
# EIGEN
${TinyXML2_LIBRARIES}
# ${GLOG_LIBRARY}
${IPOPT_LIBRARIES}
${Boost_LIBRARIES}
${PROTOBUF_LIBRARIES}
/usr/local/lib/libglog.so.0
/usr/local/lib/libqpOASES.a
${libgtest}
)
while the PTB_SRC and PTB_HDR are the protocol-buffer sources and headers. This project is already running on windows with MS projects. Unfortunately, I don't have any CMake for that. I am also happy for ideas and guesses.
I'm trying to build my C++ app using CMake (CLion on Windows). Application uses Thrift libraries, and those have been successfully (at least I hope so) built with Microsoft Visual 2015. I can built app with SCons:
import os
from os import path, listdir
gen_cpp = [path.join('gen-cpp', f) for f in listdir('gen-cpp') if f.endswith('.cpp')]
client_source = [path.join('logic', folder, f) for folder in ['', 'parser', 'mars', 'view']
for f in listdir(path.join('logic', folder)) if f.endswith('.cpp')]
server_source = [path.join('server', 'server.cpp')]
tests_source = [path.join('test_cases', f) for f in listdir('test_cases') if f.endswith('.cpp')]
cpppath = ['.','c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src\\','c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src\\thrift\\server',
'c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\']
libpath = ['C:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release\\', 'c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\stage\\x64\\lib\\',
'C:\\OpenSSL-Win64\\lib']
libs = ['libthrift','libssl','openssl','libcrypto']
env = Environment(CPPPATH = cpppath,
LIBS = libs,
LIBPATH = libpath,
MSVC_VERSION='14.0',
CPPFLAGS='/EHsc',
)
gen_cpp_o = env.Object(gen_cpp)
client_o = env.Object(client_source)
tests_o = env.Object(tests_source)
tests_files = gen_cpp_o + [f for f in client_o if str(f) != path.join('logic', 'main.obj')] + tests_o
env.Program('CoreWars', gen_cpp_o + client_o)
env.Program('Server', gen_cpp_o + server_source)
env.Program('tests', tests_files)
.exe files, created as a result of the 'scons' command, work perfectly fine. But, when I try to do build app with CMake, like that:
cmake_minimum_required(VERSION 3.7)
project(client)
SET (THRIFT_ROOT "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0")
SET (THRIFT_INCLUDEDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src")
SET (THRIFT_LIBRARYDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release")
include_directories(${THRIFT_INCLUDEDIR})
MESSAGE("Thrift_LIBRARIES: ${THRIFT_LIBRARYDIR}")
MESSAGE("Thrift_INCLUDES: ${THRIFT_INCLUDEDIR}")
#find_package(Thrift REQUIRED)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
SET (BOOST_ROOT "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_INCLUDEDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_LIBRARYDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\libs")
find_package(Boost 1.64.0 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
set(SOURCE_FILES ../gen-cpp/MARS.cpp ../gen-cpp/mars_constants.cpp ../gen-cpp/mars_types.cpp main.cpp
parser/InstructionFactory.cpp parser/RedcodeParser.cpp parser/InstructionData.cpp ServerConnector.cpp
mars/Instruction.cpp mars/InstructionOperator.cpp parser/ParserException.cpp MainController.cpp
mars/MarsSimulator.cpp Initializer.cpp Player.cpp Player.h PlayerInfo.cpp PlayerInfo.h Warrior.cpp
Warrior.h PlayerCreator.cpp PlayerCreator.h view/ViewInput.cpp view/ViewInput.h MarsResult.cpp MarsResult.h
mars/DatInstruction.cpp mars/DatInstruction.h mars/MovInstruction.cpp mars/MovInstruction.h)
add_executable(CoreWars ${SOURCE_FILES})
target_link_libraries(CoreWars ${Boost_LIBRARIES} $(THRIFT_LIBRARYDIR))
CMake reports an error:
[ 4%] Linking CXX executable CoreWars.exe
G__~1.EXE: error: $(THRIFT_LIBRARYDIR): No such file or directory
mingw32-make.exe[3]: *** [logic/CoreWars.exe] Error 1
If i try to find thrift library with find_package(Thrift REQUIRED) command, I get the following error:
CMake Error at logic/CMakeLists.txt:13 (find_package):
By not providing "FindThrift.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Thrift", but
CMake did not find one.
Could not find a package configuration file provided by "Thrift" with any
of the following names:
ThriftConfig.cmake
thrift-config.cmake
I would be grateful for any help.
EDIT1:
I tried to solve my problem with the help of this question: CMake link to external library, but, unfortunately, it does not work for me.
I have edited my CMakeList.txt:
cmake_minimum_required(VERSION 3.7)
project(client)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
SET (THRIFT_ROOT "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0")
SET (THRIFT_INCLUDEDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src")
SET (THRIFT_LIBRARYDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release")
MESSAGE("Thrift_LIBRARIES: ${THRIFT_LIBRARYDIR}")
MESSAGE("Thrift_INCLUDES: ${THRIFT_INCLUDEDIR}")
find_library(THRIFT_FOUND_LIB thrift PATHS ${THRIFT_LIBRARYDIR})
MESSAGE("Thrift found lib: ${THRIFT_FOUND_LIB}")
link_libraries(thrift "${THRIFT_FOUND_LIB}")
link_directories(${THRIFT_LIBRARYDIR})
include_directories(${THRIFT_INCLUDEDIR})
SET (BOOST_ROOT "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_INCLUDEDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_LIBRARYDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\libs")
find_package(Boost 1.64.0 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
set(SOURCE_FILES ../gen-cpp/MARS.cpp ../gen-cpp/mars_constants.cpp ../gen-cpp/mars_types.cpp main.cpp
parser/InstructionFactory.cpp parser/RedcodeParser.cpp parser/InstructionData.cpp ServerConnector.cpp
mars/Instruction.cpp mars/InstructionOperator.cpp parser/ParserException.cpp MainController.cpp
mars/MarsSimulator.cpp Initializer.cpp Player.cpp Player.h PlayerInfo.cpp PlayerInfo.h Warrior.cpp
Warrior.h PlayerCreator.cpp PlayerCreator.h view/ViewInput.cpp view/ViewInput.h MarsResult.cpp MarsResult.h
mars/DatInstruction.cpp mars/DatInstruction.h mars/MovInstruction.cpp mars/MovInstruction.h)
add_executable(CoreWars ${SOURCE_FILES})
MESSAGE("Cmake prefix path: ${CMAKE_PREFIX_PATH}")
LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
target_link_libraries(CoreWars ${Boost_LIBRARIES} thrift)
Cmake commnad find_library successfully finds my thrift. Here is CMake output:
C:\Users\Antek\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\171.4073.41\bin\cmake\bin\cmake.exe -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" C:\Users\Antek\Documents\MEGAsync\_STUDIA\ZPR\proj1\Core-Wars-ZPR
Thrift_LIBRARIES: c:\Users\Antek\libs\thrift-0.10.0\thrift-0.10.0\lib\cpp\x64\Release
Thrift_INCLUDES: c:\Users\Antek\libs\thrift-0.10.0\thrift-0.10.0\lib\cpp\src
Thrift found lib: C:/Users/Antek/libs/thrift-0.10.0/thrift-0.10.0/lib/cpp/x64/Release/libthrift.lib
-- Boost version: 1.64.0
Cmake prefix path:
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Antek/Documents/MEGAsync/_STUDIA/ZPR/proj1/Core-Wars-ZPR/cmake-build-release
But, when I try to link my project, there is an error:
[ 4%] Linking CXX executable CoreWars.exe
C:/PROGRA~1/MINGW-~1/X86_64~1.2-P/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lthrift
Am I missing something? Note that thrift has been built in x64/Release mode, and I am using x64 mingw in CLion and CMake is also in release mode.
Thanks.
EDIT2:
After fiew improvements, linker seems to be able to find thrift. But, now, I get undefined reference to... error. For the thrift and also some boost libs. For example:
CMakeFiles\CoreWars.dir/objects.a(MARS.cpp.obj):MARS.cpp:(.text+0x454): undefined reference to `apache::thrift::TApplicationException::write(apache::thrift::protocol::TProtocol*) const'
and
CMakeFiles\CoreWars.dir/objects.a(MARS.cpp.obj):MARS.cpp:(.text.startup+0x11): undefined reference to `boost::system::generic_category()'
What may be the cause of this error? Shouldn't ${Boost_LIBRARIES} include also Boost.System library path? Googled solutions seem to not be appropriate in this case.
Updated CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(client)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
SET (THRIFT_ROOT "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0")
SET (THRIFT_INCLUDE_DIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src")
SET (THRIFT_LIB_DIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release")
find_library(THRIFT_FOUND_LIB thrift PATHS ${THRIFT_LIB_DIR})
MESSAGE("Found Thrift lib: ${THRIFT_FOUND_LIB}")
find_path(THRIFT_FOUND_HEADERS thrift PATHS ${THRIFT_INCLUDE_DIR})
MESSAGE("Found Thrift headers: ${THRIFT_FOUND_HEADERS}")
include_directories(${THRIFT_FOUND_HEADERS})
link_directories(${THRIFT_FOUND_HEADERS})
link_directories(${THRIFT_FOUND_LIB})
SET (BOOST_ROOT "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
#SET (BOOST_INCLUDEDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
#SET (BOOST_LIBRARYDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\libs")
find_package(Boost 1.64.0 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARIES})
set(SOURCE_FILES ../gen-cpp/MARS.cpp ../gen-cpp/mars_constants.cpp ../gen-cpp/mars_types.cpp main.cpp
parser/InstructionFactory.cpp parser/RedcodeParser.cpp parser/InstructionData.cpp ServerConnector.cpp
mars/Instruction.cpp mars/InstructionOperator.cpp parser/ParserException.cpp MainController.cpp
mars/MarsSimulator.cpp Initializer.cpp Player.cpp Player.h PlayerInfo.cpp PlayerInfo.h Warrior.cpp
Warrior.h PlayerCreator.cpp PlayerCreator.h view/ViewInput.cpp view/ViewInput.h MarsResult.cpp MarsResult.h
mars/DatInstruction.cpp mars/DatInstruction.h mars/MovInstruction.cpp mars/MovInstruction.h)
add_executable(CoreWars ${SOURCE_FILES})
target_include_directories(CoreWars SYSTEM PUBLIC ${THRIFT_FOUND_HEADERS})
target_link_libraries(CoreWars LINK_PUBLIC ${THRIFT_FOUND_LIB} ${Boost_LIBRARIES} )
Thank You again.
It looks like you are passing the directory where to look for the library, but not the name of the actual library. Add this in your CMakelists.txt, it should work:
target_include_directories(${THRIFT_INCLUDEDIR})
target_link_libraries(CoreWars ${Boost_LIBRARIES} libthrift.lib) # Or may be just 'thrift'
I have C++ code which uses FFTW 3.3.4. Ubuntu 16.04, cmake version 3.7.2
$ locate *fftw*.so
/usr/lib/libsfftw.so
/usr/lib/libsfftw_mpi.so
/usr/lib/libsfftw_threads.so
/usr/lib/libsrfftw.so
/usr/lib/libsrfftw_mpi.so
/usr/lib/libsrfftw_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3.so
/usr/lib/x86_64-linux-gnu/libfftw3_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3f.so
/usr/lib/x86_64-linux-gnu/libfftw3f_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3f_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3f_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3l.so
/usr/lib/x86_64-linux-gnu/libfftw3l_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3l_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3l_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3q.so
/usr/lib/x86_64-linux-gnu/libfftw3q_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3q_threads.so
$ locate fftw3.h
/usr/include/fftw3.h
I can compile it in this way:
g++ main.cpp -o main -lfftw3
but I have a problem with cmake.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1)
project (main)
SET(CMAKE_C_COMPILER gcc)
SET(CMAKE_CXX_COMPILER g++)
file(GLOB SOURCES "*.cpp")
SET(CMAKE_CXX_FLAGS "-lm -lfftw3")
SET(CMAKE_C_FLAGS "-lm -lfftw3")
INCLUDE_DIRECTORIES(/usr/include)
LINK_DIRECTORIES(/usr/lib/x86_64-linux-gnu)
add_library(fftw3 STATIC IMPORTED)
set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
add_executable(main ${SOURCES})
cmake . && make
gives
undefined reference to `fftw_malloc'
and the same for the other fftw functions.
The command add_library will create a library in your project (CMake -
add_library). I assume that is not what you want.
The command: g++ main.cpp -o main -lfftw3 will link the executable to the fftw library. In CMake you can reproduce the linking with:
add_executable(main ${SOURCES})
target_link_libraries(main fftw3)
Docu: CMake - target_link_libraries
Notice: It is important that the add_executable command comes before the linking.
Have fun with FFTW :)
We delegate this to pkg-config:
find_package(PkgConfig REQUIRED)
pkg_search_module(FFTW REQUIRED fftw3 IMPORTED_TARGET)
include_directories(PkgConfig::FFTW)
link_libraries (PkgConfig::FFTW)
This works with cmake 3.11 (at least, it may work with earlier versions too).
NOTE: This doesn't work with fftw3_thread component because they don't have a separate .pc file. (see https://github.com/FFTW/fftw3/issues/180).
This may work to add the component (not tested, doesn't work in Macs --see comments--):
link_libraries (PkgConfig::FFTW -lfftw3_thread)
NOTE 2: I am pasting here #OlafWilkocx solution to get the thread component as well
cmake_minimum_required(VERSION 3.20)
...
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-math-errno -ffinite-math-only") # clang
find_package(OpenMP REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFTW IMPORTED_TARGET REQUIRED fftw3)
if( NOT FFTW_ROOT AND DEFINED ENV{FFTWDIR} )
set( FFTW_ROOT $ENV{FFTWDIR} )
endif()
find_library(
FFTW_DOUBLE_THREADS_LIB
NAMES "fftw3_threads"
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
)
if (FFTW_DOUBLE_THREADS_LIB)
set(FFTW_DOUBLE_THREADS_LIB_FOUND TRUE)
set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_THREADS_LIB})
add_library(FFTW::DoubleThreads INTERFACE IMPORTED)
set_target_properties(FFTW::DoubleThreads
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_THREADS_LIB}"
)
else()
set(FFTW_DOUBLE_THREADS_LIB_FOUND FALSE)
endif()
include_directories(PkgConfig::FFTW)
add_executable(solver_step src/solver_step.cc)
target_link_libraries(solver_step PRIVATE OpenMP::OpenMP_CXX ${VTK_LIBRARIES} PkgConfig::FFTW ${FFTW_DOUBLE_THREADS_LIB})
NOTE 3
I am told that the line include_directories(PkgConfig::FFTW) is always incorrect and suggested to either only use link_libraries(PkgConfig::FFTW) or target_link_libraries(target_name PRIVATE PkgConfig::FFTW).
see here: Avoid bad include paths in CMake's pkg-config fallback
I have a cmake project where I want to add a class containing the matlab engine. For compiling it I need to include two libraries eng and mx, which I do by adding
target_link_libraries( ${TARGET} /usr/local/MATLAB/R2013b/bin/glnxa64/libeng.so)
target_link_libraries( ${TARGET} /usr/local/MATLAB/R2013b/bin/glnxa64/libmx.so)
to my CMakeLists.txt file.
However there are also lots of other old versions of libraries in /usr/local/MATLAB/R2013b/bin/glnxa64/, which seem
to be automatically added to the path as well when calling the above command. I think this causes the compiler to not find my
normal libraries anymore and produces an error.
How can I include only the two above libraries, and not all the others in the glnxa64 folder?
The warning shown after running cmake . :
CMake Warning at CMakeLists.txt:23 (add_executable):
Cannot generate a safe runtime search path for target CCDWidget because
files in some directories may conflict with libraries in implicit
directories:
runtime library [libboost_program_options.so.1.49.0] in /usr/lib may be hidden by files in:
/usr/local/MATLAB/R2013b/bin/glnxa64
runtime library [libboost_system.so.1.49.0] in /usr/lib may be hidden by files in:
/usr/local/MATLAB/R2013b/bin/glnxa64
runtime library [libboost_filesystem.so.1.49.0] in /usr/lib may be hidden by files in:
/usr/local/MATLAB/R2013b/bin/glnxa64
runtime library [libboost_regex.so.1.49.0] in /usr/lib may be hidden by files in:
/usr/local/MATLAB/R2013b/bin/glnxa64
Some of these libraries may not be found correctly.
And the error message during linking:
Linking CXX executable CCDWidget
/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0: undefined reference to `FT_Face_GetCharVariantIndex'
/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0: undefined reference to `FT_Get_Advance'
collect2: error: ld returned 1 exit status
make[2]: *** [CCDWidget] Error 1
make[1]: *** [CMakeFiles/CCDWidget.dir/all] Error 2
make: *** [all] Error 2
Below is my full CMakeLists.txt file. Lines commented out with two ## are alternatives that I tried before and didn't solve my problem.
I also added LINK_PRIVATE to the target_link_libraries command as shown in the code below, which didn't make a difference.
The option PRIVATE alone seems to be not accepted by my cmake version, as it changed the error meassage to
/usr/bin/ld: cannot find -lPRIVATE
collect2: error: ld returned 1 exit status
When the #eng line is commented out, the compilation and linking works without errors
(when calling the matlab engine is also commented out in Readout.cpp), so the error must be produced by that line.
#Specify the version being used as well as the language
cmake_minimum_required(VERSION 2.6)
##cmake_policy(SET CMP0003 NEW)
#Name your project here
project(CCDWidget)
set(TARGET CCDWidget)
set(MAIN_SOURCES CCDWidget.cpp main.cc CCDControl.cpp VideoWindow.cpp ImageWindow.cpp ThisMeasurement.cpp KineticSeries.cpp FastKinetics.cpp Readout.cpp)
##SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
#set_source_files_properties(Readout.cpp PROPERTIES COMPILE_FLAGS "-I/usr/local/MATLAB/R2013b/extern/include -I/usr/local/MATLAB/R2013b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -I/usr/local/MATLAB/R2013b/extern/include/cpp -I/usr/local/MATLAB/R2013b/extern/include -DGLNXA64 -DGCC -DMX_COMPAT_32 -DNDEBUG -Wno-effc++")
find_package(Boost COMPONENTS program_options system filesystem regex REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTKMM gtkmm-3.0)
include_directories( ${GTKMM_INCLUDE_DIRS} )
include_directories( ${Boost_INCLUDE_DIR} )
include_directories( ${PROJECT_SOURCE_DIR} )
##link_directories(/usr/local/MATLAB/R2013b/bin/glnxa64)
##target_link_libraries( ${TARGET} eng)
##target_link_libraries( ${TARGET} mx)
set(CMAKE_CXX_FLAGS "--std=c++11")
add_executable( ${TARGET} ${MAIN_SOURCES} )
target_link_libraries( ${TARGET} ${GTKMM_LIBRARIES} )
target_link_libraries( ${TARGET} ${Boost_LIBRARIES} )
target_link_libraries( ${TARGET} LINK_PRIVATE /usr/local/MATLAB/R2013b/bin/glnxa64/libeng.so) # eng
#target_link_libraries( ${TARGET} LINK_PRIVATE /usr/local/MATLAB/R2013b/bin/glnxa64/libmx.so ) # mx
target_link_libraries( ${TARGET} andor )
You could try using an imported target:
add_library(eng SHARED IMPORTED)
set_property(TARGET eng PROPERTY IMPORTED_LOCATION /usr/local/MATLAB/R2013b/bin/glnxa64/libeng.so)
...
add_executable( ${TARGET} ${MAIN_SOURCES} )
...
target_link_libraries(${TARGET} eng)
For debugging you could try to build with "make VERBOSE=1".
This will show you the used gcc command line.
CMake probably transforms your target_link_libraries command to something like:
g++ ... -L/usr/local/MATLAB/R2013b/bin/glnxa64 -leng ...
gcc then finds some boost libraries in this folder.