Skip to content
Merged
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
36 changes: 36 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,39 @@ jobs:
- name: Verify Logging Pipeline
run: |
python -u tests/verify_pipeline.py

build-macos:
name: Build macOS Metal monitor
runs-on: macos-14

steps:
- uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install build tools
run: python -m pip install cmake==3.31.6

- name: Build native Metal monitor
run: ./build.sh --monitor --build-dir build-macos-ci

- name: Configure C++ tests
run: |
cmake -S . -B build-macos-ci \
-DBUILD_TESTING=ON \
-DBUILD_GPUFL_EXAMPLE=OFF \
-DBUILD_PYTHON=OFF \
-DBUILD_GPUFL_MONITOR=ON \
-DBUILD_GPUFL_LAUNCHER=OFF \
-DBUILD_GPUFL_INJECT=OFF \
-DGPUFL_ENABLE_NVIDIA=OFF \
-DGPUFL_ENABLE_AMD=OFF \
-DGPUFL_ENABLE_METAL=ON

- name: Run C++ unit tests
run: |
cmake --build build-macos-ci --target gpufl_tests --parallel
ctest --test-dir build-macos-ci --output-on-failure --verbose --timeout 60
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
### ai
.claude/
.junie/
.cache/

### idea
.idea/**
build/
build-*/
build_metal_stub/
build_tests/
gpufl-monitor-macos/
cmake-build-*/
CMakeFiles/
CMakeCache.txt
Expand Down Expand Up @@ -92,6 +95,8 @@ dist/

*.log

AGENTS.md

### Python
# Byte-compiled / optimized files
__pycache__/
Expand Down
56 changes: 52 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,17 @@ set(CMAKE_CXX_EXTENSIONS OFF)
# -----------------------
# Options
# -----------------------
option(GPUFL_ENABLE_NVIDIA "Enable NVIDIA backends (CUDA + NVML when available)" ON)
if(APPLE)
set(GPUFL_ENABLE_NVIDIA_DEFAULT OFF)
set(GPUFL_ENABLE_METAL_DEFAULT ON)
else()
set(GPUFL_ENABLE_NVIDIA_DEFAULT ON)
set(GPUFL_ENABLE_METAL_DEFAULT OFF)
endif()

option(GPUFL_ENABLE_NVIDIA "Enable NVIDIA backends (CUDA + NVML when available)" ${GPUFL_ENABLE_NVIDIA_DEFAULT})
option(GPUFL_ENABLE_AMD "Enable AMD backends (ROCm when available)" OFF)
option(GPUFL_ENABLE_METAL "Enable Apple Metal backend (macOS basic monitoring)" ${GPUFL_ENABLE_METAL_DEFAULT})
option(GPUFL_ENABLE_AMD_ROCPROFILER "Enable AMD rocprofiler-sdk tracing backend when available" ON)
# OFF builds the configuration release wheels ship (manylinux has no nvperf),
# so CI can catch #if GPUFL_HAS_PERFWORKS mistakes.
Expand Down Expand Up @@ -226,6 +235,7 @@ set(GPUFL_HAS_ROCM 0)
set(GPUFL_HAS_ROCM_SMI 0)
set(GPUFL_HAS_HIP 0)
set(GPUFL_HAS_ROCPROFILER_SDK 0)
set(GPUFL_HAS_METAL 0)
set(GPUFL_HAS_CUPTI 0)
set(GPUFL_HAS_PERFWORKS 0)
# ZLIB - try system install first, fall back to FetchContent so every platform
Expand Down Expand Up @@ -285,6 +295,12 @@ target_sources(gpufl PRIVATE include/gpufl/core/logger/file_compressor.cpp)
# and log a warning so the user knows HTTPS endpoints will fail.
# -----------------------
include(FetchContent)

# Resolve OpenSSL in this directory before cpp-httplib configures itself.
# Imported targets created only inside FetchContent's subdirectory are not
# guaranteed to be visible here, even though OpenSSL_FOUND can remain true.
find_package(OpenSSL 3.0 QUIET COMPONENTS SSL Crypto)

