Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setup.py #40

Merged
merged 18 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/build-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ name: build-docker-image

on:
workflow_dispatch:
pull_request:
push:
branches:
- main
Expand Down
41 changes: 21 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,29 @@ name: continuous-integration
on: [push, pull_request]

jobs:
test-package:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
test-package:
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository }}/ci-image:latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]

steps:
- name: Check out repository
uses: actions/checkout@v4
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install package and its dependencies
run: pip install -e .[dev]
- name: Install package and its dependencies
run: python3 -m pip install -e .[dev]

- name: Run pytest
run: pytest -v --cov --cov-report json
- name: Run pytest
run: pytest -v --cov --cov-report json

- name: Upload coverage report
uses: codecov/codecov-action@v3
with:
flags: python-${{ matrix.python-version }}
- name: Upload coverage report
uses: codecov/codecov-action@v3
with:
flags: python-${{ matrix.python-version }}
8 changes: 3 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# Use Ubuntu as the base image
FROM ubuntu:latest AS base
FROM alpine:latest AS base

# Install build-essential, cmake, and OpenBLAS
RUN apt-get update && \
apt-get install -y build-essential cmake libopenblas-dev
RUN apk update && \
apk add --no-cache build-base cmake openblas-dev python3
4 changes: 2 additions & 2 deletions cleedpy/cleed/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ set(CMAKE_C_STANDARD 90)
set(CMAKE_C_STANDARD_REQUIRED True)

# Set the output directories
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

# Where to find CMake modules
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
Expand Down
31 changes: 26 additions & 5 deletions cleedpy/interface/cleed.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import math
from ctypes import POINTER, Structure, c_char_p, c_double, c_int, cdll
import pathlib as pl
import platform
from ctypes import CDLL, POINTER, Structure, c_char_p, c_double, c_int, cdll
from dataclasses import dataclass
from pathlib import Path

from ..config import (
AtomParametersStructured,
Expand Down Expand Up @@ -188,9 +189,29 @@ def generate_crystal_structure(inp: AtomParametersVariants) -> Crystal:
raise ValueError("Not implemented")


def call_cleed():
path = Path(__file__).parent.parent / "cleed" / "build" / "lib" / "libcleed.dylib"
lib = cdll.LoadLibrary(str(path))
def get_cleed_lib() -> CDLL:
lib_path = pl.Path(__file__).parent.parent / "cleed" / "lib"

lib_exts = {
"Windows": ".dll",
"Darwin": ".dylib",
"Linux": ".so",
}

try:
cleed_lib = (
(lib_path / "libcleed").with_suffix(lib_exts[platform.system()]).as_posix()
)
except KeyError as err:
raise ValueError(
f"Platform {platform.system()} not supported by cleedpy"
) from err

return cdll.LoadLibrary(cleed_lib)


def call_cleed() -> None:
lib = get_cleed_lib()

lib.my_test_function.argtypes = [c_int, c_int, POINTER(Crystal)]
lib.my_test_function.restype = c_int
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools>=61.2"]
requires = ["setuptools>=61.2", "cmake>=3.5"]
build-backend = "setuptools.build_meta"


Expand Down
77 changes: 77 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import os
import pathlib as pl
import platform
import subprocess
import sys

from setuptools import Extension, setup
from setuptools.command.build_ext import build_ext


class CMakeExtension(Extension):
def __init__(self, name, source_dir=""):
Extension.__init__(self, name, sources=[])
self.source_dir = pl.Path(source_dir).absolute()


class CMakeBuild(build_ext):
def run(self):
try:
subprocess.check_output(["cmake", "--version"])
except subprocess.CalledProcessError as err:
raise RuntimeError(
"CMake must be installed to build the following extensions: "
+ ", ".join(e.name for e in self.extensions)
) from err

for ext in self.extensions:
self.build_extension(ext)

def build_extension(self, ext: CMakeExtension):
ext_dir = pl.Path(self.get_ext_fullpath(ext.name)).parent.absolute()

cmake_args = ["-DPYTHON_EXECUTABLE=" + sys.executable]

cfg = "Debug" if self.debug else "Release"
build_args = ["--config", cfg]

if platform.system() == "Windows":
cmake_args += [f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{cfg.upper()}={ext_dir}"]
if sys.maxsize > 2**32:
# We are on a Win 64-bit system
cmake_args += ["-A", "x64"]
build_args += ["--", "/m"]
else:
# These flags are passed as-is to the underlying build tool (make)
build_args += ["--", "-j2"]

env = os.environ.copy()
env["CXXFLAGS"] = '{} -DVERSION_INFO="{}"'.format(
env.get("CXXFLAGS", ""), self.distribution.get_version()
)

build_dir = pl.Path(self.build_temp)
build_dir.mkdir(parents=True, exist_ok=True)

try:
subprocess.check_call(
["cmake", "-S", ext.source_dir.as_posix(), "-B", "."] + cmake_args,
cwd=build_dir,
env=env,
)
subprocess.check_call(["cmake", "--build", "."] + build_args, cwd=build_dir)
except subprocess.CalledProcessError as err:
raise RuntimeError(f"CMake error: {err}") from err


setup(
name="cleedpy",
ext_modules=[
CMakeExtension(
"cleed", (pl.Path(__file__).parent / "cleedpy" / "cleed").as_posix()
)
],
cmdclass={"build_ext": CMakeBuild},
# The following includes *any* library file found in the package directory
package_data={"cleedpy": ["**/*.dylib", "**/*.so", "**/*.dll"]},
)