I am trying to create a lib and include for my project so that others can use my project.
So I have my project structured as
├── mlce
├── CMakeLists.txt
├── README.txt
├── include
├── lib
└── src
├── io
│ └── IO.h
└── mesh
├── Mesh.cpp
└── Mesh.h
Currenly include and lib are empty. I created them manually so that latter on when I make install those will get filled.
My CMakeLists.txt looks like
cmake_minimum_required(VERSION 3.0.2)
project(mlcelib)
set (SOURCE
${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/src/mesh/Mesh.cpp
)
set (HEADER
${HEADER}
${CMAKE_CURRENT_SOURCE_DIR}/src/mesh/Mesh.h
${CMAKE_CURRENT_SOURCE_DIR}/src/io/IO.h
)
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
add_library(${PROJECT_NAME} SHARED ${SOURCE})
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries (${PROJECT_NAME} Eigen3::Eigen)
message(${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) # <--- I was hoping
# this "PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}" would place all the header file of my project inside include folder.
# But apparently it is not doing that. The include folder is empty.
Then what I do is :
mkdir build
cd build
cmake -DCMAKE_INSTALL_LIBDIR=/path/to/mlce/lib -DCMAKE_INSTALL_INCLUDEDIR=/path/to/mlce/include ..
make
make install
So when I do make install only the lib is filled by the shared lib but the install is not.
├── include
├── lib
│ └── libmlcelib.dylib
I was expecting include would contain mesh/Mesh.h and IO/IO.h
Related
I'm trying to use my own library in a different project using CMake and FetchContent. My library is a static one that's built with CMake in a separate git repo, and it works fine when built with a demo in the same repo. When I use FetchContent to use it in a separate project it can't find the header files and I don't know how to include them.
dynamic-shadow-lib tree:
.
├── CMakeLists.txt
├── demo
│ ├── CMakeLists.txt
│ └── main.cpp
├── include
│ ├── line2D.hpp
│ ├── math.hpp
│ ├── mathplotUtil.hpp
│ ├── shape2D.hpp
│ ├── square2D.hpp
│ ├── triangle2D.hpp
│ └── vec2f.hpp
├── LICENSE
├── README.md
├── src
│ ├── line2D.cpp
│ ├── math.cpp
│ ├── square2D.cpp
│ ├── triangle2D.cpp
│ └── vec2f.cpp
└── tests
├── CMakeLists.txt
├── unit_tests
│ ├── CMakeLists.txt
│ ├── line2DTests.cpp
│ ├── main.cpp
│ ├── mathTests.cpp
│ ├── square2DTests.cpp
│ └── vec2fTests.cpp
└── visual_tests
├── CMakeLists.txt
├── main.cpp
└── visualTests.hpp
dynamic-shadow-lib root CmakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(
dynamic-shadows
VERSION 1.0
LANGUAGES CXX
)
# Build config variables
set(BUILD_DEMO FALSE)
set(BUILD_TESTS FALSE)
# Set C++ to version 14
set(CMAKE_CXX_STANDARD 14)
# Set binary destinations
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Set header dir
set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${HEADERS_DIR})
# Set source dir
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
# Set a name for the target
set(TARGET_LIB ${CMAKE_PROJECT_NAME}-lib)
# Make library ${TARGET_LIB}
add_library(
${TARGET_LIB} STATIC
${SOURCE_DIR}/math.cpp
${SOURCE_DIR}/vec2f.cpp
${SOURCE_DIR}/line2D.cpp
${SOURCE_DIR}/square2D.cpp
${SOURCE_DIR}/triangle2D.cpp
)
if (${BUILD_TESTS})
# Enable testing (GoogleTests)
include(CTest)
enable_testing()
add_subdirectory(tests)
endif()
if (${BUILD_DEMO})
# Demo
add_subdirectory(demo)
endif()
Project that I'm trying to include my lib in (tree):
.
├── CMakeLists.txt
├── include
│ ├── Game.hpp
│ └── Primitive.hpp
├── LICENSE
├── README.md
├── src
│ ├── Game.cpp
│ └── main.cpp
└── tests
├── CMakeLists.txt
└── main.cpp
Projects root CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(realtime-light-shadow-2D
LANGUAGES CXX
VERSION 1.0
)
# Set extra compiler flags
set(CMAKE_CXX_FLAGS "-W -Wall -std=c++14 -fopenmp")
# Set binary destinations
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Dependencies
include(FetchContent)
set (FETCHCONTENT_QUIET FALSE)
# SFML
message (STATUS "Adding SFML..")
FetchContent_Declare(
sfml
GIT_REPOSITORY "https://github.com/SFML/SFML"
GIT_TAG 218154cf0098de3f495e31ced489da24b7318638 # Latest
GIT_PROGRESS TRUE
)
# No need to build audio and network modules
set(SFML_BUILD_AUDIO FALSE)
set(SFML_BUILD_NETWORK FALSE)
FetchContent_MakeAvailable(sfml)
# ImGui
message (STATUS "Adding ImGui")
FetchContent_Declare(
imgui
GIT_REPOSITORY https://github.com/ocornut/imgui
GIT_TAG 5c8f8d031166765d2f1e2ac2de27df6d3691c05a # Latest
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(imgui)
# ImGui-SFML
message (STATUS "Adding ImGui-SFML")
FetchContent_Declare(
imgui-sfml
GIT_REPOSITORY https://github.com/eliasdaler/imgui-sfml
GIT_TAG 4129d276d45845581b6ba99ede50db6f761e5089 # Latest
GIT_PROGRESS TRUE
)
set(IMGUI_DIR ${imgui_SOURCE_DIR})
set(IMGUI_SFML_FIND_SFML OFF)
set(IMGUI_SFML_IMGUI_DEMO ON)
FetchContent_MakeAvailable(imgui-sfml)
# dynamic-shadows-lib
message( STATUS "Adding dynamic-shadow-lib")
FetchContent_Declare(
dynamic-shadows-lib
GIT_REPOSITORY https://github.com/JesperGlas/dynamic-shadows-lib/
GIT_TAG 59c7884caac7cc98f902fd880ccb1c9b0f50cca0 # Latest
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(dynamic-shadows-lib)
# Set header dir
set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${HEADERS_DIR})
# Set source dir
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(TARGET_BIN ${CMAKE_PROJECT_NAME})
add_executable(
${TARGET_BIN}
${SOURCE_DIR}/main.cpp
${SOURCE_DIR}/Game.cpp
)
target_link_libraries(
${TARGET_BIN}
PUBLIC
sfml-system
sfml-graphics
ImGui-SFML::ImGui-SFML
dynamic-shadows-lib
)
When I try to build the project (sfml-dynamic-light-demo) I get the following error:
[build] /home/jesper/dev/cpp/sfml-dynamic-light-demo/include/Primitive.hpp:4:10: fatal error: vec2f.hpp: No such file or directory
[build] 4 | #include "vec2f.hpp"
Which tells me that the libraries include folder might not be available to the project. I've tried to include it as an install(DIRECTORY ${HEADER_DIR}) in the libs root CMakeLists, but it has no effect. I suspect I'm using it wrong since when I build the project I still get "No install step for 'dynamic-shadows-lib-populate'".
What am I doing wrong? If it's a concept that I'm missing, what should I read up on to make it work?
Thanks to the comments I was able to solve this. In my library (Built with CMake) I used the variable CMAKE_PROJECT_NAME when creating my library (CMAKE_PROJECT_NAME-lib). This variable references the top root CMakeLists.txt which resultet in my library getting the wrong name when I used it in another project. By changing all of those variables to PROJECT_NAME, and other similar ones, everything worked as it should.
TLDR: Make sure to use local variables when you want to use a CMake project as a subproject. (In this case PROJECT_NAME, instead of CMAKE_PROJECT_NAME etc...).
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.
RT~ ps: cmake version 3.9.2
My codebase just like this.
suzanwen#n224-004-133:~/repos/C++/ttt:)$ tree -L 2
.
├── build
│ ├── bin
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── lib
│ ├── Makefile
│ ├── test
│ └── thirdparty
├── build.sh
├── CMakeLists.txt
├── Makefile
├── test
│ ├── CMakeLists.txt
│ └── main.cc
└── thirdparty
├── CMakeLists.txt
├── gflags
└── hellolib
10 directories, 9 files
my thirdparty/hellolib/CMakeLists.txt is
PROJECT(hello)
SET(LIBHELLO_SRC hello.cc)
MESSAGE(STATUS "LIBRARY PATH=" ${LIBRARY_OUTPUT_PATH})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES ARCHIVE_OUTPUT_NAME "hello")
my test/CMakeLists.txt is
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/thirdparty/hellolib
${PROJECT_SOURCE_DIR}/thirdparty/gflags/include)
IF(LIBRARY_OUTPUT_PATH)
LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH})
ENDIF(LIBRARY_OUTPUT_PATH)
ADD_EXECUTABLE(main main.cc)
TARGET_LINK_LIBRARIES(main hello)
# TARGET_LINK_LIBRARIES(main hello_static)
when I build my top-level project, an error occurs like this.
/usr/bin/c++ -rdynamic CMakeFiles/main.dir/main.cc.o -o ../bin/main -L/home/suzanwen/repos/C++/ttt/build/lib -Wl,-rpath,/home/suzanwen/repos/C++/ttt/build/lib -lhello
/usr/bin/ld: cannot find -lhello
But when I comment the line # SET_TARGET_PROPERTIES(hello_static PROPERTIES ARCHIVE_OUTPUT_NAME "hello") and TARGET_LINK_LIBRARIES with hello_static, everything goes fine.
It seems that TARGET_LINK_LIBRARIES cannot find renamed lib target. Could anyone explain it? thanks in advance.
It seems that TARGET_LINK_LIBRARIES cannot find renamed lib target.
Setting ARCHIVE_OUTPUT_NAME property renames not a target, but an output file. So linking with a target still works:
TARGET_LINK_LIBRARIES(main hello_static)
One cannot rename the target once it is created, but it is possible to create ALIAS for a target:
ADD_LIBRARY(hello ALIAS hello_static)
After that it is possible to link with the alias:
TARGET_LINK_LIBRARIES(main hello)
I want to include caffe in my project. This is the folder structure of the project:
.
├── AUTHORS
├── ChangeLog
├── cmake
│ ├── FindCaffe.cmake
│ └── FindCUDA.cmake
├── CMakeLists.txt
├── CMakeLists.txt.user
├── data
│ └── info.plist
├── deep-app.pro.user
├── LICENSE.txt
├── README.md
├── [reference]
│ ├── deep-app.pro
│ ├── deep-app.pro.user
│ ├── deployment.pri
│ ├── main.cpp
│ ├── main.qml
│ ├── Page1Form.ui.qml
│ ├── Page1.qml
│ └── qml.qrc
└── src
├── CMakeLists.txt
├── code
│ └── main.cpp
├── icons.yml
└── res
├── assets
│ ├── assets.qrc
│ ├── book-open-page.svg
│ └── book-open.svg
├── icons
│ ├── action_home.svg
│ ├── action_list.svg
│ ├── action_search.svg
│ ├── action_settings.svg
│ ├── file_cloud_done.svg
│ ├── icons.qrc
│ ├── maps_place.svg
│ ├── navigation_check.svg
│ └── social_school.svg
└── qml
├── main.qml
├── Page1Form.ui.qml
├── Page1.qml
└── qml.qrc
Here is the root/CMakeLists.txt:
project(generic-object-detection)
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
cmake_policy(VERSION 3.4.1)
ENABLE_LANGUAGE(C)
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc and rrc automatically when needed
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# Apple-specific configuration
set(APPLE_SUPPRESS_X11_WARNING ON)
# Build flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -Werror -Wall -Wextra -Wno-unused-parameter -pedantic -std=c++11")
### Set libraries' locations
# Set Caffe
set(Caffe_DIR "/home/ubuntu/Libraries/caffe")
set(Caffe_INCLUDE_DIRS "/home/cortana/Libraries/caffe/include")
set(Caffe_LIBRARIES "/usr/lib/x86_64-linux-gnu/libcaffe.so")
# Disable debug output for release builds
if(CMAKE_BUILD_TYPE MATCHES "^[Rr]elease$")
add_definitions(-DQT_NO_DEBUG_OUTPUT)
endif()
# Minimum version requirements
set(QT_MIN_VERSION "5.4.0")
# Find Qt5
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Core
Qml
Quick
Concurrent)
# Find OpenCV 3.1
find_package(OpenCV 3.1.0 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# Find Boost
FIND_PACKAGE(Boost COMPONENTS program_options REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
# Find CUDA
FIND_PACKAGE(CUDA REQUIRED)
# Find Caffe
FIND_PACKAGE(Caffe REQUIRED)
if(UNIX)
if(APPLE)
set(MACOSX_BUNDLE_INFO_STRING "generic-object-detection")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.mybitchinapp.generic-object-detection")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}-${PROJECT_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_NAME "generic-object-detection")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
else()
# Assume linux
# TODO: Install desktop and appdata files
endif()
elseif(WIN32)
# Nothing to do here
endif()
add_subdirectory(src)
The file root/src/CMakeLists.txt:
file(GLOB_RECURSE SOURCES
*.cpp *.h
code/*.cpp code/*.h)
set(SOURCES ${SOURCES}
res/assets/assets.qrc
res/icons/icons.qrc
res/qml/qml.qrc)
add_executable(deep-app ${SOURCES})
target_link_libraries(deep-app
Qt5::Core
Qt5::Qml
Qt5::Quick
Qt5::Concurrent
${OpenCV_LIBS}
${Boost_LIBRARIES}
${CUDA_LIBRARIES})
set_target_properties(deep-app PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/data/Info.plist)
install(TARGETS deep-app
RUNTIME DESTINATION bin
DESTINATION ${CMAKE_INSTALL_BINDIR})
The error is:
CMake Error at CMakeLists.txt:55 (FIND_PACKAGE):
By not providing "FindCaffe.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Caffe", but
CMake did not find one.
Could not find a package configuration file provided by "Caffe" with any of
the following names:
CaffeConfig.cmake
caffe-config.cmake
Add the installation prefix of "Caffe" to CMAKE_PREFIX_PATH or set
"Caffe_DIR" to a directory containing one of the above files. If "Caffe"
provides a separate development package or SDK, be sure it has been
installed.
-- Configuring incomplete, errors occurred!
I have setup Caffe_DIR and other required variables. But it still gives the same errors. I removed the previous [cmake] cache so thats not the problem. I cant figure out how to resolve this problem and I need to use Caffe in the project. Please help.
You want to set your CMAKE_MODULE_PATH to location where cmake module files are located for Caffe project, which would be directory pointed to below:
.
├── AUTHORS
├── ChangeLog
├── cmake <---------Set Caffe_DIR it to this directory
│ ├── FindCaffe.cmake
│ └── FindCUDA.cmake
If that doesn't work then you should set your Caffe_DIR to the above directory and make sure your rename the files under that directory to one of the names mentioned in the following error:
Could not find a package configuration file provided by "Caffe" with any of
the following names:
CaffeConfig.cmake
caffe-config.cmake
I am trying link one of my programs to libevent. I am using CMake as build system. My project structure is as follows:
my_project
├── CMakeLists.txt
├── README.md
├── build
│ └── Build stuff
└── software
├── README.md
├── CMakeLists.txt
├── include
├── libraries
│ ├── libevent
│ │ └── CMakeLists.txt
│ └── anotherlibrary
│ └── CMakeLists.txt
├── prog1
│ ├── CMakeLists.txt
├── prog2
│ ├── CMakeLists.txt
└── prog3
└── CMakeLists.txt
CMakeList.txt of prog1 (the one that's needs to be linked to libevent)
cmake_minimum_required(VERSION 2.6)
project (prog1)
file(GLOB prog1
"*.h"
"*.cpp"
)
include_directories("${PROJECT_INCLUDE_DIR}/libevent/include")
add_executable(${PROJECT_NAME} ${prog1})
target_link_libraries(${PROJECT_NAME} event_core)
But when I build the project make can't find the library build by libevent. it searched for: libraries/libevent/lib/libevent_core.a this is the wrong path since libevent builds it libs inside: my_project/build/software/libraries/libevent/lib/libevent_core.a
How do I tell CMake to search there for the library? I already added the following lines to my Cmake file but this wasn't working
link_directories(/my_project/build/software/libraries/libevent/lib/)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/lib)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build/bin)
Anyone a suggestion?
I fixed the problem myself by removing the content from the build directory and re running cmake .. inside the build directory.
I think CMake was somehow not aware of the changes I made and by rebuilding the project the problem was fixed.