File: cpp_bindgen.cmake.in

package info (click to toggle)
gridtools 2.0.0-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 21,728 kB
  • sloc: cpp: 45,263; python: 9,383; javascript: 8,445; ansic: 2,564; sh: 509; f90: 370; makefile: 216
file content (211 lines) | stat: -rw-r--r-- 11,400 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# Create a library with c- and Fortran-bindings
#
# Usage of this module:
#
#  bindgen_add_library(<library-name> SOURCES <sources>[...] [FORTRAN_OUTPUT_DIR fortran_dir] [C_OUTPUT_DIR c_dir] [FORTRAN_MODULE_NAME name])
#
#  Arguments:
#   SOURCES: sources of the library
#   FORTRAN_OUTPUT_DIR: destination for generated Fortran files (default: ${CMAKE_CURRENT_LIST_DIR})
#   C_OUTPUT_DIR: destination for generated C files (default: ${CMAKE_CURRENT_LIST_DIR})
#   FORTRAN_MODULE_NAME: name for the Fortran module (default: <library-name>)
#
# Variables used by this module:
#
#  GT_ENABLE_BINDINGS_GENERATION:
#  If GT_ENABLE_BINDINGS_GENERATION=OFF, bindings will not be generated, but expected to be provided,
#  as part of the user source code, e.g. by updating bindings with the bindings generator during development.
#  If GT_ENABLE_BINDINGS_GENERATION is not defined already it will be made available after including this file.
#
# In the default case (GT_ENABLE_BINDINGS_GENERATION=ON), the bindings files are generated in the directory
# where the CMakeLists.txt with the call to bindgen_add_library() is located.
#
# Targets generated by bindgen_add_library(<library-name> ...):
#  - <library_name> library build from <Sources...> without bindings (ususally this target is not used)
#  - <library_name>_declarations will run the generator for this library
#  - <library_name>_c the C-bindings with <library_name> linked to it
#  - <library_name>_fortran the Fortran-bindings with <library_name> linked to it

include_guard(GLOBAL)

option(GT_ENABLE_BINDINGS_GENERATION "If turned off, bindings will not be generated." ON)

# in some conditions the include guard above doesn't work
if( NOT TARGET cpp_bindgen_interface )

# variables are unset after use for scoping, they need to be redefined in the macros
set(__CPP_BINDGEN_SOURCE_DIR @__CPP_BINDGEN_SOURCE_DIR@)
set(__CPP_BINDGEN_INCLUDE_DIR @__CPP_BINDGEN_INCLUDE_DIR@)

add_library(cpp_bindgen_interface INTERFACE)
target_include_directories(cpp_bindgen_interface INTERFACE $<BUILD_INTERFACE:${__CPP_BINDGEN_INCLUDE_DIR}> $<INSTALL_INTERFACE:include>)
target_compile_features(cpp_bindgen_interface INTERFACE cxx_std_11)
target_compile_definitions(cpp_bindgen_interface INTERFACE BOOST_PP_VARIADICS=1)
if(CPP_BINDGEN_GT_LEGACY)
    target_compile_definitions(cpp_bindgen_interface INTERFACE CPP_BINDGEN_GT_LEGACY)
endif()

add_library(cpp_bindgen_generator STATIC ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/generator.cpp)
# PUBLIC to make export.hpp available in the sources passed to add_bindings_library()
target_link_libraries(cpp_bindgen_generator PUBLIC Boost::boost)
target_link_libraries(cpp_bindgen_generator PUBLIC cpp_bindgen_interface)

add_library(cpp_bindgen_handle STATIC ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/handle.cpp)
target_link_libraries(cpp_bindgen_handle PUBLIC cpp_bindgen_interface)

unset(__CPP_BINDGEN_SOURCE_DIR)
unset(__CPP_BINDGEN_INCLUDE_DIR)

endif()

