Skip to content

Commit a292b78

Browse files
wdeconinckhavogt
authored andcommitted
Modifications to allow Serialbox to be used in CMake superbuild projects (#201)
This PR allows Serialbox to be used in CMake superbuild projects, so that one could have code like ``` add_subdirectory( serialbox2 ) # --> will set "Serialbox_DIR" in cache add_subdirectory( project_using_serialbox ) ``` and within `project_using_serialbox` we have ``` find_package( Serialbox ) # --> will use Serialbox_DIR as default hint ``` Most issues were related to use of `${CMAKE_BINARY_DIR}` and `${CMAKE_SOURCE_DIR}` which reflect the top-level CMake project rather than `${PROJECT_BINARY_DIR}` and `${PROJECT_SOURCE_DIR}` which reflect the most recent project. As a result it could be that certain products are no longer in a previously expected directory now, as I am not able to test everything --- Moreover in this PR I have created alias targets (if possible) `Serialbox::Serialbox_C` and `Serialbox::Serialbox_Fortran` that prefer the shared versions `Serialbox::SerialboxCShared` and `Serialbox::SerialboxFortranShared` over the static versions `Serialbox::SerialboxCStatic` and `Serialbox::SerialboxFortranStatic` In the client software you can then just use the alias target instead.
1 parent 6f2010c commit a292b78

File tree

19 files changed

+237
-187
lines changed

19 files changed

+237
-187
lines changed

CMakeLists.txt

+14-13
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ cmake_minimum_required(VERSION 3.9.0)
2020
set(CMAKE_CXX_EXTENSIONS OFF)
2121
set(CMAKE_C_EXTENSIONS OFF)
2222

23-
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
23+
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")
2424
include(ExternalProject)
2525
include(CMakeParseArguments)
2626
include(CheckCXXCompilerFlag)
27+
include(SerialboxInstallTargets)
2728

2829
#---------------------------------------- Configure ------------------------------------------------
2930

@@ -102,11 +103,13 @@ if(NOT CMAKE_BUILD_TYPE)
102103
endif(NOT CMAKE_BUILD_TYPE)
103104

104105
# Clear all cmake generated files
105-
add_custom_target(clean-all
106-
COMMAND ${CMAKE_MAKE_PROGRAM} clean
107-
COMMAND ${CMAKE_COMMAND} -P
108-
"${CMAKE_SOURCE_DIR}/cmake/modules/SerialboxCleanAll.cmake")
109-
106+
if( NOT TARGET clean-all )
107+
add_custom_target(clean-all
108+
COMMAND ${CMAKE_MAKE_PROGRAM} clean
109+
COMMAND ${CMAKE_COMMAND} -P
110+
"${PROJECT_SOURCE_DIR}/cmake/modules/SerialboxCleanAll.cmake")
111+
endif()
112+
110113
# We need thread support
111114
find_package(Threads REQUIRED)
112115

@@ -208,6 +211,7 @@ if(${SERIALBOX_USE_NETCDF})
208211
message(FATAL_ERROR "NetCDF library not found!")
209212
endif()
210213
set(SERIALBOX_HAS_NETCDF 1)
214+
serialbox_install_targets( TARGETS NETCDF_TARGET )
211215
endif()
212216

213217
#---------------------------------------- Python ---------------------------------------------------
@@ -273,9 +277,7 @@ if(_use_boost_filesystem)
273277
set(SERIALBOX_FILESYSTEM_LIBRARY_STRING "SERIALBOX_USE_BOOST_FILESYSTEM")
274278
endif()
275279

276-
install(TARGETS SerialboxFilesytemTarget
277-
EXPORT SerialboxTargets
278-
)
280+
serialbox_install_targets( TARGETS SerialboxFilesytemTarget )
279281

280282

281283
#---------------------------------------- STELLA ---------------------------------------------------
@@ -383,6 +385,7 @@ if(SERIALBOX_CODE_COVERAGE)
383385
endif(SERIALBOX_CODE_COVERAGE)
384386

385387
#---------------------------------------- Compilation ----------------------------------------------
388+
386389
# Generate serialbox/core/Config.h
387390
set(SERIALBOX_CONFIG_FILE_DISCLAIMER "WARNING! All changes made in this file will be lost!")
388391
set(SERIALBOX_CXX_CONFIG_FILE_IN ${PROJECT_SOURCE_DIR}/src/serialbox/core/Config.h.cmake)
@@ -419,9 +422,9 @@ if(SERIALBOX_TESTING)
419422

420423
# Generate utility/Config.h
421424
set(SERIALBOX_CPP_CONFIG_FILE_IN ${PROJECT_SOURCE_DIR}/test/utility/Config.h.cmake)
422-
set(SERIALBOX_CPP_CONFIG_FILE ${CMAKE_BINARY_DIR}/test/utility/Config.h)
425+
set(SERIALBOX_CPP_CONFIG_FILE ${PROJECT_BINARY_DIR}/test/utility/Config.h)
423426
configure_file(${SERIALBOX_CPP_CONFIG_FILE_IN} ${SERIALBOX_CPP_CONFIG_FILE})
424-
include_directories(${CMAKE_BINARY_DIR}/test)
427+
include_directories(${PROJECT_BINARY_DIR}/test)
425428

426429
add_subdirectory(test)
427430
endif(SERIALBOX_TESTING)
@@ -441,5 +444,3 @@ if(SERIALBOX_TESTING)
441444
endif(SERIALBOX_TESTING)
442445

443446
include(cmake/Packaging.cmake)
444-
445-

cmake/Packaging.cmake

+8-25
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ install(EXPORT SerialboxTargets
2222
)
2323

2424
## Generate and install SerialboxConfig.cmake
25-
configure_package_config_file(${CMAKE_SOURCE_DIR}/cmake/SerialboxConfig.cmake.in
25+
configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/SerialboxConfig.cmake.in
2626
"${PROJECT_BINARY_DIR}/cmake/SerialboxConfig.cmake"
2727
INSTALL_DESTINATION ${CMAKE_INSTALL_DIR}
2828
PATH_VARS CMAKE_INSTALL_DIR PYTHON_INSTALL_DIR
2929
)
3030
install(FILES "${PROJECT_BINARY_DIR}/cmake/SerialboxConfig.cmake" DESTINATION cmake)
3131

3232
## Install SerialboxTooling.cmake
33-
install(FILES ${CMAKE_SOURCE_DIR}/cmake/SerialboxTooling.cmake DESTINATION cmake/)
33+
install(FILES ${PROJECT_SOURCE_DIR}/cmake/SerialboxTooling.cmake DESTINATION cmake/)
3434

3535
# Generate and install SerialboxConfigVersion.cmake
3636
write_basic_package_version_file(
@@ -41,34 +41,17 @@ write_basic_package_version_file(
4141
install(FILES "${PROJECT_BINARY_DIR}/cmake/SerialboxConfigVersion.cmake" DESTINATION cmake)
4242

4343
## For build tree
44-
export(TARGETS SerialboxStatic SerialboxObjects SerialboxFilesytemTarget
45-
FILE ${PROJECT_BINARY_DIR}/SerialboxTargets.cmake
46-
NAMESPACE Serialbox::
47-
)
48-
if(SERIALBOX_HAS_NETCDF)
49-
export(TARGETS NETCDF_TARGET
50-
APPEND FILE ${PROJECT_BINARY_DIR}/SerialboxTargets.cmake
51-
NAMESPACE Serialbox::
52-
)
53-
endif()
54-
if(SERIALBOX_ENABLE_C)
55-
export(TARGETS SerialboxCStatic SerialboxCObjects
56-
APPEND FILE ${PROJECT_BINARY_DIR}/SerialboxTargets.cmake
57-
NAMESPACE Serialbox::
58-
)
59-
endif()
60-
if(SERIALBOX_ENABLE_FORTRAN)
61-
export(TARGETS SerialboxFortranStatic SerialboxFortranObjects SerialboxFortranSerializeObjects
62-
APPEND FILE ${PROJECT_BINARY_DIR}/SerialboxTargets.cmake
63-
NAMESPACE Serialbox::
64-
)
65-
endif()
6644

6745
set(CMAKE_INSTALL_DIR ${PROJECT_SOURCE_DIR}/cmake)
6846
set(PYTHON_INSTALL_DIR ${PROJECT_SOURCE_DIR}/src/serialbox-python)
69-
configure_package_config_file(${CMAKE_SOURCE_DIR}/cmake/SerialboxConfig.cmake.in
47+
48+
49+
set( ${PROJECT_NAME}_DIR ${PROJECT_BINARY_DIR} CACHE STRING "" )
50+
51+
configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/SerialboxConfig.cmake.in
7052
${PROJECT_BINARY_DIR}/SerialboxConfig.cmake
7153
INSTALL_DESTINATION ${PROJECT_BINARY_DIR}
54+
INSTALL_PREFIX ${PROJECT_BINARY_DIR}
7255
PATH_VARS CMAKE_INSTALL_DIR PYTHON_INSTALL_DIR
7356
)
7457
write_basic_package_version_file(

cmake/SerialboxConfig.cmake.in

+79-28
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,78 @@ set(SERIALBOX_BOOST_LIBRARY_DIRS "@Boost_LIBRARY_DIRS@")
4040
set(SERIALBOX_BOOST_INCLUDE_DIRS "@Boost_INCLUDE_DIRS@")
4141
set(SERIALBOX_REQUIRED_BOOST_COMPONENTS "@REQUIRED_BOOST_COMPONENTS@")
4242

43+
#===---------------------------------------------------------------------------------------------===
44+
# Helper functions used in this file
45+
#====--------------------------------------------------------------------------------------------===
46+
47+
function( serialbox_print_targets )
48+
#
49+
# serialbox_print_targets( targets_list )
50+
#
51+
# Print exported and unavailable targets
52+
#
53+
message( STATUS "Serialbox exported targets:")
54+
foreach( target ${ARGV} )
55+
if( TARGET ${target} )
56+
message( STATUS " ${target}" )
57+
else()
58+
list( APPEND _unavailable_targets ${target} )
59+
endif()
60+
endforeach()
61+
if( _unavailable_targets )
62+
message( STATUS "Serialbox unavailable targets:")
63+
foreach( target ${_unavailable_targets} )
64+
message( STATUS " ${target}" )
65+
endforeach()
66+
endif()
67+
endfunction()
68+
69+
function( serialbox_alias_targets )
70+
#
71+
# serialbox_alias_targets( alias target_shared target_static align )
72+
#
73+
# Creates ALIAS target for given targets. Prefer target_shared if availabe
74+
#
75+
set( _alias ${ARGV0} )
76+
set( _target_shared ${ARGV1} )
77+
set( _target_static ${ARGV2} )
78+
set( _align ${ARGV3} )
79+
string( REPLACE "Serialbox::" "" _target_shared_build "${_target_shared}" )
80+
string( REPLACE "Serialbox::" "" _target_static_build "${_target_static}" )
81+
if( TARGET ${_target_shared_build} )
82+
message( STATUS " ${_alias} ${_align}--> Serialbox::${_target_shared_build}" )
83+
if( NOT TARGET ${_alias} )
84+
add_library( ${_alias} ALIAS ${_target_shared_build} )
85+
endif()
86+
elseif( TARGET ${_target_shared} AND CMAKE_VERSION GREATER 3.11 )
87+
message( STATUS " ${_alias} ${_align}--> ${_target_shared}" )
88+
set_target_properties( ${_target_shared} PROPERTIES IMPORTED_GLOBAL TRUE) # required for aliasing imports
89+
if( NOT TARGET ${_alias} )
90+
add_library( ${_alias} ALIAS ${_target_shared} )
91+
endif()
92+
elseif( TARGET ${_target_static_build} )
93+
message( STATUS " ${_alias} ${_align}--> Serialbox::${_target_static_build}" )
94+
if( NOT TARGET ${_alias} )
95+
add_library( ${_alias} ALIAS ${_target_static_build} )
96+
endif()
97+
elseif( TARGET ${_target_static} AND CMAKE_VERSION GREATER 3.11 )
98+
message( STATUS " ${_alias} ${_align}--> ${_target_static}" )
99+
set_target_properties( ${_target_static} PROPERTIES IMPORTED_GLOBAL TRUE) # required for aliasing imports
100+
if( NOT TARGET ${_alias} )
101+
add_library( ${_alias} ALIAS ${_target_static} )
102+
endif()
103+
endif()
104+
endfunction()
105+
43106
#===---------------------------------------------------------------------------------------------===
44107
# Find Serialbox libraries
45108
#====--------------------------------------------------------------------------------------------===
46109

47110
# Import library targets
48-
include("${CMAKE_CURRENT_LIST_DIR}/SerialboxTargets.cmake")
111+
if( NOT @PROJECT_NAME@_TARGETS_EXPORTED )
112+
include("${CMAKE_CURRENT_LIST_DIR}/SerialboxTargets.cmake")
113+
set( ${PROJECT_NAME}_TARGETS_EXPORTED TRUE )
114+
endif()
49115

50116
set(SERIALBOX_HAS_SHARED_LIBRARY FALSE)
51117
if(TARGET Serialbox::SerialboxShared)
@@ -60,37 +126,22 @@ if(TARGET Serialbox::SerialboxFortranStatic)
60126
set(SERIALBOX_HAS_FORTRAN TRUE)
61127
endif()
62128

63-
# Report findings
64-
message(STATUS "Found Serialbox version: ${SERIALBOX_VERSION}")
129+
### Report findings
65130

66-
get_property(_static_lib TARGET Serialbox::SerialboxStatic PROPERTY LOCATION)
67-
message(STATUS " Static serialbox: ${_static_lib}")
131+
message(STATUS "Found Serialbox (version: ${SERIALBOX_VERSION}) in ${PACKAGE_PREFIX_DIR}" )
68132

69-
if(SERIALBOX_HAS_SHARED_LIBRARY)
70-
get_property(_shared_lib TARGET Serialbox::SerialboxShared PROPERTY LOCATION)
71-
message(STATUS " Shared serialbox: ${_shared_lib}")
72-
endif()
73-
74-
if(SERIALBOX_HAS_C)
75-
get_property(_static_lib TARGET Serialbox::SerialboxCStatic PROPERTY LOCATION)
76-
message(STATUS " Static serialbox-c: ${_static_lib}")
77-
78-
if(SERIALBOX_HAS_SHARED_LIBRARY)
79-
get_property(_shared_lib TARGET Serialbox::SerialboxCShared PROPERTY LOCATION)
80-
message(STATUS " Shared serialbox-c: ${_shared_lib}")
81-
endif()
82-
endif(SERIALBOX_HAS_C)
83-
84-
if(SERIALBOX_HAS_FORTRAN)
85-
get_property(_static_lib TARGET Serialbox::SerialboxFortranStatic PROPERTY LOCATION)
86-
message(STATUS " Static serialbox FORTRAN: ${_static_lib}")
133+
serialbox_print_targets(
134+
Serialbox::SerialboxCStatic
135+
Serialbox::SerialboxCShared
136+
Serialbox::SerialboxFortranStatic
137+
Serialbox::SerialboxFortranShared
138+
)
87139

88-
if(SERIALBOX_HAS_SHARED_LIBRARY)
89-
get_property(_shared_lib TARGET Serialbox::SerialboxFortranShared PROPERTY LOCATION)
90-
message(STATUS " Shared serialbox FORTRAN: ${_shared_lib}")
91-
endif()
140+
### Create ALIAS targets
92141

93-
endif(SERIALBOX_HAS_FORTRAN)
142+
message( STATUS "Serialbox ALIAS targets:" )
143+
serialbox_alias_targets( Serialbox::Serialbox_C Serialbox::SerialboxCShared Serialbox::SerialboxCStatic " " )
144+
serialbox_alias_targets( Serialbox::Serialbox_Fortran Serialbox::SerialboxFortranShared Serialbox::SerialboxFortranStatic )
94145

95146
#===---------------------------------------------------------------------------------------------===
96147
# Find external libraries

cmake/SerialboxTooling.cmake

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#
1919
# SOURCES - Sources to preprocess
2020
# OUTPUT_DIR - Output directory of the the source files. If nothing is specified
21-
# `${CMAKE_BINARY_DIR}/pp` is used.
21+
# `${PROJECT_BINARY_DIR}/pp` is used.
2222
#
2323

2424
include(CMakeParseArguments)
@@ -47,8 +47,8 @@ function(serialbox_run_pp_ser)
4747
endif()
4848

4949
if(NOT(output_dir))
50-
# If output_dir is not set, we place them in ${CMAKE_BINARY_DIR}/pp
51-
set(output_dir ${CMAKE_BINARY_DIR}/pp)
50+
# If output_dir is not set, we place them in ${PROJECT_BINARY_DIR}/pp
51+
set(output_dir ${PROJECT_BINARY_DIR}/pp)
5252
endif()
5353

5454
# Create directory if it does not exist

cmake/modules/FindNetCDF.cmake

-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ if(NetCDF_FOUND)
4545
target_include_directories(NETCDF_TARGET INTERFACE ${NETCDF_INCLUDES})
4646
target_compile_definitions(NETCDF_TARGET INTERFACE "SERIALBOX_HAS_NETCDF")
4747
target_link_libraries(NETCDF_TARGET INTERFACE ${NETCDF_LIBRARIES})
48-
install(TARGETS NETCDF_TARGET
49-
EXPORT SerialboxTargets)
5048
else()
5149
# If the package was required we abort the process
5250
if(${NetCDF_FIND_REQUIRED})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
##===------------------------------------------------------------------------------*- CMake -*-===##
2+
##
3+
## S E R I A L B O X
4+
##
5+
## This file is distributed under terms of BSD license.
6+
## See LICENSE.txt for more information.
7+
##
8+
##===------------------------------------------------------------------------------------------===##
9+
10+
#
11+
# serialbox_install_targets( TARGETS [ target1 [ target2 ... ] )
12+
#
13+
# Arguments:
14+
#
15+
# TARGETS [target1 [ target2 ...] ] Targets to be exported and installed.
16+
#
17+
function( serialbox_install_targets )
18+
cmake_parse_arguments( serialbox_install_targets "" "" "TARGETS" ${ARGN})
19+
20+
set(target_list ${serialbox_install_targets_TARGETS})
21+
22+
foreach( target ${target_list} )
23+
if( TARGET ${target} )
24+
install(TARGETS ${target}
25+
EXPORT SerialboxTargets
26+
LIBRARY DESTINATION lib
27+
ARCHIVE DESTINATION lib
28+
)
29+
export( TARGETS ${target}
30+
APPEND FILE ${PROJECT_BINARY_DIR}/SerialboxTargets.cmake
31+
NAMESPACE Serialbox::
32+
)
33+
add_library( Serialbox::${target} ALIAS ${target} )
34+
endif()
35+
endforeach()
36+
endfunction()

0 commit comments

Comments
 (0)