diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab1daeea..07237a76 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -212,3 +212,43 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./genDocs + + build-bundled-symengine: + # Build SymEngine from source as part of the Python build + # (USE_SYSTEM_SYMENGINE=OFF) instead of using a preinstalled one. + runs-on: ${{ matrix.OS }} + strategy: + fail-fast: false + matrix: + include: + - OS: ubuntu-24.04 + PYTHON_VERSION: '3.13' + - OS: macos-15 + PYTHON_VERSION: '3.14' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # setuptools-scm needs tags + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.PYTHON_VERSION }} + + - name: Build sdist + run: | + python -m pip install build + python -m build --sdist + + - name: Build and install from sdist + run: | + python -m pip install -v dist/symengine-*.tar.gz \ + -Ccmake.define.USE_SYSTEM_SYMENGINE=OFF + + - name: Test + run: | + python -m pip install pytest + mkdir -p empty && cd empty + python -m pytest -v --pyargs symengine + python ../bin/test_python.py diff --git a/CMakeLists.txt b/CMakeLists.txt index f75f09ce..24027ee4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,18 +9,25 @@ endif() project(${SKBUILD_PROJECT_NAME} LANGUAGES C CXX) -set(CMAKE_PREFIX_PATH ${SymEngine_DIR} ${CMAKE_PREFIX_PATH}) +option(USE_SYSTEM_SYMENGINE + "Use an installed SymEngine instead of building it from source" ON) include(GNUInstallDirs) -find_package(SymEngine 0.15.0 REQUIRED CONFIG - PATH_SUFFIXES lib/cmake/symengine cmake/symengine CMake/) -message("SymEngine_DIR : " ${SymEngine_DIR}) -message("SymEngine Version : " ${SymEngine_VERSION}) -set(CMAKE_BUILD_TYPE ${SYMENGINE_BUILD_TYPE}) -set(CMAKE_CXX_FLAGS_RELEASE ${SYMENGINE_CXX_FLAGS_RELEASE}) -set(CMAKE_CXX_FLAGS_DEBUG ${SYMENGINE_CXX_FLAGS_DEBUG}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYMENGINE_CXX_FLAGS}") +if (USE_SYSTEM_SYMENGINE) + set(CMAKE_PREFIX_PATH ${SymEngine_DIR} ${CMAKE_PREFIX_PATH}) + find_package(SymEngine 0.15.0 REQUIRED CONFIG + PATH_SUFFIXES lib/cmake/symengine cmake/symengine CMake/) + message("SymEngine_DIR : " ${SymEngine_DIR}) + message("SymEngine Version : " ${SymEngine_VERSION}) + set(CMAKE_BUILD_TYPE ${SYMENGINE_BUILD_TYPE}) + set(CMAKE_CXX_FLAGS_RELEASE ${SYMENGINE_CXX_FLAGS_RELEASE}) + set(CMAKE_CXX_FLAGS_DEBUG ${SYMENGINE_CXX_FLAGS_DEBUG}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYMENGINE_CXX_FLAGS}") +else() + include(cmake/ExternalSymEngine.cmake) + message("SymEngine URL : " ${SYMENGINE_URL}) +endif() find_package( Python diff --git a/cmake/ExternalSymEngine.cmake b/cmake/ExternalSymEngine.cmake new file mode 100644 index 00000000..692892ad --- /dev/null +++ b/cmake/ExternalSymEngine.cmake @@ -0,0 +1,61 @@ +# Build SymEngine at the commit in symengine_version.txt with +# ExternalProject_Add, as a static library using Boost.Multiprecision integers +# and no optional dependencies. SymEngine downloads the standalone +# Boost.Multiprecision headers itself, so nothing needs to be installed. +# Sets SYMENGINE_INCLUDE_DIRS and SYMENGINE_LIBRARIES like +# find_package(SymEngine) does. + +include(ExternalProject) + +if (POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) # set extracted file timestamps to now +endif() + +file(STRINGS ${PROJECT_SOURCE_DIR}/symengine_version.txt SYMENGINE_COMMIT + LIMIT_COUNT 1) +set(SYMENGINE_URL + "https://github.com/symengine/symengine/archive/${SYMENGINE_COMMIT}.tar.gz" + CACHE STRING "URL or path of the SymEngine source archive to build") + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +set(SYMENGINE_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/symengine-install) +set(SYMENGINE_LIBRARY + ${SYMENGINE_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}symengine${CMAKE_STATIC_LIBRARY_SUFFIX}) + +ExternalProject_Add( + symengine_external + URL ${SYMENGINE_URL} + INSTALL_DIR ${SYMENGINE_INSTALL_DIR} + CMAKE_CACHE_ARGS + -DCMAKE_INSTALL_PREFIX:PATH= + -DCMAKE_INSTALL_LIBDIR:STRING=lib + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} + -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} + -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} + -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON + -DBUILD_SHARED_LIBS:BOOL=OFF + -DBUILD_TESTS:BOOL=OFF + -DBUILD_BENCHMARKS:BOOL=OFF + -DINTEGER_CLASS:STRING=boostmp + -DUSE_SYSTEM_BOOSTMP:BOOL=OFF + -DWITH_SYMENGINE_RCP:BOOL=ON + -DWITH_SYMENGINE_THREAD_SAFE:BOOL=ON + BUILD_BYPRODUCTS ${SYMENGINE_LIBRARY} +) + +# The include directory of an imported target must exist at configure time +file(MAKE_DIRECTORY ${SYMENGINE_INSTALL_DIR}/include) +add_library(symengine STATIC IMPORTED) +set_target_properties(symengine PROPERTIES IMPORTED_LOCATION ${SYMENGINE_LIBRARY}) +add_dependencies(symengine symengine_external) + +set(SYMENGINE_INCLUDE_DIRS + ${SYMENGINE_INSTALL_DIR}/include + ${SYMENGINE_INSTALL_DIR}/include/symengine/utilities/cereal/include + ${SYMENGINE_INSTALL_DIR}/include/symengine/utilities/boost_multiprecision/include) +set(SYMENGINE_LIBRARIES symengine) diff --git a/symengine_version.txt b/symengine_version.txt index d2e11173..81797b0a 100644 --- a/symengine_version.txt +++ b/symengine_version.txt @@ -1 +1 @@ -266ea64d2eb83ca1dc3939fdc82100a00d537f84 +c3b2d541f2ffef52f4f8bb26c04c6c494bfce65f