Whisper.cpp CMake Guide for MacOS & iOS Apps
Integrate whisper.cpp on your xcode project with ease
Solving the Whisper Library Issue on macOS
As a non-programmer, I struggled for weeks to solve the Whisper library issue with my macOS application, VoiceInk. With the help of Claude Sonnet, I was finally able to get it working. I hope this guide will help others who are facing similar issues.
Note: This guide is written with the help of claude-sonnet 3.5 as well. So there might be mistakes. Make sure you properly check everything.
Prerequisites
- Xcode installed
- Command line tools installed
- Basic understanding of terminal usage
Step-by-Step Implementation
1. Clone and Setup
# Clone the repository
git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
# Create build directory
mkdir build
cd build
2. Configure and Build
For macOS:
# Configure with macOS specific settings
cmake .. \
-DCMAKE_SYSTEM_NAME=Darwin \
-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
-DWHISPER_BUILD_EXAMPLES=OFF \
-DWHISPER_BUILD_TESTS=OFF \
-DWHISPER_BUILD_SERVER=OFF \
-DGGML_METAL_EMBED_LIBRARY=ON
# Build the project
cmake --build . --config Release
# Install (requires sudo)
sudo cmake --install . --config Release
For iOS:
# Configure with iOS specific settings
cmake .. \
-G Xcode \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
-DWHISPER_BUILD_EXAMPLES=OFF \
-DWHISPER_BUILD_TESTS=OFF \
-DWHISPER_BUILD_SERVER=OFF \
-DGGML_METAL_EMBED_LIBRARY=ON
# Build the project
cmake --build . --config Release
# Install (requires sudo)
sudo cmake --install . --config Release
3. Critical Xcode Configuration Steps
- Add Header Search Paths
- Path:
/usr/local/include
- Reason: Allows compiler to find
whisper.h
and related header files To add the header search path, follow these steps: - Go to
Build Settings
- Click on
Header Search Paths
- Click the
+
button to add a new path - Enter
/usr/local/include
- Path:
- Add Library Search Paths
- Path:
/usr/local/lib
- Reason: Enables linker to locate the compiled libraries To add the library search path, follow these steps:
- Go to
Build Settings
- Click on
Library Search Paths
- Click the
+
button to add a new path - Enter
/usr/local/lib
- Path:
- Configure Run Path
- Path:
/usr/local/lib
- Reason: Crucial for runtime library loading To configure the run path, follow these steps:
- Go to
Build Settings
- Click on
Runpath Search Paths
- Click the
+
button to add a new path - Enter
/usr/local/lib
- Path:
- Setup Framework Copy Phase
- Create a new “Copy Files” phase in Build Phases
- Set Destination to “Frameworks”
- Add all required dylib files
- Reason: Ensures libraries are bundled with the app To set up the framework copy phase, follow these steps:
- Go to
Build Phases
- Click the
+
button to add a new phase - Select “New Copy Files Phase”
- Set Destination to “Frameworks”
- Add the required dylib files
4. Library Files Process
- Drag the following files into your Xcode project:
libwhisper.dylib
libwhisper.1.dylib
libwhisper.1.7.4.dylib
- Add these files to the Copy Files phase
- Ensure “Code Sign On Copy” is enabled for each
Why This Works (And Why Other Steps Were Unnecessary)
- Essential Components
- Header paths: Compiler needs to find the header files
- Library paths: Linker needs to find the libraries
- Run paths: Runtime loader needs to locate libraries
- Framework copying: App needs libraries bundled for distribution
- Unnecessary Steps That Were Skipped
- Additional linker flags: Not needed as proper paths sufficient
- Complex framework configurations: Unnecessary with correct copy phase
- Manual symlink handling: Handled by proper framework copying
Common Issues and Solutions
- Dylib Not Found
- Cause: Incorrect run path or missing framework copy
- Solution: Verify run paths and framework copy phase
- Symbol Not Found
- Cause: Incorrect library linking
- Solution: Verify library search paths
- Header Not Found
- Cause: Incorrect header search path
- Solution: Verify header search path includes
/usr/local/include
Verification Steps
// Add to your Swift code to verify setup
import Foundation
guard whisper_print_system_info() == 0 else {
print("Whisper initialization failed")
return
}
print("Whisper successfully initialized")