How to Fix “Undefined symbols for architecture arm64” When Building Google Test on Mac ARM64
I’m encountering a linker error when building Google Test (gtest) on a Mac with ARM64 architecture. The error message is:
Undefined symbols for architecture arm64:
"_main", referenced from:
<initial-undefines>
ld: symbol(s) not found for architecture arm64
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
My system information:
> uname -a
Darwin Martins-MacBook-Pro-2.local 25.0.0 Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:45 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T6000 arm64
Build Process
The build system first creates the Google Test libraries with these commands:
cd ${GTEST_ROOT}
g++ -std=c++20 -I${GTEST_ROOT}/googletest/include -I${GTEST_ROOT}/googletest -c ${GTEST_ROOT}/googletest/src/gtest-all.cc
g++ -std=c++20 -I${GTEST_ROOT}/googletest/include -I${GTEST_ROOT}/googletest -c ${GTEST_ROOT}/googletest/src/gtest_main.cc
ar -rv libgtest.a gtest-all.o gtest_main.o
I’ve verified that main() is in the static library:
> nm ${GTEST_ROOT}/libgtest.a | grep main
gtest_main.o:
0000000000000000 T _main
Then my build file executes:
g++ \
-o coverage/unittest.prog \
-L/opt/homebrew/lib \
coverage/BasicUpTest.o \
coverage/FixTest.o \
coverage/FrameTest.o \
coverage/unittest.o \
-fPIC \
-g \
-std=c++20 \
-L./coverage \
-lUnitTest \
-L../coverage \
-L${GTEST_ROOT} \
-lgtest \
-fprofile-arcs \
-ftest-coverage \
-lpthread
Question
Is there a way to verify that all my files are being built for the “arm64” processor architecture, and not accidentally created in a backward-compatible mode?
The “Undefined symbols for architecture arm64” error when building Google Test on Apple Silicon Macs typically occurs due to architecture mismatches between your build files and the target architecture. This happens when libraries or object files are compiled for x86_64 but the linker expects arm64 code, or when the Google Test libraries themselves aren’t properly built for ARM64.
Contents
- Verifying Build Architecture
- Fixing Google Test Build for ARM64
- Common Solutions
- Prevention Strategies
- Troubleshooting Checklist
Verifying Build Architecture
To verify that your files are being built for the correct arm64 architecture, use these commands:
Check Object File Architecture
Use the file command to verify the architecture of your object files:
file ${GTEST_ROOT}/gtest-all.o
file ${GTEST_ROOT}/gtest_main.o
file coverage/BasicUpTest.o
file coverage/FixTest.o
file coverage/FrameTest.o
You should see output indicating arm64 architecture:
${GTEST_ROOT}/gtest-all.o: Mach-O 64-bit object arm64
${GTEST_ROOT}/gtest_main.o: Mach-O 64-bit object arm64
Check Static Library Architecture
Use lipo to inspect the architecture slices in your static library:
lipo -info ${GTEST_ROOT}/libgtest.a
If it only shows x86_64 or no architecture information, you need to rebuild it properly for arm64.
Check Dynamic Libraries
Verify that any system libraries you’re linking against are compatible:
file /opt/homebrew/lib/libgtest*.dylib 2>/dev/null || echo "No dynamic gtest libraries found"
lipo -info /opt/homebrew/lib/lib*.a 2>/dev/null | grep gtest || echo "No architecture info for gtest"
Fixing Google Test Build for ARM64
Based on the research findings, here are the specific fixes for Google Test on ARM64:
Method 1: Rebuild Google Test with ARM64 Flags
Modify your build commands to explicitly specify the architecture:
cd ${GTEST_ROOT}
g++ -std=c++20 -I${GTEST_ROOT}/googletest/include -I${GTEST_ROOT}/googletest \
-c ${GTEST_ROOT}/googletest/src/gtest-all.cc -arch arm64
g++ -std=c++20 -I${GTEST_ROOT}/googletest/include -I${GTEST_ROOT}/googletest \
-c ${GTEST_ROOT}/googletest/src/gtest_main.cc -arch arm64
ar -rv libgtest.a gtest-all.o gtest_main.o
Method 2: Use Homebrew Google Test
According to the Stack Overflow discussion, you might need to use the Homebrew version:
brew install googletest
Then use the Homebrew libraries in your build:
g++ -o coverage/unittest.prog \
coverage/BasicUpTest.o coverage/FixTest.o coverage/FrameTest.o coverage/unittest.o \
-L/opt/homebrew/lib -lgtest -lgtest_main -lpthread \
-std=c++20 -arch arm64
Method 3: Build from Source Properly
The GitHub issue #3802 indicates that the pre-built libgtest.a may not contain arm64 architecture. Build from source:
cd ${GTEST_ROOT}
mkdir build && cd build
cmake .. -DCMAKE_OSX_ARCHITECTURES="arm64"
make
This will create properly ARM64-compatible libraries.
Common Solutions
Architecture-Specific Compilation
Ensure all your compilation commands include the -arch arm64 flag:
# For your test files
g++ -c coverage/BasicUpTest.cpp -o coverage/BasicUpTest.o -std=c++20 -arch arm64
g++ -c coverage/FixTest.cpp -o coverage/FixTest.o -std=c++20 -arch arm64
g++ -c coverage/FrameTest.cpp -o coverage/FrameTest.o -std=c++20 -arch arm64
g++ -c coverage/unittest.cpp -o coverage/unittest.o -std=c++20 -arch arm64
Linker Architecture Specification
Add architecture flags to your final link command:
g++ -o coverage/unittest.prog \
coverage/BasicUpTest.o coverage/FixTest.o coverage/FrameTest.o coverage/unittest.o \
-L./coverage -L../coverage -L${GTEST_ROOT} -lgtest \
-fPIC -g -std=c++20 -fprofile-arcs -ftest-coverage -lpthread \
-arch arm64
Use of Dynamic Libraries
As mentioned in the research, some users found success using .dylib instead of .a files:
# Convert static library to dynamic if needed
g++ -shared -o libgtest.so ${GTEST_ROOT}/gtest-all.o ${GTEST_ROOT}/gtest_main.o
Then link with the dynamic library:
g++ -o coverage/unittest.prog \
coverage/*.o -L${GTEST_ROOT} -lgtest \
-std=c++20 -arch arm64
Prevention Strategies
Build Configuration
Set up your build system to always target the correct architecture:
# Create a build script with architecture detection
ARCH=$(uname -m)
if [ "$ARCH" = "arm64" ]; then
CXX_ARCH_FLAGS="-arch arm64"
else
CXX_ARCH_FLAGS=""
fi
echo "Building for architecture: $ARCH"
Xcode Project Settings (if applicable)
If using Xcode, ensure:
- Build Active Architecture Only = NO
- Valid Architectures includes arm64
- Architectures in Build Settings set to $(ARCHS_STANDARD_64_BIT)
Continuous Integration
Add architecture checks to your CI pipeline:
# Verify all libraries are for correct architecture
check_architecture() {
local lib_path=$1
if lipo -info "$lib_path" | grep -q "arm64"; then
echo "✓ $lib_path contains arm64 architecture"
return 0
else
echo "✗ $lib_path missing arm64 architecture"
return 1
fi
}
Troubleshooting Checklist
Use this systematic approach to diagnose and fix the issue:
-
Verify System Architecture
bashuname -m # Should show arm64 -
Check All Object Files
bashfind . -name "*.o" -exec file {} \; | grep -v arm64 -
Inspect Library Architectures
bashlipo -info libgtest.a lipo -info /opt/homebrew/lib/libgtest*.a 2>/dev/null
-
Clean and Rebuild
bashrm -f *.o *.a # Rebuild with proper flags -
Test Linking Step by Step
bash# Link just the GTest library first g++ -o test_gtest -L${GTEST_ROOT} -lgtest -arch arm64 -
Check for Missing Symbols
bashnm -U libgtest.a | grep "testing::" -
Verify Compiler Compatibility
bashg++ -v | grep -E "Target|Architecture"
The key is ensuring that every component in your build chain - from individual object files to final libraries - is compiled explicitly for the arm64 architecture. As noted in the Stack Overflow discussion, this architecture mismatch is particularly common with static libraries on Apple Silicon Macs.
Sources
- Stack Overflow: symbol(s) not found for architecture arm64 while writing unit tests through Google Test library on M1 Chip
- GitHub Issue: apple M1 chip Mac build failed because of */libgtest.a does not contain the arm64 architecture
- Stack Overflow: Undefined symbols for architecture arm64
- Exercism Issue: x86_64 on Apple Silicon: ld: symbol(s) not found for architecture arm64
- Apple Developer Forums: ld: symbol(s) not found for architecture arm64
Conclusion
The “Undefined symbols for architecture arm64” error when building Google Test on Apple Silicon Macs is typically caused by architecture mismatches in your build chain. To resolve this:
- Always verify that all object files and libraries are built specifically for arm64 using
fileandlipocommands - Rebuild Google Test with explicit
-arch arm64flags or use the Homebrew version - Ensure consistent architecture across all compilation and linking steps
- Consider using dynamic libraries (.dylib) if static libraries continue to cause issues
- Implement architecture checks in your build process to prevent future problems
By systematically checking each component in your build chain and ensuring they all target the correct arm64 architecture, you can resolve this linker error and successfully build Google Test on your Apple Silicon Mac.