Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
208 views
in Technique[技术] by (71.8m points)

c++ - CMake one build directory for multiple projects

I′m a beginner user of CMake. My environment has several projects like:

project
  |------ CMakeLists.txt (The main Cmake)
  |------ ProjectA
  |          |----- .cpp files
  |          |----- .hpp files
  |          |----- CMakeList.txt
  |------ ProjectB
  |          |----- .cpp files
  |          |----- .hpp files
  |          |----- CMakeList.txt
  | 
  |------ build
  |         |-----  CMakeStuff
  |------ bin
  |        |---- executables
  |------ lib
  |        |---- libwhatever.a
  |------ db 
           |---- Database stuff

I would like to use a single build directory for every project, as showed above. Preferrably that It can be divided into multiple subprojects, like build/projectA, build/ProjectB so that if I need to rebuild a single project I can delete the whole build/Project file and all is gone and a new Cmake will build it again.

I′m having difficulties configuring CMAKE.

My original CMakeList.txt on the project folder:

cmake_minimum_required(VERSION 3.2.2.)
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)

project(projectA)
set(CMAKE_BUILD_TYPE Debug)

file(GLOB SOURCES "*.cpp")

add_library(commonmessage SHARED ${SOURCES})

install(TARGETS commonmessage DESTINATION ../lib)

My questions are:

A) What will happen if I run cmake on a single build directory - is that possible and what would be the correct CMAKE configuration ?

B) My compilation for ProjectA needs to include files from ProjectB - how can I set that in the CMakeLists.txt for each individual project ?

C) At the end I need a single makefile to build all, as well as the option to build each project individually. Will that be possible with a single build directory ?

Thanks for helping.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First of all, it doesn't look like the CMake code you posted belongs to the top CMakeList.txt file, since it directly references .cpp files, and "projectA". There are also a few things that are not idiomatic:

cmake_minimum_required(VERSION 3.2.2.)

why the trailing dot here ? Not sure whether cmake will complain, but it is useless either way.

set(CMAKE_BUILD_TYPE Debug)

Don't do that. Instead invoke cmake using the -DCMAKE_BUILD_TYPE=Debug command line flag, or use ccmake, or a GUI, or edit the CMakeCache.txt file.

file(GLOB SOURCES "*.cpp")

Don't do that either. It is good practice to explicitely list source files in CMake, because globbing will not make cmake detect newly added or deleted files automatically. Some people might disagree though.

Now for the heart of the topic, here is how things are usually done:

Top CMakeLists.txt file:

cmake_minimum_required(VERSION 3.2.2)
project(globalProject)

add_subdirectory(projectA)
add_subdirectory(projectB)

ProjectA CMakeLists.txt file (assuming projectA is an executable):

add_executable(projectA file1.cpp file2.cpp ... )
include_directories(${CMAKE_SOURCE_DIR}/projectB) # include files from ProjectB
target_link_libraries(projectA projectB)

install(TARGETS projectA RUNTIME DESTINATION bin)

ProjectB CMakeLists.txt file (assuming projectB is a library):

add_library(projectB file1.cpp file2.cpp ... )

install(TARGETS projectB
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)

Please note that this setup needs the make install step to create bin and lib at the location of your choice as given in the command line invocation of cmake -DCMAKE_INSTALL_PREFIX=.. (assuming make is run from the build dir).

Also, this setup lets you choose if you want to build static or shared libraries, by using: -DBUILD_SHARED_LIBS=ON. To build both, you need to have two add_library calls with two different names, one STATIC, the other SHARED.

To sum up the steps required to make this work:

$ mkdir build && cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=.. -DBUILD_SHARED_LIBS=ON
$ make
$ make install

You could put these commands in a script for reusability.

Now, your questions can be answered:

A) it is possible and recommended, see the code above, only one build directory is necessary.

B) See the code for the projectA/CMakeLists.txt, you have to call include_directories()

C) Yes it is possible. Each target in your project can be built individually from the build directory by using make and the target name: make projectB and make projectA


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...