diff --git a/.github/workflows/backend_build_darwin.yml b/.github/workflows/backend_build_darwin.yml index 4c87e8d66..61f87eff6 100644 --- a/.github/workflows/backend_build_darwin.yml +++ b/.github/workflows/backend_build_darwin.yml @@ -98,6 +98,7 @@ jobs: /opt/homebrew/Cellar/hiredis /opt/homebrew/Cellar/xxhash /opt/homebrew/Cellar/zstd + /opt/homebrew/Cellar/nlohmann-json key: brew-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('.github/workflows/backend_build_darwin.yml') }} - name: Dependencies @@ -109,7 +110,10 @@ jobs: # Without explicitly installing them, a brew cache-hit run restores # ccache's Cellar dir but skips installing those transitive deps, # and ccache fails at runtime with `dyld: Library not loaded`. - brew install protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd + # nlohmann-json is header-only and required by the ds4 backend + # (dsml_renderer.cpp includes ); on Linux it comes + # from the apt-installed nlohmann-json3-dev in the build image. + brew install protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json # Force-reinstall ccache so brew re-validates its full runtime-dep # closure on every run. This is the durable fix: when the upstream # ccache formula gains a new transitive dep (as it has multiple times @@ -128,7 +132,7 @@ jobs: # and decides "already installed" without re-linking, so on a cache- # hit run the formulas aren't on PATH. Force-link them; --overwrite # tolerates pre-existing symlinks from earlier installs. - brew link --overwrite protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd 2>/dev/null || true + brew link --overwrite protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json 2>/dev/null || true - name: Save Homebrew cache if: github.event_name != 'pull_request' && steps.brew-cache.outputs.cache-hit != 'true' @@ -148,6 +152,7 @@ jobs: /opt/homebrew/Cellar/hiredis /opt/homebrew/Cellar/xxhash /opt/homebrew/Cellar/zstd + /opt/homebrew/Cellar/nlohmann-json key: brew-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('.github/workflows/backend_build_darwin.yml') }} # ---- ccache for llama.cpp CMake builds ---- diff --git a/backend/cpp/ds4/CMakeLists.txt b/backend/cpp/ds4/CMakeLists.txt index 666f369ed..afc3dd43f 100644 --- a/backend/cpp/ds4/CMakeLists.txt +++ b/backend/cpp/ds4/CMakeLists.txt @@ -9,6 +9,22 @@ option(DS4_NATIVE "Compile with -march=native / -mcpu=native" ON) set(DS4_GPU "cpu" CACHE STRING "GPU backend: cpu, cuda, or metal") set(DS4_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ds4" CACHE PATH "Path to cloned ds4 source") +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # Homebrew installs protobuf/grpc under a non-default prefix. The generated + # backend.pb.cc / backend.grpc.pb.cc pull in google/protobuf and grpcpp + # headers, but the hw_grpc_proto library links neither target, so on macOS + # the headers (e.g. google/protobuf/runtime_version.h) are never on the + # compiler's include path. Add the Homebrew prefix globally, matching the + # llama-cpp backend which builds on Darwin CI. + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm64") + set(HOMEBREW_DEFAULT_PREFIX "/opt/homebrew") + else() + set(HOMEBREW_DEFAULT_PREFIX "/usr/local") + endif() + link_directories("${HOMEBREW_DEFAULT_PREFIX}/lib") + include_directories("${HOMEBREW_DEFAULT_PREFIX}/include") +endif() + find_package(Threads REQUIRED) find_package(Protobuf CONFIG QUIET) if(NOT Protobuf_FOUND) diff --git a/backend/cpp/ds4/Makefile b/backend/cpp/ds4/Makefile index 8d77f7bce..78e48dd15 100644 --- a/backend/cpp/ds4/Makefile +++ b/backend/cpp/ds4/Makefile @@ -1,10 +1,10 @@ # ds4 backend Makefile. # -# Upstream pin lives below as DS4_VERSION?=d881f2a05e8ff6bec001315a36b794b4aa310173 +# Upstream pin lives below as DS4_VERSION?=e34a8086693ba7ca5cfabd2b9028ee52f0bfac2e # (.github/bump_deps.sh) can find and update it - matches the # llama-cpp / ik-llama-cpp / turboquant convention. -DS4_VERSION?=d881f2a05e8ff6bec001315a36b794b4aa310173 +DS4_VERSION?=e34a8086693ba7ca5cfabd2b9028ee52f0bfac2e DS4_REPO?=https://github.com/antirez/ds4 CURRENT_MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) diff --git a/scripts/build/ds4-darwin.sh b/scripts/build/ds4-darwin.sh index 2da359668..16e7cdf2b 100755 --- a/scripts/build/ds4-darwin.sh +++ b/scripts/build/ds4-darwin.sh @@ -41,12 +41,17 @@ done echo "Bundled libraries:" ls -la build/darwin/lib -# Build an OCI tar that local-ai backends install can consume. -# scripts/build/oci-pack.sh is the existing helper used by llama-cpp-darwin -# - if your tree doesn't have it, write one (5 lines: tar + manifest.json). -if [ -f scripts/build/oci-pack.sh ]; then - bash scripts/build/oci-pack.sh build/darwin backend-images/ds4.tar "$IMAGE_NAME" -else - # Fallback: simple tar - local-ai accepts a flat tar in dev environments. - tar -C build/darwin -cvf backend-images/ds4.tar . -fi +# Build an OCI image tar (with manifest.json) that `local-ai backends install` +# can consume - mirrors llama-cpp-darwin.sh. The previously referenced +# scripts/build/oci-pack.sh helper was never added to the tree, so the +# plain-tar fallback produced a manifest-less tarball the installer rejects +# with "file manifest.json not found in tar". +PLATFORMARCH="${PLATFORMARCH:-darwin/arm64}" + +./local-ai util create-oci-image \ + build/darwin/. \ + --output ./backend-images/ds4.tar \ + --image-name "$IMAGE_NAME" \ + --platform "$PLATFORMARCH" + +rm -rf build/darwin