Skip to content

Commit

Permalink
Use CMake and pyproject.toml from ngsolve-addon-template
Browse files Browse the repository at this point in the history
  • Loading branch information
mhochsteger committed Jun 19, 2024
1 parent 0986727 commit 078c81f
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 103 deletions.
79 changes: 79 additions & 0 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Build and upload to PyPI

on:
push:
branches:
- master
- use_ngsolve_addon_template
tags:
- '*'

jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-13]
# include:
# - os: windows-2019
# cibw-arch: AMD64
# cmake-generator: "Visual Studio 16 2019"
# cmake_generator_platform: "x64"

steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
fetch-tags: 'true'
fetch-depth: 0

- name: Build wheels
uses: pypa/cibuildwheel@v2.19.0

- uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl

build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
fetch-tags: 'true'
fetch-depth: 0

- name: Build sdist
run: pipx run build --sdist

- uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz

upload_pypi:
if: false # remove this if you want to enable upload to pypi (you need to setup that on pypi first)
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
#if: github.event_name == 'release' && github.event.action == 'published'
# or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this)
#if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/download-artifact@v4
with:
# unpacks all CIBW artifacts into dist/
pattern: cibw-*
path: dist
merge-multiple: true

- uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
password: ${{ secrets.PYPI_API_TOKEN_2 }}
# To test: repository-url: https://test.pypi.org/legacy/
125 changes: 69 additions & 56 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,66 +1,79 @@
include (ExternalProject)

# get command line cmake arguments
# MUST be done before call to 'project'
get_cmake_property(vars CACHE_VARIABLES)
foreach(var ${vars})
get_property(currentHelpString CACHE "${var}" PROPERTY HELPSTRING)
if("${currentHelpString}" MATCHES "No help, variable specified on the command line." OR "${currentHelpString}" STREQUAL "")
# message("${var} = [${${var}}] -- ${currentHelpString}") # uncomment to see the variables being processed
list(APPEND CL_ARGS "-D${var}=${${var}}")
endif()
endforeach()

project(ngs_special_functions_super)
cmake_minimum_required(VERSION 3.28)

include(FetchContent)

cmake_minimum_required(VERSION 3.8)
project(ngsolve_special_functions)
include(ngsolve_addon.cmake)

find_package(NGSolve CONFIG REQUIRED
HINTS /usr $ENV{NETGENDIR}/.. /opt/netgen/ /Applications/Netgen.app/Contents/Resources/CMake C:/netgen
# Fetch f2c utility and library
FetchContent_Declare(
f2c
GIT_REPOSITORY https://github.com/mhochsteger/f2c.git
GIT_TAG 96c2fbf
EXCLUDE_FROM_ALL
)

# check if CMAKE_INSTALL_PREFIX is set by user, if not install in NGSolve python dir
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX ${NGSOLVE_INSTALL_DIR}/${NGSOLVE_INSTALL_DIR_PYTHON} CACHE PATH "Install dir" FORCE)
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
FetchContent_MakeAvailable(f2c)

if(UNIX)
target_compile_options(f2c_exe PRIVATE -Wno-implicit-function-declaration)
endif()

################################
# Build f2c utility and library
ExternalProject_Add(
project_f2c
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/f2c
GIT_REPOSITORY https://github.com/mhochsteger/f2c.git
GIT_TAG 747683f
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${NGSOLVE_INSTALL_DIR}
-DF2C_INSTALL_DIR_BIN=${NETGEN_INSTALL_DIR_BIN}
-DF2C_INSTALL_DIR_LIB=${NETGEN_INSTALL_DIR_LIB}
-DF2C_INSTALL_DIR_INCLUDE=${NETGEN_INSTALL_DIR_INCLUDE}
-DCMAKE_C_FLAGS="-Wno-implicit-function-declaration"
)
get_target_property(F2C_DIR f2c_exe BINARY_DIR)
if(WIN32)
set(F2C_COMMAND ${F2C_DIR}/Release/f2c.exe)
else()
set(F2C_COMMAND ${F2C_DIR}/f2c)
endif()

