Skip to content

Commit

Permalink
chore: Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lewisjared committed Apr 9, 2024
0 parents commit de7bc73
Show file tree
Hide file tree
Showing 39 changed files with 4,891 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .cmakelang.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
format:
# If a statement is wrapped to more than one line, than dangle
dangle_parens: true
# How wide to allow formatted cmake files
line_width: 110
# If the statement spelling length (including space and
# parenthesis) is smaller than this amount, then force reject
# nested layouts.
min_prefix_chars: 0
# If the statement spelling length (including space and
# parenthesis) is larger than the tab width by more than this
# amount, then force reject un-nested layouts.
max_prefix_chars: 0
max_pargs_hwrap: 1
12 changes: 12 additions & 0 deletions .copier-answers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changes here will be overwritten by Copier
_commit: da4fb5e
_src_path: ../copier-fgen-based-repository
email: [email protected]
extension_module_name: _lib
initial_setup: true
name: Jared Lewis
project_description_short: Example project using fgen to wrap a simple module
project_name_human: Fgen Example
project_name_pip: fgen-example
project_name_python: fgen_example
project_url: https://gitlab.com/magicc/fgen-example
150 changes: 150 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# fgen
fgen

# Notebooks
*.ipynb

# Databases
*.db

# Jupyter cache
.jupyter_cache

# IDE stuff
.idea/

# Licence check
licence-check.txt

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# Mac stuff
*.DS_Store
53 changes: 53 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: 'v4.4.0'
hooks:
- id: check-added-large-files
- id: check-ast
- id: check-case-conflict
- id: check-json
- id: check-merge-conflict
- id: check-symlinks
- id: check-yaml
- id: debug-statements
- id: detect-private-key
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: trailing-whitespace
- repo: local
hooks:
# Prevent committing .rej files
- id: forbidden-files
name: forbidden files
entry: found Copier update rejection files; review them and remove them
language: fail
files: "\\.rej$"
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.1.8'
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]
- id: ruff-format
- repo: https://github.com/python-poetry/poetry
rev: '1.4.2'
hooks:
- id: poetry-check
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: 'v0.6.10'
hooks:
- id: cmake-format
files: "CMakeLists.txt$"
entry: cmake-format -c .cmakelang.yaml
additional_dependencies: [ pyyaml ]

- id: cmake-lint
files: "CMakeLists.txt$"
entry: cmake-format -c .cmakelang.yaml
additional_dependencies: [ pyyaml ]
- repo: https://github.com/pseewald/fprettify
rev: 'v0.3.7'
hooks:
- id: fprettify
123 changes: 123 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# TODO: auto-generate this with fgen instead (I think that makes more sense because fgen can actually set the
# dependency files , install paths etc. correctly, related to https://gitlab.com/magicc/fgen/-/issues/2)
cmake_minimum_required(VERSION 3.17.2...3.26)

project(
${SKBUILD_PROJECT_NAME}
LANGUAGES C
Fortran
)

list(
APPEND
CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
)

find_package(
"fgen"
REQUIRED
)

# Get information about the current python installation
find_package(
Python
COMPONENTS
Interpreter
Development.Module
NumPy
REQUIRED
)

# Find f2py header files
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" -c "import numpy.f2py; print(numpy.f2py.get_include())"
OUTPUT_VARIABLE F2PY_INCLUDE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# Variables to hold the identified sources
set(ANCILLARY_FORTRAN_SOURCES)
set(WRAPPED_FORTRAN_SOURCES)

# ~~~
# Find the required sources to build the extension.
# This also generates the required wrapper code
# and adds the required sources to
# ANCILLARY_FORTRAN_SOURCES and WRAPPED_FORTRAN_SOURCES
# (implicitly, so this could be considered to be a side-effect).
# ~~~
include(src/fgen_example/_lib/CMakeLists.txt)

# ------------------------------------
# TODO: discuss and document the below (xref
# https://gitlab.com/magicc/copier-fgen-based-repository/-/merge_requests/4#note_1696739902)
#
# extension_module_name: the name of the extension module that will be available from Python, usually a more
# generic name like _lib

# _lib build

add_library(
${SKBUILD_PROJECT_NAME}-lib
STATIC
${ANCILLARY_FORTRAN_SOURCES}
)

# TODO: add explanation of why this is useful (somewhat related to
# https://gitlab.com/magicc/copier-fgen-based-repository/-/issues/6)
set_target_properties(
${SKBUILD_PROJECT_NAME}-lib
PROPERTIES POSITION_INDEPENDENT_CODE
ON
)

add_custom_command(
OUTPUT ${EXTENSION_MODULE_NAME}module.c
${EXTENSION_MODULE_NAME}-f2pywrappers2.f90
DEPENDS ${WRAPPED_FORTRAN_SOURCES}
VERBATIM
COMMAND "${Python_EXECUTABLE}" -m numpy.f2py ${WRAPPED_FORTRAN_SOURCES} -m ${EXTENSION_MODULE_NAME} --lower
COMMENT "Run f2py to generate Python-Fortran interface files"
)

# when linking _lib, search for fgen here
target_link_directories(
${SKBUILD_PROJECT_NAME}-lib
PUBLIC
${FGEN_LIB_DIR}
)

# when linking _lib, use libfgen (CMake info https://cmake.org/cmake/help/v3.17/guide/tutorial/index.html)
target_link_libraries(${SKBUILD_PROJECT_NAME}-lib PUBLIC "fgen::fgen")

# Create a compiled Python extension using the f2py generated code
python_add_library(
${EXTENSION_MODULE_NAME}
MODULE
"${CMAKE_CURRENT_BINARY_DIR}/${EXTENSION_MODULE_NAME}module.c"
"${CMAKE_CURRENT_BINARY_DIR}/${EXTENSION_MODULE_NAME}-f2pywrappers2.f90"
${WRAPPED_FORTRAN_SOURCES}
"${F2PY_INCLUDE_DIR}/fortranobject.c"
WITH_SOABI
)
target_link_libraries(
${EXTENSION_MODULE_NAME}
PUBLIC Python::NumPy
"fgen::fgen"
)
target_include_directories(${EXTENSION_MODULE_NAME} PUBLIC "${F2PY_INCLUDE_DIR}")

# If you are interested, here is an incredibly helpful page to understand why some inclusions/links are public
# and others are private:
# https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#transitive-usage-requirements Our
# translation: the extension module doesn't have any `use fgen` statement, but it won't run without fgen i.e.
# fgen is used by its implementation, but the extension module doesn't use any fgen header files hence
# private. In contrast, the extension module needs numpy's header files so in this we have to use the public
# identifier.
target_link_libraries(${EXTENSION_MODULE_NAME} PRIVATE "${SKBUILD_PROJECT_NAME}-lib")

# Installation location configuration (i.e. where should things be installed) Known limitation of
# scikit-build-core: it doesn't really work with editable installs in expected way always. See
# https://scikit-build-core.readthedocs.io/en/latest/configuration.html#editable-installs
install(TARGETS ${EXTENSION_MODULE_NAME} DESTINATION ${SKBUILD_PROJECT_NAME})
Loading

0 comments on commit de7bc73

Please sign in to comment.