I'm new to CMake and I'm trying to figure out how to build dependencies. My project folders are organized like this:
Scrubber
-- FileIO
-- CDEs
-- Utilities
-- Scrubber
FileIO, CDEs, and Utilities are static libraries that are used by the executable in Scrubber.
I want to be able to execute a single make command from the top dir that will build everything. If I build each library independently, then it all comes together fine when I execute the top make. But if I don't do that it ahead of time then it won't build the dependencies and, not surprisingly, complains that the libraries weren't found.
So very simple question: how do I cause the system to build the libraries?
TOP LEVEL CMAKELISTS IN SCRUBBER
cmake_minimum_required(VERSION 3.2)
project(Scrubber)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_subdirectory(FileIO)
add_subdirectory(CDEs)
add_subdirectory(Utilities)
add_subdirectory(Scrubber)
FILEIO CMAKELISTS IN SCRUBBER/FILEIO
cmake_minimum_required(VERSION 3.2)
project(FileIO)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
file(GLOB SOURCE_FILES *.cpp)
add_library(FileIO STATIC ${SOURCE_FILES})
#Don't prepend with "lib"
set_target_properties(FileIO PROPERTIES PREFIX "")
CDES CMAKELISTS IN SCRUBBER/CDES
cmake_minimum_required(VERSION 3.2)
project(CDEs)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(BOOST_INCLUDE_DIR "/usr/lib/boost_1_60_0")
include_directories( ${BOOST_INCLUDE_DIR} )
file(GLOB SOURCE_FILES *.cpp)
add_library(CDEs STATIC ${SOURCE_FILES})
#Don't prepend with "lib"
set_target_properties(CDEs PROPERTIES PREFIX "")
UTILITIES CMAKELIST IN SCRUBBER/UTILITIES
cmake_minimum_required(VERSION 3.2)
project(Utilities)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(BOOST_INCLUDE_DIR "/usr/lib/boost_1_60_0")
include_directories( ${BOOST_INCLUDE_DIR} )
file(GLOB SOURCE_FILES *.cpp)
add_library(Utilities STATIC ${SOURCE_FILES})
#Don't prepend with "lib"
set_target_properties(Utilities PROPERTIES PREFIX "")
SCRUBBER CMAKELIST IN SCRUBBER/SCRUBBER
cmake_minimum_required(VERSION 3.2)
project(Scrubber)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(BOOST_INCLUDE_DIR "/usr/lib/boost_1_60_0")
set(PROJECT_INCLUDE_DIR "..")
include_directories(${BOOST_INCLUDE_DIR} ${PROJECT_INCLUDE_DIR})
find_library(FILEIO_LIB FileIO.a HINTS ../FileIO/)
find_library(CDES_LIB CDEs.a HINTS ../CDEs/)
find_library(UTILITIES_LIB Utilities.a HINTS ../Utilities/)
file(GLOB SOURCE_FILES *.cpp)
add_executable(Scrubber ${SOURCE_FILES})
target_link_libraries(Scrubber ${FILEIO_LIB} ${CDES_LIB} ${UTILITIES_LIB})
This is wrong:
target_link_libraries(Scrubber ${FILEIO_LIB} ${CDES_LIB} ${UTILITIES_LIB})
if you have library add_library(FileIO STATIC ${SOURCE_FILES}), then you should
write:
target_link_libraries(Scrubber FileIO )
cmake find out that this is also target, and create make file with proper dependencies, and you not have to point any dependencies with add_dependency,
cmake do it for automatically. At least current for me cmake version 3.5
CMake includes the add_dependency command that does exactly what you need.
Make a top-level depend on other top-level targets to ensure that they build before does.
Related
I am newbie on CMAKE. I am trying to make "fat executable file".
The term, fat executeable file, I mentioned, is a executable binary file which contains all shared libraries and can be just run in another environment.
Example (Trouble Situation)
There is ComputerA which is a computer that I used for developing. There is GCC, Boost libraries, librados etc.
And there is ComputerB which is a computer that I wanted to execute the binary that I built.
* Of course, Both Computer A and B have some conditions. Same Intel CPU Arch. (i7), Same CentOS.
I built binary file in ComputerA using CMAKE with this command, cmake .. && make. And I copied this file to ComputerB and executed.
When I execute the copied binary file in Computer B, it said like below.
[root#ComputerB ~]# ./binaryFile 123.123.123.123
./binaryFile: error while loading shared libraries: libboost_json.so.1.80.0: cannot open shared object file: No such file or directory
I understand what this error message say. There is no shared library which it needed. So, what I want to ask in this community is, What is CMAKE Command for containing shared libraries.
Similar thing :: fat JAR
The reason, why I called "fat executable file", is that there is a word "fat JAR" in Java. I am not familiar with Java. But it is commonly used word in Java community.
My CMAKE File
It contains some libraries like Boost, Rados, RBD etc. (There will be more according to progress of developing)
cmake_minimum_required(VERSION 3.2.0)
project(BinaryHelper VERSION 0.1.0)
find_package(Boost REQUIRED COMPONENTS json)
include_directories(${Boost_INCLUDE_DIR})
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrados -std=c++17")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
add_executable(
${PROJECT_NAME}
main.cpp
utils/binary.cpp
utils/message.cpp
utils/header.cpp
)
target_link_libraries (
${PROJECT_NAME}
${Boost_LIBRARIES}
rados
rbd
Threads::Threads
)
Thanks to #HolyBlackCat, I solved the problem with static link.
Modified CMAKE
cmake_minimum_required(VERSION 3.2.0)
project(BinaryHelper VERSION 0.1.0)
find_package(Boost REQUIRED COMPONENTS json)
include_directories(${Boost_INCLUDE_DIR})
set(Boost_USE_STATIC_LIBS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrados -std=c++17")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
add_library(
boost_json
STATIC
IMPORTED
)
set_target_properties(
boost_json
PROPERTIES
IMPORTED_LOCATION /usr/local/lib/libboost_json.a
)
add_executable(
${PROJECT_NAME}
main.cpp
utils/binary.cpp
utils/message.cpp
utils/header.cpp
)
# target_link_libraries (
# ${PROJECT_NAME}
# ${Boost_LIBRARIES}
# rados
# rbd
# Threads::Threads
# )
target_link_libraries(
${PROJECT_NAME}
boost_json
rados
rbd
Threads::Threads
)
There is additional(modified) keywords, add_library, set_target_properties, target_link_libraries.
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;
I have installed Intel opencl sdk for windows and opencl variable are added to the environment variables. I want to use this sdk with my Clion ide which I am unable to include it in my current project since it was CL/cl.hpp not found. How can add it to my project in Clion?
Cl/cl.hpp is located atC:\Program Files(x86)\IntelSWTools\OpenCL\sdk\include\CL
following is my CMakeLists.txt
project(tpch_framework)
# enable c++11
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE "Release")
find_package(OpenMP REQUIRED)
find_package(OpenCL REQUIRED)
if (OPENMP_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
# Configure required Boost libraries
set(BOOST_ROOT "" CACHE PATH "Boost build root (useful on Windows)")
option(Boost_USE_STATIC_LIBS
"Search for static boost libs" OFF)
option(Boost_USE_MULTITHREADED
"Search for multithreaded boost libs" ON)
option(Boost_USE_STATIC_RUNTIME
"Search for boost libs linked against static C++ runtime" OFF)
find_package(Boost 1.47.0 REQUIRED filesystem system)
# ensure that dependant libraries not explicitly specified here
# are found by the linker:
link_directories(${Boost_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
set(LIBS ${LIBS} ${Boost_LIBRARIES})
#Bring the headers into the project
include_directories(include)
FILE(GLOB_RECURSE INC_ALL "include/*.hpp")
#However, the file(GLOB...) allows for wildcard additions:
file(GLOB SOURCES "src/*.cpp")
add_library(tpch_framework ${SOURCES})
add_executable(framework main.cpp ${INC_ALL})
target_link_libraries(framework tpch_framework)
#target_link_libraries(framework stdc++fs)
target_link_libraries(framework ${LIBS})
You need to provide information about include directory for OpenCL headers like you provided for Boost headers. Also, you need to link OpenCL libraries with your target.
In your CMakeLists...
For include and link directories:
link_directories(${Boost_LIBRARY_DIRS} ${OpenCL_LIBRARY})
include_directories(${Boost_INCLUDE_DIRS} ${OpenCL_INCLUDE_DIRS})
For linking libraries:
set(LIBS ${LIBS} ${Boost_LIBRARIES} ${OpenCL_LIBRARY})
I am new to C++ and have just started to use Cmake for linking the libraries to my project. I need to use a library:
https://github.com/Gnimuc/FastPD
Fortunately, I managed to build the library using Cmake (in my build there is no *.lib file at all), but I don't know how to link it to my project. I mean that I don't know how to add it to my cmakelists.txt :
(PS. I'm also using two other libraries ITK and VTK; but I can't link the above mentioned library to my project or main.cpp.)
################################################
cmake_minimum_required(VERSION 2.8)
project(My_project)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
if (ITKVtkGlue_LOADED)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
else()
find_package(ItkVtkGlue REQUIRED)
include(${ItkVtkGlue_USE_FILE})
set(Glue ItkVtkGlue)
endif()
add_executable(My_project MACOSX_BUNDLE main.cpp)
target_link_libraries(My_project
${Glue} ${VTK_LIBRARIES} ${ITK_LIBRARIES})
################################################
Thanks in advance for your helps,
Assuming you installed the library and its header files, you can then search for the header files using find_path, and add the found path to the include directories. Then you can search for the library by using find_library, and add the library with the target_link_libraries command.
I tried both shared and static types for creation of the library. In the case of shared, no *.lib file was created, and in the case of static, my project couldn't link to the library. Therefore, in my project's CmakeLists.txt, I decided to add all the *.cpp and headers as libraries and then link them together (as I didn't know the dependency among them!!!), and finally, I linked them to my project. Perhaps it does not make sense but it works; hope it helps you:
CmakeLists.txt
##############################################
cmake_minimum_required(VERSION 2.6)
set(PROJ_NAME PROJECT46)
PROJECT(${PROJ_NAME})
# Prevent compilation in-source
if( ${CMAKE_BINARY_DIR} STREQUAL ${PROJECT_SOURCE_DIR} )
Message( " " )
Message( FATAL_ERROR "Source and build directories are the same.
Create an empty build directory,
change into it and re-invoke cmake")
endif()
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support.
Please use a different C++ compiler.")
endif()
##############################################
## External libraries
##############################################
list( APPEND CMAKE_MODULE_PATH
${PROJECT_SOURCE_DIR}/cmake
)
# Blitz
find_package( Blitz++ REQUIRED )
list( APPEND PROJ_INCLUDE_DIRS
${Blitz++_INCLUDE_DIR}
)
list( APPEND
PROJ_LIB
${Blitz++_LIBRARIES}
)
# ITK and VTK
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
if (ITKVtkGlue_LOADED)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
else()
find_package(ItkVtkGlue REQUIRED)
include(${ItkVtkGlue_USE_FILE})
set(Glue ItkVtkGlue)
endif()
##############################################
# FASTPD
add_library(FASTPD Fast_PD.cpp Fast_PD.h common.h block.h)
add_library(GRAPH graph.h graph.cpp)
add_library(linked LinkedBlockList.h LinkedBlockList.cpp)
add_library(MAXFLOW maxflow.cpp)
include_directories(${PROJ_INCLUDE_DIRS})
add_executable(${PROJ_NAME} main.cpp)
target_link_libraries(linked MAXFLOW)
target_link_libraries(GRAPH linked)
target_link_libraries(FASTPD GRAPH)
target_link_libraries(${PROJ_NAME} FASTPD)
target_link_libraries(${PROJ_NAME}
${PROJ_LIB} ${Glue} ${VTK_LIBRARIES} ${ITK_LIBRARIES}
)
I have a directory structure in CMake as follows:
root
CMakeLists.txt
subproject_folder
my_dll_library
CMakeLists.txt
src
source1.cpp
source2.cpp
inc
library.h
CMakeLists.txt
library_demo
src
demo.cpp
CMakeLists.txt
build
bin
My root CmakeLists.txt contains this:
cmake_minimum_required(VERSION 2.8)
add_subdirectory(subproject_folder)
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
# Update if necessary
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
endif()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
The CMakeLists in the subproject folder just contains
add_subdirectory(my_dll_library)
add_subdirectory(library_demo)
The CMakeLists in the library_demo folder contains
project(library_demo)
add_executable(librarydemo src/demo.cpp)
target_link_libraries(librarydemo my_dll_library)
install(TARGETS librarydemo DESTINATION bin)
The CMakeLists in the my_dll_library folder contains
add_library(lib_zaber SHARED src/source1.cpp src/source2.cpp)
install(TARGETS lib_zaber DESTINATION bin)
I want to have the demo executable and the library DLL copied to the bin folder, but it isn't working.
What am I doing wrong?
Try to set those variables too:
CMAKE_BINARY_DIR
CMAKE_CURRENT_BINARY_DIR
There's a whole list of variables you could try here:
http://www.cmake.org/Wiki/CMake_Useful_Variables
The command
install(.. DESTINATION <dir>)
installs to ${CMAKE_INSTALL_PREFIX}/<dir>.
You need to set CMAKE_INSTALL_PREFIX either in the CMakeLists.txt or when calling cmake:
cmake ... -DCMAKE_INSTALL_PREFIX=<dir>