I have the following CMakeLists file:
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(PointCloudComparator)
find_package(PCL 1.7 REQUIRED COMPONENTS common io)
set(PCL_DIR "/usr/share/pcl-1.7/PCLConfig.cmake")
set(PCL_INCLUDE_DIRS "/usr/include/pcl-1.7")
set(PCL_LIBRARY_DIRS "/usr/lib/")
include_directories(${PCL_INCLUDE_DIRS} "/usr/include/eigen3" "include")
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (segmentator src/segmentation.cpp include/segmentation.h)
target_link_libraries (segmentator ${PCL_LIBRARIES}
${PCL_COMMON_LIBRARIES} ${PCL_IO_LIBRARIES}
"/usr/lib/libpcl_visualization.so" "/usr/lib/libpcl_keypoints.so"
"/usr/lib/libpcl_features.so" "/usr/lib/libpcl_kdtree.so"
"/usr/lib/libpcl_search.so" "/usr/lib/libpcl_filters.so"
"/usr/lib/libpcl_segmentation.so"
"/usr/lib/libpcl_sample_consensus.so")
add_executable (comparator src/comparator.cpp include/comparator.h
include/segmentation.h)
target_link_libraries (comparator ${PCL_LIBRARIES}
${PCL_COMMON_LIBRARIES}
${PCL_IO_LIBRARIES} "/usr/lib/libpcl_visualization.so"
"/usr/lib/libpcl_keypoints.so" "/usr/lib/libpcl_features.so"
"/usr/lib/libpcl_kdtree.so" "/usr/lib/libpcl_search.so"
"/usr/lib/libpcl_filters.so" "/usr/lib/libpcl_segmentation.so"
"/usr/lib/libpcl_sample_consensus.so")
But, when I try to compile my code, I get the error:
CMakeFiles/comparator.dir/src/comparator.cpp.o: In function `main':
comparator.cpp:(.text+0x3313): reference to
`region_growing_segmentation(std::string)' not defined
collect2: error: ld returned 1 exit status
region_growing_segmentation(std::string) is a function declared in segmentation.h and defined in segmentation.cpp. Eclipse actually knows where the function is but when I try to run make it just simply cant find it. Any ideas?
Regards
You are building two separate executables (segmentator and comparator). Each executable is made from one single source file and one single header file. That is what you say with the add_executable commands. The source files used by a single add_executable command is not shared with any other executable target you create.
If you have common code that should be shared between the two programs, then you should put it in a separate source file that you add to each executable (add the new common source file to the add_executable command). Or create a library target that is linked with the two executables.
Related
I am currently trying to utilize a self-built shared library. The Library FooBar utilizes the "Foo" Library to do some costly calculations. "Foo" however needs "Bar", the licensing library. It has been successfully cross-compiled when using the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(FooBar LANGUAGES CXX)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_library(Curl
NAMES curl)
find_library(Foo
NAMES foo)
find_library(Bar
NAMES bar)
file(GLOB OBJECT_FILES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/resources/*.o)
file(GLOB SOURCE_FILES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/*.cpp)
add_library(FooBar SHARED ${SOURCE_FILES} ${OBJECT_FILES})
target_link_libraries(FooBar PRIVATE Threads::Threads)
target_link_libraries(FooBar PRIVATE -L${Foo} -L${Bar} -L${Curl})
The compilation is successful without any errors but when I want to include it in the executable, "FooBar" does give me an undefined reference to an function in "Bar", the licensing library. I already checked the "Bar"-library, it contains the used function!
CMakeLists.txt of the executable:
cmake_minimum_required(VERSION 3.12)
project(FooBarExe)
add_subdirectory(FooBar)
add_executable(FooBarExe ${FooBarExe_SRC} ${FooBarExe_INC}) # FooBarExe is just the placeholder for its original name!
target_link_libraries(FooBarExe PRIVATE FooBar)
Error message:
"FooBarExe/FooBar/FooBar.so: undefined reference to 'function'
collect2: error: ld returned 1 exit status"
Does anyone have another idea to solve this issue? I already reordered the libraries in target_link_libraries, compiled it as a static library, included and linked both libraries to FooBarExe via set_target_properties and INTERFACE_LINK_LIBRARIES without any success...
Edit:
I tried the following suggested solutions:
Removing "-L" when adding Library
Added a Check after the find_library(Bar ...)
There was an interface change in the "Bar" Library, which went unnoticed by me. Had to replace the header file and the library. Found the change by looking deeper into the library, using the nm -gDC xxxx.so command.
Thank you all for your help, the error was done by me...
My program includes a subdirectory, because a header and a source file are there which are needed. My project looks like this:
EDIT: Perhaps I didn't specify: my goal is to link frame_cap.cpp to the header grab_cut.h, as I require its functions.
[-] raspicam
| [-] main_folder
| frame_cap.cpp
| CMakeLists.txt
| [-] opencv-plus
| grab_cut.cpp
| grab_cut.h
| CMakeLists.txt
Now, I have already linked the two using the CMakeLists.txt in main_folder. It looks as follows:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(frame_cap)
SET(OpenCVPLUS_DIR "/home/pi/Desktop/raspicam/main_folder/opencv-plus")
FIND_PACKAGE( OpenCV REQUIRED )
SET(OpenCV_PACKAGE ${OpenCV_LIBRARIES})
INCLUDE_DIRECTORIES( ${OpenCV_INCLUDE_DIRS} )
INCLUDE_DIRECTORIES(${OpenCVPLUS_DIR})
LINK_DIRECTORIES(${OpenCVPLUS_DIR})
ADD_SUBDIRECTORY(${OpenCVPLUS_DIR})
ADD_EXECUTABLE( frame_cap frame_cap.cpp )
TARGET_LINK_LIBRARIES( frame_cap ${OpenCV_LIBS} ${OpenCVPLUS_DIR})
As you can see, OpenCVPLUS_DIR is, well, the opencv-plus directory, where both the header and source file are located. The CMakeLists.txt file in the opencv-plus folder looks as follows:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(grab_cut)
SET(OpenCVPLUS_DIR "/home/pi/Desktop/raspicam/main_folder/opencv-plus")
FIND_PACKAGE(OpenCV REQUIRED)
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
SET(SOURCES grab_cut.cpp ${OpenCVPLUS_DIR}/grab_cut.h)
ADD_EXECUTABLE(grab_cut grab_cut.cpp ${SOURCES})
TARGET_LINK_LIBRARIES(grab_cut ${OpenCV_LIBS})
Finally, this is the exact error I get:
[ 25%] Linking CXX executable frame_cap
/usr/bin/ld: cannot find -lraspicam/main_folder/opencv-plus/
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/frame_cap.dir/build.make:102: frame_cap] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/frame_cap.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I'd be happy to hear your suggestions as I'm a newbie at CMake and am not really sure what I'm doing wrong.
The error:
/usr/bin/ld: cannot find -lraspicam/main_folder/opencv-plus/
occurs because you try to link a directory to your frame_cap executable here:
TARGET_LINK_LIBRARIES( frame_cap ${OpenCV_LIBS} ${OpenCVPLUS_DIR})
This doesn't make sense; only libraries should be linked to your executable.
From your comments, it sounds like you want to build two executables, but use the grab_cut functions in both. This is certainly achievable with CMake. But you appear to have a design problem, because compiling the grab_cut.cpp file with the frame_cap executable will probably cause issues, assuming both files contain a main function. You'll need to split the main function into a separate file (say, main.cpp), then you can include grab_cut.cpp in the compilation of both executables.
BTW, you can use CMAKE_CURRENT_LIST_DIR to refer to the directory of the current CMakeLists.txt file, so there is no need to list out directories in your source-tree explicitly. Also, I pray you are using a newer CMake than version 2.8. Some of the steps in your CMake files seemed unnecessary, so here are the simplified files that might work for you.
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(frame_cap)
# There is no need to spell out this directory since it exists
# in the source-tree already.
SET(OpenCVPLUS_DIR "/home/pi/Desktop/raspicam/main_folder/opencv-plus")
FIND_PACKAGE( OpenCV REQUIRED )
# Seems unused, remove it.
SET(OpenCV_PACKAGE ${OpenCV_LIBRARIES})
# Include the OpenCV and opencv-plus headers in this executable.
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS} ${CMAKE_CURRENT_LIST_DIR}/opencv-plus)
# There is no library to link from this directory, so we don't need this call.
LINK_DIRECTORIES(${OpenCVPLUS_DIR})
ADD_SUBDIRECTORY(opencv-plus)
# Add the grap_cut.cpp file to the frame_cap executable.
ADD_EXECUTABLE( frame_cap frame_cap.cpp opencv-plus/grab_cut.cpp)
# We don't link anything from opencv-plus, we compiling it directly.
TARGET_LINK_LIBRARIES( frame_cap ${OpenCV_LIBS} ${OpenCVPLUS_DIR})
And your opencv-plus/CMakeLists.txt file can be simplified to something like this:
# If this CMake file is always called as part of the top-level CMake
# file, don't need this.
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(grab_cut)
# Don't need this, as explained earlier.
SET(OpenCVPLUS_DIR "/home/pi/Desktop/raspicam/main_folder/opencv-plus")
# The top-level CMake file already found OpenCV, so the variables
# we need are already defined.
FIND_PACKAGE(OpenCV REQUIRED)
# The include directories get initialized from the parent CMake file, so no need
# for this call if the include directories are the same for both executables.
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
# Separate 'main' function into separate file, and add it here.
SET(SOURCES grab_cut.cpp grab_cut.h main.cpp)
# Don't need to add 'grab_cut.cpp' to the executable twice! It was
# already added using the 'SOURCES' variable.
ADD_EXECUTABLE(grab_cut grab_cut.cpp ${SOURCES})
TARGET_LINK_LIBRARIES(grab_cut ${OpenCV_LIBS})
I want to use the SQLAPI library, i have copied all files in the include directory to usr/local/include/SQLAPI and all files from the lib directory to usr/local/lib. The lib files are named libsqlapi.a /libsqlapi.so and libsqlapiu.a /libsqlapiu.so .
My cmakeLists.txt looks like this:
project(gsl_test)
cmake_minimum_required(VERSION 2.8)
SET(CMAKE_CXX_FLAGS "-std=c++0x")
aux_source_directory(. SRC_LIST)
include_directories(usr/local/include)
link_directories(usr/local/lib)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} libsqlapi)
I get the build/linker error: cannot find -llibsqlapi.
I did also try target_link_libraries(${PROJECT_NAME} sqlapi), but it gives me additional "skipping incompatible //usr/local/lib/libsqlapi.so"
(and the same for .a) with cannot find -lsqlapi
Ok, i'll change my edit to an answer:
The reason linker complained was the fact that you specified the library in the wrong manner. lib is just prefix - if you use target_link_libraries you use the rest of library name. Changing to
target_link_libraries(${PROJECT_NAME} sqlapi)
solved that issue. The error you receive now
skipping incompatible //usr/local/lib/libsqlapi.so
Is most probably caused by the fact that you have copied all the files from some pre-build package and it's not compatible with your system. You need to recompile the library on your own.
I am building a C++ library called alpha in Ubuntu with cmake, which contains one source file:
cmake_minimum_required(VERSION 2.8)
project(Alpha)
add_library (alpha alpha.cpp)
This creates a file called libalpha.a, which I now want to link to. So, I copy it into the source directory of another C++ projected called beta, which also contains one source file:
cmake_minimum_required(VERSION 2.8)
project(Beta)
add_executable(beta beta.cpp)
target_link_libraries(beta alpha)
However, I get the following error:
/usr/bin/ld: cannot find -lalpha
The same thing happens if I use the line:
target_link_libraries(beta libalpha.a)
Why can beta not find the alpha library?
If you wish to build the library and the program completely separately, you have to use imported targets. When you try to link your executable against a "completely unknown" library, CMake build system automatically passes the task of locating the library to the linker, simply adding -lalpha option. When the linker encounters the option it attempts to locate libalpha.so in one of the standard library locations (i.e. /usr/lib/, /usr/local/lib etc) and expectedly fails. You can use an absolute path to the libalpha.a: target_link_libraries(beta /path/to/libalpha.a).
However if you can build things together, this greatly simplifies the task. Consider
<project>/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
Project(Test)
add_subdirectory(alpha)
add_subdirectory(beta)
<project>/alpha/CMakeLists.txt
cmake_minimum_required(VERSION 2.8.11)
project(alpha)
set(SOURCES alpha.c)
add_library(alpha ${SOURCES})
target_include_directories(
alpha INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
)
target_include_directories() with the complex expression within is required to automatically add libalpha include directories to all components which later are linked against libalpha.
<project>/beta/CMakeLists.txt
project(beta)
set(SOURCES beta.c)
add_executable(beta ${SOURCES})
target_link_libraries(beta alpha)
Add this line with the path to alpha-library.
link_directories( <library path> )
I am trying to compile a project that has only one main function, but CMake find more.
My CMakeLists.txt is like:
cmake_minimum_required(VERSION 2.8)
project(my_proj)
include_directories(".")
add_subdirectory(main)
add_subdirectory(resources)
find_package(OpenCV REQUIRED)
find_package(Boost REQUIRED COMPONENTS system regex program_options)
include_directories(${Boost_INCLUDE_DIRS})
file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE HDR_FILES ${PROJECT_SOURCE_DIR}/*.hpp)
add_executable(my_proj ${SRC_FILES} ${HDR_FILES})
target_link_libraries(my_proj ${OpenCV_LIBS})
target_link_libraries(my_proj ${OpenCV_LIBS}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_REGEX_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY})
I have more folders with .hpp and .cpp files that is why I have added file(GLOB_RECURSE... statements and also include_directories(".").
I get an error after it compiles all files that says:
CMakeFiles/my_proj.dir/CMakeFiles/CompilerIdCXX/CMakeCXXCompilerId.cpp.o: In function `main':
/media/N/my_proj/build/CMakeFiles/CompilerIdCXX/CMakeCXXCompilerId.cpp:209: multiple definition of `main'
CMakeFiles/my_proj.dir/main.cpp.o:/media/N/my_proj/main.cpp:10: first defined here
CMakeFiles/my_proj.dir/main/solution2/sources/CRunSolution2.cpp.o: In function `boost::filesystem3::path::codecvt()':
/usr/include/boost/filesystem/v3/path.hpp:377: undefined reference to `boost::filesystem3::path::wchar_t_codecvt_facet()'
Has anyone met something like that? If yes, how to fix it?
In your executable you simply have 2 main functions (print out SRC_FILES by MESSAGE(${SRC_FILES})). One is in main.cpp and one in CMakeCXXCompilerId.cpp (which is a file that CMake generates to test if your CXX compiler works correctly). The GLOB_RECURSE probably finds and adds both of these files to SRC_FILES
Using FILE(GLOB ...) is tricky:
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
You should list your source and header files in your CMakeLists.txt directly