FetchContent_Declare(
httplib
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
Expand All @@ -302,8 +318,7 @@ set(HTTPLIB_COMPILE OFF CACHE BOOL "" FORCE)
set(HTTPLIB_INSTALL ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(httplib)

find_package(OpenSSL QUIET)
if(OpenSSL_FOUND)
if(TARGET OpenSSL::SSL AND TARGET OpenSSL::Crypto)
message(STATUS "Found OpenSSL: ${OPENSSL_VERSION} - HTTPS upload enabled")
target_compile_definitions(gpufl PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT=1)
target_link_libraries(gpufl PRIVATE OpenSSL::SSL OpenSSL::Crypto)
Expand All @@ -312,7 +327,7 @@ else()
message(WARNING
"OpenSSL not found - gpufl::uploadLogs will support HTTP only. "
"Pointing backend_url at an https:// endpoint will fail to verify. "
"Install OpenSSL (apt: libssl-dev, vcpkg: openssl, brew: openssl) "
"Install OpenSSL (apt: libssl-dev, vcpkg: openssl, brew: openssl@3) "
"to enable TLS.")
set(GPUFL_HTTPLIB_TLS 0)
endif()
Expand Down Expand Up @@ -353,6 +368,12 @@ else()
target_compile_definitions(gpufl PUBLIC GPUFL_ENABLE_AMD=0)
endif()

if(GPUFL_ENABLE_METAL)
target_compile_definitions(gpufl PUBLIC GPUFL_ENABLE_METAL=1)
else()
target_compile_definitions(gpufl PUBLIC GPUFL_ENABLE_METAL=0)
endif()

if(GPUFL_ENABLE_NVIDIA)
#
# CUDA capability: only if CUDA toolkit is available
Expand Down Expand Up @@ -729,6 +750,32 @@ if(GPUFL_ENABLE_AMD)
endif()
endif()

# -----------------------
# Metal backend (basic native monitoring)
# -----------------------
if(GPUFL_ENABLE_METAL)
if(APPLE)
enable_language(OBJCXX)
find_library(METAL_FRAMEWORK Metal)
find_library(FOUNDATION_FRAMEWORK Foundation)
if(METAL_FRAMEWORK AND FOUNDATION_FRAMEWORK)
set(GPUFL_HAS_METAL 1)
target_sources(gpufl PRIVATE
include/gpufl/backends/metal/metal_collector.mm
)
target_link_libraries(gpufl PRIVATE
${METAL_FRAMEWORK}
${FOUNDATION_FRAMEWORK}
)
message(STATUS "Found Metal framework: ${METAL_FRAMEWORK}")
else()
message(WARNING "GPUFL_ENABLE_METAL=ON but Metal/Foundation framework not found; GPUFL_HAS_METAL=0.")
endif()
else()
message(WARNING "GPUFL_ENABLE_METAL=ON is only supported on macOS; GPUFL_HAS_METAL=0.")
endif()
endif()

target_compile_definitions(gpufl PUBLIC
GPUFL_HAS_CUDA=${GPUFL_HAS_CUDA}
GPUFL_HAS_NVML=${GPUFL_HAS_NVML}
Expand All @@ -739,6 +786,7 @@ target_compile_definitions(gpufl PUBLIC
GPUFL_HAS_ROCM_SMI=${GPUFL_HAS_ROCM_SMI}
GPUFL_HAS_HIP=${GPUFL_HAS_HIP}
GPUFL_HAS_ROCPROFILER_SDK=${GPUFL_HAS_ROCPROFILER_SDK}
GPUFL_HAS_METAL=${GPUFL_HAS_METAL}
)

# -----------------------
Expand Down
55 changes: 52 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ CMAKE_ARGS="-DBUILD_TESTING=OFF" pip install "./gpufl-client[analyzer,viz]"

The repository includes platform-specific helper scripts for local source
builds. Use these scripts when you need to build against a specific CUDA
Toolkit, Python virtual environment, or wheel ABI.
Toolkit, Python virtual environment, Metal backend, or wheel ABI.

#### Ubuntu / Linux

`build.sh` is the Linux entrypoint. It delegates to `build-ubuntu.sh`.
On Linux, `build.sh` delegates to `build-ubuntu.sh`.

```bash
# Install into the active Python environment
Expand Down Expand Up @@ -97,6 +97,43 @@ Useful options:
| `--cuda-root PATH` | CUDA Toolkit root, for example `/usr/local/cuda-13.2`. |
| `--wheel-dir PATH` | Output directory for built wheels. |

#### macOS / Apple Metal

On macOS, `build.sh` delegates to `build-macos.sh`. The script builds with
Metal enabled and NVIDIA/AMD disabled. When Homebrew's `openssl@3` is
installed, the script passes its keg-only prefix to CMake automatically.

The Metal backend currently supports native monitoring only. CUDA trace
injection and the `--trace` build mode are not available on macOS.

```bash
# Install into the active Python environment
./build.sh

# Build a wheel into ./dist
./build.sh --wheel

# Build the native monitor binary
./build.sh --monitor

# Build and run the monitor with a writable local log directory
./scripts/run-monitor-macos.sh

# Use an explicit Python venv
./build-macos.sh --wheel --python .venv/bin/python
```

Useful options:

| Option | Meaning |
|---|---|
| `--install` | Install the package into the selected Python environment. This is the default. |
| `--wheel` | Build a wheel into `./dist` or `--wheel-dir`. |
| `--monitor` | Build the native `gpufl-monitor` binary with the Metal backend. |
| `--python PATH` | Python executable to use for install or wheel mode. |
| `--wheel-dir PATH` | Output directory for built wheels. |
| `--build-dir PATH` | CMake build directory for `--monitor`. |

#### Windows

Use `build-windows.ps1` from PowerShell. The script imports the Visual Studio
Expand Down Expand Up @@ -128,7 +165,7 @@ Useful parameters:
| `-WheelDir PATH` | Output directory for built wheels. |
| `-NoVcVars` | Skip importing `vcvars64.bat` and use the current shell environment. |

Both platform scripts pass the current CMake options:
Linux and Windows Python builds pass the current CUDA CMake options:

```text
BUILD_PYTHON=ON
Expand All @@ -141,6 +178,18 @@ CUDAToolkit_ROOT=<selected CUDA Toolkit>
CMAKE_CUDA_COMPILER=<selected nvcc>
```

macOS Python builds pass:

```text
BUILD_PYTHON=ON
BUILD_GPUFL_EXAMPLE=OFF
BUILD_TESTING=OFF
PYBIND11_FINDPYTHON=ON
GPUFL_ENABLE_NVIDIA=OFF
GPUFL_ENABLE_AMD=OFF
GPUFL_ENABLE_METAL=ON
```

### C++ (CMake FetchContent)
```cmake
cmake_minimum_required(VERSION 3.31)
Expand Down
Loading
Loading