Skip to content

Commit

Permalink
Use CMake and cibuildwheel (#3)
Browse files Browse the repository at this point in the history
Switch build system to CMake and use cibuildwheel for building wheels.
Other notable changes:

* remove setup.py and various requirements.txt
* replace autotools with CMake
* remove various helper scripts
* move `class_public` and `cuba` submodules to `external` dir
* move `coffe` to `python/coffe`
* fix C-based tests
* add CI action for building wheels (EXPERIMENTAL!)
* update README.md
  • Loading branch information
JCGoran authored Sep 1, 2024
2 parents f4e0619 + 80500d4 commit 7cb95f0
Show file tree
Hide file tree
Showing 45 changed files with 1,112 additions and 813 deletions.
13 changes: 6 additions & 7 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,25 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true

# Install dependencies
- name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.9

- name: Install Poetry
uses: snok/install-poetry@v1

- name: Install dependencies
run: |
python3 -m pip install coffe
python3 -m pip install -r pip-requirements-dev.txt
python3 -m pip install cibuildwheel
SETUPTOOLS_SCM_PRETEND_VERSION=0.1.0 CIBW_BUILD='cp39*' python3 -m cibuildwheel --platform linux
python3 -m pip install wheelhouse/*.whl
# Build the site
- name: Build the site
run: |
rm -fr coffe/__init__.py
sh generate_docs.sh
bash scripts/generate_docs.sh
# If we've pushed to master, push the book's HTML to github-pages
- if: ${{ github.ref == 'refs/heads/master' }}
Expand Down
62 changes: 62 additions & 0 deletions .github/workflows/build-wheels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Build

on:
pull_request:
push:
branches:
- master
workflow_dispatch:
inputs:
version:
description: 'The version of COFFE to release'

jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-13, macos-14]

steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Setup all external dependencies
if: runner.os == 'macOS'
run: |
brew install automake
# Used to host cibuildwheel
- uses: actions/setup-python@v3

- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.16.5 conan

# if we're not doing a release version (manual!), only build one python version
- name: Setup versions
if: ${{ ! (github.event_name == 'workflow_dispatch' && github.event.inputs.version) }}
run: |
echo "CIBW_BUILD=cp311-*" >> "$GITHUB_ENV"
# pretend version so setuptools doesn't fail
echo "SETUPTOOLS_SCM_PRETEND_VERSION=0.1.0" >> "$GITHUB_ENV"
- name: SCM
if: github.event_name == 'workflow_dispatch' && github.event.inputs.version
run: echo "SETUPTOOLS_SCM_PRETEND_VERSION=${{ github.event.input.version }}" >> "$GITHUB_ENV"

- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
# to supply options, put them in 'env', like:
env:
# we skip tests in CI to save time
CIBW_TEST_COMMAND: 'true'
CIBW_ENVIRONMENT_PASS_LINUX: 'SETUPTOOLS_SCM_PRETEND_VERSION'
CUBA_INSTALL_DIR: ${{ github.workspace }}/cuba_install
CLASS_INSTALL_DIR: ${{ github.workspace }}/class_install

- uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[submodule "class_public"]
path = class_public
path = external/class_public
url = https://github.com/JCGoran/class_public
branch = feature/conda
[submodule "libcuba"]
path = libcuba
path = external/libcuba
url = https://github.com/JCGoran/libcuba
branch = master
248 changes: 248 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
cmake_minimum_required(VERSION 3.10)
project(
coffe
VERSION ${SKBUILD_PROJECT_VERSION}
LANGUAGES C)

# Default build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

# Add the option to disable silent rules
option(DISABLE_SILENT_RULES "Disable silent rules" OFF)
if(NOT DISABLE_SILENT_RULES)
set(CMAKE_VERBOSE_MAKEFILE OFF)
endif()

# Get the current arch (because MacOS can have both)
execute_process(
COMMAND uname -m
COMMAND tr -d '\n'
OUTPUT_VARIABLE BUILD_ARCHITECTURE)

# Check whether the user requested Python
if(COFFE_ENABLE_PYTHON)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND (DEFINED CONAN_C_FLAGS
OR DEFINED CONAN_CXX_FLAGS))
# For some reason, Conan does not find Python from the venv on MacOS, so we
# need to use this annoying hack. Note that this does not guarantee that the
# Python executable is the one from the venv, but at least it finds the one
# compatible with all of the packages from the venv
find_package(
Python "3.${COFFE_PYTHON_MINOR_VERSION}" EXACT
COMPONENTS Interpreter Development.Module
REQUIRED)
else()
find_package(
Python
COMPONENTS Interpreter Development.Module
REQUIRED)
endif()
include(cmake/FindCython.cmake)
endif()

# Define source directory
set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)

# Compiler flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic")
set(CMAKE_C_STANDARD 99)

# Check for libraries
find_package(GSL 2.1 REQUIRED)
find_library(FFTW3_LIB fftw3 NAMES fftw fftw3 libfftw libfftw3 REQUIRED)
find_library(CONFIG_LIB config NAMES config config++ libconfig libconfig++
REQUIRED)
find_library(M_LIB m NAMES m libm REQUIRED)
set(CONFIG_INCLUDE_DIRS)
set(FFTW3_INCLUDE_DIRS)
set(CUBA_INCLUDE_DIRS)
set(CLASS_INCLUDE_DIRS)

# Check for optional libraries
if(COFFE_ENABLE_CUBA)
find_library(
CUBA_LIB cuba
NAMES cuba libcuba
PATHS /opt/cuba_${BUILD_ARCHITECTURE}/lib $ENV{CUBA_INSTALL_DIR}/lib
REQUIRED)
endif()
if(COFFE_ENABLE_CLASS)
find_library(
CLASS_LIB class
NAMES class libclass
PATHS /opt/class_${BUILD_ARCHITECTURE}/lib
/opt/class_public_${BUILD_ARCHITECTURE}/lib
$ENV{CLASS_INSTALL_DIR}/lib REQUIRED)
endif()

get_filename_component(BASE_DIR ${CONFIG_LIB} DIRECTORY)
string(REGEX REPLACE "/lib$" "/include" CONFIG_INCLUDE_DIRS ${BASE_DIR})

get_filename_component(BASE_DIR ${FFTW3_LIB} DIRECTORY)
string(REGEX REPLACE "/lib$" "/include" FFTW3_INCLUDE_DIRS ${BASE_DIR})

get_filename_component(BASE_DIR ${CLASS_LIB} DIRECTORY)
string(REGEX REPLACE "/lib$" "/include" CLASS_INCLUDE_DIRS ${BASE_DIR})

get_filename_component(BASE_DIR ${CUBA_LIB} DIRECTORY)
string(REGEX REPLACE "/lib$" "/include" CUBA_INCLUDE_DIRS ${BASE_DIR})

# OpenMP support
find_package(OpenMP)
if(OpenMP_C_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
endif()

# Optimization flags
include(CheckCCompilerFlag)
if(COFFE_ENABLE_MATHOPTS)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(COFFE_MATHOPTS "-ffast-math")
endif()
else()
set(COFFE_MATHOPTS)
endif()
# Add definitions for conditional compilation
if(COFFE_ENABLE_CLASS)
add_compile_definitions(-DHAVE_CLASS)
endif()
if(COFFE_ENABLE_CUBA)
add_compile_definitions(-DHAVE_CUBA)
endif()

message("COFFE configuration")
message("============================")
message("Build architecture: ${BUILD_ARCHITECTURE}")
message("Math library: ${M_LIB}")
message("GSL library: ${GSL_LIBRARIES}")
message("FFTW library: ${FFTW3_LIB}")
message("libconfig library: ${CONFIG_LIB}")
if(COFFE_ENABLE_PYTHON)
message("Python path: ${Python_EXECUTABLE}")
message("Cython path: ${CYTHON_EXECUTABLE}")
endif()
if(COFFE_ENABLE_CLASS)
message("CLASS library: ${CLASS_LIB}")
endif()
if(COFFE_ENABLE_CUBA)
message("CUBA library: ${CUBA_LIB}")
endif()
message("OpenMP enabled: ${OpenMP_C_FOUND}")
message("Additional optimizations: ${COFFE_MATHOPTS}")

set(COFFE_HEADERS
${SRC_DIR}/common.h
${SRC_DIR}/covariance.h
${SRC_DIR}/utils.h
${SRC_DIR}/twobessel.h
${SRC_DIR}/errors.h
${SRC_DIR}/parser.h
${SRC_DIR}/twofast.h
${SRC_DIR}/integrals.h
${SRC_DIR}/background.h
${SRC_DIR}/functions.h
${SRC_DIR}/tanhsinh.h
${SRC_DIR}/signal.h
${SRC_DIR}/corrfunc.h
${SRC_DIR}/multipoles.h
${SRC_DIR}/average_multipoles.h)

set(COFFE_LIB_SOURCES
${SRC_DIR}/common.c
${SRC_DIR}/covariance.c
${SRC_DIR}/utils.c
${SRC_DIR}/twobessel.c
${SRC_DIR}/errors.c
${SRC_DIR}/parser.c
${SRC_DIR}/twofast.c
${SRC_DIR}/integrals.c
${SRC_DIR}/background.c
${SRC_DIR}/functions.c
${SRC_DIR}/tanhsinh.c
${SRC_DIR}/signal.c
${SRC_DIR}/corrfunc.c
${SRC_DIR}/multipoles.c
${SRC_DIR}/average_multipoles.c)

# Main program
add_executable(coffe-cli ${SRC_DIR}/main.c ${COFFE_LIB_SOURCES}
${SRC_DIR}/output.c)

# Include directories
target_include_directories(
coffe-cli PRIVATE ${CONFIG_INCLUDE_DIRS} ${FFTW3_INCLUDE_DIRS}
${CUBA_INCLUDE_DIRS} ${SRC_DIR} ${CLASS_INCLUDE_DIRS})

# Add definition
target_compile_definitions(coffe-cli PRIVATE PACKAGE_STRING="${VERSION}")

# Link libraries
target_link_libraries(
coffe-cli
${M_LIB}
${GSL_LIBRARIES}
${FFTW3_LIBRARIES}
${FFTW3_LIB}
${libconfig_LIBRARIES}
${CONFIG_LIB}
${CUBA_LIB}
${CLASS_LIB})

target_compile_options(coffe-cli PRIVATE ${COFFE_MATHOPTS})

# Tests
if(COFFE_ENABLE_TESTS)
enable_testing()

if(NOT DEFINED COFFE_TEST_DATADIR)
set(COFFE_TEST_DATADIR ${CMAKE_SOURCE_DIR})
endif()

set(COFFE_TESTS background integrals corrfunc multipoles covariance)
foreach(name IN LISTS COFFE_TESTS)
# Add the test executable
add_executable(test_${name} ${CMAKE_SOURCE_DIR}/tests/test_${name}.c
${COFFE_LIB_SOURCES})
target_include_directories(
test_${name}
PRIVATE ${CONFIG_INCLUDE_DIRS} ${FFTW3_INCLUDE_DIRS} ${CUBA_INCLUDE_DIRS}
${SRC_DIR} ${CLASS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/tests)
# Add defines
target_compile_definitions(
test_${name} PRIVATE COFFE_TEST_DATADIR="${COFFE_TEST_DATADIR}")
# Link libraries
target_link_libraries(
test_${name}
${M_LIB}
${GSL_LIBRARIES}
${FFTW3_LIB}
${CONFIG_LIB}
${CUBA_LIB}
${CLASS_LIB})
# Register tests
add_test(NAME test_${name} COMMAND test_${name})
endforeach()
endif()

if(COFFE_ENABLE_PYTHON)
add_subdirectory(${CMAKE_SOURCE_DIR}/python/coffe)
endif()

# Installation
if(NOT SKBUILD)
install(
TARGETS coffe-cli
COMPONENT Runtime
DESTINATION bin)

# Install headers and other files
install(FILES ${COFFE_HEADERS} DESTINATION include/coffe)

install(
FILES ${SRC_DIR}/WAVENUMBER_HEADER.dat ${SRC_DIR}/POWER_SPECTRUM_HEADER.dat
${CMAKE_SOURCE_DIR}/settings.cfg ${CMAKE_SOURCE_DIR}/separations.dat
${CMAKE_SOURCE_DIR}/PkL_CLASS.dat ${CMAKE_SOURCE_DIR}/README.md
DESTINATION share/coffe)
endif()
Loading

0 comments on commit 7cb95f0

Please sign in to comment.