Let's say I wanted to develop a simple library with the following structure:
My CMakeLists.txt then looks like this:
cmake_minimum_required(VERSION 3.17)
set(CMAKE_CXX_STANDARD 14)
set(INC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/")
set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/")
file(GLOB INCLUDES "${INC_DIR}/httplib/*.hpp")
file(GLOB SOURCES "${SRC_DIR}/*.cpp")
project(httplib)
add_library(httplib STATIC ${INCLUDES} ${SOURCES})
include_directories(${INC_DIR})
This works fine but what is the usual way to configure CLion projects and CMake in order to test a library effectively ?
Related
I want to build my C++ project with CMake and I want to include automatically every new file on "cmake ." my project structure is:
Application/ Graphics/ CMakeLists.txt CMakeLists.txt.user main.cpp
./Application:
CMakeLists.txt Logger/ Recovery/ application.cpp application.hpp firstclass.cpp firstclass.hpp singleton.hpp
./Application/Logger:
CMakeLists.txt logger.cpp logger.hpp
./Application/Recovery:
CMakeLists.txt recovery.cpp recovery.hpp
./Graphics:
CMakeLists.txt drawableobject.cpp drawableobject.hpp graphics.cpp graphics.hpp
Each folder has own CMakeLists.txt
I did so far this in master CMake:
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Asteri VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
message("Source dir: ${SOURCE_DIR}")
#file(GLOB_RECURSE SRC_FILES ${SOURCE_DIR}/*.cpp)
#file(GLOB_RECURSE HEADER_FILES ${HEADER_DIR}/*.hpp)
set(PROJECT_NAME "Asteri")
macro(SUBDIRLIST result curdir)
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
set(dirlist "")
foreach(child ${children})
if(IS_DIRECTORY ${curdir}/${child})
list(APPEND dirlist ${child})
endif()
endforeach()
set(${result} ${dirlist})
endmacro()
SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR})
foreach(subdir ${SUBDIRS})
message("Subdirectory: ${subdir}")
add_subdirectory(${subdir})
endforeach()
add_executable(${Asteri} main.cpp)
The question is how to connect all pieces together?
What I need in other CMakeLists.txt?
How to communicate children -> parent or I misunderstood the concept of CMake?
No need for other CMakeLists.
I guess you want something like this in top CMakeLists:
cmake_minimum_required(VERSION 3.12)
project(Asteri VERSION 1.0)
file(GLOB_RECURSE ASTERI_SRC_FILES CONFIGURE_DEPENDS
"${PROJECT_SOURCE_DIR}/Application/*.cpp"
"${PROJECT_SOURCE_DIR}/Graphics/*.cpp"
)
add_executable(Asteri main.cpp ${ASTERI_SRC_FILES})
It's worth noting that GLOB/GLOB_RECURSE -even with CONFIGURE_DEPENDS- is bad practice: it's slow, specially on Windows from my experience, and may not work as expected depending on generator used.
I found out the answer to my problems.
set(SOURCES "${PROJECT_DIR}/main.cpp" CACHE INTERNAL STRINGS)
add_subdirectory(application)
FOREACH(it ${SOURCES})
message("source file: ${it}")
ENDFOREACH()
add_executable(Asteri ${SOURCES})
In this way I store main.cpp path into variable SOURCES
You can see your variables after 'make' in CMakeCache.txt.
After this is done, my variable SOURCES looks like:
/STRINGS
SOURCES:INTERNAL=/home/default/cpp_testing_project/cmake_project/source/main.cpp;
After that in application subdirectory I have CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
# Get source files
file(GLOB CPP_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(SOURCES ${SOURCES} ${CPP_LIST} CACHE INTERNAL STRINGS)
And now SOURCES looks like:
SOURCES:INTERNAL=/home/default/cpp_testing_project/cmake_project/source/main.cpp;/home/default/cpp_testing_project/cmake_project/source/application/application.cpp;/home/default/cpp_testing_project/cmake_project/source/application/drawableobject.cpp;/home/default/cpp_testing_project/cmake_project/source/application/firstclass.cpp;/home/default/cpp_testing_project/cmake_project/source/application/graphics.cpp;/home/default/cpp_testing_project/cmake_project/source/application/application.hpp;/home/default/cpp_testing_project/cmake_project/source/application/drawableobject.hpp;/home/default/cpp_testing_project/cmake_project/source/application/firstclass.hpp;/home/default/cpp_testing_project/cmake_project/source/application/graphics.hpp;
How to make a project in cmake that collects all c++ files into one header?
I have this project structure.
/
project/
folder1/
file.cpp
file.hpp
folder2/
...etc
CMakeLists.txt
tests/
test.cpp
CMakeLists.txt
CMakeList.txt
root cmakelists.txt
cmake_minimum_required (VERSION 3.8)
project ("CMakeProject"
LANGUAGES C CXX)
set(CMAKE_EXECUTABLE_SUFFIX ".exe")
include(GNUInstallDirs)
add_subdirectory ("project")
option(ENABLE_TESTING OFF)
if (ENABLE_TESTING)
enable_testing()
add_subdirectory("tests")
endif()
CMakeLists.txt in project
cmake_minimum_required (VERSION 3.8)
file(GLOB projectSRC
"*/*.cpp"
"*/*.hpp"
"*.cpp"
"*.hpp"
)
add_library(project INTERFACE)
message(STATUS "CMake inatall directory: " ${CMAKE_INSTALL_INCLUDEDIR})
target_include_directories(project
INTERFACE
$<BUILD_INTERFACE:${PROJECT_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
and test cmakelist.txt
cmake_minimum_required (VERSION 3.8)
# install Catch2 testing library
# (https://github.com/catchorg/Catch2/blob/master/docs/cmake-integration.md#installing-catch2-from-git-repository or use packet manager)
find_package(Catch2 REQUIRED)
file(GLOB testSRC
"*.cpp"
)
add_executable(tests ${testSRC})
target_link_libraries(tests
Catch2::Catch2
project)
include(CTest)
include(Catch)
catch_discover_tests(tests)
How to generate one header and use it (in tests or other projects) or make this library able to have templates? The first is better.
How to make a header-only library with cmake?
Like this:
add_library(project INTERFACE)
target_include_directories(project INTERFACE .)
Then in the target that uses the library:
target_link_libraries(dependee
PUBLIC/INTERFACE/PRIVATE # pick one
project)
and include the header like this:
#include <project/folder1/file.hpp>
How to make a project in cmake that collects all c++ files into one header?
I have this project structure.
/
project/
folder1/
file.cpp
file.hpp
folder2/
...etc
CMakeLists.txt
tests/
test.cpp
CMakeLists.txt
CMakeList.txt
root cmakelists.txt
cmake_minimum_required (VERSION 3.8)
project ("CMakeProject"
LANGUAGES C CXX)
set(CMAKE_EXECUTABLE_SUFFIX ".exe")
include(GNUInstallDirs)
add_subdirectory ("project")
option(ENABLE_TESTING OFF)
if (ENABLE_TESTING)
enable_testing()
add_subdirectory("tests")
endif()
CMakeLists.txt in project
cmake_minimum_required (VERSION 3.8)
file(GLOB projectSRC
"*/*.cpp"
"*/*.hpp"
"*.cpp"
"*.hpp"
)
add_library(project INTERFACE)
message(STATUS "CMake inatall directory: " ${CMAKE_INSTALL_INCLUDEDIR})
target_include_directories(project
INTERFACE
$<BUILD_INTERFACE:${PROJECT_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
and test cmakelist.txt
cmake_minimum_required (VERSION 3.8)
# install Catch2 testing library
# (https://github.com/catchorg/Catch2/blob/master/docs/cmake-integration.md#installing-catch2-from-git-repository or use packet manager)
find_package(Catch2 REQUIRED)
file(GLOB testSRC
"*.cpp"
)
add_executable(tests ${testSRC})
target_link_libraries(tests
Catch2::Catch2
project)
include(CTest)
include(Catch)
catch_discover_tests(tests)
How to generate one header and use it (in tests or other projects) or make this library able to have templates? The first is better.
How to make a header-only library with cmake?
Like this:
add_library(project INTERFACE)
target_include_directories(project INTERFACE .)
Then in the target that uses the library:
target_link_libraries(dependee
PUBLIC/INTERFACE/PRIVATE # pick one
project)
and include the header like this:
#include <project/folder1/file.hpp>
I'm trying to add a new library to a project built using CMake and am having trouble. I'm trying to follow this. I've made a test project that looks like this:
cmake_test/
test.cpp
CMakeLists.txt
liblsl/
include/
lsl_cpp.h
CMakeLists.txt
liblsl64.dll
liblsl64.so
build/
the CMakeLists.txt in cmake_test looks like this:
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(Tutorial test.cpp)
add_subdirectory(liblsl)
target_link_libraries(Tutorial PUBLIC ${LSL_LIBRARY})
and the CMakeLists.txt in liblsl looks like this:
find_path(LSL_INCLUDE_DIR lsl_cpp.h)
find_library(LSL_LIBRARY liblsl64)
include_directories(${LSL_INCLUDE_DIR})
But I keep getting the error No rule to make target '.../liblsl64.lib', needed by 'Tutorial.exe'. Stop.
Any idea what I'm doing wrong?
I'm on Windows 10 using mingw-w64 v5.4.0 if that makes any difference.
CMakeLists.txt in cmake_test:
cmake_minimum_required(VERSION 3.10)
project(Tutorial VERSION 1.0)
add_subdirectory(liblsl)
add_executable(Tutorial test.cpp)
target_compile_features(Tutorial PUBLIC cxx_std_11)
target_link_libraries(Tutorial PUBLIC liblsl)
CMakeLists.txt in liblsl:
add_library(liblsl SHARED IMPORTED GLOBAL)
set_target_properties(liblsl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/include")
set_target_properties(liblsl PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/liblsl64.so")
For Windows use:
set_target_properties(liblsl PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/liblsl64.dll")
set_target_properties(liblsl PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/liblsl64.lib")
In add_library, you say SHARED because your library is a shared one (so/dll), you say IMPORTED because you don't want to build the library, and you say GLOBAL because you want it to be visible outside liblsl.
I know how the basic Makefile for a simple project using pjsip library looks like. But what does the equivalent CMake file look like?
project(myapp)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
include (FindPkgConfig)
if (PKG_CONFIG_FOUND) # true if pkg-config works on the system
pkg_check_modules(PJSIP REQUIRED libpjproject)
endif()
include_directories(${PJSIP_INCLUDE_DIRS})
link_directories(${PJSIP_LIBRARY_DIRS})
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} ${PJSIP_LIBRARIES})