Skip to content

Add native Apple Silicon (arm64) build support - #1493

Open
jaczkal wants to merge 1 commit into
k4yt3x:masterfrom
jaczkal:feat/apple-silicon-arm64
Open

Add native Apple Silicon (arm64) build support#1493
jaczkal wants to merge 1 commit into
k4yt3x:masterfrom
jaczkal:feat/apple-silicon-arm64

Conversation

@jaczkal

@jaczkal jaczkal commented Jun 17, 2026

Copy link
Copy Markdown

yo, I like the repo and spent some tokens to make it work on my machine, here are changes that worked for me

  • Guard x86-64 [[gnu::target_clones]] behind a VIDEO2X_TARGET_CLONES macro (include/libvideo2x/multiversion.h) so the attribute is emitted only on x86-64 with GCC/Clang. Fixes build failures on arm64 (Apple Silicon, Raspberry Pi, Jetson) and Apple Clang. Covers all 7 annotated sites.
  • CMake: use ld64-compatible link flags on Apple (-dead_strip instead of -s/--gc-sections); restrict -march=native to x86-64; link Homebrew libomp for ncnn's OpenMP on Apple Clang; honor _ROOT (CMP0074).
  • vulkan_utils: request VK_KHR_portability_enumeration on macOS (MoltenVK), guarded by APPLE so Linux/Windows are unaffected.
  • Add 'just macos' build recipe, macos-14 CI jobs (build + release), and docs/building/macos.md.

Closes #1362 for Apple Silicon; supersedes #1475.

- Guard x86-64 [[gnu::target_clones]] behind a VIDEO2X_TARGET_CLONES macro
  (include/libvideo2x/multiversion.h) so the attribute is emitted only on
  x86-64 with GCC/Clang. Fixes build failures on arm64 (Apple Silicon,
  Raspberry Pi, Jetson) and Apple Clang. Covers all 7 annotated sites.
- CMake: use ld64-compatible link flags on Apple (-dead_strip instead of
  -s/--gc-sections); restrict -march=native to x86-64; link Homebrew libomp
  for ncnn's OpenMP on Apple Clang; honor <Pkg>_ROOT (CMP0074).
- vulkan_utils: request VK_KHR_portability_enumeration on macOS (MoltenVK),
  guarded by __APPLE__ so Linux/Windows are unaffected.
- Add 'just macos' build recipe, macos-14 CI jobs (build + release),
  and docs/building/macos.md.

Closes k4yt3x#1362 for Apple Silicon; supersedes k4yt3x#1475.
@k4yt3x

k4yt3x commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Thanks for sharing the work. I'm not fond of how the VIDEO2X_TARGET_CLONES macro. I'll have to review the approach we use for macOS and figure something else out.

While I might not merge this PR, you can leave this around since it's a known working approach for macOS. I might still reference it when I eventually find time to work on this.

@Antman1526

Copy link
Copy Markdown

Confirming this PR's approach works end-to-end on Apple Silicon — I've been running a build based on it for real upscaling work. Details that may help land it:

Verified configuration

  • MacBook Pro M4 Max, macOS 26.5, Xcode 26.6 toolchain
  • Built against Homebrew's external ncnn/spdlog/boost (VIDEO2X_USE_EXTERNAL_NCNN=ON etc.) rather than the submodules — Homebrew's ncnn is Vulkan-enabled and links MoltenVK directly, and the build is much faster. Both paths work.
  • FFmpeg 8.1 links and runs fine (no API issues), in addition to 7.x.
  • --list-devices correctly enumerates the Apple GPU via MoltenVK; Real-ESRGAN 4× runs ~46 fps on 320×180 test content; RealCUGAN, libplacebo/Anime4K, and RIFE all verified working.

The MoltenVK ICD workaround in this PR's docs is definitely needed — current Homebrew molten-vk ships a dangling symlink for the ICD manifest, and writing a private manifest pointing at libMoltenVK.dylib (as documented here) fixes Vulkan instance creation.

One additional fix worth folding in: HEVC output is unplayable in QuickTime/Photos without an hvc1 tag. When encoding HEVC into MP4/MOV (e.g. -c hevc_videotoolbox, which is the natural encoder choice on macOS), the muxer defaults to the hev1 sample-entry tag, which Apple's players refuse. Small patch to Encoder::init in src/encoder.cpp:

// Apple players (QuickTime, Photos) only recognize HEVC in MP4/MOV when the
// sample entry is tagged 'hvc1'; the mux default 'hev1' renders unplayable.
if (enc_ctx_->codec_id == AV_CODEC_ID_HEVC && ofmt_ctx_->oformat->name != nullptr &&
    (std::strcmp(ofmt_ctx_->oformat->name, "mp4") == 0 ||
     std::strcmp(ofmt_ctx_->oformat->name, "mov") == 0)) {
    out_vstream->codecpar->codec_tag = MKTAG('h', 'v', 'c', '1');
}

(after the frame-rate copy, before the stream-map section — verified via ffprobe: codec_tag_string=hvc1, plays in QuickTime.) This benefits Windows/Linux users producing files for Apple devices too.

Also FWIW for anyone bundling a relocatable app from this: dylibbundler leaves duplicate LC_RPATH entries that make dyld hard-error, and skips ncnn's weak dylib reference to MoltenVK — both need manual install_name_tool fixes afterward. Happy to share the full bundle recipe if useful.

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.

Add proper support for arm64

3 participants