diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38a49b60219..75e0b785908 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,9 +34,9 @@ jobs: vectfit: [n] include: - - python-version: "3.12" - omp: n - mpi: n + # - python-version: "3.12" + # omp: n + # mpi: n - python-version: "3.13" omp: n mpi: n @@ -64,7 +64,7 @@ jobs: mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }}, libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }} vectfit=${{ matrix.vectfit }})" - + continue-on-error: true env: MPI: ${{ matrix.mpi }} PHDF5: ${{ matrix.mpi }} @@ -110,6 +110,7 @@ jobs: COMMIT_MESSAGE=$(git log $BRANCH_SHA -1 --pretty=%B | tr '\n' ' ') echo ${COMMIT_MESSAGE} echo "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV - name: Apt dependencies shell: bash diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 3578144b254..a21bf9006b3 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,6 +4,11 @@ build: os: "ubuntu-24.04" tools: python: "3.12" + apt_packages: + - g++ + - cmake + - libhdf5-dev + - libpng-dev jobs: post_checkout: - git fetch --unshallow || true diff --git a/CMakeLists.txt b/CMakeLists.txt index 461abe508ab..815a60afcab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16 FATAL_ERROR) +cmake_minimum_required(VERSION 3.18 FATAL_ERROR) project(openmc C CXX) # Set module path @@ -299,23 +299,48 @@ include(GNUInstallDirs) # installed one in CMAKE_INSTALL_PREFIX. Ref: # https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling -# use, i.e. don't skip the full RPATH for the build tree -set(CMAKE_SKIP_BUILD_RPATH FALSE) -# when building, don't use the install RPATH already -# (but later on when installing) -set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) +if(SKBUILD) + # By default, scikit-build will install everything to ${SKBUILD_PLATLIB_DIR}/openmc + # Install include and bin directories to ${SKBUILD_PLATLIB_DIR}/openmc/SKBUILD_SUBDIR + set(SKBUILD_SUBDIR core/) + set(CMAKE_INSTALL_BINDIR ${SKBUILD_SUBDIR}${CMAKE_INSTALL_BINDIR}) + set(CMAKE_INSTALL_INCLUDEDIR ${SKBUILD_SUBDIR}${CMAKE_INSTALL_INCLUDEDIR}) + set(CMAKE_INSTALL_DATADIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_DATADIR}) + set(CMAKE_INSTALL_DOCDIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_DOCDIR}) + set(CMAKE_INSTALL_INFODIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_INFODIR}) + set(CMAKE_INSTALL_MANDIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_MANDIR}) + set(CMAKE_INSTALL_LOCALEDIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_LOCALEDIR}) + set(CMAKE_INSTALL_LOCALSTATEDIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_LOCALSTATEDIR}) + set(CMAKE_INSTALL_RUNSTATEDIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_RUNSTATEDIR}) + + # Set RPATH + if(APPLE) + set(CMAKE_MACOSX_RPATH ON) + set(OPENMC_LIBRARY_RPATH "@loader_path") + set(OPENMC_BINARY_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}") + elseif(UNIX) + set(OPENMC_LIBRARY_RPATH "$ORIGIN") + set(OPENMC_BINARY_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") + endif() +else() + # use, i.e. don't skip the full RPATH for the build tree + set(CMAKE_SKIP_BUILD_RPATH FALSE) -# add the automatically determined parts of the RPATH -# which point to directories outside the build tree to the install RPATH -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + # when building, don't use the install RPATH already + # (but later on when installing) + set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -# the RPATH to be used when installing, but only if it's not a system directory -list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_FULL_LIBDIR}" isSystemDir) -if("${isSystemDir}" STREQUAL "-1") - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") + # the RPATH to be used when installing, but only if it's not a system directory + list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_FULL_LIBDIR}" isSystemDir) + if("${isSystemDir}" STREQUAL "-1") + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") + endif() endif() +# add the automatically determined parts of the RPATH +# which point to directories outside the build tree to the install RPATH +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) #=============================================================================== # libopenmc #=============================================================================== @@ -458,7 +483,7 @@ endif() target_include_directories(libopenmc PUBLIC - $ + $ $ ${HDF5_INCLUDE_DIRS} ) @@ -466,6 +491,14 @@ target_include_directories(libopenmc # Set compile flags target_compile_options(libopenmc PRIVATE ${cxxflags}) +if(OPENMC_LIBRARY_RPATH) + set_target_properties( + libopenmc + PROPERTIES + INSTALL_RPATH "${OPENMC_LIBRARY_RPATH}" + ) +endif() + # Add include directory for configured version file target_include_directories(libopenmc PUBLIC $) @@ -557,15 +590,14 @@ target_compile_features(openmc PUBLIC cxx_std_17) target_compile_features(libopenmc PUBLIC cxx_std_17) set_target_properties(openmc libopenmc PROPERTIES CXX_EXTENSIONS OFF) -#=============================================================================== -# Python package -#=============================================================================== - -add_custom_command(TARGET libopenmc POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - $ - ${CMAKE_CURRENT_SOURCE_DIR}/openmc/lib/$ - COMMENT "Copying libopenmc to Python module directory") +# Set rpath for openmc executable +if(OPENMC_BINARY_RPATH) + set_target_properties( + openmc + PROPERTIES + INSTALL_RPATH "${OPENMC_BINARY_RPATH}" + ) +endif() #=============================================================================== # Install executable, scripts, manpage, license @@ -574,17 +606,35 @@ add_custom_command(TARGET libopenmc POST_BUILD configure_file(cmake/OpenMCConfig.cmake.in "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/OpenMCConfig.cmake" @ONLY) configure_file(cmake/OpenMCConfigVersion.cmake.in "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/OpenMCConfigVersion.cmake" @ONLY) -set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/OpenMC) +if(SKBUILD) + set(INSTALL_CONFIGDIR ${SKBUILD_DATA_DIR}/${CMAKE_INSTALL_LIBDIR}/cmake/OpenMC) +else() + set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/OpenMC) +endif() + install(TARGETS openmc libopenmc EXPORT openmc-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${SKBUILD_SUBDIR}${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${SKBUILD_SUBDIR}${CMAKE_INSTALL_LIBDIR} ) + +set(INSTALL_TARGETDIR ${SKBUILD_SUBDIR}${CMAKE_INSTALL_LIBDIR}/cmake/OpenMC) install(EXPORT openmc-targets FILE OpenMCTargets.cmake NAMESPACE OpenMC:: - DESTINATION ${INSTALL_CONFIGDIR}) + DESTINATION ${INSTALL_TARGETDIR} +) + +# Collect scripts +file(GLOB SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/*") + +# Install scripts to bin directory +if(SKBUILD) + install(PROGRAMS ${SCRIPTS} DESTINATION ${SKBUILD_SCRIPTS_DIR}) +else() + install(PROGRAMS ${SCRIPTS} DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() install(FILES "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/OpenMCConfig.cmake" diff --git a/cmake/OpenMCConfig.cmake.in b/cmake/OpenMCConfig.cmake.in index 5cab4790abc..994cde0e293 100644 --- a/cmake/OpenMCConfig.cmake.in +++ b/cmake/OpenMCConfig.cmake.in @@ -4,6 +4,9 @@ find_package(fmt REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../fmt) find_package(pugixml REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../pugixml) find_package(xtl REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../xtl) find_package(xtensor REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../xtensor) + +find_package(HDF5 REQUIRED COMPONENTS C HL) + if(@OPENMC_USE_DAGMC@) find_package(DAGMC REQUIRED HINTS @DAGMC_DIR@) endif() @@ -17,7 +20,48 @@ endif() find_package(PNG) -if(NOT TARGET OpenMC::libopenmc) +if(@SKBUILD@) + # Find the Python interpreter and ensure it's available. + find_package(Python COMPONENTS Interpreter REQUIRED) + + # Function to run Python commands and validate their execution. + function(run_python_command output_var command) + execute_process( + COMMAND ${Python_EXECUTABLE} -c "${command}" + OUTPUT_VARIABLE ${output_var} + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE result + ) + # Check if the command was successful + if(NOT result EQUAL 0) + message(FATAL_ERROR "Failed to run Python command: ${command}") + else() + # Add the output variable to the parent scope + set(${output_var} "${${output_var}}" PARENT_SCOPE) + endif() + endfunction() + + # Extract MOAB include paths, library paths, and extra libraries + run_python_command(OpenMC_INCLUDE_DIRS "import openmc; print(' '.join(openmc.include_path))") + run_python_command(OpenMC_LIBRARY_DIRS "import openmc; print(' '.join(openmc.lib_path))") + run_python_command(OpenMC_EXTRA_LIBRARIES "import openmc; print(' '.join(openmc.extra_lib))") + + # Check if the wheel was repaired using auditwheel or delocate + if(OpenMC_EXTRA_LIBRARIES) + message(FATAL_ERROR + "This build of OpenMC is not supported. " + "It appears that the wheel was repaired using tools like auditwheel or delocate, " + "that modifies the shared libraries, which may cause problems.\n" + "OpenMC_EXTRA_LIBRARIES is not empty: ${OpenMC_EXTRA_LIBRARIES}.\n" + "To resolve this, please build OpenMC from scratch. " + "For more information, visit: https://docs.openmc.org/" + ) + endif() + + # Add OpenMC targets + file(TO_CMAKE_PATH "${OpenMC_LIBRARY_DIRS}/cmake/OpenMC/OpenMCTargets.cmake" OpenMC_TARGETS_FILE) + include(${OpenMC_TARGETS_FILE}) +elseif(NOT TARGET OpenMC::libopenmc) include("${OpenMC_CMAKE_DIR}/OpenMCTargets.cmake") endif() diff --git a/docs/source/devguide/workflow.rst b/docs/source/devguide/workflow.rst index c49326a2090..ead87164165 100644 --- a/docs/source/devguide/workflow.rst +++ b/docs/source/devguide/workflow.rst @@ -140,15 +140,14 @@ pip_. From the root directory of the OpenMC repository, run: .. code-block:: sh - python -m pip install -e .[test] - -This installs the OpenMC Python package in `"editable" mode -`_ so that 1) -it can be imported from a Python interpreter and 2) any changes made are -immediately reflected in the installed version (that is, you don't need to keep -reinstalling it). While the same effect can be achieved using the -:envvar:`PYTHONPATH` environment variable, this is generally discouraged as it -can interfere with virtual environments. + python -m pip install --no-build-isolation \ + -Ceditable.rebuild=true \ + -Ccmake.build-type=Debug \ + -Cbuild-dir=build \ + -ve ".[test]" + +This feature allows for rebuilding on initial import, providing +flexibility for iterative development or testing changes to the codebase. .. _git: https://git-scm.com/ .. _GitHub: https://github.com/ diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index 21526242f18..1e7b9d2afab 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -128,38 +128,66 @@ source below. Building Source on Linux or macOS --------------------------------- -All OpenMC source code is hosted on `GitHub -`_. If you have `git -`_, a modern C++ compiler, `CMake `_, -and `HDF5 `_ installed, you can -download and install OpenMC by entering the following commands in a terminal: +All OpenMC source code is hosted on GitHub (`OpenMC GitHub `_). +Depending on your needs, you can either: -.. code-block:: sh +- Build only the OpenMC executable (using CMake). +- Build both the OpenMC executable and Python package (using pip). + +1. Building the OpenMC Executable Only (CMake) +============================================== + +If you only need the OpenMC executable without Python bindings, you can build it using +the following steps. You will need `git `_, a modern C++ compiler, +`CMake `_, and `HDF5 `_ installed: + +.. code-block:: bash git clone --recurse-submodules https://github.com/openmc-dev/openmc.git cd openmc - mkdir build && cd build - cmake .. - make - sudo make install + python -m pip install . -This will build an executable named ``openmc`` and install it (by default in -/usr/local/bin). If you do not have administrator privileges, the cmake command -should specify an installation directory where you have write access, e.g. +The easiest way to install it is using `pip `_. +This `pip` command will install the `openmc` Python package and compile an executable named ``openmc`` +and install it (by default in the bin folder of the Python package directory). .. code-block:: sh cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local .. + make + make install -The :mod:`openmc` Python package must be installed separately. The easiest way -to install it is using `pip `_. -From the root directory of the OpenMC repository, run: +2. Building the OpenMC Executable with Python Support (pip) +=========================================================== + +If you also want to install the OpenMC Python package,you can use +`pip `_ to build both the executable and +the Python package at the same time. This requires a Python environment +and pip installed. From the root directory of the OpenMC repository, run: .. code-block:: sh python -m pip install . +This will build the ``openmc`` executable and install it along with the Python bindings. +There is no need to manually run ``cmake`` or ``make``, as the pip command handles +both the C++ and Python build processes. + +Custom Build Options +~~~~~~~~~~~~~~~~~~~~ + +If you need to customize the build options (e.g., enabling MPI, DAGMC, or LibMesh), +you can pass CMake arguments using the ``SKBUILD_CMAKE_ARGS`` environment variable +before running pip. For example: + +.. code-block:: bash + + export SKBUILD_CMAKE_ARGS="-DOPENMC_USE_MPI=on;-DOPENMC_USE_DAGMC=on" + python -m pip install ".[test,depletion-mpi]" + +This allows you to configure your build just like you would with CMake. + By default, OpenMC will be built with multithreading support. To build -distributed-memory parallel versions of OpenMC using MPI or to configure other -options, directions can be found in the :ref:`detailed installation instructions +distributed-memory parallel versions of OpenMC using MPI the above command can be run. +There are other options that can be set, more details can be found in the :ref:`detailed installation instructions `. diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index d294770e0e0..576136449b7 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -154,9 +154,9 @@ feature can be used to access the installed packages. .. _install_source: ----------------------- -Installing from Source ----------------------- +-------------------------------- +Compiling from source with CMake +-------------------------------- .. _prerequisites: @@ -345,6 +345,8 @@ Note that first a build directory is created as a subdirectory of the source directory. The Makefile in the top-level directory will automatically perform an out-of-source build with default options. +.. _cmake_arguemnts: + CMakeLists.txt Options ++++++++++++++++++++++ @@ -480,29 +482,72 @@ To run the test suite, you will first need to download a pre-generated cross section library along with windowed multipole data. Please refer to our :ref:`devguide_tests` documentation for further details. ---------------------- -Installing Python API ---------------------- +----------------------------------------------- +Installing Python API and compiling from source +----------------------------------------------- If you installed OpenMC using :ref:`Conda `, no further steps are -necessary in order to use OpenMC's :ref:`Python API `. However, if -you are :ref:`installing from source `, the Python API is not -installed by default when ``make install`` is run because in many situations it -doesn't make sense to install a Python package in the same location as the -``openmc`` executable (for example, if you are installing the package into a -`virtual environment `_). The -easiest way to install the :mod:`openmc` Python package is to use pip_, which is -included by default in Python 3.4+. From the root directory of the OpenMC -distribution/repository, run: +necessary to use OpenMC's :ref:`Python API `. However, if you are +:ref:`installing from source `, the Python API is not installed +by default when building OpenMC because, in many cases, it doesn't make sense to +install a Python package in the same location as the OpenMC executable (for example, +if you are using a virtual environment `virtualenv `_). -.. code-block:: sh +To install OpenMC and its Python API, the recommended method is to use pip, +which includes both the Python package and the OpenMC executable. +From the root directory of the OpenMC repository, run: + +.. code-block:: bash + + python -m pip install ".[test,depletion-mpi]" + +This command installs both the OpenMC executable and the Python API together. +There's no need to manually run ``cmake`` or ``make install`` as pip automatically +handles the build process, including any CMake configuration. + +Custom Build Options +==================== + +If you need to customize the build (for example, to enable MPI, DAGMC, or LibMesh), +you can pass the necessary CMake arguments through the ``SKBUILD_CMAKE_ARGS`` +environment variable before running pip install: + +.. code-block:: bash + + export SKBUILD_CMAKE_ARGS="-DOPENMC_USE_MPI=on;-DOPENMC_USE_DAGMC=on" + python -m pip install ".[test,depletion-mpi]" + +Alternatively, pip provides additional ways to configure the build using +``--config-settings`` or ``-C``: - python -m pip install . +.. code-block:: bash + + python -m pip install . --config-settings=cmake.args="-DOPENMC_USE_MPI=ON;-DOPENMC_USE_MCPL=ON" pip will first check that all :ref:`required third-party packages ` have been installed, and if they are not present, they will be installed by downloading the appropriate packages from the Python -Package Index (`PyPI `_). +Package Index (`PyPI `_). The pip command will also compile +an executable named ``openmc`` and install it (by default in the bin folder of +the Python package directory). + +Passing CMake arguments via pip +-------------------------------- + +If you need to pass CMake options to the build process, you can do so by +running pip install with some additional options. All the CMake arguments +covered in the :ref:`CMakeLists.txt Options` are supported. +For example, to build OpenMC with MPI support, you can run: + +.. code-block:: sh + + python -m pip install . --config-settings=cmake.args=-DOPENMC_USE_MPI=ON + +To build OpenMC with DAGMC support two CMake arguments are needed, you can run: + +.. code-block:: sh + + python -m pip install . --config-settings=cmake.args="-DOPENMC_USE_DAGMC=ON;DDAGMC_ROOT=/path/to/dagmc/installation" Installing in "Development" Mode -------------------------------- diff --git a/manylinux.Dockerfile b/manylinux.Dockerfile new file mode 100644 index 00000000000..3a7a2e2ba7f --- /dev/null +++ b/manylinux.Dockerfile @@ -0,0 +1,445 @@ +# ---------------------------------------------------------------------------- +# Dockerfile for building the OpenMC project with support for various dependencies +# and configurations. This Dockerfile allows you to build OpenMC with support +# for GCC or OpenMPI compilers, along with several libraries like NJOY2016, HDF5, +# NetCDF, MOAB, EMBREE, Double Down, DAGMC, NCrystal, PyBind11, Xtensor, Vectfit, +# libMesh, and MCPL. Each of these dependencies is installed from their respective +# repositories and tags. + +# The build process is split into stages: +# 1. Base Stage: Sets up a Manylinux base image and installs necessary dependencies. +# 2. Compiler Configuration: Defines the compilers (GCC or OpenMPI) to be used. +# 3. Dependencies Stage: Downloads and builds all external dependencies. +# 4. Python Dependencies Stage: Downloads and installs Python dependencies. +# 5. OpenMC Stage: Copies OpenMC source code, build wheel with specific +# flags and installs it in the container. Then, runs tests. + +# Arguments and environment variables can be customized for different compiler and +# dependency versions. +# +# To build the Docker image, use the following command from the repository's root: +# docker build -t openmc -f tools/ci/manylinux.dockerfile . +# +# For more information about each step, refer to the inline comments. +# ---------------------------------------------------------------------------- + +# Configure base image +ARG MANYLINUX_IMAGE=manylinux_2_28_x86_64 +# ARG MANYLINUX_IMAGE=manylinux_2_24_x86_64 +# ARG MANYLINUX_IMAGE=manylinux2014_x86_64 + +# Configure Compiler to use (gcc or openmpi) +ARG COMPILER="gcc" + +# Configure Python ABI to use +ARG Python_ABI="cp310-cp310" + +# OpenMC options +ARG OPENMC_USE_OPENMP="ON" +ARG OPENMC_BUILD_TESTS="ON" +ARG OPENMC_ENABLE_PROFILE="OFF" +ARG OPENMC_ENABLE_COVERAGE="OFF" +ARG OPENMC_USE_DAGMC="ON" +ARG OPENMC_USE_LIBMESH="ON" +ARG OPENMC_USE_MCPL="ON" +ARG OPENMC_USE_NCRYSTAL="OFF" +ARG OPENMC_USE_UWUW="OFF" + +# Configure dependencies tags +ARG GSL_LITE_TAG="v0.41.0" +ARG XTL_TAG="0.7.7" +ARG XTENSOR_TAG="0.25.0" +ARG XTENSOR_BLAS_TAG="0.21.0" +ARG CATCH2_TAG="v3.7.1" +ARG NJOY2016_TAG="2016.76" +ARG HDF5_TAG="hdf5_1.14.4.3" +ARG NETCDF_TAG="v4.9.2" +ARG MOAB_TAG="5.5.1" +ARG EMBREE_TAG="v4.3.3" +ARG DD_TAG="v1.1.0" +ARG DAGMC_TAG="v3.2.4" +ARG NCrystal_TAG="v3.9.7" +ARG PYBIND_TAG="v2.13.6" +ARG XTENSOR_PYTHON_TAG="0.27.0" +ARG VECTFIT_TAG="master" +ARG LIBMESH_TAG="v1.7.7" +ARG MCPL_TAG="v1.6.2" + + +# Base stage +FROM quay.io/pypa/${MANYLINUX_IMAGE} AS base + +# Set timezone +ENV TZ=America/Chicago +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Set Home directory +ENV HOME=/root +WORKDIR $HOME + +# Setup Epel repository and install build dependencies +RUN yum install -y epel-release && \ + yum config-manager --enable epel && \ + yum install -y \ + wget \ + git \ + gcc \ + gcc-c++ \ + gcc-gfortran \ + make \ + python3.12-devel \ + # python3.10-devel \ + # python3.10-dev \ + # python3.10-venv \ + zlib-devel \ + curl-devel \ + eigen3-devel \ + lapack-devel \ + libpng-devel \ + pugixml-devel \ + fmt-devel && \ + yum clean all + +# Set up environment variables for shared libraries +ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64:$LD_LIBRARY_PATH + +# Compiler configuration stage: gcc +FROM base AS compiler-gcc + +ENV CC=gcc +ENV CXX=g++ +ENV FC=gfortran +ENV F77=gfortran + + +# Compiler configuration stage: openmpi +FROM base AS compiler-openmpi + +# Install OpenMPI +RUN yum install -y \ + openmpi-devel && \ + yum clean all + +ENV CC=mpicc +ENV CXX=mpicxx +ENV FC=mpif90 +ENV F77=mpif77 + +# Set up OpenMPI environment variables +ENV PATH=/usr/lib64/openmpi/bin:$PATH +ENV LD_LIBRARY_PATH=/usr/lib64/openmpi/lib:$LD_LIBRARY_PATH + + +# Dependencies stage +FROM compiler-${COMPILER} AS dependencies + +ARG COMPILER + +# Build and install gsl-lite +ARG GSL_LITE_TAG +RUN git clone --depth 1 -b ${GSL_LITE_TAG} https://github.com/gsl-lite/gsl-lite.git gsl-lite && \ + cd gsl-lite && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf gsl-lite + +# Build and install xtl +ARG XTL_TAG +RUN git clone --depth 1 -b ${XTL_TAG} https://github.com/xtensor-stack/xtl.git xtl && \ + cd xtl && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf xtl + +# Build and install xtensor +ARG XTENSOR_TAG +RUN git clone --depth 1 -b ${XTENSOR_TAG} https://github.com/xtensor-stack/xtensor.git xtensor && \ + cd xtensor && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf xtensor + +# Build and install xtensor-blas +ARG XTENSOR_BLAS_TAG +RUN git clone --depth 1 -b ${XTENSOR_BLAS_TAG} https://github.com/xtensor-stack/xtensor-blas.git xtensor-blas && \ + cd xtensor-blas && \ + mkdir build && cd build && \ + cmake .. && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf xtensor-blas + +# Build and install Catch2 +ARG CATCH2_TAG +RUN git clone --depth 1 -b ${CATCH2_TAG} https://github.com/catchorg/Catch2.git catch2 && \ + cd catch2 && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf catch2 + +# Build and install NJOY2016 +# ARG NJOY2016_TAG +# RUN git clone --depth 1 -b ${NJOY2016_TAG} https://github.com/njoy/njoy2016.git njoy && \ +# cd njoy && \ +# mkdir build && cd build && \ +# cmake .. \ +# -DCMAKE_INSTALL_PREFIX=/usr/local \ +# -Dstatic=ON && \ +# make -j$(nproc) && make install && \ +# cd ../.. && \ +# rm -rf njoy + +# Build and install HDF5 +ARG HDF5_TAG +RUN git clone --depth 1 -b ${HDF5_TAG} https://github.com/HDFGroup/hdf5.git hdf5 && \ + cd hdf5 && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DHDF5_ENABLE_PARALLEL=$([ ${COMPILER} == "openmpi" ] && echo "ON" || echo "OFF") \ + -DHDF5_BUILD_HL_LIB=ON \ + -DBUILD_SHARED_LIBS=ON && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf hdf5 + +# Build and install NetCDF +ARG NETCDF_TAG +RUN git clone --depth 1 -b ${NETCDF_TAG} https://github.com/Unidata/netcdf-c.git netcdf && \ + cd netcdf && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DBUILD_SHARED_LIBS=ON \ + -DENABLE_DAP=ON \ + -DENABLE_TESTS=OFF && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf netcdf + +# Build and install MOAB +ARG MOAB_TAG +RUN git clone --depth 1 -b ${MOAB_TAG} https://bitbucket.org/fathomteam/moab.git moab && \ + cd moab && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DENABLE_MPI=$([ ${COMPILER} == "openmpi" ] && echo "ON" || echo "OFF") \ + -DENABLE_HDF5=ON \ + -DHDF5_ROOT=/usr/local \ + -DENABLE_NETCDF=ON \ + -DNETCDF_ROOT=/usr/local \ + -DBUILD_SHARED_LIBS=ON \ + -DENABLE_BLASLAPACK=OFF \ + -DENABLE_PYMOAB=OFF && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf moab + +# Build and install Embree +ARG EMBREE_TAG +RUN git clone --depth 1 -b ${EMBREE_TAG} https://github.com/embree/embree.git embree && \ + cd embree && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DEMBREE_TASKING_SYSTEM=INTERNAL \ + -DEMBREE_ISPC_SUPPORT=OFF \ + -DEMBREE_TUTORIALS=OFF && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf embree + +# Build and install Double Down +ARG DD_TAG +RUN git clone --depth 1 -b ${DD_TAG} https://github.com/pshriwise/double-down.git dd && \ + cd dd && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf dd + +# Build and install DAGMC +ARG DAGMC_TAG +RUN git clone --depth 1 -b ${DAGMC_TAG} https://github.com/svalinn/DAGMC.git dagmc && \ + cd dagmc && \ + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DMOAB_DIR=/usr/local \ + -Ddd_ROOT=/usr/local \ + -DBUILD_TALLY=ON \ + -DBUILD_UWUW=ON \ + -DDOUBLE_DOWN=ON \ + -DBUILD_STATIC_LIBS=OFF \ + -DBUILD_RPATH=OFF && \ + make -j$(nproc) && make install && \ + cd ../.. && \ + rm -rf dagmc + +# Build and install libMesh +# ARG LIBMESH_TAG +# RUN git clone --depth 1 -b ${LIBMESH_TAG} https://github.com/libMesh/libmesh.git libmesh && \ +# cd libmesh && \ +# git submodule update --init --recursive && \ +# mkdir build && cd build && \ +# export METHODS="opt" && \ +# ../configure \ +# $([ ${COMPILER} = 'openmpi' ] && echo '--enable-mpi' || echo '--disable-mpi') \ +# --prefix=/usr/local \ +# --enable-exodus \ +# --disable-netcdf-4 \ +# --disable-eigen \ +# --disable-lapack && \ +# make -j$(nproc) && make install && \ +# cd ../.. && \ +# rm -rf libmesh + +# Build and install MCPL +# ARG MCPL_TAG +# RUN git clone --depth 1 -b ${MCPL_TAG} https://github.com/mctools/mcpl.git mcpl && \ +# cd mcpl && \ +# mkdir build && cd build && \ +# cmake .. \ +# -DCMAKE_INSTALL_PREFIX=/usr/local && \ +# make -j$(nproc) && make install && \ +# cd ../.. && \ +# rm -rf mcpl + +# Download and extract HDF5 data +# RUN wget -q -O - https://anl.box.com/shared/static/teaup95cqv8s9nn56hfn7ku8mmelr95p.xz | tar -C $HOME -xJ +# ENV OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml + +# # Download and extract ENDF/B-VII.1 distribution +# RUN wget -q -O - https://anl.box.com/shared/static/4kd2gxnf4gtk4w1c8eua5fsua22kvgjb.xz | tar -C $HOME -xJ +# ENV OPENMC_ENDF_DATA=$HOME/endf-b-vii.1 + + +# Python dependencies stage +FROM dependencies AS python-dependencies + +ARG Python_ABI + +# Use Python from manylinux as the default Python +ENV PYTHONHOME="" +# ENV PYTHONHOME="/opt/python/${Python_ABI}" +ENV PATH="/opt/python/${Python_ABI}/bin:${PATH}" + +# Build and install NCrystal +# ARG NCrystal_TAG +# RUN git clone --depth 1 -b ${NCrystal_TAG} https://github.com/mctools/ncrystal.git ncrystal && \ +# cd ncrystal && \ +# mkdir build && cd build && \ +# cmake .. \ +# -DCMAKE_INSTALL_PREFIX=/usr/local \ +# -DBUILD_SHARED_LIBS=ON \ +# -DNCRYSTAL_NOTOUCH_CMAKE_BUILD_TYPE=ON \ +# -DNCRYSTAL_MODIFY_RPATH=OFF \ +# -DCMAKE_BUILD_TYPE=Release \ +# -DNCRYSTAL_ENABLE_EXAMPLES=OFF \ +# -DNCRYSTAL_ENABLE_SETUPSH=OFF \ +# -DNCRYSTAL_ENABLE_DATA=EMBED \ +# -DPython3_EXECUTABLE=$(which python) && \ +# make -j$(nproc) && make install && \ +# cd ../.. && \ +# rm -rf ncrystal + +# Build and install pybind +# ARG PYBIND_TAG +# RUN git clone --depth 1 -b ${PYBIND_TAG} https://github.com/pybind/pybind11.git pybind11 && \ +# cd pybind11 && \ +# mkdir build && cd build && \ +# cmake .. \ +# -DCMAKE_INSTALL_PREFIX=/usr/local && \ +# make -j$(nproc) && make install && \ +# cd .. && \ +# python -m pip install . && \ +# cd .. && \ +# rm -rf pybind11 + +# # Build and install xtensor-python +# ARG XTENSOR_PYTHON_TAG +# RUN git clone --depth 1 -b ${XTENSOR_PYTHON_TAG} https://github.com/xtensor-stack/xtensor-python.git xtensor-python && \ +# cd xtensor-python && \ +# mkdir build && cd build && \ +# python -m pip install numpy && \ +# cmake .. \ +# -DCMAKE_INSTALL_PREFIX=/usr/local \ +# -DNUMPY_INCLUDE_DIRS=$(python -c "import numpy; print(numpy.get_include())") && \ +# make -j$(nproc) && make install && \ +# cd ../.. && \ +# rm -rf xtensor-python + +# # Build and install vectfit +# ARG VECTFIT_TAG +# RUN git clone --depth 1 -b ${VECTFIT_TAG} https://github.com/liangjg/vectfit.git vectfit && \ +# cd vectfit && \ +# python -m pip install . && \ +# cd .. && \ +# rm -rf vectfit + + +# OpenMC stage +FROM python-dependencies AS openmc + +ARG COMPILER +ARG Python_ABI +ARG OPENMC_USE_OPENMP +ARG OPENMC_BUILD_TESTS +ARG OPENMC_ENABLE_PROFILE +ARG OPENMC_ENABLE_COVERAGE +ARG OPENMC_USE_DAGMC +ARG OPENMC_USE_LIBMESH +ARG OPENMC_USE_MCPL +ARG OPENMC_USE_NCRYSTAL +ARG OPENMC_USE_UWUW + +# Copy OpenMC source to docker image +COPY . $HOME/openmc + +# Configure SKBUILD CMake arguments +RUN export SKBUILD_CMAKE_ARGS="-DOPENMC_USE_MPI=$([ ${COMPILER} == 'openmpi' ] && echo 'ON' || echo 'OFF'); \ + -DOPENMC_USE_OPENMP=${OPENMC_USE_OPENMP}; \ + -DOPENMC_BUILD_TESTS=${OPENMC_BUILD_TESTS}; \ + -DOPENMC_ENABLE_PROFILE=${OPENMC_ENABLE_PROFILE}; \ + -DOPENMC_ENABLE_COVERAGE=${OPENMC_ENABLE_COVERAGE}; \ + -DOPENMC_USE_DAGMC=${OPENMC_USE_DAGMC}; \ + # -DOPENMC_USE_LIBMESH=${OPENMC_USE_LIBMESH}; \ + # -DOPENMC_USE_MCPL=${OPENMC_USE_MCPL}; \ + # -DOPENMC_USE_NCRYSTAL=${OPENMC_USE_NCRYSTAL}; \ + -DOPENMC_USE_UWUW=${OPENMC_USE_UWUW}" && \ + cd $HOME/openmc && \ + python -m build . -w + +# Install OpenMC wheel +RUN python -m pip install \ + "$(echo $HOME/openmc/dist/*.whl)[$([ ${COMPILER} == 'openmpi' ] && echo 'depletion-mpi,')test,ci,vtk]" + +# Test OpenMC +# RUN cd $HOME/openmc && \ + # eval $(ncrystal-config --setup) && \ + # nctool --test && \ + # pytest --cov=openmc -v $([ ${COMPILER} == 'openmpi' ] && echo '--mpi') --event tests + +# Repair wheel +RUN auditwheel repair $HOME/openmc/dist/openmc-*.whl -w $HOME/openmc/dist/ + +# Test repaired wheel +RUN python -m pip uninstall openmc -y +RUN ls $HOME/openmc/dist/*manylinux**.whl +RUN python -m pip install $HOME/openmc/dist/*manylinux**.whl +RUN openmc --version \ No newline at end of file diff --git a/openmc/__init__.py b/openmc/__init__.py index bb972b4e6ad..254b227d76b 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -1,3 +1,6 @@ +import os +import sys +import glob import importlib.metadata from openmc.arithmetic import * from openmc.bounding_box import * @@ -43,3 +46,49 @@ __version__ = importlib.metadata.version("openmc") + +try: + OPENMC_CORE_BASE_PATH = os.path.join(__path__[0], "core") +except NameError: + OPENMC_CORE_BASE_PATH = None + + +def get_paths(subdir, pattern="*", recursive=False): + """ + Helper function to return paths that match a given pattern within a subdirectory. + + Args: + subdir (str): The subdirectory within the 'core' directory. + pattern (str): The pattern to match files or directories. + recursive (bool): Whether to search recursively in subdirectories. + + Returns: + list: A list of matched paths. + """ + search_pattern = os.path.join(OPENMC_CORE_BASE_PATH, subdir, "**", pattern) if recursive else os.path.join(OPENMC_CORE_BASE_PATH, subdir, pattern) + return glob.glob(search_pattern, recursive=recursive) + +def get_include_path(): + """Return includes and include path for OpenMC headers.""" + include = get_paths("include", "*", recursive=True) + include_path = get_paths("include", "", recursive=False) + return include, include_path + +def get_core_libraries(): + """Return libraries and library paths for OpenMC.""" + lib = [lib_file for lib in ["lib", "lib64"] for lib_file in get_paths(lib, "libopenmc*", recursive=True)] + lib_path = [lib_file for lib in ["lib", "lib64"] for lib_file in get_paths(lib, "", recursive=False)] + return lib, lib_path + +def get_extra_libraries(): + """Return the extra libraries installed by auditwheel or delocate.""" + libs_path = os.path.join(__path__[0], ".dylibs") if sys.platform == "darwin" else os.path.normpath(os.path.join(__path__[0], "..", "openmc.libs")) + return (glob.glob(os.path.join(libs_path, "*")), libs_path) if os.path.exists(libs_path) else ([], []) + +# Setup variables +include, include_path = get_include_path() +lib, lib_path = get_core_libraries() +extra_lib, extra_lib_path = get_extra_libraries() + +# Export variables for easy access +__all__ = ["include", "include_path", "lib", "lib_path", "extra_lib", "extra_lib_path"] \ No newline at end of file diff --git a/openmc/_cli_openmc.py b/openmc/_cli_openmc.py new file mode 100644 index 00000000000..20c9249b852 --- /dev/null +++ b/openmc/_cli_openmc.py @@ -0,0 +1,53 @@ +def get_ncrystal_libdir(): + """ + Returns NCrystal library directory or None. + """ + import shutil + cmd = shutil.which('ncrystal-config') + if cmd: + import subprocess + res = subprocess.run([cmd,'--show','shlibdir'],capture_output=True) + if res.returncode == 0: + return res.stdout.decode('utf8').strip() + +def runtime_env(): + """ + + Perform any dynamic environment modifications needed for openmc to load + shared libraries etc. + """ + + #Currently this only concerns NCrystal, which needs the directory with the + #NCrystal library to be added to the relevant lib path variable: + import platform + libpathvar = { 'Linux' : 'LD_LIBRARY_PATH', + 'Darwin' : 'DYLD_LIBRARY_PATH' }.get(platform.system()) + if not libpathvar: + return + + #Currently we only need this for NCrystal (in principle it is not needed + #when NCrystal is from Conda or a system package, but it doesn't actually + #hurt in that case): + nc_libdir = get_ncrystal_libdir() + if not nc_libdir: + return + + import os + env = os.environ.copy() + env[libpathvar] = '%s:%s'%(env.get(libpathvar),nc_libdir) + return env + +def main(): + """ + Entry point wrapper for the binary openmc executable, for when OpenMC is + installed from a Python wheel. + """ + import subprocess + import pathlib + import sys + f = pathlib.Path(__file__).parent.joinpath('core','bin','openmc') + a = sys.argv[:] + a[0] = f + env = runtime_env() + rv = subprocess.run( a, env = env ) + raise SystemExit(rv.returncode) diff --git a/openmc/lib/__init__.py b/openmc/lib/__init__.py index 15642b42be3..73b64801ba0 100644 --- a/openmc/lib/__init__.py +++ b/openmc/lib/__init__.py @@ -13,20 +13,21 @@ """ from ctypes import CDLL, c_bool, c_int -import importlib.resources import os -import sys - - -# Determine shared-library suffix -if sys.platform == 'darwin': - _suffix = 'dylib' -else: - _suffix = 'so' if os.environ.get('READTHEDOCS', None) != 'True': + # Load libNCrystal first if it exists + try: + import subprocess + ncrystal_path = subprocess.check_output(["ncrystal-config", "--show", "libpath"], text=True).strip() + if os.path.isfile(ncrystal_path): + CDLL(ncrystal_path, mode=os.RTLD_GLOBAL) + except Exception: + pass # NCrystal is not installed + # Open shared library - _filename = importlib.resources.files(__name__) / f'libopenmc.{_suffix}' + import openmc + _filename = openmc.lib[0] _dll = CDLL(str(_filename)) # TODO: Remove str() when Python 3.12+ else: # For documentation builds, we don't actually have the shared library diff --git a/pyproject.toml b/pyproject.toml index 6e8ed798e78..b6e8df59957 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -requires = ["setuptools", "setuptools-scm", "wheel"] -build-backend = "setuptools.build_meta" +requires = ["scikit-build-core"] +build-backend = "scikit_build_core.build" [project] name = "openmc" @@ -9,7 +9,7 @@ authors = [ ] description = "OpenMC" dynamic = ["version"] -requires-python = ">=3.11" +requires-python = ">=3.10" license = {file = "LICENSE"} classifiers = [ "Development Status :: 4 - Beta", @@ -58,13 +58,15 @@ Documentation = "https://docs.openmc.org" Repository = "https://github.com/openmc-dev/openmc" Issues = "https://github.com/openmc-dev/openmc/issues" -[tool.setuptools.packages.find] -include = ['openmc*'] -exclude = ['tests*'] +# Scikit-Build Configuration +[tool.scikit-build] +build.verbose = true +logging.level = "INFO" +wheel.install-dir = "openmc" +wheel.packages = ["openmc"] +sdist.include = ["*.h5"] -[tool.setuptools.package-data] -"openmc.data.effective_dose" = ["**/*.txt"] -"openmc.data" = ["*.txt", "*.DAT", "*.json", "*.h5"] -"openmc.lib" = ["libopenmc.dylib", "libopenmc.so"] +[project.scripts] +openmc = "openmc._cli_openmc:main" [tool.setuptools_scm] diff --git a/tools/ci/gha-install.py b/tools/ci/gha-install.py index 1cc792f8d78..a30faac93ed 100644 --- a/tools/ci/gha-install.py +++ b/tools/ci/gha-install.py @@ -3,48 +3,61 @@ import subprocess -def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False): +def install(omp=False, mpi=False, phdf5=False, dagmc=False, libmesh=False, ncrystal=False): # Create build directory and change to it shutil.rmtree('build', ignore_errors=True) os.mkdir('build') os.chdir('build') # Build in debug mode by default with support for MCPL - cmake_cmd = ['cmake', '-DCMAKE_BUILD_TYPE=Debug', '-DOPENMC_USE_MCPL=on'] + cmake_args = ['-DCMAKE_BUILD_TYPE=Debug', '-DOPENMC_USE_MCPL=on'] # Turn off OpenMP if specified if not omp: - cmake_cmd.append('-DOPENMC_USE_OPENMP=off') + cmake_args.append('-DOPENMC_USE_OPENMP=off') # Use MPI wrappers when building in parallel if mpi: - cmake_cmd.append('-DOPENMC_USE_MPI=on') + cmake_args.append('-DOPENMC_USE_MPI=on') # Tell CMake to prefer parallel HDF5 if specified if phdf5: if not mpi: - raise ValueError('Parallel HDF5 must be used in ' - 'conjunction with MPI.') - cmake_cmd.append('-DHDF5_PREFER_PARALLEL=ON') + raise ValueError('Parallel HDF5 must be used in conjunction with MPI.') + cmake_args.append('-DHDF5_PREFER_PARALLEL=ON') else: - cmake_cmd.append('-DHDF5_PREFER_PARALLEL=OFF') + cmake_args.append('-DHDF5_PREFER_PARALLEL=OFF') if dagmc: - cmake_cmd.append('-DOPENMC_USE_DAGMC=ON') - cmake_cmd.append('-DOPENMC_USE_UWUW=ON') + cmake_args.append('-DOPENMC_USE_DAGMC=ON') + cmake_args.append('-DOPENMC_USE_UWUW=ON') dagmc_path = os.environ.get('HOME') + '/DAGMC' - cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + dagmc_path) + cmake_args.append('-DCMAKE_PREFIX_PATH=' + dagmc_path) if libmesh: - cmake_cmd.append('-DOPENMC_USE_LIBMESH=ON') + cmake_args.append('-DOPENMC_USE_LIBMESH=ON') libmesh_path = os.environ.get('HOME') + '/LIBMESH' - cmake_cmd.append('-DCMAKE_PREFIX_PATH=' + libmesh_path) + cmake_args.append('-DCMAKE_PREFIX_PATH=' + libmesh_path) # Build in coverage mode for coverage testing - cmake_cmd.append('-DOPENMC_ENABLE_COVERAGE=on') + cmake_args.append('-DOPENMC_ENABLE_COVERAGE=on') - # Build and install - cmake_cmd.append('..') + # Set environment variable for SKBUILD + os.environ['SKBUILD_cmake_args'] = ';'.join(cmake_args) + + # Run pip to build and install + pip_suffix = '--config-settings=cmake.args="' + ';'.join(cmake_args) + '"' + + subprocess.check_call(['pip', '-v', 'install', '.[test,vtk,ci]', pip_suffix]) + + # Using standard CMake method + # Create build directory and change to it + shutil.rmtree('build', ignore_errors=True) + os.mkdir('build') + os.chdir('build') + + # Add CMake arguments for standard method + cmake_cmd = ['cmake', '..'] + cmake_args print(' '.join(cmake_cmd)) subprocess.check_call(cmake_cmd) subprocess.check_call(['make', '-j4']) diff --git a/tools/ci/gha-install.sh b/tools/ci/gha-install.sh index d8a3a7600e4..3ab12f825d3 100755 --- a/tools/ci/gha-install.sh +++ b/tools/ci/gha-install.sh @@ -45,5 +45,3 @@ fi # Build and install OpenMC executable python tools/ci/gha-install.py -# Install Python API in editable mode -pip install -e .[test,vtk,ci] diff --git a/tools/ci/gha-script.sh b/tools/ci/gha-script.sh index c7c634ffa33..38f308ad251 100755 --- a/tools/ci/gha-script.sh +++ b/tools/ci/gha-script.sh @@ -16,3 +16,6 @@ fi # Run regression and unit tests pytest --cov=openmc -v $args tests + +# Rename to openmc back +mv openmc-test openmc