Skip to content

Commit

Permalink
[eudsl] llvm-c python bindings (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
makslevental authored Jan 20, 2025
1 parent 7f1c8de commit 42d83b5
Show file tree
Hide file tree
Showing 13 changed files with 801 additions and 37 deletions.
108 changes: 85 additions & 23 deletions .github/workflows/build_test_release_eudsl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ jobs:
- name: "macos_arm64"
runs-on: "macos-14"
os: "macos"
- name: "macos_x86_64"
runs-on: "macos-13"
os: "macos"

runs-on: ${{ matrix.runs-on }}

Expand Down Expand Up @@ -126,26 +123,33 @@ jobs:
# ld: warning: object file (libLLVMTableGen.a[3](Error.cpp.o)) was built for newer 'macOS' version (13.7) than being linked (10.13)
if [[ "${{ matrix.runs-on }}" == "macos-14" ]]; then
echo MACOSX_DEPLOYMENT_TARGET=14.0 >> $GITHUB_ENV
elif [[ "${{ matrix.runs-on }}" == "macos-13" ]]; then
echo MACOSX_DEPLOYMENT_TARGET=13.7 >> $GITHUB_ENV
fi
# prevent OOM on free GHA
echo "EUDSLPY_DISABLE_COMPILE_OPT=${{ inputs.eudslpy_disable_compile_opt == 'true' && 'ON' || 'OFF' }}" >> $GITHUB_ENV
pip install cibuildwheel
- name: "Build eudsl-tblgen"
- name: "Build eudsl-llvmpy"
if: ${{ ! startsWith(matrix.os, 'windows') }}
run: |
if [[ "${{ matrix.os }}" == "ubuntu" ]]; then
export CCACHE_DIR=/host/$CCACHE_DIR
fi
$python3_command -m cibuildwheel "$PWD/projects/eudsl-llvmpy" --output-dir wheelhouse
- name: "Build eudsl-tblgen"
run: |
if [[ "${{ matrix.os }}" == "ubuntu" ]]; then
export CCACHE_DIR=/host/$CCACHE_DIR
fi
$python3_command -m cibuildwheel "$PWD/projects/eudsl-tblgen" --output-dir wheelhouse
- name: "Build eudsl-nbgen"
run: |
if [[ "${{ matrix.os }}" == "ubuntu" ]]; then
export CCACHE_DIR=/host/$CCACHE_DIR
fi
Expand All @@ -154,7 +158,7 @@ jobs:
- name: "Build eudsl-py"
if: ${{ ! startsWith(matrix.os, 'windows') }}
run: |
if [[ "${{ matrix.os }}" == "ubuntu" ]]; then
export CCACHE_DIR=/host/$CCACHE_DIR
fi
Expand All @@ -163,7 +167,7 @@ jobs:
# just to/make sure total build continues to work
- name: "Build all of eudsl"
run: |
pip install -r requirements.txt
cmake -B $PWD/eudsl-build -S $PWD \
-DCMAKE_PREFIX_PATH=$PWD/llvm-install \
Expand Down Expand Up @@ -199,13 +203,12 @@ jobs:
strategy:
fail-fast: false
matrix:
runs-on: ["ubuntu-22.04", "macos-14", "macos-13", "windows-2019"]
runs-on: ["ubuntu-22.04", "macos-14", "windows-2019"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
include: [
{runs-on: "ubuntu-22.04", name: "ubuntu_x86_64", os: "ubuntu"},
{runs-on: "windows-2019", name: "windows_x86_64", os: "windows"},
{runs-on: "macos-14", name: "macos_arm64", os: "macos"},
{runs-on: "macos-13", name: "macos_x86_64", os: "macos"},
{runs-on: "macos-14", name: "macos_arm64", os: "macos"}
]

runs-on: ${{ matrix.runs-on }}
Expand Down Expand Up @@ -255,16 +258,17 @@ jobs:
strategy:
fail-fast: false
matrix:
runs-on: ["ubuntu-22.04", "macos-14", "macos-13",
# "windows-2019"
runs-on: [
"ubuntu-22.04",
"macos-14"
# "windows-2019"
]
python-version: ["3.9", "3.10", "3.11", "3.12"]
include: [
{runs-on: "ubuntu-22.04", name: "ubuntu_x86_64", os: "ubuntu"},
# TODO(max): enable on windows by statically linking
# {runs-on: "windows-2019", name: "windows_x86_64", os: "windows"},
{runs-on: "macos-14", name: "macos_arm64", os: "macos"},
{runs-on: "macos-13", name: "macos_x86_64", os: "macos"},
{runs-on: "macos-14", name: "macos_arm64", os: "macos"}
]

runs-on: ${{ matrix.runs-on }}
Expand Down Expand Up @@ -303,10 +307,70 @@ jobs:
export TESTS_DIR="$PWD/projects/eudsl-py/tests"
python -m pytest -rA --capture=tee-sys $TESTS_DIR
test-eudsl-llvmpy:

needs: [build-eudsl]

strategy:
fail-fast: false
matrix:
runs-on: [
"ubuntu-22.04",
"macos-14",
# "windows-2019"
]
python-version: ["3.10", "3.11", "3.12"]
include: [
{runs-on: "ubuntu-22.04", name: "ubuntu_x86_64", os: "ubuntu"},
# TODO(max): enable on windows by statically linking
# {runs-on: "windows-2019", name: "windows_x86_64", os: "windows"},
{runs-on: "macos-14", name: "macos_arm64", os: "macos"},
]

runs-on: ${{ matrix.runs-on }}

name: "Test eudsl-llvmpy ${{ matrix.name }}"

defaults:
run:
shell: bash

steps:
- name: "Check out repository"
uses: actions/[email protected]
with:
submodules: false

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

- uses: actions/download-artifact@v4
with:
name: eudsl_${{ matrix.name }}_artifact
path: wheelhouse

- name: "Install eudsl-llvmpy"
run: |
python -m pip install pytest
python -m pip install eudsl-llvmpy -f wheelhouse
- name: "Test eudsl-llvmpy"
run: |
export TESTS_DIR="$PWD/projects/eudsl-llvmpy/tests"
python -m pytest -rA --capture=tee-sys $TESTS_DIR
release-eudsl:

if: ${{ github.event_name == 'workflow_dispatch' }}
needs: [test-eudsl-tblgen, test-eudsl-py]
needs: [
test-eudsl-tblgen,
test-eudsl-py,
test-eudsl-llvmpy
]
runs-on: "ubuntu-22.04"
name: "Release eudsl"

Expand All @@ -317,12 +381,10 @@ jobs:
strategy:
fail-fast: false
matrix:
runs-on: ["ubuntu-22.04"]
include: [
{runs-on: "ubuntu-22.04", name: "ubuntu_x86_64"},
{runs-on: "ubuntu-22.04", name: "macos_arm64"},
{runs-on: "ubuntu-22.04", name: "macos_x86_64"},
{runs-on: "ubuntu-22.04", name: "windows_x86_64"},
name: [
"ubuntu_x86_64",
"macos_arm64",
"windows_x86_64"
]

steps:
Expand Down
1 change: 1 addition & 0 deletions projects/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

if(NOT WIN32)
add_subdirectory(eudsl-py)
add_subdirectory(eudsl-llvmpy)
endif()
add_subdirectory(eudsl-nbgen)
add_subdirectory(eudsl-tblgen)
164 changes: 164 additions & 0 deletions projects/eudsl-llvmpy/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# Copyright (c) 2024.

cmake_minimum_required(VERSION 3.29)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(LLVM_SUBPROJECT_TITLE "EUDSLLLVM")
set(EUDSLLLVM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})

if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
message("Building ${LLVM_SUBPROJECT_TITLE} as a standalone project.")
project(${LLVM_SUBPROJECT_TITLE} CXX C)
set(EUDSLLLVM_STANDALONE_BUILD ON)
else()
enable_language(CXX C)
set(EUDSLLLVM_STANDALONE_BUILD OFF)
endif()

find_package(Python 3.9...<3.14 REQUIRED
REQUIRED COMPONENTS Interpreter Development.Module
OPTIONAL_COMPONENTS Development.SABIModule)

if(EUDSLLLVM_STANDALONE_BUILD)
find_package(LLVM REQUIRED CONFIG)

message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/bin)

list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
function(set_install_rpath_origin target)
set(_origin_prefix "\$ORIGIN")
if (APPLE)
set(_origin_prefix "@loader_path")
endif()
set_target_properties(${target} PROPERTIES INSTALL_RPATH "${_origin_prefix}")
endfunction()
function(patch_llvm_rpath target)
cmake_parse_arguments(ARG "STANDALONE" "" "" ${ARGN})
# hack so we can move libLLVM into the wheel
# see AddLLVM.cmake#llvm_setup_rpath
if (APPLE OR UNIX)
set(_origin_prefix "\$ORIGIN")
if (APPLE)
set(_origin_prefix "@loader_path")
endif()
if (STANDALONE)
get_target_property(_llvm_loc ${target} LOCATION)
else()
set(_llvm_loc "$<TARGET_FILE:${target}>")
endif()
set(_old_rpath "${_origin_prefix}/../lib${LLVM_LIBDIR_SUFFIX}")
if (APPLE)
if (EXISTS ${_llvm_loc})
execute_process(COMMAND install_name_tool -rpath "${_old_rpath}" ${_origin_prefix} "${_llvm_loc}" ERROR_VARIABLE rpath_err)
endif()
# maybe already updated...
if (rpath_err AND NOT rpath_err MATCHES "no LC_RPATH load command with path: ${_old_rpath}")
message(FATAL_ERROR "couldn't update rpath because: ${rpath_err}")
endif()
else()
# sneaky sneaky - undocumented
if (EXISTS ${_llvm_loc})
file(RPATH_CHANGE FILE "${_llvm_loc}" OLD_RPATH "${_old_rpath}" NEW_RPATH "${_origin_prefix}")
endif()
endif()
set_target_properties(${target} PROPERTIES INSTALL_RPATH "${_origin_prefix}")
endif()
endfunction()

include(AddLLVM)
endif()

include_directories(${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_BUILD_LIBRARY_DIR})
add_definitions(${LLVM_DEFINITIONS})

if(NOT TARGET LLVMSupport)
message(FATAL_ERROR "LLVMSupport not found")
endif()

execute_process(
COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_DIR)
find_package(nanobind CONFIG REQUIRED)

set(nanobind_options
-Wno-cast-qual
-Wno-deprecated-literal-operator
-Wno-covered-switch-default
-Wno-nested-anon-types
-Wno-zero-length-array
-Wno-c++98-compat-extra-semi
-Wno-c++20-extensions
$<$<PLATFORM_ID:Linux>:-fexceptions -frtti>
$<$<PLATFORM_ID:Darwin>:-fexceptions -frtti>
$<$<PLATFORM_ID:Windows>:/EHsc /GR>
)

set(EUDSLLLVM_SRC_DIR "${CMAKE_CURRENT_LIST_DIR}/src")
include_directories(${EUDSLLLVM_BINARY_DIR})
include_directories(${EUDSLLLVM_SRC_DIR})

execute_process(
COMMAND "${Python_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/eudsl-llvmpy-generate.py"
${LLVM_INCLUDE_DIRS}/llvm-c "${EUDSLLLVM_BINARY_DIR}/generated"
RESULT_VARIABLE _has_err_generate
)
if (_has_err_generate AND NOT _has_err_generate EQUAL 0)
message(FATAL_ERROR "couldn't generate sources: ${_has_err_generate}")
endif()
include_directories("${EUDSLLLVM_BINARY_DIR}/generated")
file(GLOB _gen_src CONFIGURE_DEPENDS "${EUDSLLLVM_BINARY_DIR}/generated/*.cpp")

nanobind_add_module(eudslllvm_ext
NB_STATIC
NB_DOMAIN eudslllvm
src/eudslllvm_ext.cpp
${_gen_src}
)
target_link_libraries(eudslllvm_ext PRIVATE LLVM LTO)
set_target_properties(eudslllvm_ext
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${EUDSLLLVM_SRC_DIR}/llvm"
)

set(STANDALONE)
if(EUDSLLLVM_STANDALONE_BUILD OR EUDSL_STANDALONE_BUILD)
set(STANDALONE STANDALONE)
endif()
patch_llvm_rpath(LLVM ${STANDALONE})
patch_llvm_rpath(LTO ${STANDALONE})
set_install_rpath_origin(eudslllvm_ext)
# copy libLLVM into the ext dir for wheels
install(IMPORTED_RUNTIME_ARTIFACTS LLVM LTO LIBRARY DESTINATION llvm)

target_compile_options(eudslllvm_ext PRIVATE ${nanobind_options})
target_compile_options(nanobind-static PRIVATE ${nanobind_options})

# note WORKING_DIRECTORY
set(NB_STUBGEN_CMD "${Python_EXECUTABLE}" "-m" "nanobind.stubgen"
--module eudslllvm_ext --recursive --include-private --output-dir .)
set(NB_STUBGEN_OUTPUTS "__init__.pyi")
add_custom_command(
OUTPUT ${NB_STUBGEN_OUTPUTS}
COMMAND ${NB_STUBGEN_CMD}
WORKING_DIRECTORY "${EUDSLLLVM_SRC_DIR}/llvm"
DEPENDS eudslllvm_ext
)
add_custom_target(eudslllvm_ext_stub ALL DEPENDS ${NB_STUBGEN_OUTPUTS})

install(TARGETS eudslllvm_ext LIBRARY DESTINATION llvm)
install(
DIRECTORY "${EUDSLLLVM_SRC_DIR}/llvm"
DESTINATION ${CMAKE_INSTALL_PREFIX}
PATTERN "*.pyc" EXCLUDE
PATTERN "*.so" EXCLUDE
PATTERN "*.a" EXCLUDE
PATTERN "__pycache__" EXCLUDE
PATTERN ".gitignore" EXCLUDE
)
Loading

0 comments on commit 42d83b5

Please sign in to comment.