├── .clang-format ├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── LICENSE ├── LICENSE_HEADER ├── README.md ├── cmake ├── bindings.cmake ├── cpp_bindgen-config.cmake.in ├── cpp_bindgen.cmake.in ├── cpp_bindgen_fortran_helpers.cmake ├── cpp_bindgen_generate.cmake ├── detect_features.cmake └── export.cmake ├── example ├── simple │ ├── .gitignore │ ├── CMakeLists.txt │ ├── driver.f90 │ └── simple.cpp └── simple_fetch_content │ ├── .gitignore │ ├── CMakeLists.txt │ ├── driver.f90 │ └── simple.cpp ├── include └── cpp_bindgen │ ├── array_descriptor.h │ ├── common │ ├── any_moveable.hpp │ ├── disjunction.hpp │ ├── for_each.hpp │ ├── function_traits.hpp │ ├── make_indices.hpp │ └── type_traits.hpp │ ├── export.hpp │ ├── fortran_array_view.hpp │ ├── fortran_string_view.hpp │ ├── function_wrapper.hpp │ ├── generator.hpp │ ├── handle.h │ ├── handle_impl.hpp │ └── string_descriptor.h ├── jenkins └── build.sh ├── src └── cpp_bindgen │ ├── array_descriptor.f90 │ ├── generator.cpp │ ├── generator_main.cpp │ ├── handle.cpp │ ├── handle.f90 │ └── string_descriptor.f90 ├── tests ├── CMakeLists.txt ├── regression │ ├── CMakeLists.txt │ ├── array │ │ ├── CMakeLists.txt │ │ ├── bindgen_regression_array.f90 │ │ ├── bindgen_regression_array.h │ │ ├── bindgen_regression_array_cu.f90 │ │ ├── bindgen_regression_array_cu.h │ │ ├── driver.f90 │ │ ├── driver_cu.f90 │ │ ├── implementation.cpp │ │ └── implementation.cu │ ├── simple │ │ ├── CMakeLists.txt │ │ ├── bindgen_regression_simple.f90 │ │ ├── bindgen_regression_simple.h │ │ ├── driver.c │ │ ├── driver.f90 │ │ └── simple.cpp │ └── string │ │ ├── CMakeLists.txt │ │ ├── driver.f90 │ │ └── implementation.cpp └── unit_tests │ ├── CMakeLists.txt │ ├── common │ ├── CMakeLists.txt │ ├── test_any_moveable.cpp │ ├── test_any_moveable.cu │ ├── test_make_indices.cpp │ └── test_make_indices.cu │ ├── test_export.cpp │ ├── test_export.cu │ ├── test_fortran_array_view.cpp │ ├── test_fortran_array_view.cu │ ├── test_function_traits.cpp │ ├── test_function_traits.cu │ ├── test_function_wrapper.cpp │ ├── test_function_wrapper.cu │ ├── test_generator.cpp │ └── test_generator.cu └── version.txt /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | ConstructorInitializerIndentWidth: 4 6 | #AlignEscapedNewlinesLeft: false 7 | AlignTrailingComments: true 8 | AllowAllParametersOfDeclarationOnNextLine: true 9 | AllowShortBlocksOnASingleLine: false 10 | AllowShortIfStatementsOnASingleLine: false 11 | AllowShortLoopsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: All 13 | AlwaysBreakTemplateDeclarations: true 14 | AlwaysBreakBeforeMultilineStrings: false 15 | BreakBeforeBinaryOperators: false 16 | BreakBeforeTernaryOperators: true 17 | BreakConstructorInitializersBeforeComma: false 18 | BinPackParameters: false 19 | BinPackArguments: false 20 | ColumnLimit: 120 21 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 22 | DerivePointerAlignment: false 23 | ExperimentalAutoDetectBinPacking: false 24 | IndentCaseLabels: false 25 | IndentWrappedFunctionNames: false 26 | IndentFunctionDeclarationAfterType: false 27 | MaxEmptyLinesToKeep: 1 28 | KeepEmptyLinesAtTheStartOfBlocks: true 29 | NamespaceIndentation: All 30 | ObjCSpaceAfterProperty: false 31 | ObjCSpaceBeforeProtocolList: true 32 | PenaltyBreakBeforeFirstCallParameter: 19 33 | PenaltyBreakComment: 300 34 | PenaltyBreakString: 1000 35 | PenaltyBreakFirstLessLess: 120 36 | PenaltyExcessCharacter: 1000000 37 | PenaltyReturnTypeOnItsOwnLine: 60 38 | PointerAlignment: Right 39 | SpacesBeforeTrailingComments: 1 40 | Cpp11BracedListStyle: true 41 | Standard: Cpp11 42 | IndentWidth: 4 43 | TabWidth: 8 44 | UseTab: Never 45 | BreakBeforeBraces: Attach 46 | SpacesInParentheses: false 47 | SpacesInAngles: false 48 | SpaceInEmptyParentheses: false 49 | SpacesInCStyleCastParentheses: false 50 | SpacesInContainerLiterals: true 51 | SpaceBeforeAssignmentOperators: true 52 | ContinuationIndentWidth: 4 53 | CommentPragmas: '*' 54 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 55 | SpaceBeforeParens: ControlStatements 56 | DisableFormat: false 57 | AlignAfterOpenBracket: false 58 | AlignEscapedNewlinesLeft: true 59 | ... 60 | 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDEs 2 | *.project 3 | *.cproject 4 | *.settings 5 | .idea 6 | .pydevproject 7 | .clangd 8 | 9 | # Build folders 10 | build*/ 11 | install*/ 12 | 13 | # Prerequisites 14 | *.d 15 | 16 | # Compiled Object files 17 | *.slo 18 | *.lo 19 | *.o 20 | *.obj 21 | 22 | # Precompiled Headers 23 | *.gch 24 | *.pch 25 | 26 | # Compiled Dynamic libraries 27 | *.so 28 | *.dylib 29 | *.dll 30 | 31 | # Fortran module files 32 | *.mod 33 | *.smod 34 | 35 | # Compiled Static libraries 36 | *.lai 37 | *.la 38 | *.a 39 | *.lib 40 | 41 | # Executables 42 | *.exe 43 | *.out 44 | *.app 45 | 46 | # Logs 47 | *.log 48 | 49 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Anton Afanasyev (anstaf), ETH Zurich (CSCS) 2 | Lukas Mosimann (lukasm91), ETH Zurich (CSCS), NVIDIA 3 | Hannes Vogt (havogt), ETH Zurich (CSCS) 4 | Mauro Bianco (mbianco), ETH Zurich (CSCS) 5 | Felix Thaler (fthaler), ETH Zurich (CSCS) 6 | Willem Deconinck (wdeconinck), ECMWF 7 | 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14.5) 2 | # when increasing the minium required version, consider updating in examples as well 3 | 4 | file(STRINGS "version.txt" __CPP_BINDGEN_VERSION) 5 | project(cpp_bindgen VERSION ${__CPP_BINDGEN_VERSION} LANGUAGES CXX) 6 | unset(__CPP_BINDGEN_VERSION) 7 | 8 | # Switch default of NO_PACKAGE_REGISTRY. TODO: Can be removed with CMake 3.15+ 9 | set(CMAKE_EXPORT_NO_PACKAGE_REGISTRY ON CACHE BOOL "") 10 | mark_as_advanced(CMAKE_EXPORT_NO_PACKAGE_REGISTRY) 11 | 12 | set(REQUIRED_BOOST_VERSION 1.58) 13 | find_package(Boost ${REQUIRED_BOOST_VERSION} REQUIRED) 14 | 15 | # if used via FetchContent/add_subdirectory() we need to make the add_bindings_library() available here 16 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/bindings.cmake) 17 | 18 | if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) 19 | include(CTest) 20 | if(BUILD_TESTING) 21 | add_subdirectory(tests) 22 | endif() 23 | endif() 24 | 25 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/export.cmake) 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GridTools 2 | 3 | Copyright (c) 2014-2019, ETH Zurich 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | 3. Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | For information: https://eth-cscs.github.io/gridtools/ 34 | -------------------------------------------------------------------------------- /LICENSE_HEADER: -------------------------------------------------------------------------------- 1 | /* 2 | * GridTools 3 | * 4 | * Copyright (c) 2014-2019, ETH Zurich 5 | * All rights reserved. 6 | * 7 | * Please, refer to the LICENSE file in the root directory. 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | ![License: BSD][BSD.License] 4 | 5 | **cpp_bindgen** is a library to generate C and Fortran bindings for C++ functions from C++. It is part of the GridTools framework, a set of libraries and utilities to develop performance portable applications in the area of weather and climate. 6 | 7 | Currently the documentation of **cpp_bindgen** is part of the [GridTools documentation](https://gridtools.github.io/gridtools/latest/user_manual/user_manual.html#interfacing-to-other-programming-languages). For simple examples, see the examples folder of this repository. More advanced examples are available in https://github.com/GridTools/gridtools. 8 | 9 | ### Installation instructions 10 | 11 | You can easily integrate **cpp_bindgen** in your CMake project with the following snippet which makes the function `bindgen_add_library()` available. 12 | 13 | ```cmake 14 | include(FetchContent) 15 | FetchContent_Declare( 16 | cpp_bindgen 17 | GIT_REPOSITORY https://github.com/GridTools/cpp_bindgen.git 18 | GIT_TAG master # consider replacing master by a tagged version 19 | ) 20 | FetchContent_MakeAvailable(cpp_bindgen) 21 | ``` 22 | 23 | See also https://github.com/GridTools/cpp_bindgen/tree/master/example/simple_fetch_content. 24 | 25 | ##### Requirements 26 | 27 | - Boost (1.65.1 or later) 28 | - CMake (3.14.5 or later) 29 | 30 | ##### Known issues 31 | 32 | - The library doesn't work with NVCC <= 9.2 using Clang as host compiler, if c++14 is enabled, due to a bug in NVCC. 33 | 34 | ### Continuous integration 35 | 36 | We use Jenkins to test this library. To test your PR use 37 | - `launch jenkins` to execute the tests which are part of this repository. 38 | - `launch gridtools` to run the changes against the GridTools integration tests from the GridTools/gridtools repository. 39 | 40 | ### Contributing 41 | 42 | Contributions to the GridTools framework are welcome. Please open an issue for any bugs that you encounter or provide a fix or enhancement as a PR. External contributions to GridTools require us a signed copy of a copyright release form to ETH Zurich. We will contact you on the PR. 43 | 44 | [BSD.License]: https://img.shields.io/badge/License-BSD--3--Clause-blue.svg 45 | -------------------------------------------------------------------------------- /cmake/bindings.cmake: -------------------------------------------------------------------------------- 1 | function(generate_gt_bindings) 2 | set(__CPP_BINDGEN_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 3 | set(__CPP_BINDGEN_CMAKE_DIR ${PROJECT_SOURCE_DIR}/cmake) 4 | set(__CPP_BINDGEN_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) 5 | configure_file(${PROJECT_SOURCE_DIR}/cmake/cpp_bindgen.cmake.in 6 | ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/bindings_for_build/cpp_bindgen.cmake 7 | @ONLY) 8 | endfunction() 9 | 10 | generate_gt_bindings() 11 | include(${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/bindings_for_build/cpp_bindgen.cmake) 12 | -------------------------------------------------------------------------------- /cmake/cpp_bindgen-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | get_filename_component(cpp_bindgen_CONFIG_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 4 | 5 | message(STATUS "GridTools cpp_bindgen version @PROJECT_VERSION@ found at ${cpp_bindgen_CONFIG_CMAKE_DIR}") 6 | 7 | include(CMakeFindDependencyMacro) 8 | find_dependency(Boost @REQUIRED_BOOST_VERSION@) 9 | 10 | set_and_check(cpp_bindgen_CMAKE_DIR @PACKAGE_cpp_bindgen_CMAKE_DIR@) 11 | set_and_check(cpp_bindgen_SOURCE_DIR @PACKAGE_cpp_bindgen_SOURCE_DIR@) 12 | set_and_check(cpp_bindgen_INCLUDE_DIR @PACKAGE_cpp_bindgen_INCLUDE_DIR@) 13 | 14 | include(${cpp_bindgen_CMAKE_DIR}/cpp_bindgen.cmake) 15 | -------------------------------------------------------------------------------- /cmake/cpp_bindgen.cmake.in: -------------------------------------------------------------------------------- 1 | # Create a library with c- and Fortran-bindings 2 | # 3 | # Usage of this module: 4 | # 5 | # bindgen_add_library( SOURCES [...] [FORTRAN_OUTPUT_DIR fortran_dir] [C_OUTPUT_DIR c_dir] [FORTRAN_MODULE_NAME name]) 6 | # 7 | # Arguments: 8 | # SOURCES: sources of the library 9 | # FORTRAN_OUTPUT_DIR: destination for generated Fortran files (default: ${CMAKE_CURRENT_LIST_DIR}) 10 | # C_OUTPUT_DIR: destination for generated C files (default: ${CMAKE_CURRENT_LIST_DIR}) 11 | # FORTRAN_MODULE_NAME: name for the Fortran module (default: ) 12 | # 13 | # Variables used by this module: 14 | # 15 | # GT_ENABLE_BINDINGS_GENERATION: 16 | # If GT_ENABLE_BINDINGS_GENERATION=OFF, bindings will not be generated, but expected to be provided, 17 | # as part of the user source code, e.g. by updating bindings with the bindings generator during development. 18 | # If GT_ENABLE_BINDINGS_GENERATION is not defined already it will be made available after including this file. 19 | # 20 | # In the default case (GT_ENABLE_BINDINGS_GENERATION=ON), the bindings files are generated in the directory 21 | # where the CMakeLists.txt with the call to bindgen_add_library() is located. 22 | # 23 | # Targets generated by bindgen_add_library( ...): 24 | # - library build from without bindings (ususally this target is not used) 25 | # - _declarations will run the generator for this library 26 | # - _c the C-bindings with linked to it 27 | # - _fortran the Fortran-bindings with linked to it 28 | 29 | include_guard(GLOBAL) 30 | 31 | option(GT_ENABLE_BINDINGS_GENERATION "If turned off, bindings will not be generated." ON) 32 | 33 | # in some conditions the include guard above doesn't work 34 | if( NOT TARGET cpp_bindgen_interface ) 35 | 36 | # variables are unset after use for scoping, they need to be redefined in the macros 37 | set(__CPP_BINDGEN_SOURCE_DIR @__CPP_BINDGEN_SOURCE_DIR@) 38 | set(__CPP_BINDGEN_INCLUDE_DIR @__CPP_BINDGEN_INCLUDE_DIR@) 39 | 40 | add_library(cpp_bindgen_interface INTERFACE) 41 | target_include_directories(cpp_bindgen_interface INTERFACE $ $) 42 | target_compile_features(cpp_bindgen_interface INTERFACE cxx_std_11) 43 | target_compile_definitions(cpp_bindgen_interface INTERFACE BOOST_PP_VARIADICS=1) 44 | 45 | add_library(cpp_bindgen_generator STATIC ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/generator.cpp) 46 | # PUBLIC to make export.hpp available in the sources passed to add_bindings_library() 47 | target_link_libraries(cpp_bindgen_generator PUBLIC Boost::boost) 48 | target_link_libraries(cpp_bindgen_generator PUBLIC cpp_bindgen_interface) 49 | 50 | add_library(cpp_bindgen_handle STATIC ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/handle.cpp) 51 | target_link_libraries(cpp_bindgen_handle PUBLIC cpp_bindgen_interface) 52 | 53 | unset(__CPP_BINDGEN_SOURCE_DIR) 54 | unset(__CPP_BINDGEN_INCLUDE_DIR) 55 | 56 | endif() 57 | 58 | # bindgen_enable_fortran_library() 59 | # 60 | # Create a target to compile the generated Fortran module. 61 | # In the default case, when Fortran is enabled on the call to bindgen_add_library(), this target is automatically created. 62 | # In case when the Fortran language was not enabled, we cannot create a library (add_library()) with Fortran files. 63 | # However if the user wants to use the target at a later stage, e.g. in testing (with Fortran enabled), the target can 64 | # be created by a call to bindgen_enable_fortran_library(). 65 | function(bindgen_enable_fortran_library target_name) 66 | set(__CPP_BINDGEN_SOURCE_DIR @__CPP_BINDGEN_SOURCE_DIR@) 67 | set(__CPP_BINDGEN_CMAKE_DIR @__CPP_BINDGEN_CMAKE_DIR@) 68 | 69 | if(CMAKE_Fortran_COMPILER_LOADED) 70 | if(NOT TARGET cpp_bindgen_fortran_handle) 71 | add_library( 72 | cpp_bindgen_fortran_handle 73 | ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/array_descriptor.f90 74 | ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/string_descriptor.f90 75 | ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/handle.f90) 76 | # the following variable is used to install the .mod files in install_cpp_bindgen_targets() and 77 | # therefore needs to be available project-wide 78 | set(CPP_BINDGEN_Fortran_MODULES_DIRECTORY ${CMAKE_BINARY_DIR}/cpp_bindgen_modules 79 | CACHE INTERNAL "Directory for Fortran modules of cpp_bindgen") 80 | set_target_properties(cpp_bindgen_fortran_handle PROPERTIES Fortran_MODULE_DIRECTORY ${CPP_BINDGEN_Fortran_MODULES_DIRECTORY}) 81 | target_link_libraries(cpp_bindgen_fortran_handle PUBLIC cpp_bindgen_handle) 82 | target_include_directories(cpp_bindgen_fortran_handle INTERFACE $ $) 83 | include(${__CPP_BINDGEN_CMAKE_DIR}/cpp_bindgen_fortran_helpers.cmake) 84 | bindgen_enable_fortran_preprocessing_on_target(cpp_bindgen_fortran_handle) 85 | endif() 86 | if(NOT TARGET ${target_name}_fortran) 87 | set_source_files_properties(GT_${${target_name}_fortran_bindings_path} PROPERTIES GENERATED TRUE) 88 | add_library(${target_name}_fortran EXCLUDE_FROM_ALL ${CPP_BINDGEN_${target_name}_fortran_bindings_path}) 89 | target_link_libraries(${target_name}_fortran PUBLIC ${target_name}) 90 | target_link_libraries(${target_name}_fortran PUBLIC cpp_bindgen_fortran_handle) 91 | # location of .mod file (we cannot know the INSTALL_INTERFACE directory here) 92 | target_include_directories(${target_name}_fortran PUBLIC $) 93 | add_dependencies(${target_name}_fortran ${target_name}_declarations) 94 | endif() 95 | elseif(NOT ${ARGN}) # internal: the second (optional) parameter can be used to surpress this fatal error 96 | message(FATAL_ERROR "Please enable_language(Fortran) to compile the Fortran bindings.") 97 | endif() 98 | endfunction() 99 | 100 | function(bindgen_add_library target_name) 101 | set(options) 102 | set(one_value_args FORTRAN_OUTPUT_DIR C_OUTPUT_DIR FORTRAN_MODULE_NAME) 103 | set(multi_value_args SOURCES) 104 | cmake_parse_arguments(ARG "${options}" "${one_value_args};" "${multi_value_args}" ${ARGN}) 105 | 106 | set(__CPP_BINDGEN_SOURCE_DIR @__CPP_BINDGEN_SOURCE_DIR@) 107 | set(__CPP_BINDGEN_CMAKE_DIR @__CPP_BINDGEN_CMAKE_DIR@) 108 | 109 | if(NOT DEFINED ARG_FORTRAN_MODULE_NAME) 110 | set(ARG_FORTRAN_MODULE_NAME ${target_name}) # default value 111 | endif() 112 | 113 | if(ARG_C_OUTPUT_DIR) 114 | set(bindings_c_decl_filename ${ARG_C_OUTPUT_DIR}/${target_name}.h) 115 | else() 116 | set(bindings_c_decl_filename ${CMAKE_CURRENT_LIST_DIR}/${target_name}.h) # default value 117 | endif() 118 | if(ARG_FORTRAN_OUTPUT_DIR) 119 | set(bindings_fortran_decl_filename ${ARG_FORTRAN_OUTPUT_DIR}/${target_name}.f90) 120 | else() 121 | set(bindings_fortran_decl_filename ${CMAKE_CURRENT_LIST_DIR}/${target_name}.f90) # default value 122 | endif() 123 | 124 | add_library(${target_name} STATIC ${ARG_SOURCES}) 125 | target_link_libraries(${target_name} PRIVATE cpp_bindgen_generator) 126 | 127 | if(GT_ENABLE_BINDINGS_GENERATION) 128 | # generator 129 | add_executable(${target_name}_decl_generator 130 | ${__CPP_BINDGEN_SOURCE_DIR}/cpp_bindgen/generator_main.cpp) 131 | set_target_properties(${target_name}_decl_generator PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/decl_generator") 132 | target_link_libraries(${target_name}_decl_generator cpp_bindgen_generator) 133 | 134 | if (${APPLE}) 135 | target_link_libraries(${target_name}_decl_generator 136 | -Wl,-force_load ${target_name}) 137 | else() 138 | target_link_libraries(${target_name}_decl_generator 139 | -Xlinker --whole-archive ${target_name} 140 | -Xlinker --no-whole-archive) 141 | endif() 142 | 143 | add_custom_target(${target_name}_declarations 144 | ALL 145 | COMMAND ${CMAKE_COMMAND} 146 | -DGENERATOR=${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/decl_generator/${target_name}_decl_generator 147 | -DBINDINGS_C_DECL_FILENAME=${bindings_c_decl_filename} 148 | -DBINDINGS_FORTRAN_DECL_FILENAME=${bindings_fortran_decl_filename} 149 | -DFORTRAN_MODULE_NAME=${ARG_FORTRAN_MODULE_NAME} 150 | -P ${__CPP_BINDGEN_CMAKE_DIR}/cpp_bindgen_generate.cmake 151 | BYPRODUCTS ${bindings_c_decl_filename} ${bindings_fortran_decl_filename} 152 | DEPENDS $) 153 | else() 154 | if(EXISTS ${bindings_c_decl_filename} AND (EXISTS ${bindings_fortran_decl_filename})) 155 | add_custom_target(${target_name}_declarations) # noop, the dependencies are satisfied if the files exist 156 | else() 157 | message(FATAL_ERROR "Cross-compilation for bindings is enabled: no bindings will be generated, but " 158 | "${bindings_c_decl_filename} and/or " 159 | "${bindings_fortran_decl_filename} " 160 | "are missing. Generate the bindings and consider making them part of your repository.") 161 | endif() 162 | endif() 163 | 164 | # bindings c library 165 | add_library(${target_name}_c INTERFACE) 166 | target_link_libraries(${target_name}_c INTERFACE ${target_name}) 167 | target_link_libraries(${target_name}_c INTERFACE cpp_bindgen_handle) 168 | target_link_libraries(${target_name}_c INTERFACE cpp_bindgen_interface) 169 | 170 | add_dependencies(${target_name}_c ${target_name}_declarations) 171 | 172 | # bindings Fortran library 173 | # Export the name of the generated file. The variable needs to exist in the whole cmake! 174 | # Reason: see description of bindgen_enable_fortran_library(). 175 | set(CPP_BINDGEN_${target_name}_fortran_bindings_path ${bindings_fortran_decl_filename} 176 | CACHE INTERNAL "Path to the generated Fortran file for ${target_name}") 177 | bindgen_enable_fortran_library(${target_name} TRUE) 178 | endfunction() 179 | 180 | # install_cpp_bindgen_targets() 181 | # 182 | # cpp_bindgen contains some generic files which are being built on first use of bindgen_add_library(). 183 | # These libraries can be installed with this function which takes the same arguments 184 | # as install(TARGETS targets... [other-options]), except 185 | # - you must not specify "TARGETS targets..." but only all [other-options]. 186 | # - if Fortran is enabled Fortran_MODULE_DESTINATION needs to be set to the location where Fortran modules 187 | # should be installed to (e.g. include) 188 | function(install_cpp_bindgen_targets) 189 | set(options) 190 | set(oneValueArgs Fortran_MODULE_DESTINATION) 191 | set(multiValueArgs TARGETS) 192 | cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 193 | 194 | if(ARG_TARGETS) 195 | message(FATAL_ERROR "install_cpp_bindgen_targets() must not be called with TARGETS argument.") 196 | endif() 197 | 198 | if(TARGET cpp_bindgen_fortran_handle) # Fortran is enabled, we need to install a mod file 199 | if(ARG_Fortran_MODULE_DESTINATION) 200 | install(DIRECTORY ${CPP_BINDGEN_Fortran_MODULES_DIRECTORY}/ DESTINATION ${ARG_Fortran_MODULE_DESTINATION}) 201 | else() 202 | message(WARNING "Fortran_MODULE_DESTINATION was NOT specified, but Fortran was enabled. Modules files for 203 | cpp_bindgen won't be installed.") 204 | endif() 205 | install(TARGETS cpp_bindgen_fortran_handle ${ARG_UNPARSED_ARGUMENTS}) 206 | else() 207 | if(ARG_Fortran_MODULE_DESTINATION) 208 | message(WARNING "Fortran_MODULE_DESTINATION was specified, but Fortran is disabled.") 209 | endif() 210 | endif() 211 | install(TARGETS cpp_bindgen_generator cpp_bindgen_handle cpp_bindgen_interface ${ARG_UNPARSED_ARGUMENTS}) 212 | endfunction() 213 | -------------------------------------------------------------------------------- /cmake/cpp_bindgen_fortran_helpers.cmake: -------------------------------------------------------------------------------- 1 | function(bindgen_enable_fortran_openacc_on_target target) 2 | # TODO check if find_package(OpenACC) solves this problem 3 | if(CMAKE_Fortran_COMPILER_ID STREQUAL "Cray") 4 | target_compile_options(${target} PRIVATE $<$:-h acc>) 5 | elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") 6 | target_compile_options(${target} PRIVATE $<$:-fopenacc>) 7 | set_target_properties(${target} PROPERTIES APPEND_STRING PROPERTY LINK_FLAGS -fopenacc) 8 | else() 9 | message(FATAL_ERROR "OpenACC is not configured for this compiler.") 10 | endif() 11 | endfunction() 12 | 13 | function(bindgen_enable_fortran_preprocessing_on_target target) 14 | if (CMAKE_Fortran_COMPILER_ID STREQUAL "Cray") 15 | target_compile_options(${target} PRIVATE $<$:-eF>) 16 | else() 17 | target_compile_options(${target} PRIVATE $<$:-cpp>) 18 | endif() 19 | endfunction() 20 | -------------------------------------------------------------------------------- /cmake/cpp_bindgen_generate.cmake: -------------------------------------------------------------------------------- 1 | function(check_and_update target_file new_file) 2 | execute_process( 3 | COMMAND ${CMAKE_COMMAND} -E compare_files ${target_file} ${new_file} 4 | RESULT_VARIABLE compare_result 5 | ) 6 | 7 | if(${compare_result} EQUAL 0) 8 | message(STATUS "${target_file} is up-to-date") 9 | else() 10 | message(WARNING "${target_file} was generated! " 11 | "If you ship the generated bindings with your sources, don't forget to ship this updated file (and its variants). " 12 | "Otherwise, this warning can be ignored.") 13 | 14 | get_filename_component(target_path ${target_file} PATH) 15 | file(COPY ${new_file} DESTINATION ${target_path}) 16 | endif() 17 | file(REMOVE ${new_file}) 18 | endfunction() 19 | 20 | # Generate bindings and compare against existing ones 21 | message(STATUS "Generating bindings for library ${FORTRAN_MODULE_NAME}") 22 | 23 | set(generator_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/generated_bindings) 24 | file(MAKE_DIRECTORY ${generator_dir}) 25 | get_filename_component(filename_BINDINGS_C_DECL_FILENAME ${BINDINGS_C_DECL_FILENAME} NAME) 26 | set(new_BINDINGS_C_DECL_FILENAME ${generator_dir}/${filename_BINDINGS_C_DECL_FILENAME}) 27 | get_filename_component(filename_BINDINGS_FORTRAN_DECL_FILENAME ${BINDINGS_FORTRAN_DECL_FILENAME} NAME) 28 | set(new_BINDINGS_FORTRAN_DECL_FILENAME ${generator_dir}/${filename_BINDINGS_FORTRAN_DECL_FILENAME}) 29 | 30 | # run generator 31 | execute_process(COMMAND ${GENERATOR} ${new_BINDINGS_C_DECL_FILENAME} ${new_BINDINGS_FORTRAN_DECL_FILENAME} ${FORTRAN_MODULE_NAME} 32 | RESULT_VARIABLE generate_result 33 | OUTPUT_VARIABLE generate_out 34 | ERROR_VARIABLE generate_out 35 | ) 36 | 37 | if(${generate_result} STREQUAL "0") 38 | # only update the bindings if they changed (file not touched -> no rebuild is triggered) 39 | check_and_update(${BINDINGS_C_DECL_FILENAME} ${new_BINDINGS_C_DECL_FILENAME}) 40 | check_and_update(${BINDINGS_FORTRAN_DECL_FILENAME} ${new_BINDINGS_FORTRAN_DECL_FILENAME}) 41 | else() 42 | message(FATAL_ERROR "GENERATING BINDINGS FAILED. Possibly you cross-compiled the bindings generator for a target " 43 | " which cannot be executed on this host. Consider using the cross-compilation option.\n Exit code: ${generate_result}\n${generate_out}") 44 | endif() 45 | -------------------------------------------------------------------------------- /cmake/detect_features.cmake: -------------------------------------------------------------------------------- 1 | if(NOT DEFINED CPP_BINDGEN_ENABLE_COMPILER_DETECTION) 2 | if(${PROJECT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) 3 | set(CPP_BINDGEN_ENABLE_COMPILER_DETECTION ON) 4 | else() 5 | # If turned OFF, it will still use the compilers, 6 | # - if they are available from a super-project, or 7 | # - if compilers are forced to on via other options. 8 | set(CPP_BINDGEN_ENABLE_COMPILER_DETECTION OFF) 9 | endif() 10 | endif() 11 | 12 | macro(detect_cuda) 13 | if(CPP_BINDGEN_ENABLE_COMPILER_DETECTION) 14 | if(NOT DEFINED CPP_BINDGEN_TEST_CUDA) 15 | # detect CUDA support 16 | include(CheckLanguage) 17 | check_language(CUDA) 18 | 19 | if(CMAKE_CUDA_COMPILER) 20 | enable_language (CUDA) 21 | message(STATUS "Enable CUDA tests") 22 | set(CUDA_AVAILABLE ON) 23 | else() 24 | message(STATUS "Disable CUDA tests") 25 | set(CUDA_AVAILABLE OFF) 26 | endif() 27 | elseif(CPP_BINDGEN_TEST_CUDA) 28 | enable_language(CUDA) 29 | message(STATUS "Enable CUDA tests") 30 | set(CUDA_AVAILABLE ON) 31 | else() 32 | message(STATUS "Disable CUDA tests") 33 | set(CUDA_AVAILABLE OFF) 34 | endif() 35 | endif() 36 | endmacro(detect_cuda) 37 | 38 | include (CMakeDependentOption) 39 | 40 | macro(detect_fortran_compiler) 41 | if(CPP_BINDGEN_ENABLE_COMPILER_DETECTION) 42 | CMAKE_DEPENDENT_OPTION (CPP_BINDGEN_REQUIRE_TEST_Fortran "CMake will abort if no Fortran compiler can be found" 43 | OFF "BUILD_TESTING" OFF) 44 | 45 | include(CheckLanguage) 46 | check_language(Fortran) 47 | if (CMAKE_Fortran_COMPILER OR CPP_BINDGEN_REQUIRE_TEST_Fortran) 48 | enable_language(Fortran) 49 | else() 50 | message(WARNING "Fortran Compiler has not been found. Tests using Fortran will not be built!") 51 | endif() 52 | endif() 53 | endmacro(detect_fortran_compiler) 54 | 55 | macro(detect_c_compiler) 56 | if(CPP_BINDGEN_ENABLE_COMPILER_DETECTION) 57 | CMAKE_DEPENDENT_OPTION (CPP_BINDGEN_REQUIRE_TEST_C "CMake will abort if no C compiler can be found" 58 | OFF "BUILD_TESTING" OFF) 59 | 60 | include(CheckLanguage) 61 | check_language(C) 62 | if (CMAKE_C_COMPILER OR CPP_BINDGEN_REQUIRE_TEST_C) 63 | enable_language(C) 64 | else() 65 | message(WARNING "C Compiler has not been found. Tests using C will not be built!") 66 | endif() 67 | endif() 68 | endmacro(detect_c_compiler) 69 | -------------------------------------------------------------------------------- /cmake/export.cmake: -------------------------------------------------------------------------------- 1 | # this registers the build-tree with a global CMake-registry 2 | export(PACKAGE cpp_bindgen) 3 | 4 | include(CMakePackageConfigHelpers) 5 | 6 | # for build tree 7 | set(cpp_bindgen_CMAKE_DIR ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build-install/lib/cmake) 8 | set(cpp_bindgen_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 9 | set(cpp_bindgen_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) 10 | configure_package_config_file( 11 | cmake/cpp_bindgen-config.cmake.in 12 | ${PROJECT_BINARY_DIR}/cpp_bindgen-config.cmake 13 | PATH_VARS cpp_bindgen_CMAKE_DIR cpp_bindgen_SOURCE_DIR cpp_bindgen_INCLUDE_DIR 14 | INSTALL_DESTINATION ${PROJECT_BINARY_DIR} 15 | ) 16 | write_basic_package_version_file( 17 | ${PROJECT_BINARY_DIR}/cpp_bindgen-config-version.cmake 18 | VERSION ${PROJECT_VERSION} 19 | COMPATIBILITY SameMajorVersion 20 | ) 21 | 22 | # for install tree 23 | set(cpp_bindgen_CMAKE_DIR lib/cmake) 24 | set(cpp_bindgen_SOURCE_DIR src) 25 | set(cpp_bindgen_INCLUDE_DIR include) 26 | configure_package_config_file( 27 | cmake/cpp_bindgen-config.cmake.in 28 | ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/cpp_bindgen-config.cmake 29 | PATH_VARS cpp_bindgen_CMAKE_DIR cpp_bindgen_SOURCE_DIR cpp_bindgen_INCLUDE_DIR 30 | INSTALL_DESTINATION lib/cmake 31 | ) 32 | write_basic_package_version_file( 33 | ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/cpp_bindgen-config-version.cmake 34 | VERSION ${PROJECT_VERSION} 35 | COMPATIBILITY SameMajorVersion 36 | ) 37 | 38 | install( 39 | FILES 40 | ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/cpp_bindgen-config.cmake 41 | ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/cpp_bindgen-config-version.cmake 42 | DESTINATION lib/cmake 43 | ) 44 | 45 | set(__CPP_BINDGEN_CMAKE_DIR "\${cpp_bindgen_CMAKE_DIR}") 46 | set(__CPP_BINDGEN_SOURCE_DIR "\${cpp_bindgen_SOURCE_DIR}") 47 | set(__CPP_BINDGEN_INCLUDE_DIR "\${cpp_bindgen_INCLUDE_DIR}") 48 | configure_file(cmake/cpp_bindgen.cmake.in 49 | ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build-install/lib/cmake/cpp_bindgen.cmake 50 | @ONLY) 51 | unset(__CPP_BINDGEN_CMAKE_DIR) 52 | unset(__CPP_BINDGEN_SOURCE_DIR) 53 | unset(__CPP_BINDGEN_INCLUDE_DIR) 54 | 55 | set(CMAKE_SOURCES 56 | "${PROJECT_SOURCE_DIR}/cmake/cpp_bindgen_generate.cmake" 57 | "${PROJECT_SOURCE_DIR}/cmake/cpp_bindgen_fortran_helpers.cmake" 58 | "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build-install/lib/cmake/cpp_bindgen.cmake" 59 | ) 60 | set(CBINDINGS_SOURCES 61 | "${PROJECT_SOURCE_DIR}/src/cpp_bindgen/generator.cpp" 62 | "${PROJECT_SOURCE_DIR}/src/cpp_bindgen/generator_main.cpp" 63 | "${PROJECT_SOURCE_DIR}/src/cpp_bindgen/array_descriptor.f90" 64 | "${PROJECT_SOURCE_DIR}/src/cpp_bindgen/string_descriptor.f90" 65 | "${PROJECT_SOURCE_DIR}/src/cpp_bindgen/handle.f90" 66 | "${PROJECT_SOURCE_DIR}/src/cpp_bindgen/handle.cpp" 67 | ) 68 | 69 | install(DIRECTORY include/ DESTINATION include) 70 | install(FILES ${CMAKE_SOURCES} DESTINATION "lib/cmake") 71 | install(FILES ${CBINDINGS_SOURCES} DESTINATION "src/cpp_bindgen") 72 | 73 | file(COPY ${CMAKE_SOURCES} DESTINATION "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build-install/lib/cmake") 74 | -------------------------------------------------------------------------------- /example/simple/.gitignore: -------------------------------------------------------------------------------- 1 | simple.f90 2 | simple.h 3 | 4 | -------------------------------------------------------------------------------- /example/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14.5) 2 | project(simple_example LANGUAGES CXX C Fortran) 3 | 4 | # 1) find installed cpp_bindgen version 5 | find_package(cpp_bindgen) 6 | 7 | # 2) create a library with bindings 8 | bindgen_add_library(simple SOURCES simple.cpp) 9 | 10 | # 3) link the library to a fortran executable 11 | add_executable(driver driver.f90) 12 | target_link_libraries(driver simple_fortran) 13 | -------------------------------------------------------------------------------- /example/simple/driver.f90: -------------------------------------------------------------------------------- 1 | ! GridTools 2 | ! 3 | ! Copyright (c) 2014-2019, ETH Zurich 4 | ! All rights reserved. 5 | ! 6 | ! Please, refer to the LICENSE file in the root directory. 7 | ! SPDX-License-Identifier: BSD-3-Clause 8 | 9 | program main 10 | use iso_c_binding 11 | use bindgen_handle 12 | use simple 13 | implicit none 14 | integer, parameter :: i = 9 15 | 16 | call print_number_from_cpp(i) 17 | 18 | end 19 | -------------------------------------------------------------------------------- /example/simple/simple.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * GridTools 3 | * 4 | * Copyright (c) 2014-2019, ETH Zurich 5 | * All rights reserved. 6 | * 7 | * Please, refer to the LICENSE file in the root directory. 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | // In this example, we demonstrate how the cpp_bindgen library can be used to export functions to C and Fortran. 15 | 16 | namespace { 17 | void print_number(int i) { std::cout << "Printing from C++: " << i << std::endl; } 18 | 19 | BINDGEN_EXPORT_BINDING_1(print_number_from_cpp, print_number); 20 | } // namespace 21 | -------------------------------------------------------------------------------- /example/simple_fetch_content/.gitignore: -------------------------------------------------------------------------------- 1 | simple.f90 2 | simple.h 3 | 4 | -------------------------------------------------------------------------------- /example/simple_fetch_content/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14.5) 2 | project(simple_example_with_fetch_content LANGUAGES CXX Fortran) 3 | 4 | # 1) fetch cpp_bindgen from the repository 5 | include(FetchContent) 6 | FetchContent_Declare( 7 | cpp_bindgen 8 | # In your application remove SOURCE_DIR ... 9 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../.. 10 | # By the following 2 lines to fetch content directly from github 11 | # GIT_REPOSITORY https://github.com/GridTools/cpp_bindgen.git 12 | # GIT_TAG master # consider replacing master by a tagged version 13 | ) 14 | FetchContent_MakeAvailable(cpp_bindgen) 15 | 16 | # 2) create a library with bindings. This will generate the files simple.h and simple.f90 which can be included within C and Fortran. In CMake you can use them by linking against `simple_c`or `simple_fortran`. 17 | bindgen_add_library(simple SOURCES simple.cpp) 18 | 19 | # 3) link the generated library to a fortran executable 20 | add_executable(driver driver.f90) 21 | target_link_libraries(driver simple_fortran) 22 | 23 | # 4) optional: demonstrates installing the library with CMake 24 | # installs general cpp_bindgen targets 25 | install_cpp_bindgen_targets( 26 | EXPORT simple_fortran_targets 27 | Fortran_MODULE_DESTINATION include 28 | LIBRARY DESTINATION lib 29 | ARCHIVE DESTINATION lib 30 | ) 31 | # install your library (simple) and the generated bindings library (simple_fortran) as usual 32 | install( 33 | TARGETS simple simple_fortran 34 | EXPORT simple_fortran_targets 35 | LIBRARY DESTINATION lib 36 | ARCHIVE DESTINATION lib 37 | ) 38 | install(EXPORT simple_fortran_targets DESTINATION cmake NAMESPACE SimpleFortran::) 39 | -------------------------------------------------------------------------------- /example/simple_fetch_content/driver.f90: -------------------------------------------------------------------------------- 1 | ! GridTools 2 | ! 3 | ! Copyright (c) 2014-2019, ETH Zurich 4 | ! All rights reserved. 5 | ! 6 | ! Please, refer to the LICENSE file in the root directory. 7 | ! SPDX-License-Identifier: BSD-3-Clause 8 | 9 | program main 10 | use iso_c_binding 11 | use bindgen_handle 12 | use simple 13 | implicit none 14 | integer, parameter :: i = 9 15 | 16 | call print_number_from_cpp(i) 17 | 18 | end 19 | -------------------------------------------------------------------------------- /example/simple_fetch_content/simple.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * GridTools 3 | * 4 | * Copyright (c) 2014-2019, ETH Zurich 5 | * All rights reserved. 6 | * 7 | * Please, refer to the LICENSE file in the root directory. 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | // In this example, we demonstrate how the cpp_bindgen library can be used to export functions to C and Fortran. 15 | 16 | namespace { 17 | void print_number(int i) { std::cout << "Printing from C++: " << i << std::endl; } 18 | 19 | // Exports a unary function with the name `print_number_from_cpp`, which forwards to `print_number`. 20 | BINDGEN_EXPORT_BINDING_1(print_number_from_cpp, print_number); 21 | } // namespace 22 | -------------------------------------------------------------------------------- /include/cpp_bindgen/array_descriptor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GridTools 3 | * 4 | * Copyright (c) 2014-2019, ETH Zurich 5 | * All rights reserved. 6 | * 7 | * Please, refer to the LICENSE file in the root directory. 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum bindgen_fortran_array_kind { 16 | bindgen_fk_Bool, 17 | bindgen_fk_Int, 18 | bindgen_fk_Short, 19 | bindgen_fk_Long, 20 | bindgen_fk_LongLong, 21 | bindgen_fk_Float, 22 | bindgen_fk_Double, 23 | bindgen_fk_LongDouble, 24 | bindgen_fk_SignedChar, 25 | }; 26 | typedef enum bindgen_fortran_array_kind bindgen_fortran_array_kind; 27 | 28 | struct bindgen_fortran_array_descriptor { 29 | bindgen_fortran_array_kind type; 30 | int rank; 31 | int dims[7]; 32 | void *data; 33 | bool is_acc_present; 34 | // TODO: add support for strides, bounds end type bindgen_fortran_array_descriptor 35 | }; 36 | typedef struct bindgen_fortran_array_descriptor bindgen_fortran_array_descriptor; 37 | -------------------------------------------------------------------------------- /include/cpp_bindgen/common/any_moveable.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * GridTools 3 | * 4 | * Copyright (c) 2014-2019, ETH Zurich 5 | * All rights reserved. 6 | * 7 | * Please, refer to the LICENSE file in the root directory. 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace cpp_bindgen { 18 | 19 | struct bad_any_cast : std::bad_cast { 20 | const char *what() const noexcept override { return "cpp_bindgen::bad_any_cast"; } 21 | }; 22 | 23 | /** 24 | * this class implements the subset of std::any interface and can hold move only objects. 25 | * 26 | * TODO(anstaf): implement missing std::any components: piecewise ctors, emplace, reset, swap, make_any 27 | */ 28 | class any_moveable { 29 | struct iface { 30 | virtual ~iface() = default; 31 | virtual std::type_info const &type() const noexcept = 0; 32 | }; 33 | template 34 | struct impl : iface { 35 | T m_obj; 36 | impl(T const &obj) : m_obj(obj) {} 37 | impl(T &&obj) : m_obj(std::move(obj)) {} 38 | std::type_info const &type() const noexcept override { return typeid(T); } 39 | }; 40 | std::unique_ptr m_impl; 41 | 42 | public: 43 | any_moveable() = default; 44 | 45 | template ::type> 46 | any_moveable(Arg &&arg) : m_impl(new impl(std::forward(arg))) {} 47 | any_moveable(any_moveable &&) = default; 48 | 49 | template ::type> 50 | any_moveable &operator=(Arg &&obj) { 51 | m_impl.reset(new impl(std::forward(obj))); 52 | return *this; 53 | } 54 | any_moveable &operator=(any_moveable &&) = default; 55 | 56 | bool has_value() const noexcept { return !!m_impl; } 57 | std::type_info const &type() const noexcept { return m_impl->type(); } 58 | 59 | template 60 | friend T *any_cast(any_moveable *src) noexcept { 61 | return src && src->type() == typeid(T) ? &static_cast *>(src->m_impl.get())->m_obj : nullptr; 62 | } 63 | }; 64 | 65 | template 66 | T const *any_cast(any_moveable const *src) noexcept { 67 | return any_cast(const_cast(src)); 68 | } 69 | 70 | template 71 | T any_cast(any_moveable &src) { 72 | auto *ptr = any_cast::type>(&src); 73 | if (!ptr) 74 | throw bad_any_cast{}; 75 | using ref_t = typename std:: 76 | conditional::value, T, typename std::add_lvalue_reference::type>::type; 77 | return static_cast(*ptr); 78 | } 79 | 80 | template 81 | T any_cast(any_moveable const &src) { 82 | return any_cast(const_cast(src)); 83 | } 84 | 85 | template 86 | T any_cast(any_moveable &&src) { 87 | static_assert( 88 | std::is_rvalue_reference::value || std::is_const::type>::value, 89 | "any_cast shall not be used for getting nonconst references to temporary objects"); 90 | return any_cast(src); 91 | } 92 | } // namespace cpp_bindgen 93 | -------------------------------------------------------------------------------- /include/cpp_bindgen/common/disjunction.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * GridTools 3 | * 4 | * Copyright (c) 2014-2019, ETH Zurich 5 | * All rights reserved. 6 | * 7 | * Please, refer to the LICENSE file in the root directory. 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | #pragma once 11 | 12 | #include 13 | 14 | namespace cpp_bindgen { 15 | 16 | template 17 | struct disjunction : std::false_type {}; 18 | template 19 | struct disjunction : B1 {}; 20 | template 21 | struct disjunction : std::conditional>::type {}; 22 | } // namespace cpp_bindgen 23 | -------------------------------------------------------------------------------- /include/cpp_bindgen/common/for_each.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * GridTools 3 | * 4 | * Copyright (c) 2014-2019, ETH Zurich 5 | * All rights reserved. 6 | * 7 | * Please, refer to the LICENSE file in the root directory. 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | 11 | #pragma once 12 | 13 | namespace cpp_bindgen { 14 | 15 | namespace for_each_detail { 16 | template 17 | struct for_each_impl; 18 | 19 | template