Use Ceres_[SOURCE/BINARY]_DIR not CMAKE_XXX_DIR to support nesting. - Using Ceres_[SOURCE/BINARY]_DIR (which are defined by CMake when project(Ceres) is called, in favour of CMAKE_[SOURCE/BINARY]_DIR enables Ceres to be nested within (and built by) a larger CMake project (which also contains other projects). - CMAKE_[SOURCE/BINARY]_DIR always refers to the top-level source and binary directories (i.e. the first encountered), as a result if Ceres is a nested project within a larger project, these would not correctly identify the source/binary directories for Ceres (as they would refer to the root project in which Ceres is nested). - Using Ceres_[SOURCE/BINARY]_DIR should ensure that Ceres always uses the correct source/binary directories, irrespective of whether Ceres is nested or not. Change-Id: I62226ea3f6552b1d7e2bdac1aef02f1f489ae55e
diff --git a/CMakeLists.txt b/CMakeLists.txt index cf5f845..a782c34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -39,15 +39,24 @@ project(Ceres C CXX) +# NOTE: The 'generic' CMake variables CMAKE_[SOURCE/BINARY]_DIR should not be +# used. Always use the project-specific variants (generated by CMake): +# <PROJECT_NAME_MATCHING_CASE>_[SOURCE/BINARY]_DIR, e.g. +# Ceres_SOURCE_DIR (note, *not* CERES_SOURCE_DIR) instead, as these will +# always point to the correct directories for the Ceres project, even if +# it is nested inside another source tree, whereas the 'generic' +# CMake variables refer to the *first* project() declaration, i.e. the +# top-level project, not Ceres, if Ceres is nested. + # Make CMake aware of the cmake folder for local FindXXX scripts, # append rather than set in case the user has passed their own # additional paths via -D. -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH "${Ceres_SOURCE_DIR}/cmake") include(UpdateCacheVariable) # Set up the git hook to make Gerrit Change-Id: lines in commit messages. include(AddGerritCommitHook) -add_gerrit_commit_hook() +add_gerrit_commit_hook(${Ceres_SOURCE_DIR} ${Ceres_BINARY_DIR}) # On OS X, add the Homebrew prefix to the set of prefixes searched by # CMake in find_path & find_library. This should ensure that we can @@ -67,9 +76,9 @@ endif() endif() -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/lib) # Set postfixes for generated libraries based on buildtype. set(CMAKE_RELEASE_POSTFIX "") set(CMAKE_DEBUG_POSTFIX "-debug") @@ -77,7 +86,7 @@ # Read the Ceres version from the source, such that we only ever have a single # definition of the Ceres version. include(ReadCeresVersionFromSource) -read_ceres_version_from_source(${CMAKE_SOURCE_DIR}) +read_ceres_version_from_source(${Ceres_SOURCE_DIR}) enable_testing() @@ -724,13 +733,13 @@ list(REMOVE_DUPLICATES CERES_COMPILE_OPTIONS) include(CreateCeresConfig) create_ceres_config("${CERES_COMPILE_OPTIONS}" - ${CMAKE_BINARY_DIR}/config/ceres/internal) + ${Ceres_BINARY_DIR}/config/ceres/internal) # Force the location containing the configured config.h to the front of the # include_directories list (by default it is appended to the back) to ensure # that if the user has an installed version of Ceres in the same location as one # of the dependencies (e.g. /usr/local) that we find the config.h we just # configured, not the (older) installed config.h. -include_directories(BEFORE ${CMAKE_BINARY_DIR}/config) +include_directories(BEFORE ${Ceres_BINARY_DIR}/config) add_subdirectory(internal/ceres) @@ -758,21 +767,21 @@ endif (BUILD_EXAMPLES) # Setup installation of Ceres public headers. -file(GLOB CERES_HDRS ${CMAKE_SOURCE_DIR}/include/ceres/*.h) +file(GLOB CERES_HDRS ${Ceres_SOURCE_DIR}/include/ceres/*.h) install(FILES ${CERES_HDRS} DESTINATION include/ceres) -file(GLOB CERES_PUBLIC_INTERNAL_HDRS ${CMAKE_SOURCE_DIR}/include/ceres/internal/*.h) +file(GLOB CERES_PUBLIC_INTERNAL_HDRS ${Ceres_SOURCE_DIR}/include/ceres/internal/*.h) install(FILES ${CERES_PUBLIC_INTERNAL_HDRS} DESTINATION include/ceres/internal) # Also setup installation of Ceres config.h configured with the current # build options into the installed headers directory. -install(FILES ${CMAKE_BINARY_DIR}/config/ceres/internal/config.h +install(FILES ${Ceres_BINARY_DIR}/config/ceres/internal/config.h DESTINATION include/ceres/internal) if (MINIGLOG) # Install miniglog header if being used as logging #includes appear in # installed public Ceres headers. - install(FILES ${CMAKE_SOURCE_DIR}/internal/ceres/miniglog/glog/logging.h + install(FILES ${Ceres_SOURCE_DIR}/internal/ceres/miniglog/glog/logging.h DESTINATION include/ceres/internal/miniglog/glog) endif (MINIGLOG) @@ -805,8 +814,8 @@ # Create a CeresConfigVersion.cmake file containing the version information, # used by both export() & install(). -configure_file("${CMAKE_SOURCE_DIR}/cmake/CeresConfigVersion.cmake.in" - "${CMAKE_BINARY_DIR}/CeresConfigVersion.cmake" @ONLY) +configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfigVersion.cmake.in" + "${Ceres_BINARY_DIR}/CeresConfigVersion.cmake" @ONLY) # Install method #1: Put Ceres in CMAKE_INSTALL_PREFIX: /usr/local or equivalent. @@ -838,31 +847,31 @@ # # NOTE: The -install suffix is necessary to distinguish the install version from # the exported version, which must be named CeresConfig.cmake in -# CMAKE_BINARY_DIR to be detected. The suffix is removed when +# Ceres_BINARY_DIR to be detected. The suffix is removed when # it is installed. set(SETUP_CERES_CONFIG_FOR_INSTALLATION TRUE) -configure_file("${CMAKE_SOURCE_DIR}/cmake/CeresConfig.cmake.in" - "${CMAKE_BINARY_DIR}/CeresConfig-install.cmake" @ONLY) +configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfig.cmake.in" + "${Ceres_BINARY_DIR}/CeresConfig-install.cmake" @ONLY) # Install the configuration files into the same directory as the autogenerated # CeresTargets.cmake file. We include the find_package() scripts for libraries # whose headers are included in the public API of Ceres and should thus be # present in CERES_INCLUDE_DIRS. -install(FILES "${CMAKE_BINARY_DIR}/CeresConfig-install.cmake" +install(FILES "${Ceres_BINARY_DIR}/CeresConfig-install.cmake" RENAME CeresConfig.cmake DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR}) -install(FILES "${CMAKE_BINARY_DIR}/CeresConfigVersion.cmake" - "${CMAKE_SOURCE_DIR}/cmake/FindEigen.cmake" - "${CMAKE_SOURCE_DIR}/cmake/FindGlog.cmake" - "${CMAKE_SOURCE_DIR}/cmake/FindGflags.cmake" +install(FILES "${Ceres_BINARY_DIR}/CeresConfigVersion.cmake" + "${Ceres_SOURCE_DIR}/cmake/FindEigen.cmake" + "${Ceres_SOURCE_DIR}/cmake/FindGlog.cmake" + "${Ceres_SOURCE_DIR}/cmake/FindGflags.cmake" DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR}) # Create an uninstall target to remove all installed files. -configure_file("${CMAKE_SOURCE_DIR}/cmake/uninstall.cmake.in" - "${CMAKE_BINARY_DIR}/cmake/uninstall.cmake" +configure_file("${Ceres_SOURCE_DIR}/cmake/uninstall.cmake.in" + "${Ceres_BINARY_DIR}/cmake/uninstall.cmake" @ONLY) add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake/uninstall.cmake) + COMMAND ${CMAKE_COMMAND} -P ${Ceres_BINARY_DIR}/cmake/uninstall.cmake) # Install method #2: Put Ceres build into local CMake registry. # @@ -874,18 +883,18 @@ # Save the relative path from the build directory to the source directory. file(RELATIVE_PATH INSTALL_ROOT_REL_CONFIG_INSTALL_DIR - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}) + ${Ceres_BINARY_DIR} + ${Ceres_SOURCE_DIR}) # Analogously to install(EXPORT ...), export the Ceres target from the build # directory as a package called Ceres into the local CMake package registry. - export(TARGETS ceres FILE ${CMAKE_BINARY_DIR}/CeresTargets.cmake) + export(TARGETS ceres FILE ${Ceres_BINARY_DIR}/CeresTargets.cmake) export(PACKAGE ${CMAKE_PROJECT_NAME}) # Configure a CeresConfig.cmake file for the export of the Ceres build # directory from the template, reflecting the current build options. set(SETUP_CERES_CONFIG_FOR_INSTALLATION FALSE) - configure_file("${CMAKE_SOURCE_DIR}/cmake/CeresConfig.cmake.in" - "${CMAKE_BINARY_DIR}/CeresConfig.cmake" @ONLY) + configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfig.cmake.in" + "${Ceres_BINARY_DIR}/CeresConfig.cmake" @ONLY) endif (EXPORT_BUILD_DIR)
diff --git a/cmake/AddGerritCommitHook.cmake b/cmake/AddGerritCommitHook.cmake index 071e84a..4347028 100644 --- a/cmake/AddGerritCommitHook.cmake +++ b/cmake/AddGerritCommitHook.cmake
@@ -30,20 +30,28 @@ # alexs.mac@gmail.com (Alex Stewart) # Set up the git hook to make Gerrit Change-Id: lines in commit messages. -function(ADD_GERRIT_COMMIT_HOOK) +function(ADD_GERRIT_COMMIT_HOOK SOURCE_DIR BINARY_DIR) + if (NOT EXISTS ${SOURCE_DIR} AND IS_DIRECTORY ${SOURCE_DIR}) + message(FATAL_ERROR "Specified SOURCE_DIR: ${SOURCE_DIR} does not exist, " + "or is not a directory, cannot add Gerrit commit hook.") + endif() + if (NOT EXISTS ${BINARY_DIR} AND IS_DIRECTORY ${BINARY_DIR}) + message(FATAL_ERROR "Specified BINARY_DIR: ${BINARY_DIR} does not exist, " + "or is not a directory, cannot add Gerrit commit hook.") + endif() unset (LOCAL_GIT_DIRECTORY) - if (EXISTS ${CMAKE_SOURCE_DIR}/.git) - if (IS_DIRECTORY ${CMAKE_SOURCE_DIR}/.git) + if (EXISTS ${SOURCE_DIR}/.git) + if (IS_DIRECTORY ${SOURCE_DIR}/.git) # .git directory can be found on Unix based system, or on Windows with # Git Bash (shipped with msysgit). - set (LOCAL_GIT_DIRECTORY ${CMAKE_SOURCE_DIR}/.git) - else(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/.git) + set (LOCAL_GIT_DIRECTORY ${SOURCE_DIR}/.git) + else(IS_DIRECTORY ${SOURCE_DIR}/.git) # .git is a file, this means Ceres is a git submodule of another project # and our .git file contains the path to the git directory which manages # Ceres, so we should add the gerrit hook there. - file(READ ${CMAKE_SOURCE_DIR}/.git GIT_SUBMODULE_FILE_CONTENTS) + file(READ ${SOURCE_DIR}/.git GIT_SUBMODULE_FILE_CONTENTS) # Strip any trailing newline characters, s/t we get a valid path. - string(REGEX REPLACE "gitdir:[ ]*([^$].*)[\n].*" "${CMAKE_SOURCE_DIR}/\\1" + string(REGEX REPLACE "gitdir:[ ]*([^$].*)[\n].*" "${SOURCE_DIR}/\\1" GIT_SUBMODULE_GIT_DIRECTORY_PATH "${GIT_SUBMODULE_FILE_CONTENTS}") get_filename_component(GIT_SUBMODULE_GIT_DIRECTORY_PATH "${GIT_SUBMODULE_GIT_DIRECTORY_PATH}" ABSOLUTE) @@ -52,9 +60,9 @@ set(LOCAL_GIT_DIRECTORY "${GIT_SUBMODULE_GIT_DIRECTORY_PATH}") endif() endif() - else (EXISTS ${CMAKE_SOURCE_DIR}/.git) + else (EXISTS ${SOURCE_DIR}/.git) # TODO(keir) Add proper Windows support. - endif (EXISTS ${CMAKE_SOURCE_DIR}/.git) + endif (EXISTS ${SOURCE_DIR}/.git) if (EXISTS ${LOCAL_GIT_DIRECTORY}) if (NOT EXISTS ${LOCAL_GIT_DIRECTORY}/hooks/commit-msg) @@ -62,10 +70,10 @@ "commit hook for Gerrit to: ${LOCAL_GIT_DIRECTORY}") # Download the hook only if it is not already present. file(DOWNLOAD https://ceres-solver-review.googlesource.com/tools/hooks/commit-msg - ${CMAKE_BINARY_DIR}/commit-msg) + ${BINARY_DIR}/commit-msg) # Make the downloaded file executable, since it is not by default. - file(COPY ${CMAKE_BINARY_DIR}/commit-msg + file(COPY ${BINARY_DIR}/commit-msg DESTINATION ${LOCAL_GIT_DIRECTORY}/hooks/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
diff --git a/docs/source/CMakeLists.txt b/docs/source/CMakeLists.txt index 0f07a5b..70bf998 100644 --- a/docs/source/CMakeLists.txt +++ b/docs/source/CMakeLists.txt
@@ -1,7 +1,7 @@ find_package(Sphinx REQUIRED) # HTML output directory -set(SPHINX_HTML_DIR "${CMAKE_BINARY_DIR}/docs/html") +set(SPHINX_HTML_DIR "${Ceres_BINARY_DIR}/docs/html") # Install documentation install(DIRECTORY ${SPHINX_HTML_DIR} @@ -12,8 +12,8 @@ # Building using 'make_docs.py' python script add_custom_target(ceres_docs ALL python - "${CMAKE_SOURCE_DIR}/scripts/make_docs.py" - "${CMAKE_SOURCE_DIR}" - "${CMAKE_BINARY_DIR}/docs" + "${Ceres_SOURCE_DIR}/scripts/make_docs.py" + "${Ceres_SOURCE_DIR}" + "${Ceres_BINARY_DIR}/docs" "${SPHINX_EXECUTABLE}" COMMENT "Building HTML documentation with Sphinx")
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index 6eb6979..4159e39 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -294,7 +294,7 @@ add_test(NAME ${NAME}_test COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${NAME}_test --test_srcdir - ${CMAKE_SOURCE_DIR}/data) + ${Ceres_SOURCE_DIR}/data) endmacro (CERES_TEST) ceres_test(array_utils)