Add Windows build support and instructions

This commit is contained in:
Duncan Ogilvie
2025-12-21 03:01:51 +01:00
parent 46917df48c
commit d3e12d32c9
8 changed files with 112 additions and 5 deletions
+2
View File
@@ -4,6 +4,8 @@ cmake-build*/
CMakerLists.txt
CMakeLists.txt.user
CMakeUserPresets.json
.cache/
.venv/
+9 -1
View File
@@ -1,7 +1,7 @@
# This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/build-cpp/cmkr for more information
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.27)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
@@ -99,6 +99,14 @@ target_link_libraries(llvm-c-test-vendored PRIVATE
LLVM-C-Wrapper
)
if(NOT TARGET LLVM-Wrapper)
message(FATAL_ERROR "Target \"LLVM-Wrapper\" referenced by \"llvm-c-test-vendored\" does not exist!")
endif()
target_link_libraries(llvm-c-test-vendored PRIVATE
LLVM-Wrapper
)
set_target_properties(llvm-c-test-vendored PROPERTIES
OUTPUT_NAME
llvm-c-test
+70
View File
@@ -101,3 +101,73 @@ For development documentation, see `devdocs/README.md`.
This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
LLVM is licensed under the Apache License v2.0 with LLVM Exceptions.
## Windows
Download LLVM+Clang:
- https://github.com/vovkos/llvm-package-windows/releases/download/llvm-21.1.1/llvm-21.1.1-windows-amd64-msvc17-msvcrt.7z
- https://github.com/vovkos/llvm-package-windows/releases/download/clang-20.1.8/clang-20.1.8-windows-amd64-msvc17-msvcrt.7z
Merge them together in `C:\llvm-21.1.1`.
Create `CMakeUserPresets.json`:
```json
{
"version": 3,
"configurePresets": [
{
"name": "clang-cl",
"displayName": "Ninja with clang-cl",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_C_COMPILER": "C:/Program Files/LLVM/bin/clang-cl.exe",
"CMAKE_CXX_COMPILER": "C:/Program Files/LLVM/bin/clang-cl.exe",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_PREFIX_PATH": "d:/llvm-21.1.1"
}
}
],
"buildPresets": [
{
"name": "clang-cl",
"configurePreset": "clang-cl"
}
]
}
```
Create a virtual environment:
```bash
uv venv
```
Activate the virtual environment:
```bash
.venv/Scripts/activate
```
Configure the CMake project (this should find the Python from your venv):
```bash
cmake --preset clang-cl
```
_Note_: This saves the LLVM prefix to a file called `.llvm-prefix`, make sure to delete that if you change the LLVM prefix path.
Build the bindings:
```bash
cmake --build build
```
After that works you can build the Python package with `uv`:
```bash
uv sync --verbose
```
+2 -1
View File
@@ -1,5 +1,5 @@
[cmake]
version = "3.18"
version = "3.27" # IMPORTED_RUNTIME_ARTIFACTS, $<LIST:FILTER,...>
cmkr-include = "cmake/cmkr.cmake"
[project]
@@ -39,6 +39,7 @@ type = "test"
sources = ["llvm-c/llvm-c-test/*.c", "llvm-c/llvm-c-test/*.cpp"]
headers = ["llvm-c/llvm-c-test/*.h"]
properties = { OUTPUT_NAME = "llvm-c-test" }
link-libraries = ["::LLVM-Wrapper"]
# Test targets
[target.test_context]
+20 -1
View File
@@ -72,6 +72,19 @@ function(nanobind_add_typed_module name)
${ARGN}
)
# Copy runtime DLLs next to the module for testing on Windows
# Filter out Python and system DLLs
set(dll_filter_regex "python[0-9]*\\.dll|system32|Python[0-9]*/|api-ms-")
set(filtered_runtime_dlls $<LIST:FILTER,$<TARGET_RUNTIME_DLLS:${name}>,EXCLUDE,${dll_filter_regex}>)
if(WIN32)
add_custom_command(
TARGET ${name}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${filtered_runtime_dlls} $<TARGET_FILE_DIR:${name}>
COMMAND_EXPAND_LISTS
)
endif()
# Generate type stubs for the extension module
nanobind_add_stub(
${name}_stub
@@ -100,4 +113,10 @@ function(nanobind_add_typed_module name)
DESTINATION ${name}
RENAME __init__.pyi
)
endfunction()
if(WIN32)
install(
FILES ${filtered_runtime_dlls}
DESTINATION ${name}
)
endif()
endfunction()
+3 -1
View File
@@ -22,7 +22,7 @@ def get_llvm_prefix() -> Path:
with open(prefix_file, "r") as f:
llvm_prefix = os.path.expanduser(f.read().strip())
path = Path(llvm_prefix)
if not path.exists():
print(f"Error: LLVM prefix from .llvm-prefix does not exist: {path}", file=sys.stderr)
@@ -36,6 +36,8 @@ def main():
sys.exit(1)
tool = sys.argv[1]
if sys.platform == "win32":
tool += ".exe"
args = sys.argv[2:]
llvm_prefix = get_llvm_prefix()
+3
View File
@@ -45,6 +45,9 @@ cache-keys = [
{ file = "CMakeLists.txt" },
{ file = "src/**/*.cpp" },
{ file = "src/**/*.h" },
{ file = "llvm-c/llvm-c-test/*.c" },
{ file = "llvm-c/llvm-c-test/*.cpp" },
{ file = "llvm-c/llvm-c-test/*.h" },
]
[tool.ty.environment]
+3 -1
View File
@@ -194,6 +194,8 @@ def main():
# Verify required LLVM tools exist
required_tools = ["llvm-as", "llvm-dis", "FileCheck", "not"]
if sys.platform == "win32":
required_tools = [tool + ".exe" for tool in required_tools]
missing_tools = []
for tool in required_tools:
if not (llvm_tools_dir / tool).exists():
@@ -224,7 +226,7 @@ def main():
# Build lit command - use lit from the same venv/environment as this script
# Try to find lit executable in the same directory as the Python interpreter
python_dir = Path(sys.executable).parent
lit_exe = python_dir / "lit"
lit_exe = python_dir / (sys.platform == "win32" and "lit.exe" or "lit")
# Default options: single-threaded, deterministic order
# User can override with e.g. -j 10 for parallel execution