# bindgen_enable_fortran_library()
#
# Create a target to compile the generated Fortran module.
# In the default case, when Fortran is enabled on the call to bindgen_add_library(), this target is automatically created.
# In case when the Fortran language was not enabled, we cannot create a library (add_library()) with Fortran files.
# However if the user wants to use the target at a later stage, e.g. in testing (with Fortran enabled), the target can
# be created by a call to bindgen_enable_fortran_library().
function(bindgen_enable_fortran_library target_name)
    set(__CPP_BINDGEN_SOURCE_DIR @__CPP_BINDGEN_SOURCE_DIR@)
    set(__CPP_BINDGEN_CMAKE_DIR @__CPP_BINDGEN_CMAKE_DIR@)

    if(CMAKE_Fortran_COMPILER_LOADED)
        if(NOT TARGET cpp_bindgen_fortran_handle)
            add_library(cpp_bindgen_fortran_handle ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/array_descriptor.f90 ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/handle.f90)
            # the following variable is used to install the .mod files in install_cpp_bindgen_targets() and
            # therefore needs to be available project-wide
            set(CPP_BINDGEN_Fortran_MODULES_DIRECTORY ${CMAKE_BINARY_DIR}/cpp_bindgen_modules
                CACHE INTERNAL "Directory for Fortran modules of cpp_bindgen")
            set_target_properties(cpp_bindgen_fortran_handle PROPERTIES Fortran_MODULE_DIRECTORY ${CPP_BINDGEN_Fortran_MODULES_DIRECTORY})
            target_link_libraries(cpp_bindgen_fortran_handle PUBLIC cpp_bindgen_handle)
            target_include_directories(cpp_bindgen_fortran_handle INTERFACE $<BUILD_INTERFACE:${CPP_BINDGEN_Fortran_MODULES_DIRECTORY}> $<INSTALL_INTERFACE:include/>)
            include(${__CPP_BINDGEN_CMAKE_DIR}/cpp_bindgen_fortran_helpers.cmake)
            bindgen_enable_fortran_preprocessing_on_target(cpp_bindgen_fortran_handle)
        endif()
        if(NOT TARGET ${target_name}_fortran)
            set_source_files_properties(GT_${${target_name}_fortran_bindings_path} PROPERTIES GENERATED TRUE)
            add_library(${target_name}_fortran EXCLUDE_FROM_ALL ${CPP_BINDGEN_${target_name}_fortran_bindings_path})
            target_link_libraries(${target_name}_fortran PUBLIC ${target_name})
            target_link_libraries(${target_name}_fortran PUBLIC cpp_bindgen_fortran_handle)
            # location of .mod file (we cannot know the INSTALL_INTERFACE directory here)
            target_include_directories(${target_name}_fortran PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
            add_dependencies(${target_name}_fortran ${target_name}_declarations)
        endif()
    elseif(NOT ${ARGN}) # internal: the second (optional) parameter can be used to surpress this fatal error
        message(FATAL_ERROR "Please enable_language(Fortran) to compile the Fortran bindings.")
    endif()
endfunction()

function(bindgen_add_library target_name)
    set(options)
    set(one_value_args FORTRAN_OUTPUT_DIR C_OUTPUT_DIR FORTRAN_MODULE_NAME)
    set(multi_value_args SOURCES)
    cmake_parse_arguments(ARG "${options}" "${one_value_args};" "${multi_value_args}" ${ARGN})

    set(__CPP_BINDGEN_SOURCE_DIR @__CPP_BINDGEN_SOURCE_DIR@)
    set(__CPP_BINDGEN_CMAKE_DIR @__CPP_BINDGEN_CMAKE_DIR@)

    if(NOT DEFINED ARG_FORTRAN_MODULE_NAME)
        set(ARG_FORTRAN_MODULE_NAME ${target_name}) # default value
    endif()

    if(ARG_C_OUTPUT_DIR)
        set(bindings_c_decl_filename ${ARG_C_OUTPUT_DIR}/${target_name}.h)
    else()
        set(bindings_c_decl_filename ${CMAKE_CURRENT_LIST_DIR}/${target_name}.h) # default value
    endif()
    if(ARG_FORTRAN_OUTPUT_DIR)
        set(bindings_fortran_decl_filename ${ARG_FORTRAN_OUTPUT_DIR}/${target_name}.f90)
    else()
        set(bindings_fortran_decl_filename ${CMAKE_CURRENT_LIST_DIR}/${target_name}.f90) # default value
    endif()

    add_library(${target_name} STATIC ${ARG_SOURCES})
    target_link_libraries(${target_name} PRIVATE cpp_bindgen_generator)

    if(GT_ENABLE_BINDINGS_GENERATION)
        # generator
        add_executable(${target_name}_decl_generator
            ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/generator_main.cpp)
        set_target_properties(${target_name}_decl_generator PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/decl_generator")
        target_link_libraries(${target_name}_decl_generator cpp_bindgen_generator)

        if (${APPLE})
            target_link_libraries(${target_name}_decl_generator
                -Wl,-force_load ${target_name})
        else()
            target_link_libraries(${target_name}_decl_generator
                -Xlinker --whole-archive ${target_name}
                -Xlinker --no-whole-archive)
        endif()

        add_custom_target(${target_name}_declarations
            ALL
            COMMAND ${CMAKE_COMMAND}
                -DGENERATOR=${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/decl_generator/${target_name}_decl_generator
                -DBINDINGS_C_DECL_FILENAME=${bindings_c_decl_filename}
                -DBINDINGS_FORTRAN_DECL_FILENAME=${bindings_fortran_decl_filename}
                -DFORTRAN_MODULE_NAME=${ARG_FORTRAN_MODULE_NAME}
                -P ${__CPP_BINDGEN_CMAKE_DIR}/cpp_bindgen_generate.cmake
            BYPRODUCTS ${bindings_c_decl_filename} ${bindings_fortran_decl_filename}
            DEPENDS $<TARGET_FILE:${target_name}_decl_generator>)
    else()
        if(EXISTS ${bindings_c_decl_filename} AND (EXISTS ${bindings_fortran_decl_filename}))
            add_custom_target(${target_name}_declarations) # noop, the dependencies are satisfied if the files exist
        else()
            message(FATAL_ERROR "Cross-compilation for bindings is enabled: no bindings will be generated, but "
                "${bindings_c_decl_filename} and/or "
                "${bindings_fortran_decl_filename} "
                "are missing. Generate the bindings and consider making them part of your repository.")
        endif()
    endif()

    # bindings c library
    add_library(${target_name}_c INTERFACE)
    target_link_libraries(${target_name}_c INTERFACE ${target_name})
    target_link_libraries(${target_name}_c INTERFACE cpp_bindgen_handle)
    target_link_libraries(${target_name}_c INTERFACE cpp_bindgen_interface)

    add_dependencies(${target_name}_c ${target_name}_declarations)

    # bindings Fortran library
    # Export the name of the generated file. The variable needs to exist in the whole cmake!
    # Reason: see description of bindgen_enable_fortran_library().
    set(CPP_BINDGEN_${target_name}_fortran_bindings_path ${bindings_fortran_decl_filename}
        CACHE INTERNAL "Path to the generated Fortran file for ${target_name}")
    bindgen_enable_fortran_library(${target_name} TRUE)
endfunction()

# install_cpp_bindgen_targets()
#
# cpp_bindgen contains some generic files which are being built on first use of bindgen_add_library().
# These libraries can be installed with this function which takes the same arguments
# as install(TARGETS targets... [other-options]), except
# - you must not specify "TARGETS targets..." but only all [other-options].
# - if Fortran is enabled Fortran_MODULE_DESTINATION needs to be set to the location where Fortran modules
#   should be installed to (e.g. include)
function(install_cpp_bindgen_targets)
    set(options)
    set(oneValueArgs Fortran_MODULE_DESTINATION)
    set(multiValueArgs TARGETS)
    cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    if(ARG_TARGETS)
        message(FATAL_ERROR "install_cpp_bindgen_targets() must not be called with TARGETS argument.")
    endif()

    if(TARGET cpp_bindgen_fortran_handle) # Fortran is enabled, we need to install a mod file
        if(ARG_Fortran_MODULE_DESTINATION)
            install(DIRECTORY ${CPP_BINDGEN_Fortran_MODULES_DIRECTORY}/ DESTINATION ${ARG_Fortran_MODULE_DESTINATION})
        else()
            message(WARNING "Fortran_MODULE_DESTINATION was NOT specified, but Fortran was enabled. Modules files for
                             cpp_bindgen won't be installed.")
        endif()
        install(TARGETS cpp_bindgen_fortran_handle ${ARG_UNPARSED_ARGUMENTS})
    else()
        if(ARG_Fortran_MODULE_DESTINATION)
            message(WARNING "Fortran_MODULE_DESTINATION was specified, but Fortran is disabled.")
        endif()
    endif()
    install(TARGETS cpp_bindgen_generator cpp_bindgen_handle cpp_bindgen_interface ${ARG_UNPARSED_ARGUMENTS})
endfunction()