set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}/specialcf)

macro( fetch_slatec_function slatec_function )
file(DOWNLOAD http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=slatec%2Fsrc%2F${slatec_function}.f ${BIN_DIR}/${slatec_function}.tgz)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ${BIN_DIR}/${slatec_function}.tgz WORKING_DIRECTORY ${BIN_DIR})
endmacro( fetch_slatec_function )

ExternalProject_Add(
project_fetch_slatec
DEPENDS project_f2c
DOWNLOAD_COMMAND ""
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-DBIN_DIR=${CMAKE_CURRENT_BINARY_DIR}/specialcf
-DNGSOLVE_BINARY_DIR=${NGSOLVE_BINARY_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/src/fetch_and_convert_slatec.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/specialcf/slatec/src
BUILD_COMMAND ""
INSTALL_COMMAND ""
fetch_slatec_function(zbesi)
fetch_slatec_function(zbesj)
fetch_slatec_function(zbesk)
fetch_slatec_function(gamln)
fetch_slatec_function(zbesh)

file(DOWNLOAD http://www.netlib.org/blas/i1mach.f ${BIN_DIR}/slatec/src/i1mach.f)
file(DOWNLOAD http://www.netlib.org/blas/r1mach.f ${BIN_DIR}/slatec/src/r1mach.f)
file(DOWNLOAD http://www.netlib.org/blas/d1mach.f ${BIN_DIR}/slatec/src/d1mach.f)

file(DOWNLOAD http://ab-initio.mit.edu/Faddeeva.cc ${BIN_DIR}/Faddeeva/Faddeeva.cc)
file(DOWNLOAD http://ab-initio.mit.edu/Faddeeva.hh ${BIN_DIR}/Faddeeva/Faddeeva.hh)

file(GLOB SLATEC_SOURCES_FORTRAN ${BIN_DIR}/slatec/src/*.f )

set(SLATEC_SOURCES_C)
foreach(FORTRAN_FILE ${SLATEC_SOURCES_FORTRAN})
string(REGEX REPLACE "\\.f$" ".c" C_FILE ${FORTRAN_FILE})
list(APPEND SLATEC_SOURCES_C ${C_FILE})
endforeach()
message(STATUS "C files: ${SLATEC_SOURCES_C}")

add_custom_target(convert_sources ALL
DEPENDS ${SLATEC_SOURCES_FORTRAN} f2c_exe
COMMAND ${CMAKE_COMMAND} -E make_directory ${BIN_DIR}/slatec/src
COMMAND ${F2C_COMMAND} -a ${SLATEC_SOURCES_FORTRAN} WORKING_DIRECTORY ${BIN_DIR}/slatec/src
BYPRODUCTS ${SLATEC_SOURCES_C}
USES_TERMINAL
)

################################
# Build actual project
ExternalProject_Add(
project_ngsolve_specialcfs
DEPENDS project_f2c project_fetch_slatec
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/specialcf
CMAKE_ARGS -DNGSolve_DIR=${NGSolve_DIR} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} ${CL_ARGS} -DCMAKE_C_FLAGS="-Wno-implicit-function-declaration"
BUILD_ALWAYS 1
)
add_ngsolve_addon(ngsolve_special_functions src/specialcf.cpp ${SLATEC_SOURCES_C} ${CMAKE_CURRENT_BINARY_DIR}/specialcf/Faddeeva/Faddeeva.cc)
add_custom_target(ngsolve_special_functions_convert ALL DEPENDS convert_sources)
target_sources(ngsolve_special_functions PRIVATE ${SLATEC_SOURCES_C})
target_include_directories(ngsolve_special_functions PRIVATE ${BIN_DIR}/slatec/src ${BIN_DIR}/Faddeeva inc ${f2c_SOURCE_DIR}/include ${f2c_BINARY_DIR})
target_compile_definitions(ngsolve_special_functions PRIVATE -DSPECIALCF_LIBRARY_NAME="$<TARGET_LINKER_FILE_NAME:ngsolve_special_functions>")
if(UNIX)
target_compile_options(ngsolve_special_functions PRIVATE -Wno-implicit-function-declaration)
endif()
target_link_libraries(ngsolve_special_functions PRIVATE f2c)
install(TARGETS ngsolve_special_functions DESTINATION ${ADDON_INSTALL_DIR_PYTHON})
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(ngsolve_special_functions PRIVATE -Wno-return-type-c-linkage)
endif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")

4 changes: 2 additions & 2 deletions demo/bessel.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ngsolve_special_functions
from ngsolve import *
from netgen.geom2d import unit_square
import scipy.special as sp
Expand All @@ -6,11 +7,10 @@

mesh = Mesh(unit_square.GenerateMesh(maxh=0.2))

import ngsolve.special_functions

n = 0
while n>=0:
bessel = ngsolve.special_functions.jv(z=(x-0.5)+1j*(y-0.5), v=n)
bessel = ngsolve_special_functions.jv(z=(x-0.5)+1j*(y-0.5), v=n)
Draw(bessel, mesh, 'bessel', sd=5)
n = float(input('Set order (<0 to abort): '))

97 changes: 97 additions & 0 deletions ngsolve_addon.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
###############################################################################
# This file was taken from https://github.com/NGSolve/ngsolve-addon-template
# Make sure to check for updates regularly.
# Don't change anything here (unless you know what you are doing!)
###############################################################################
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Find NGSolve and Netgen using python
if(CMAKE_VERSION VERSION_LESS "3.18")
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
else()
find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module)
endif()


set(Netgen_DIR "" CACHE PATH "Path to directory containing NetgenConfig.cmake")
set(NGSolve_DIR "" CACHE PATH "Path to directory containing NGSolveConfig.cmake")

execute_process(COMMAND ${Python3_EXECUTABLE} -m netgen.config OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE Netgen_DIR)
execute_process(COMMAND ${Python3_EXECUTABLE} -m ngsolve.config OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE NGSolve_DIR)

find_package(NGSolve CONFIG REQUIRED)

macro(add_ngsolve_addon module_name)
# Create the module
add_library(${module_name} SHARED ${ARGN})
target_link_libraries(${module_name} PUBLIC ngsolve Python3::Module)
set_target_properties(${module_name} PROPERTIES PREFIX "" CXX_STANDARD 17)

# Python does not recognize .dll (Windows) and .dylib (MacOS) file endings as modules
if(WIN32)
set_target_properties(${module_name} PROPERTIES SUFFIX ".pyd" )
else(WIN32)
set_target_properties(${module_name} PROPERTIES SUFFIX ".so")
endif(WIN32)
endmacro()

execute_process(COMMAND ${Python3_EXECUTABLE} -c "import sys,sysconfig,os.path; print(os.path.relpath(sysconfig.get_path('platlib'), sys.prefix))"
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE python3_library_dir
)

if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
if(NETGEN_BULID_FOR_CONDA)
# Netgen is assumed to be installed as python package
# Set install prefix to user-base if a user site is available, sys.prefix otherwise
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import sys; print(sys.prefix)"
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE install_prefix
)
execute_process(COMMAND ${Python3_EXECUTABLE} -m site --user-base
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE user_base RESULT_VARIABLE ret
)
if (ret EQUAL 0)
set(install_prefix ${user_base})
endif()
set(CMAKE_INSTALL_PREFIX ${install_prefix}/${python3_library_dir} CACHE PATH "Install dir" FORCE)
else()
# Netgen is self-compiled -> install into Netgen directory
set(CMAKE_INSTALL_PREFIX ${NETGEN_DIR} CACHE PATH "Install prefix" FORCE)
endif()
set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OFF)
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)

if(SKBUILD_PLATLIB_DIR)
set(ADDON_INSTALL_DIR_PYTHON ${SKBUILD_PLATLIB_DIR})
set(ADDON_INSTALL_DIR_BIN ${SKBUILD_DATA_DIR}/bin)
set(ADDON_INSTALL_DIR_INCLUDE ${SKBUILD_DATA_DIR}/include)
set(ADDON_INSTALL_DIR_LIB ${SKBUILD_DATA_DIR}/lib)
set(ADDON_INSTALL_DIR_RES ${SKBUILD_DATA_DIR}/share)
set(ADDON_INSTALL_DIR_CMAKE ${SKBUILD_DATA_DIR}/lib/cmake)
set(stubgen_working_dir ${SKBUILD_PLATLIB_DIR})
elseif(NETGEN_BUILD_FOR_CONDA)
set(stubgen_working_dir ${CMAKE_INSTALL_PREFIX})
set(ADDON_INSTALL_DIR_PYTHON ${python3_library_dir})
set(ADDON_INSTALL_DIR_BIN bin)
set(ADDON_INSTALL_DIR_INCLUDE include)
set(ADDON_INSTALL_DIR_LIB lib)
set(ADDON_INSTALL_DIR_RES share)
set(ADDON_INSTALL_DIR_CMAKE lib/cmake)
else()
set(stubgen_working_dir ${CMAKE_INSTALL_PREFIX}/${NETGEN_INSTALL_DIR_PYTHON})
set(ADDON_INSTALL_DIR_PYTHON ${NETGEN_INSTALL_DIR_PYTHON})
set(ADDON_INSTALL_DIR_BIN ${NETGEN_INSTALL_DIR_BIN})
set(ADDON_INSTALL_DIR_INCLUDE ${NETGEN_INSTALL_DIR_INCLUDE})
set(ADDON_INSTALL_DIR_LIB ${NETGEN_INSTALL_DIR_LIB})
set(ADDON_INSTALL_DIR_RES ${NETGEN_INSTALL_DIR_RES})
set(ADDON_INSTALL_DIR_CMAKE ${NETGEN_INSTALL_DIR_CMAKE})
endif()

macro(ngsolve_generate_stub_files module_name)
set(stubgen_generation_code "execute_process(WORKING_DIRECTORY ${stubgen_working_dir} COMMAND ${Python3_EXECUTABLE} -m pybind11_stubgen --ignore-all-errors -o ${CMAKE_CURRENT_BINARY_DIR}/stubs ${module_name})")
set(stubgen_directory "${CMAKE_CURRENT_BINARY_DIR}/stubs/${module_name}/")

install(CODE ${stubgen_generation_code})
install(DIRECTORY ${stubgen_directory} DESTINATION ${ADDON_INSTALL_DIR_PYTHON}/${module_name})
endmacro()

message(STATUS "Install dir: ${CMAKE_INSTALL_PREFIX}")
46 changes: 46 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Here is the project metadata, adapt it to your needs
[project]
name = "ngsolve_special_functions"
description="Additional coefficient functions based on slatec"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [] # ngsolve will be added automatically
dynamic = ["version", "dependencies"]
classifiers = [
"License :: OSI Approved :: MIT License",
]

# Update NGSolve when you rely on newer features, but keep the '>=' to allow also newer versions
# Maybe you also need to add other requirements to build your package
[build-system]
requires = ["ngsolve>=6.2.2404.post16", "scikit-build-core>=0.9.0", "pybind11_stubgen", "cmake", "toml"]
build-backend = "scikit_build_core.build"

##########################################################################
# Settings for cibuildwheel to build .whl files for Windows/Mac/Linxu
# DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU ARE DOING
##########################################################################

[tool.scikit-build]
experimental = true
metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
metadata.dependencies.provider="ngsolve._scikit_build_core_dependencies"

[tool.setuptools_scm]
local_scheme = "no-local-version"

[tool.cibuildwheel]
skip = """
pp*
*_i686
*musllinux*
*win32
"""

[tool.cibuildwheel.linux]
repair-wheel-command = "mv {wheel} {dest_dir} && rename linux_x86_64 manylinux_2_17_x86_64.manylinux2014_x86_64 {dest_dir}/*-linux_x86_64*.whl"

[tool.cibuildwheel.macos]
environment = {MACOSX_DEPLOYMENT_TARGET="10.15"}
repair-wheel-command = ""
archs = ["universal2"]
Loading

0 comments on commit 078c81f

Please sign in to comment.