occa
occa copied to clipboard
undefined symbols when linking libocca.dylib with Metal
When building with ./configure-cmake.sh
on macOS 13.3:
[ 64%] Linking CXX shared library lib/libocca.dylib
ld: warning: directory not found for option '-F/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/System/Library/Frameworks/Metal.framework /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/System/Library/Frameworks/CoreServices.framework /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/System/Library/Frameworks'
Undefined symbols for architecture arm64:
"_MTLCopyAllDevices", referenced from:
occa::api::metal::getDeviceCount() in metal.mm.o
occa::api::metal::getDevice(int) in metal.mm.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [lib/libocca.dylib] Error 1
make[1]: *** [CMakeFiles/libocca.dir/all] Error 2
make: *** [all] Error 2
@BenWibking Adding -framework Metal -framework Cocoa
to the linker flags is needed on macOS. The following build script works for me (i use llvm from brew in order to get OpenMP support):
#!/bin/bash
cmake -DCMAKE_C_COMPILER="clang"\
-DCMAKE_CXX_COMPILER="clang++"\
-DCMAKE_EXE_LINKER_FLAGS="-framework Metal -framework Cocoa"\
-DCMAKE_SHARED_LINKER_FLAGS="-framework Metal -framework Cocoa"\
-DENABLE_EXAMPLES=ON\
. -B build > ./build.log 2>&1
cd build ; make -j4 >> ../build.log 2>&1 ; cd ..
I ran into this problem as well. It seems that the link line for libocc.dylib
is missing some frameworks. It looks like this on my machine:
/usr/bin/g++ ... -Xlinker -framework -Xlinker OpenCL -Xlinker -framework -Xlinker AppKit
If I change the way linking is done in FindMETAL.cmake
like so:
diff --git a/cmake/FindMETAL.cmake b/cmake/FindMETAL.cmake
index cfbdcfb3..e1251246 100644
--- a/cmake/FindMETAL.cmake
+++ b/cmake/FindMETAL.cmake
@@ -20,7 +20,5 @@ if(METAL_FOUND AND NOT TARGET OCCA::depends::METAL)
# Create our wrapper imported target
# Put it in the OCCA namespace to make it clear that we created it.
add_library(OCCA::depends::METAL INTERFACE IMPORTED)
- set_target_properties(OCCA::depends::METAL PROPERTIES
- INTERFACE_LINK_LIBRARIES "${METAL_LIBRARY} ${CORE_SERVICES} ${APP_KIT}"
- )
+ target_link_libraries(OCCA::depends::METAL INTERFACE ${METAL_LIBRARY} ${CORE_SERVICES} ${APP_KIT})
endif()
The link line ends up being:
... -Xlinker -framework -Xlinker OpenCL -Xlinker -framework -Xlinker Metal -Xlinker \
-framework -Xlinker CoreServices -Xlinker -framework -Xlinker AppKit
notice that Metal
and CoreServices
are now included. Seems like cmake is not handling the linking correctly using the set_target_properties
. My cmake
version is 3.26.4
.