Skip to content

build: support native macOS (Darwin) build (NGT, Faiss, cgo, make test) - #3573

Open
aaf2tbz wants to merge 4 commits into
vdaas:mainfrom
aaf2tbz:feature/macos-arm64-support
Open

build: support native macOS (Darwin) build (NGT, Faiss, cgo, make test)#3573
aaf2tbz wants to merge 4 commits into
vdaas:mainfrom
aaf2tbz:feature/macos-arm64-support

Conversation

@aaf2tbz

@aaf2tbz aaf2tbz commented Jul 21, 2026

Copy link
Copy Markdown

Description

Enables building and testing Vald natively on macOS (Darwin, arm64/Apple Silicon and amd64), without Docker/devcontainer. Today make ngt/install, make faiss/install, and make test all fail at configure/compile time on macOS because the build recipes assume a GNU/Linux toolchain. This makes the flags OS-aware while preserving the existing Linux flag expansions, and fixes one cross-platform source bug. See #3570 for the full design.

What changed (6 files, +112/−27):

  1. NGT (Makefile, ngt/install): -flto=auto -ffat-lto-objectsNATIVE_LTO_FLAGS (-flto=thin on Darwin; -ffat-lto-objects is an unsupported LLVM target feature for Mach-O). OpenMP resolved via brew --prefix libomp (-DOpenMP_ROOT) so find_package(OpenMP) succeeds for Apple clang. -DCMAKE_INSTALL_RPATH=@loader_path/../lib so bin/ngt resolves libngt.2.dylib without ldconfig. ldconfig guarded (absent on Darwin).
  2. Faiss (Makefile, faiss/install): dropped the GNU LDFLAGS-as-CFLAGS and the -fopenmp -lopenblas -llapack -lgfortran linker flags on Darwin; cmake now finds OpenMP (OpenMP_ROOT) and BLAS/LAPACK (Apple Accelerate.framework) natively. BLA_VENDOR=OpenBLAS kept on Linux, unset on Darwin.
  3. HDF5 (Makefile, Makefile.d/tools.mk): skip the static example binaries on Darwin (-DHDF5_BUILD_EXAMPLES=OFF) — -static linking fails (no crt0.o on macOS). Run ldconfig only when present, while preserving a real ldconfig failure on Linux.
  4. Go cgo binary builds + make test (Makefile, Makefile.d/functions.mk): Darwin now uses thin-LTO, libc++, Homebrew libomp, and Accelerate.framework for both test and native binary link paths. GNU/ELF-only flags (-static, -z, -ffat-lto-objects, OpenBLAS/gfortran) remain on Linux only. The cgo build macros use NATIVE_LTO_FLAGS, preserve the Homebrew libomp include in all binary/example/e2e command-local cgo flags, and apply Darwin CGO_LDFLAGS to both arm64 and amd64. Darwin HDF5 flags also omit the unnecessary -ldl; Linux retains it.
  5. internal/core/algorithm/faiss/Capi.cpp (source portability bug): faiss::idx_t is int64_t = long on Linux but long long on Darwin. The C wrapper passed long* (matching Go's *C.long), which type-mismatches on Darwin. Cast to faiss::idx_t* at the 6 faiss call sites (add_with_ids, search, IDSelectorArray) — safe reinterpret_cast (both 64-bit, identical layout on LP64).

Helper vars generalized and shared: OPENMP_PREFIX, OPENMP_CFLAGS, NATIVE_LTO_FLAGS. macOS setup is documented in docs/contributing/development.md, including an architecture-neutral optional LLVM path via $(brew --prefix llvm)/bin.

Related Issue

#3570 (extends #2694 / VALD-359).

Versions

  • Vald Version: v1.7.17
  • Go Version: v1.26.5 (darwin/arm64)
  • Rust Version: n/a (this PR does not touch the Rust data plane)
  • Docker Version: n/a
  • Kubernetes Version: n/a
  • Helm Version: n/a
  • NGT Version: v2.7.2
  • Faiss Version: v1.14.1

Checklist

Special notes for your reviewer

  • Verified end-to-end on Apple M4 (darwin27/arm64): make ngt/install, make faiss/install, make hdf5/install all green; libngt.a/libfaiss.a link against libomp + Accelerate and return correct ANN search results (functional C/C++ tests); go build ./... compiles the entire codebase; NGT + faiss cgo unit tests run green; 246/254 unit-test packages pass via make test.
  • The build uses Apple clang from Xcode Command Line Toolsbrew install llvm is NOT required (verified by building with brew llvm removed from PATH).
  • Review follow-up validation at commits 0d801156a and 01a819de0: make GOOS=darwin GOARCH=arm64 cmd/agent/core/ngt/ngt cmd/agent/core/faiss/faiss passed after each flag change; both Mach-O binaries reported cgo enabled and linked Homebrew libomp plus Apple Accelerate.framework. The final compile commands include Homebrew’s libomp/include; Darwin arm64/amd64 and Linux arm64/amd64 flag expansions were also checked.
  • Linux/container flag behavior is unchangedmake -pn confirms the original GNU LTO, OpenBLAS/LAPACK, gfortran, static, and ELF linker flags remain for GOOS=linux on arm64 and amd64; the Dockerfile's NGT_EXTRA_CMAKE_FLAGS override still applies.
  • The remaining 8 non-passing test packages are not macOS build issues: 3 are environment-dependent (need Cassandra / make dockerfile codegen / ruleguard — fail on Linux too); internal/file/watch is a fsnotify kqueue/goleak behavior; and 3 NGT-agent property tests surface a pre-existing, platform-independent vqueue correctness bug filed separately as vqueue newer() timestamp collision: GetVector reports not-exists on fast CPUs (delete+insert in same nanosecond) #3571 (timestamp collision in newer()).
  • Commits are atomic per layer: build(ngt), build(faiss), build(cgo,test), docs(development), plus two focused build(darwin) review-follow-up commits.

Supersedes #3572 (identical changes; branch renamed from feature/agent/macos-arm64-support to feature/macos-arm64-support to drop the area segment, since this touches build/docs/cgo rather than a single area).

Summary by CodeRabbit

  • New Features

    • Added native build support for macOS on Apple Silicon and Intel systems.
    • Added platform-specific compiler, dependency, OpenMP, and linker configuration.
  • Bug Fixes

    • Fixed FAISS ID handling for add, search, and remove operations.
    • Prevented build failures when ldconfig is unavailable.
  • Documentation

    • Expanded macOS development prerequisites, dependencies, build steps, and testing guidance.
  • Chores

    • Excluded macOS local native-build output directories from version control.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds native macOS build support through OS-aware Makefile configuration, dependency installation changes, development documentation, and guarded ldconfig calls. FAISS C API ID buffers are explicitly cast to faiss::idx_t* for add, search, and removal operations.

Changes

Native macOS support

Layer / File(s) Summary
Platform build configuration
.gitignore, Makefile, Makefile.d/functions.mk
Adds macOS build ignores and Darwin-specific OpenMP, LTO, linker, CGO, FAISS, test, and static-linking settings.
Native dependency installation
Makefile.d/tools.mk, Makefile.d/functions.mk, docs/contributing/development.md
Passes platform-specific flags to NGT and FAISS builds, conditionally runs ldconfig, and documents macOS setup and testing.
FAISS ID type compatibility
internal/core/algorithm/faiss/Capi.cpp
Casts FAISS add, search, and removal ID buffers to faiss::idx_t*.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

  • vdaas/vald#3572 — Shares the macOS build and FAISS ID type changes.
  • vdaas/vald#3040 — Contains earlier Darwin build-flag and CGO environment changes.
  • vdaas/vald#3044 — Contains overlapping Darwin Makefile and CGO configuration changes.

Suggested labels: type/feature

Suggested reviewers: kmrmt, kpango

Poem

Darwin flags shape the build,
OpenMP paths are clearly filled.
FAISS IDs use the right type,
Native tools link clean and bright.
macOS builds proceed.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: native macOS (Darwin) build support for NGT, Faiss, cgo, and tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@aaf2tbz

aaf2tbz commented Jul 21, 2026

Copy link
Copy Markdown
Author

I don't have permission to add labels to this PR (external contributor), and the repo's labeler workflow is scoped to non-fork PRs (fork == false), so it won't auto-label this one. Suggested labels for triage:

  • type/feature
  • area/makefile
  • area/internal
  • area/agent/core/faiss
  • team/core
  • priority/medium

(The same applies to the linked issues #3570 and #3571 — currently unlabeled.)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1bd7e356f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/contributing/development.md
Comment thread Makefile Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/contributing/development.md`:
- Around line 48-55: Update the optional LLVM PATH instruction in the
development documentation to use Homebrew’s dynamic prefix via brew --prefix
llvm, rather than the hard-coded /opt/homebrew/opt/llvm/bin path. Preserve the
existing guidance to install llvm only when explicitly needed.

In `@Makefile`:
- Line 903: Replace the ldconfig expression at Makefile lines 903-903 and
929-929 with an if command -v ldconfig check that runs ldconfig only when
available and propagates failures. In Makefile.d/tools.mk lines 393-393,
preserve the surrounding recipe’s && chain while using the same conditional
ldconfig body.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 270a525b-c8b6-46b1-a56c-4b933dd1fc3d

📥 Commits

Reviewing files that changed from the base of the PR and between d50c5e7 and 1bd7e35.

📒 Files selected for processing (5)
  • .gitignore
  • Makefile
  • Makefile.d/tools.mk
  • docs/contributing/development.md
  • internal/core/algorithm/faiss/Capi.cpp

Comment thread docs/contributing/development.md Outdated
Comment thread Makefile Outdated
@aaf2tbz

aaf2tbz commented Jul 21, 2026

Copy link
Copy Markdown
Author

Following Up on this PR until Reviewer Bots are Satisfied.

@aaf2tbz
aaf2tbz force-pushed the feature/macos-arm64-support branch from 5231db7 to 0d80115 Compare July 21, 2026 20:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Makefile.d/functions.mk (1)

135-150: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Guard -static on Darwin
go-e2e-build always passes -extldflags '-static'. macOS native builds are supported here, so make e2e will fail on Darwin unless this is gated on GOOS and falls back to non-static linking.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile.d/functions.mk` around lines 135 - 150, Update the go-e2e-build
command’s linker flags around -ldflags so -extldflags '-static' is applied only
when GOOS is not Darwin. For Darwin builds, omit the static linker option and
retain the existing non-static Go test/build arguments.
Makefile (1)

225-225: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Avoid brew lookups in the sudo make path.

Makefile#L173-L225 evaluates $(shell brew --prefix ...) during parsing, so the documented sudo make ngt/install hdf5/install faiss/install flow runs Homebrew as root and can fail on macOS.

  • Makefile#L173-L225: make the Homebrew prefixes overridable or inject them before privilege escalation.
  • docs/contributing/development.md#L41-L42: split the privileged install step from the unprivileged build/configure step instead of recommending a single sudo make.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` at line 225, Make the Homebrew prefix variables used by the
Makefile build/install targets overridable or pass them into the environment
before any sudo escalation, so parsing the Makefile never runs brew as root;
update Makefile:225 and the related logic in Makefile:173-225. In
docs/contributing/development.md:41-42, replace the single sudo make workflow
with separate privileged dependency-installation and unprivileged
build/configure steps.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Makefile`:
- Around line 172-173: Update the HDF5 linker flag definitions in HDF5_LDFLAGS
and CGO_LDFLAGS so Darwin builds do not include the Linux-specific -ldl flag;
retain dynamic-loader linking only for non-Darwin targets or use the appropriate
platform-specific library.

In `@Makefile.d/functions.mk`:
- Around line 64-67: Update the cgo flag assignments in all three affected macro
blocks to preserve the exported OpenMP flags, composing CGO_CFLAGS and
CGO_CXXFLAGS with their existing values or explicitly including OPENMP_CFLAGS;
apply the same OpenMP inclusion consistently across the related C, C++, and
linker flag definitions without changing unrelated flags.

---

Outside diff comments:
In `@Makefile`:
- Line 225: Make the Homebrew prefix variables used by the Makefile
build/install targets overridable or pass them into the environment before any
sudo escalation, so parsing the Makefile never runs brew as root; update
Makefile:225 and the related logic in Makefile:173-225. In
docs/contributing/development.md:41-42, replace the single sudo make workflow
with separate privileged dependency-installation and unprivileged
build/configure steps.

In `@Makefile.d/functions.mk`:
- Around line 135-150: Update the go-e2e-build command’s linker flags around
-ldflags so -extldflags '-static' is applied only when GOOS is not Darwin. For
Darwin builds, omit the static linker option and retain the existing non-static
Go test/build arguments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 15c653a1-63ea-42ee-8bf4-dfb38cf87583

📥 Commits

Reviewing files that changed from the base of the PR and between 1bd7e35 and 5231db7.

📒 Files selected for processing (4)
  • Makefile
  • Makefile.d/functions.mk
  • Makefile.d/tools.mk
  • docs/contributing/development.md

Comment thread Makefile Outdated
Comment thread Makefile.d/functions.mk Outdated
@aaf2tbz

aaf2tbz commented Jul 21, 2026

Copy link
Copy Markdown
Author

Native macOS functional validation: image similarity search

Validated the complete native Darwin/arm64 path at signed commit 01a819de0 using a screenshot containing several game-cover images.

Test pipeline:

  1. Cropped four visible covers: Mind Scanners, Nidhogg 2, PlateUp!, and Portal 2.
  2. Generated 768-dimensional image feature vectors with macOS Vision.
  3. Started the natively built Vald NGT agent with a 768-dimensional l2 index.
  4. Inserted all four vectors through Vald's gRPC API and created the NGT index.
  5. Resized and JPEG-compressed the Portal 2 crop, generated a new query vector, and searched Vald.

Result (lower distance is more similar):

1. portal-2       distance=0.408937
2. nidhogg-2      distance=1.153264
3. plateup        distance=1.236733
4. mind-scanners  distance=1.262336

Vald correctly returned portal-2 as the nearest neighbor despite the query image being resized and re-encoded.

This exercised the working end-to-end path:

image -> Vision embedding -> gRPC insert -> native NGT indexing -> nearest-neighbor search

The temporary server and generated demo artifacts were removed afterward; the repository remained clean.

@kpango
kpango requested review from a team, kmrmt and kpango and removed request for a team July 22, 2026 04:39
@Matts966

Matts966 commented Aug 5, 2026

Copy link
Copy Markdown
Member

@aaf2tbz
Thank you for your contribution! Could you please check the following points? 🙏

  • Add an explicit C++ standard to Darwin CGO_CXXFLAGS; Faiss currently fails to compile.
  • Pass the Faiss optimization flags via CMAKE_CXX_FLAGS, as CMAKE_C_FLAGS is unused.
  • Avoid running Homebrew lookups under the documented sudo make workflow.
  • Rebase the branch and resolve the conflicts with main.

Thank you!

@aaf2tbz
aaf2tbz force-pushed the feature/macos-arm64-support branch from 01a819d to aeff4dc Compare August 5, 2026 06:19
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Makefile.d/tools.mk`:
- Around line 470-488: Replace the Faiss post-build header installation command
after the CMake configuration block with POSIX-compatible directory creation and
copying: create each destination directory using mkdir -p, then copy headers
with install -m 0644 without the GNU-only -D option. Preserve the existing
destination paths and ensure the command works on Darwin.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3f5425b3-619c-42da-adfc-8199a8fdc982

📥 Commits

Reviewing files that changed from the base of the PR and between c79f165 and aeff4dc.

📒 Files selected for processing (6)
  • .gitignore
  • Makefile
  • Makefile.d/functions.mk
  • Makefile.d/tools.mk
  • docs/contributing/development.md
  • internal/core/algorithm/faiss/Capi.cpp

Comment thread Makefile.d/tools.mk Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Makefile.d/tools.mk`:
- Line 489: Add a concise Makefile comment immediately before the FAISS
header-copy command describing that it discovers and installs headers under
$(USR_LOCAL)/include while preserving failure handling.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5c867f5b-303e-4b65-8138-55c2598823a9

📥 Commits

Reviewing files that changed from the base of the PR and between aeff4dc and e74b8d3.

📒 Files selected for processing (1)
  • Makefile.d/tools.mk

Comment thread Makefile.d/tools.mk Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants