From a611e13ff1883832e6d347e68ea1cc504ece9871 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Fri, 17 May 2024 19:49:21 +0000 Subject: [PATCH] #24 restructure cmake --- CMakeLists.txt | 152 ++++++++++++++++++++++++++++++++++++++++-- ProjectIncludes.cmake | 39 ----------- WrapPython.cmake | 136 ------------------------------------- 3 files changed, 147 insertions(+), 180 deletions(-) delete mode 100644 ProjectIncludes.cmake delete mode 100644 WrapPython.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ab892e3..e5d6a455 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,11 @@ # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +#======================================== +# Setup PyChaste project +#======================================== + +# PyChaste needs the cell_based component (and its dependencies) find_package(Chaste COMPONENTS cell_based) # PyChaste needs some additional VTK libraries @@ -73,12 +78,149 @@ else() endif() if (VTK_MAJOR_VERSION LESS 9) - list(APPEND Chaste_INCLUDES ${VTK_INCLUDE_DIRS}) - list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS ${VTK_INCLUDE_DIRS}) - list(APPEND Chaste_THIRD_PARTY_LIBRARIES ${VTK_LIBRARIES}) + list(APPEND Chaste_INCLUDES "${VTK_INCLUDE_DIRS}") + list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS "${VTK_INCLUDE_DIRS}") + list(APPEND Chaste_THIRD_PARTY_LIBRARIES "${VTK_LIBRARIES}") +else() + target_link_libraries(Chaste_COMMON_DEPS INTERFACE ${VTK_LIBRARIES}) endif () +# Do Chaste project preprocessing, which results in something like: +# add_custom_target(project_PyChaste) +# set(Chaste_project_PyChaste_SOURCE_DIR ...) +# set(Chaste_project_PyChaste_INCLUDE_DIRS ...) +# include_directories("${Chaste_THIRD_PARTY_INCLUDE_DIRS}") +# include_directories("${Chaste_project_PyChaste_INCLUDE_DIRS}") +# include_directories("${Chaste_INCLUDE_DIRS}") +# add_library(chaste_project_PyChaste ...) +# target_link_libraries(chaste_project_PyChaste ...) chaste_do_project(PyChaste) -# Include the Python wrapping build logic -include(${CMAKE_CURRENT_SOURCE_DIR}/WrapPython.cmake) +#======================================== +# Compiler options +#======================================== +add_compile_options(-Wno-unused-local-typedefs) + +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # https://stackoverflow.com/questions/25365160/boostmultiprecisionfloat128-and-c11 + add_compile_options(-fext-numeric-literals) +endif() + +#======================================== +# PyChaste non-wrapper C++ code +#======================================== + +# Non-wrapper code locations +set(PYCHASTE_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/src/ + ${CMAKE_CURRENT_SOURCE_DIR}/src/cell_based/ + ${CMAKE_CURRENT_SOURCE_DIR}/src/ode/ + ${CMAKE_CURRENT_SOURCE_DIR}/src/tutorial/ + ${CMAKE_CURRENT_SOURCE_DIR}/src/visualization/ + ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/) + +# Non-wrapper code needs to be put in a separate shared library +set(PYCHASTE_SHARED_LIB + "${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste${CMAKE_SHARED_LIBRARY_SUFFIX}") + +#======================================== +# Target for wrapper auto-generation +#======================================== +add_custom_target(project_PyChaste_Python_Bindings) +add_custom_command(TARGET project_PyChaste_Python_Bindings + COMMAND cppwg ${CMAKE_SOURCE_DIR} + -w ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers + -p ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrapper_generators/package_info.yaml + -i ${PYCHASTE_INCLUDE_DIRS} ${Chaste_INCLUDE_DIRS} ${Chaste_THIRD_PARTY_INCLUDE_DIRS} + --std c++17 +) + +#======================================== +# Build python modules from wrappers +#======================================== +include_directories(${PYCHASTE_INCLUDE_DIRS}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers) +include_directories(${PYTHON3_INCLUDE_DIRS}) + +add_subdirectory(dynamic/pybind11) + +# Copy python package structure to build directory, ignoring existing shared libraries +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/python/ + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/ + PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/python/ + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/test/) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/doc/) + +# List of modules to build into shared libraries +set (PYCHASTE_PYTHON_MODULES + # Modules with auto-generated wrappers + core + ode + pde + mesh + cell_based + visualization + tutorial + # Modules with manual wrappers + preload + tutorial_manual) + +# Locations to put each module library +set (PYCHASTE_PYTHON_MODULE_LOCATIONS + # Modules with auto-generated wrappers + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/core/ + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/ode/ + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/pde/ + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/mesh/ + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/cell_based/ + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/visualization/ + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial/ + # Modules with manual wrappers + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/ + ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial/) + +# Create a shared library target for each module +list(LENGTH PYCHASTE_PYTHON_MODULES max_module_idx) +math(EXPR max_module_idx "${max_module_idx} - 1") +set(module_prefix "_chaste_project_PyChaste_") + +foreach(idx RANGE ${max_module_idx}) + list(GET PYCHASTE_PYTHON_MODULES ${idx} module_name) + list(GET PYCHASTE_PYTHON_MODULE_LOCATIONS ${idx} module_dir) + + # Glob the module's wrapper code from the `dynamic` directory + file(GLOB module_sources ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers/${module_name}/*.cpp) + + # The module library name here must be the same as the pybind11 module name + # defined in the main wrapper e.g. `dynamic/wrappers/ode/ode.main.cpp` + # defines a pybind11 module `_chaste_project_PyChaste_ode`. By convention, + # the name starts with an underscore. The usual 'lib' prefix is disabled. + add_library(${module_prefix}${module_name} SHARED ${module_sources}) + + set_target_properties(${module_prefix}${module_name} + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${module_dir} + PREFIX "${PYTHON_MODULE_PREFIX}" + SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}") + + # The order here is important - pybind11 and python come first + target_link_libraries(${module_prefix}${module_name} + pybind11::module + ${PYTHON3_LIBRARIES} + ${Chaste_THIRD_PARTY_LIBRARIES} + ${Chaste_LIBRARIES} + ${PYCHASTE_SHARED_LIB}) + + add_dependencies(${module_prefix}${module_name} chaste_project_PyChaste) +endforeach() + +# Target for building all module shared libraries +add_custom_target(project_PyChaste_Python) +foreach(idx RANGE ${max_module_idx}) + list(GET PYCHASTE_PYTHON_MODULES ${idx} module_name) + add_dependencies(project_PyChaste_Python ${module_prefix}${module_name}) +endforeach() diff --git a/ProjectIncludes.cmake b/ProjectIncludes.cmake deleted file mode 100644 index a919baef..00000000 --- a/ProjectIncludes.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2005-2024, University of Oxford. -# All rights reserved. -# -# University of Oxford means the Chancellor, Masters and Scholars of the -# University of Oxford, having an administrative office at Wellington -# Square, Oxford OX1 2JD, UK. -# -# This file is part of Chaste. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the University of Oxford nor the names of its -# contributors may be used to endorse or promote products derived from this -# software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -######### Collect the include directories for the project. ###################### -set(PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/) -list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/cell_based) -list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/ode) -list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/tutorial) -list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/visualization) -list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/dynamic) \ No newline at end of file diff --git a/WrapPython.cmake b/WrapPython.cmake deleted file mode 100644 index 639ebd01..00000000 --- a/WrapPython.cmake +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright (c) 2005-2024, University of Oxford. -# All rights reserved. -# -# University of Oxford means the Chancellor, Masters and Scholars of the -# University of Oxford, having an administrative office at Wellington -# Square, Oxford OX1 2JD, UK. -# -# This file is part of Chaste. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the University of Oxford nor the names of its -# contributors may be used to endorse or promote products derived from this -# software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -add_compile_options(-Wno-unused-local-typedefs) - -######### Find the dependencies for wrapper building ###################### -# Add any cmake modules defined in this project -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) - -# Find the Chaste and third party dependency header files. -include_directories(${Chaste_INCLUDE_DIRS} ${Chaste_THIRD_PARTY_INCLUDE_DIRS}) - -# Any non-wrapper code (code in the src folder) in this project needs to be put in its own shared library. -if(APPLE) - set(PYCHASTE_SHARED_LIB ${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste.dylib) -elseif(WIN32) - set(PYCHASTE_SHARED_LIB ${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste.dll) -else() - set(PYCHASTE_SHARED_LIB ${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste.so) -endif() - -# Collect the header directories for this project -include(${CMAKE_CURRENT_SOURCE_DIR}/ProjectIncludes.cmake) -include_directories(${PYCHASTE_INCLUDE_DIRS}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers) - -if(CMAKE_COMPILER_IS_GNUCXX) - # https://svn.boost.org/trac/boost/ticket/9240 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals") -endif() -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/pybind11/include) - -add_subdirectory(dynamic/pybind11) -include_directories(${PYTHON3_INCLUDE_DIRS}) - -######### Build the Python modules ###################### -set (PYCHASTE_PYTHON_AUTO_MODULES "") -set (PYCHASTE_PYTHON_MODULES "") -# The shared library corresponding to this module needs to be put in the correct place in the package tree after it is built, put the location here. -set (PYCHASTE_PYTHON_MODULE_LOCATIONS "") - -# Add each module to be built to this list. -# Modules with auto wrapping -list (APPEND PYCHASTE_PYTHON_AUTO_MODULES core) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/core) -list (APPEND PYCHASTE_PYTHON_AUTO_MODULES ode) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/ode) -list (APPEND PYCHASTE_PYTHON_AUTO_MODULES pde) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/pde) -list (APPEND PYCHASTE_PYTHON_AUTO_MODULES mesh) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/mesh) -list (APPEND PYCHASTE_PYTHON_AUTO_MODULES cell_based) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/cell_based) -list (APPEND PYCHASTE_PYTHON_AUTO_MODULES visualization) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/visualization) -list (APPEND PYCHASTE_PYTHON_AUTO_MODULES tutorial) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial) -list (APPEND PYCHASTE_PYTHON_MODULES ${PYCHASTE_PYTHON_AUTO_MODULES}) - -# Modules with manual wrapping -list (APPEND PYCHASTE_PYTHON_MODULES preload) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/) -list (APPEND PYCHASTE_PYTHON_MODULES tutorial_manual) -list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial/) - -# Copy the Python package (i.e. all source files etc) to the build folder, ignore any shared libraries that might be in there. -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/python/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/ PATTERN "*.so" EXCLUDE) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/python/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/test/) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/doc/) - -# Target to generate bindings -add_custom_target(project_PyChaste_Python_Bindings) -add_custom_command( - TARGET project_PyChaste_Python_Bindings - COMMAND cppwg ${CMAKE_SOURCE_DIR} - -w ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers - -p ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrapper_generators/package_info.yaml - -i ${PYCHASTE_INCLUDE_DIRS} ${Chaste_INCLUDE_DIRS} ${Chaste_THIRD_PARTY_INCLUDE_DIRS} - --std c++17 -) - -# Loop through each module and create the shared library targets -list(LENGTH PYCHASTE_PYTHON_MODULES len1) -math(EXPR len2 "${len1} - 1") -foreach(val RANGE ${len2}) - list(GET PYCHASTE_PYTHON_MODULES ${val} python_module) - list(GET PYCHASTE_PYTHON_MODULE_LOCATIONS ${val} python_module_location) - - file(GLOB MODULE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers/${python_module}/*.cpp) - - # each module is in the 'dynamic' directory. The library name must be the same as that defined in the cpp file. It is customary - # to start the name with an underscore. The usual 'lib' prefix is disabled. - add_library(_chaste_project_PyChaste_${python_module} SHARED ${MODULE_SOURCES}) - set_target_properties(_chaste_project_PyChaste_${python_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${python_module_location} - PREFIX "${PYTHON_MODULE_PREFIX}" SUFFIX ".so") - target_compile_features(_chaste_project_PyChaste_${python_module} PRIVATE cxx_range_for) - # order is important, pybind and python come first - target_link_libraries(_chaste_project_PyChaste_${python_module} pybind11::module ${PYTHON3_LIBRARIES} ${Chaste_THIRD_PARTY_LIBRARIES} ${Chaste_LIBRARIES} ${PYCHASTE_SHARED_LIB} Chaste_COMMON_DEPS) - add_dependencies(_chaste_project_PyChaste_${python_module} chaste_project_PyChaste) -endforeach() - -# Add a target so all the libraries are built with a single command -add_custom_target(project_PyChaste_Python) -foreach(val RANGE ${len2}) - list(GET PYCHASTE_PYTHON_MODULES ${val} python_module) - add_dependencies(project_PyChaste_Python _chaste_project_PyChaste_${python_module}) -endforeach()