Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
if: ${{ matrix.py == '3.9'}}
# Ensure these versions are consistent with the minimal version requirements
# in pyproject.toml
run: pip install numpy==1.22 scipy==1.11.1
run: pip install numpy==2.0 scipy==1.13.0
- name: Install development version
run: |
# Need editable mode in order to include the test files
Expand Down
101 changes: 101 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# CMakeLists.txt — Build C extension for GBasis libcint integration (Issue: #229)

# Usage:
# Default (all platforms): pip install qc-gbasis
# qcint (x86+AVX2 only): pip install qc-gbasis -C cmake.args="-DUSE_QCINT=ON"


cmake_minimum_required(VERSION 3.17)
project(gbasis_libcint C)

# Python and NumPy are required to build the C extension module

find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
find_package(Python COMPONENTS NumPy REQUIRED)

# Get NumPy include path for C extension (numpy/arrayobject.h)

execute_process(
COMMAND "${Python_EXECUTABLE}" "-c"
"import numpy; print(numpy.get_include())"
OUTPUT_VARIABLE NumPy_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# ── Platform Detection — x86 vs ARM ──────────────────────
# Detect platform: use qcint on x86+AVX2, libcint on ARM/non-AVX
# qcint is an optimized version of libcint for x86 with SIMD support
include(CheckCCompilerFlag)

if(MSVC)
check_c_compiler_flag("/arch:AVX2" HAS_AVX2)
else()
check_c_compiler_flag("-mavx2" HAS_AVX2)
endif()

# Respect user override via -DUSE_QCINT=ON/OFF; otherwise auto-detect
if(NOT DEFINED USE_QCINT)
if(HAS_AVX2 AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
set(USE_QCINT ON CACHE BOOL "Use qcint instead of libcint" FORCE)
message(STATUS "Architecture: x86 + AVX2 detected — use qcint")
else()
set(USE_QCINT OFF CACHE BOOL "Use qcint instead of libcint" FORCE)
message(STATUS "Architecture: ARM/non-AVX detected — use libcint")
endif()
endif()


# Download libcint or qcint based on platform detection
# Both are pinned to v6.1.2 for stability
# qcint: optimized for x86+AVX2
# libcint: generic, works on all platforms

include(FetchContent)

if(USE_QCINT)
FetchContent_Declare(
libcint
GIT_REPOSITORY https://github.com/sunqm/qcint.git
GIT_TAG v6.1.2
)
else()
FetchContent_Declare(
libcint
GIT_REPOSITORY https://github.com/sunqm/libcint.git
GIT_TAG v6.1.2
)
endif()

# Compile libcint — Fortran disabled, range-separated Coulomb enabled

set(WITH_FORTRAN OFF CACHE BOOL "" FORCE)
# Enable range-separated Coulomb integrals
set(WITH_RANGE_COULOMB ON CACHE BOOL "" FORCE)

# Redirect libcint's install to build directory to avoid permission issues
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/local" CACHE PATH "" FORCE)
set(SKIP_INSTALL_ALL ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(libcint)

# Build Python C extension module from libcint_wrap.c
python_add_library(libcint_bindings MODULE
gbasis/integrals/src/libcint_wrap.c
WITH_SOABI
)

# Include NumPy and libcint headers
target_include_directories(libcint_bindings PRIVATE
${NumPy_INCLUDE_DIRS}
${libcint_SOURCE_DIR}/include
)

# Link C extension with libcint
target_link_libraries(libcint_bindings PRIVATE cint)

# Prevent libcint from installing to system directories
set(CINT_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/cint_install CACHE PATH "" FORCE)

# Install only the Python extension into the wheel
install(TARGETS libcint_bindings
LIBRARY DESTINATION ${SKBUILD_PLATLIB_DIR}/gbasis/integrals/lib
)
Comment on lines +92 to +101

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be addressed in the next PR which adds the platform-aware libcint shared library copying alongside the extension.

6 changes: 6 additions & 0 deletions gbasis/integrals/src/libcint_wrap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@


/* libcint Python/C API bindings.
* The full bindings will be implemented in a follow-up PR.
*/

58 changes: 44 additions & 14 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Replaced setuptools with scikit-build-core
# Reason: use a CMake-based build (via scikit-build-core) to compile and bundle libcint/qcint
# as part of the Python wheel build

[build-system]
requires = ["setuptools>=64", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"
requires = ["numpy>=2.0", "scikit-build-core>=0.9","setuptools-scm>=8"]
build-backend = "scikit_build_core.build"
Comment on lines 5 to +7

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added setuptools-scm to [build-system].requires.




[project]
name = "qc-gbasis"
Expand Down Expand Up @@ -31,18 +37,38 @@ classifiers = [
"Programming Language :: Python :: 3.12",
]
dependencies = [
# Ensure the minimal versions are kept consistent with those in .github/workflows/pytest.yaml
"numpy >=1.22, <2.0.0; platform_system=='Windows'",
"numpy >=1.22; platform_system=='Linux'",
"scipy>=1.11.1",
# Updated to numpy>=2.0 required for scikit-build-core C extension support
# Note: Keep consistent with .github/workflows/pytest.yaml
"numpy>=2.0",
"scipy>=1.13.0",
"importlib_resources",
"sympy",
Comment on lines 39 to 45

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raised scipy minimum to 1.13.0 which added NumPy 2.x support.

]
dynamic = ["version"]

[tool.scikit-build]
# Build type: Release for optimized production build (no debug symbols)
cmake.build-type = "Release"

# Replaces [tool.setuptools.packages.find] from old setuptools config
# Only pack gbasis folder in the wheel
wheel.packages = ["gbasis"]



[tool.scikit-build.metadata.version]
# Automatically get version from git tags via setuptools_scm
provider = "scikit_build_core.metadata.setuptools_scm"

# Required to activate setuptools_scm for automatic versioning from git tags
[tool.setuptools_scm]



[project.optional-dependencies]

# Install with: pip install qc-gbasis[dev]

dev = [
"tox",
"pre-commit",
Expand All @@ -56,29 +82,36 @@ dev = [
"sphinx_autodoc_typehints",
"sphinx-copybutton",
]

# Install with: pip install qc-gbasis[doc]

doc = [
"numpydoc",
"sphinx_copybutton",
"sphinx-autoapi",
"nbsphinx",
"sphinx_rtd_theme",
"sphinx_autodoc_typehints",
"docutils==0.16", # Needed to show bullet points in sphinx_rtd_theme
"docutils==0.16", # Needed to show bullet points in sphinx_rtd_theme
"nbsphinx-link"
]

# iodata = [
# "qc-iodata@git+https://github.com/theochem/iodata.git@main"
# ]

# Install with: pip install qc-gbasis[iodata]

iodata = [
"qc-iodata>=1.0.0a5"
]

# Install with: pip install qc-gbasis[pyscf]

pyscf = [
"pyscf>=1.6.1"
]

[tool.setuptools.packages.find]
where = ["."] # list of folders that contain the packages (["."] by default)
include = ["gbasis"] # package names should match these glob patterns (["*"] by default)

[project.urls]
Documentation = "https://gbasis.qcdevs.org"
Expand Down Expand Up @@ -112,7 +145,4 @@ addopts = "-v"
#[tool.setuptools_scm]
#write_to = "src/gbasis/_version.py"
#version_scheme = "post-release"
#local_scheme = "no-local-version"

[tool.setuptools.package-data]
gbasis = ["integrals/include/cint*.h", "integrals/lib/libcint.so*"]
#local_scheme = "no-local-version"
Loading