I am trying to first create a static library and then link it to an executable using CMake. My project file structure looks like this:
├── CMakeLists.txt
├── build
├── lib
│ ├── CMakeLists.txt
│ ├── build
│ ├── include
│ │ └── Point.hpp
│ └── src
│ └── Point.cpp
└── mainApp.cpp
I first build the library like so.
cmake_minimum_required(VERSION 2.8.9)
project(CAST3)
set(CMAKE_BUILD_TYPE Release)
include_directories(include)
file(GLOB SOURCES "src/*.cpp")
add_library(CAST3 STATIC ${SOURCES})
However, when i try to link the library to my executable I get an error.
This is my executable
#include"Point.hpp"
int main(int argc, char *argv[]){
Point p = Point(1,2,3);
return 0;
}
This is my CMake file to link the library to the executable.
cmake_minimum_required(VERSION 2.8.9)
project (CAST3)
set ( PROJECT_LINK_LIBS libCAST3.a )
link_directories( ${CMAKE_CURRENT_SOURCE_DIR}/lib/build)
add_executable(libtest mainApp.cpp)
target_link_libraries(libtest ${PROJECT_LINK_LIBS} )
When I run that I get the this error
/mainApp.cpp:1:9: fatal error: 'Point.hpp' file not found
#include"Point.hpp"
^~~~~~~~~~~
1 error generated.
make[2]: *** [CMakeFiles/libtest.dir/mainApp.cpp.o] Error 1
make[1]: *** [CMakeFiles/libtest.dir/all] Error 2
make: *** [all] Error 2
What am I missing?
What am I missing?
You are missing target_include_directories(CAST3 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) inside lib/CMakeLists.txt.
You are missing add_subdirectory(lib) from root CMakeLists.txt.
The set ( PROJECT_LINK_LIBS libCAST3.a ) and target_link_libraries(libtest ${PROJECT_LINK_LIBS} ) and link_directories( ${CMAKE_CURRENT_SOURCE_DIR}/lib/build) could be removed. Then you are missing just target_link_libraries(libtest PUBLIC CAST3). Cmake will automatically find the proper .a file and propagate include paths with target_link_libraries.
So your lib/CMakeLists.txt could look like this:
cmake_minimum_required(VERSION 3.0) # I would advise to update
project(CAST3)
include_directories(include)
file(GLOB sources src/*.cpp) # upper case variable names reserved for exported variables by convention
add_library(CAST3 ${sources}) # STATIC by default
target_include_directories(CAST3 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
And root CMakeLists.txt could look like this:
cmake_minimum_required(VERSION 3.0) # I would advise to update
project(CAST3)
add_subdirectory(lib)
add_executable(libtest mainApp.cpp)
target_link_libraries(libtest CAST3)
Related
I'm not able to link external libraries with the libraries I wrote using CMake. I'm wondering if there's something that is needed to be added to my CMakeLists.txt? Or if I need to add another CMakeLists.txt in a lower level (inside src) and what would that need to contain?
I have the following project structure:
ProjectFolder
│ ├── CMakeLists.txt
│ ├── build
│ │ └──
│ ├── include
│ │ └── helper.h
│ └── src
│ ├── helper.cpp
└── main.cpp
My CMakeList.txt is:
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(object_detection)
find_package(PCL 1.5 REQUIRED)
find_package(OpenCV REQUIRED)
file(GLOB SOURCES src/*.cpp)
file(GLOB INCLUDE include/*.h)
include_directories(${PCL_INCLUDE_DIRS} ${INCLUDE})
link_directories(${PROJECT_NAME} ${PCL_LIBRARY_DIRS} ${SOURCES} )
add_definitions(${PCL_DEFINITIONS})
add_executable (${PROJECT_NAME} src/main.cpp)
target_link_libraries (${PROJECT_NAME} ${OpenCV_LIBS} ${PCL_LIBRARIES} ${SOURCES})
In my file helper.cpp I have:
#include <pcl/io/pcd_io.h>
Which gives the error:
fatal error: 'pcl/io/pcd_io.h' file not found
#include <pcl/io/pcd_io.h>
^~~~~~~~~~~~~~~~~
However I have the same include in main.cpp with no errors.
I would be very grateful for any help, please let me know if I need to clarify my question or error.
Thank you.
There are several errors in the CMakeLists.txt with the following changes the project loads appropriate libraries and builds properly. Another note is that before, to include helper.h I needed to write:
#include "../include/helper.h".
Now it works as expected with #include "helper.h".
Here is the modified CMakeLists.txt:
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(object_detection)
find_package(PCL 1.5 REQUIRED)
find_package(OpenCV REQUIRED)
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)
include_directories(${PCL_INCLUDE_DIRS} include)
link_directories(${PROJECT_NAME} ${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
#add_executable (${PROJECT_NAME} src/helper.cpp src/main.cpp )
add_executable (${PROJECT_NAME} ${SRC_FILES} )
target_link_libraries (object_detection ${PCL_LIBRARIES} ${OpenCV_LIBS})
I successfully played trial-and-error with a CMakeLists.txt file, and now everything builds. However, I want to make sure my understanding is correct about how it's working.
I have a project with the following structure:
./
├── bin
├── CMakeLists.txt
├── include
│ └── sql-writer
│ ├── credentials.h
│ ├── database.h
│ ├── datetime.h
│ ├── market_bar.h
│ └── writer.h
├── README.md
├── src
│ ├── CMakeLists.txt
│ ├── database.cpp
│ ├── main.cpp
│ └── writer.cpp
└── test
├── CMakeLists.txt
├── test-main.cpp
├── test_sym_table_pairs
└── writer_tests.cpp
This builds an executable, a static library, and a test executable. The problem was src/CMakeLists.txt:
set(HEADER_DIR ${sql-writer_SOURCE_DIR}/include/sql-writer)
add_executable(sql-writer-demo main.cpp ${HEADER_DIR})
target_include_directories(sql-writer-demo PUBLIC ${HEADER_DIR}) #!
target_link_libraries(sql-writer-demo sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})
file(GLOB SOURCES ${sql-writer_SOURCE_DIR}/src/*.cpp)
file(GLOB HEADERS ${HEADER_DIR}/*.h)
add_library(sql-writer-lib ${HEADERS} ${SOURCES})
target_link_libraries(sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})
target_include_directories(sql-writer-lib PUBLIC ${HEADER_DIR})
the first line's set command just defines HEADER_DIR. This is easy.
target_include_directories(sql-writer-demo PUBLIC ${HEADER_DIR}) must be included after the first add_execuable because otherwise header files will need to be included with relative paths. Is that right? Why does it come after? I've heard cmake treats include directories as "separate" from "sources" (cmake sources not .cpp files). What does that mean?
target_link_libraries(sql-writer-demo sql-writer-lib mysqlcppconn ${Boost_LIBRARIES}) needs to come after add_executable(sql-writer-demo main.cpp ${HEADER_DIR}) as well, and it tells how to link to other libraries.
file(GLOB SOURCES ${sql-writer_SOURCE_DIR}/src/*.cpp) is not recomended before only because the directory/file structure could change, and then this wouldn't work anymore
target_link_libraries(sql-writer-lib mysqlcppconn ${Boost_LIBRARIES}) needs to come after add_library(sql-writer-lib ${HEADERS} ${SOURCES}) because the compulation of my library sql-writer-lib needs to use other libs, and this is where we tell cmake to look out for those.
You typically don't include headers into add_executable and add_library, but only implementation files:
add_executable(sql-writer-demo main.cpp)
add_library(sql-writer-lib ${SOURCES})
add_executable and add_library create a target, target_include_directories specifies include directories for this target. The documentation is pretty clear:
The named <target> must have been created by a command such as add_executable() or add_library() and must not be an IMPORTED target.
If you use target_include_directories(sql-writer-lib PUBLIC ${HEADER_DIR}) with PUBLIC specifier, you don't need to use target_include_directories to specify include directories for targets that link against that library, because the dependency will be propagated automatically. The same applies to target_link_libraries.
So, src/CMakeLists.txt
file(GLOB SOURCES ${sql-writer_SOURCE_DIR}/src/*.cpp)
add_library(sql-writer-lib ${SOURCES})
target_link_libraries(sql-writer-lib PUBLIC mysqlcppconn ${Boost_LIBRARIES})
target_include_directories(sql-writer-lib PUBLIC ${HEADER_DIR})
add_executable(sql-writer-demo main.cpp)
target_link_libraries(sql-writer-demo sql-writer-lib)
should work. Whether you want to use PUBLIC on mysqlcppconn ${Boost_LIBRARIES} depends on the structure of your project. I specified it as an example only.
Based on this stackoverflow answer to a similar question (Cmake include header only target from header only target), I am creating a header only library and trying to use it in an executable.
My folder structure is below:
├── CMakeLists.txt // root folder CMake file
├── srcs // this is the hdr only library
│ ├── src1.hpp
│ ├── CMakeLists.txt
│ ├── src2.hpp
│ └── src3.hpp
│ └── ...
└── test // this is the executable project
├── CMakeLists.txt
└── main.cpp
Root level CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project (MyProj CXX)
add_subdirectory(srcs)
add_subdirectory(test)
src level CMakeLists.txt (for header only library)
add_library(MyLib INTERFACE)
target_sources(MyLib INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/src1.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src2.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src3.hpp"
)
target_include_directories(MyLib
INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(plugins)
CMake file for executable test project
add_executable(MyTest main.cpp)
target_sources(MyTest
PRIVATE main.cpp
)
target_include_directories(MyTest PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(MyTest PUBLIC MyLib)
Though this configures cmake without warnings/error, running the make fails, indicating that the executable project is unable to find the header file(s) from library.
/.../nettu2/test/main.cpp:6:10: fatal error: src1.hpp: No such
file or directory #include "src1.hpp"
^~~~~~~~~~~~~~~~ compilation terminated. test/CMakeFiles/MyTest.dir/build.make:62: recipe for target
'test/CMakeFiles/MyTest.dir/main.cpp.o' failed make[2]: *
[test/CMakeFiles/MyTest.dir/main.cpp.o] Error 1
CMakeFiles/Makefile2:126: recipe for target
'test/CMakeFiles/MyTest.dir/all' failed make[1]: *
[test/CMakeFiles/MyTest.dir/all] Error 2 Makefile:129: recipe for
target 'all' failed make: *** [all] Error 2
I am sure that I am missing some crucial but trivial thing here, but yet unable to figure out, what is going wrong here. How can I get this build working?
You have a minor mistake in this line:
target_include_directories(MyLib
INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
The include directory you specify for MyLib expands to the build directory corresponding to srcs, i.e. it results in an invocation like
clang++ /path/to/build/test/test.cpp -I /path/to/build/srcs ...
but you want to pass the actual source directory to the preprocessor. To fix this, try
target_include_directories(MyLib
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
I have a simple CMake + Qt + GTest project:
.
├── CMakeLists.txt
├── src
│ ├── CMakeLists.txt
│ ├── main.cpp
│ └── utils
│ ├── calculator.cpp
│ └── calculator.h
└── tests
├── calculator_test.cpp
└── CMakeLists.txt
Root CMakeFiles.txt
cmake_minimum_required(VERSION 3.5)
project(random_project)
# Place binaries and libraries according to GNU standards.
include(GNUInstallDirs)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
# Add source folder.
add_subdirectory(src)
# Add GTest.
include(cmake/googletest.cmake)
fetch_googletest(
${PROJECT_SOURCE_DIR}/cmake
${PROJECT_BINARY_DIR}/googletest
)
enable_testing()
# Add tests folder.
add_subdirectory(tests)
And I want to reach calculator.h in calculator_test.cpp which uses GTest:
#include <gtest/gtest.h>
#include "utils/calculator.h" // <- Want to reach this in that path format.
TEST(example, add)
{
EXPECT_EQ(8, Calculator::sum(3, 5));
}
I have tried to link but then test is not found and the path is releative:
tests/CMakeFiles.txt
# Find the Qt libraries.
find_package(Qt5Widgets REQUIRED)
# Qt5 libraries.
set(QT5_LIBRARIES
Qt5::Widgets)
# Source files.
set(SOURCE_FILES
calculator_test.cpp
../src/utils/calculator.cpp
../src/utils/calculator.h
../src/main.cpp) # If I link like this, test is not found.
# Tell CMake to create the executable.
add_executable(unit_tests ${SOURCE_FILES})
# Use the Widgets module from Qt5.
target_link_libraries(unit_tests ${QT5_LIBRARIES} gtest_main)
# Add tests.
add_test(
NAME unit_tests
COMMAND ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/unit_tests
)
How to link calculator.h in calculator_test.cpp test with CMakeLists.txt?
My Qt project with CMake project file cannot resolve the path to
"someHeader.h". What can I do to fix it?
You can specify the include path:
include_directories("${PROJECT_SOURCE_DIR}/relativePathToHeader")
and likely the path needed:
include_directories("${PROJECT_SOURCE_DIR}/src/utils") or maybe
include_directories("${PROJECT_SOURCE_DIR}/utils") depending on where the source directory actually is.
You need to re-run CMake, of course.
I am learning to use cmake for a project using a shared library, but I keep getting this error:
Linking CXX executable test/test/robot_test
/usr/bin/ld: cannot open output file test/test/robot_test: No such file or directory
collect2: error: ld returned 1 exit status
make[2]: *** [test/test/robot_test] Error 1
make[1]: *** [CMakeFiles/test/robot_test.dir/all] Error 2
make: *** [all] Error 2
Here is my CMake file:
cmake_minimum_required(VERSION 2.8.12)
project("Particle Filter")
set(CMAKE_BUILD_TYPE Release)
include_directories(include)
set(LIB_SOURCES src/robot.cc src/sampler.cc src/general.cc)
set(LIB_HEADERS include/robot.h include/sampler.h include/general.h)
add_library(my_lib SHARED ${LIB_SOURCES} ${LIB_HEADERS})
install(TARGETS my_lib DESTINATION lib)
set(APP_SOURCES test/robot_test.cc test/sampler_test.cc)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test")
foreach(test ${APP_SOURCES})
#cut off .cc of src files using empty string
string(REPLACE ".cc" "" testname ${test})
add_executable(${testname} ${test})
target_link_libraries(${testname} my_lib)
endforeach(test ${APP_SOURCES})
add_definitions(
-std=c++11 # Or -std=c++0x
# Other flags
)
Here is my tree (excluding the build directory that contains a lot of this such as my makefile,.so and .a file):
├── CMakeLists.txt
├── driver.cc
├── include
│ ├── general.h
│ ├── robot.h
│ └── sampler.h
├── lib
├── notes
├── src
│ ├── general.cc
│ ├── robot.cc
│ └── sampler.cc
└── test
├── robot_test.cc
└── sampler_test.cc
Also, the .so or .a files are not getting saved to my lib folder after sudo make install, how do I fix this?
The first parameter for command add_executable is not a filename but a name of target. Target's name shouldn't contain special symbols like slash ("/").
You may control output directory of executables created by setting variable CMAKE_RUNTIME_OUTPUT_DIRECTORY:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test")
...
# Relative path to executable will be 'test/robot_test'.
add_executable(robot_test robot_test.cc)