On 11. Sep, 2009, at 15:12, Pierre-Julien Villoud wrote:

Hi everyone,

After unsuccessfully looking for an answer on Google, I contact you.
I have a question regarding the use of add_subdirectory. When a project A is depending on a project B, I add the following in A's CMakeLists.txt :

Add_subdirectory(B Path/To/B/Build/Directory)

It does build B before A. But when I build B in its build directory and I build A after, it builds B again whereas it should not since B is up to date.

Anyone sees what's wrong ?

Thanks in advance

Pierre-Julien VILLOUD


That's NOT what add_subdirectory is made for. It is intended for adding a sub-directory in the source tree. So, if your directory structure looks like this (i.e. B is a sub-project of A)

A/CMakeLists.txt
A/B/CMakeLists.txt

things are simple:

A/CMakeLists.txt:
------>8------
# ....
add_subdirectory(B)

include_directories(B/include)

add_executable(a)
target_link_libraries(a b)
------<8------

However, if the two projects are unrelated (apart from A depending on B), you should use the find_package mechanism which is much more complex. I.e, in project B you create the files BConfig.cmake (or b- config.cmake), BUse.cmake, BBuildSettings.cmake and BLibraryDepends.cmake:

B/BConfig.cmake.in:
------->8------
# Tell the user project where to find our headers and libraries
set(B_INCLUDE_DIRS "@CONFIG_HEADER_PATH@")
set(B_LIBRARY_DIRS "@CONFIG_LIBRARY_PATH@")

# Our build settings and library dependencies
set(B_BUILD_SETTINGS_FILE
  "@CONFIG_LIBRARY_PATH@/BBuildSettings.cmake"
  )
include("@CONFIG_LIBRARY_PATH@/BLibraryDepends.cmake")

# Defines
set( B_DEFINITIONS "@CONFIG_DEFINITIONS@" )

# USE file
set(B_USE_FILE "@CONFIG_USE_FILE_PATH@/BUse.cmake")
------<8------

B/BUse.cmake:
------->8------
# import B build settings
include(CMakeImportBuildSettings)
cmake_import_build_settings(${B_BUILD_SETTINGS_FILE})

# set up header search path
include_directories(${B_INCLUDE_DIRS})

# set up library search path
link_directories(${BM_LIBRARY_DIRS})

# defines
add_definitions(${B_DEFINITIONS})
------<8------

In the B/CMakeLists.txt file you do the following (just a snippet, showing the relevant stuff):

B/CMakeLists.txt:
------>8------
# ....

# say, you build two libraries, called b1 and b2
# with sources b1src1.c through b1src3.c and
# b2src1.c through b2src3.c, respectively.
add_library(b1 b1src1.c b1src2.c b1src3.c)
set_target_properties(b1 PROPERTIES
  PUBLIC_HEADER "b1hdr1.h;b1hdr2.h;b1hdr3.h"
  )

add_library(b2 b2src1.c b2src2.c b2src3.c)
set_target_properties(b2 PROPERTIES
  PUBLIC_HEADER "b2hdr1.h;b2hdr2.h;b2hdr3.h"
  )

# ....

# install the two libraries
install(TARGETS b1 b2
  LIBRARY DESTINATION lib COMPONENT shlibs
  RUNTIME DESTINATION bin COMPONENT shlibs
  ARCHIVE DESTINATION lib COMPONENT dev
  PUBLIC_HEADER DESTINATION include COMPONENT dev
  )

# ....

# AT THE VERY END OF THE FILE...

# Export library dependencies
#############################
export( TARGETS b1 b2
  NAMESPACE B_
  FILE ${CMAKE_BINARY_DIR}/BLibraryDepends.cmake
)

# Export the build settings
###########################
include(CMakeExportBuildSettings)
cmake_export_build_settings(${CMAKE_BINARY_DIR}/BBuildSettings.cmake)

# create BConfig.cmake for the build tree
#########################################
# SET TO THE PREPROCESSOR FLAGS REQUIRED TO USE PROJECT B
set(CONFIG_DEFINITIONS)
# SET TO WHATEVER INCLUDE PATH IS REQUIRED TO USE B'S BINARY TREE
set(CONFIG_HEADER_PATH ${CMAKE_SOURCE_DIR}/include )
# SET TO WHATEVER LIBRARY PATH IS REQUIRED TO USE B'S BINARY TREE
# (ACTUALLY, DUE TO CMAKE-MAGIC THIS CAN BE EMPTY)
set(CONFIG_LIBRARY_PATH)
set(CONFIG_USE_FILE_PATH ${CMAKE_SOURCE_DIR})
configure_file(
  ${CMAKE_SOURCE_DIR}/BConfig.cmake.in
  ${CMAKE_BINARY_DIR}/BConfig.cmake
  @ONLY
  )

# create BConfig.cmake for the install tree
###########################################
set(CONFIG_HEADER_PATH "${CMAKE_INSTALL_PREFIX}/include")
set(CONFIG_LIBRARY_PATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CONFIG_USE_FILE_PATH "${CMAKE_INSTALL_PREFIX}/share/cmake/B" )
configure_file(
  ${CMAKE_SOURCE_DIR}/BConfig.cmake.in
  ${CMAKE_BINARY_DIR}/InstallFiles/BConfig.cmake
  @ONLY
  )

# install the CMake config files
################################
install( FILES
  BUse.cmake
  "${CMAKE_BINARY_DIR}/InstallFiles/BConfig.cmake"
  "${CMAKE_BINARY_DIR}/BBuildSettings.cmake"
  DESTINATION share/cmake/B
  COMPONENT dev
  )

# install the BLibraryDepends.cmake file
########################################
install( EXPORT BLibraryDepends
  DESTINATION share/cmake/B
  NAMESPACE B_
  COMPONENT dev
  )
------<8------


And then, in your A/CMakeLists.txt you do the following to use B:

A/CMakeLists.txt:
------>8------

find_package(B REQUIRED)
include(${B_USE_FILE})

add_executable(a asrc1.c asrc2.c asrc3.c)
target_link_libraries(a B_b1 B_b2)

------<8------

In order for CMake to find the BConfig.cmake, it searches some known system directories (refer to the documentation of find_package). If CMake can't find the file (which is very likely if you want to use B's build tree), you have to set the cache variable B_DIR to the binary directory of B.


I hope this explains how things work. If not, there's always the CMake book...

Michael
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Follow this link to subscribe/unsubscribe:
http://www.cmake.org/mailman/listinfo/cmake

Reply via email to