調(diào)研這個(gè)的原因,是因?yàn)橛袀€(gè)同事在macOS 12.2上打包好的程序,放在macOS 10.15上運(yùn)行時(shí)報(bào)錯(cuò):
Dyld Error Message: Symbol not found: __ZNKSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv Referenced from: /Library/Application Support/XXX.dylib (which was built for Mac OS X 12.2) Expected in: /usr/lib/libc++.1.dylib
調(diào)研了一番,發(fā)現(xiàn)這個(gè)是因?yàn)锳pple的SDK使用weak linking來(lái)支持不同版本的macOS 。
目標(biāo)文件所需的最低macOS版本有個(gè)專有名稱“deployment target” 。 查看庫(kù)的deployment target查看*.dylib、*.a或者主程序的deployment target屬性、sdk版本:otool -l 7z.dylib | grep -E "(minos|sdk)"find . -name "*.a" | xargs otool -l | grep -E "(minos|sdk)"通過(guò)命令行參數(shù)設(shè)置deployment targetclang/clang++在編譯時(shí)指定deployment target的命令行參數(shù)是-mmacos-version-min,比如:-mmacos-version-min=10.15,指定最低為Catalina的最后一個(gè)版本10.15 。針對(duì)iOS等有類似的開(kāi)關(guān)如-miphoneos-version-min、-mtvos-version-min、 -mwatchos-version-min 。-mmacos-version-min有個(gè)別名-mmacosx-version-min,別名只是為了兼容,盡量不使用這個(gè)別名 。clang會(huì)根據(jù)這個(gè)命令行參數(shù)來(lái)定義編譯器內(nèi)置宏MAC_OS_X_VERSION_MIN_REQUIRED等,而SDK頭文件<AvailabilityMacros.h>、<Availability.h>中有對(duì)這些宏的檢查,根據(jù)宏決定哪些符號(hào)采用weak linking 。weak linking的符號(hào)在編譯時(shí)不會(huì)報(bào)錯(cuò),dylib加載時(shí)也不會(huì)報(bào)錯(cuò),在用到對(duì)應(yīng)的符號(hào)時(shí)如果不存在才會(huì)報(bào)錯(cuò) 。 通過(guò)環(huán)境變量設(shè)置deployment targetclang的這個(gè)參數(shù)也可通過(guò)環(huán)境變量來(lái)設(shè)置 。命令行參數(shù)優(yōu)先于環(huán)境變量 。MACOSX_DEPLOYMENT_TARGETIPHONEOS_DEPLOYMENT_TARGETTVOS_DEPLOYMENT_TARGETWATCHOS_DEPLOYMENT_TARGETDRIVERKIT_DEPLOYMENT_TARGET 我們的工程以及我們的工程所直接/間接依賴的所有靜態(tài)庫(kù)/動(dòng)態(tài)庫(kù),都需要在編譯時(shí)指定相同的deployment target 。省事的辦法是通過(guò)環(huán)境變量來(lái)統(tǒng)一設(shè)置,在開(kāi)始整個(gè)打包之前設(shè)置一下 。其次是命令行開(kāi)關(guān) 。不同工程類型的命令行開(kāi)關(guān)設(shè)置方法有差異 。以下是命令行開(kāi)關(guān)的設(shè)置 。 通過(guò)vcpkg install編譯的庫(kù)需要更改vcpkg/triplets/x64-osx.cmake文件的內(nèi)容,增加下面三行(理論上只要第一行即可,但vcpkg目前貌似有bug,導(dǎo)致VCPKG_OSX_DEPLOYMENT_TARGET只對(duì)CMake工程生效,對(duì)其他類型的工程不生效 。所以需要第二行、第三行):set(VCPKG_OSX_DEPLOYMENT_TARGET "10.15")set(VCPKG_C_FLAGS -mmacosx-version-min=10.15)set(VCPKG_CXX_FLAGS -mmacosx-version-min=10.15)也可以復(fù)制這個(gè)文件到某個(gè)目錄下,在復(fù)制出來(lái)的文件中增加上面這三行,然后給vcpkg install傳遞--overlay-triplets參數(shù)以使用這個(gè)修改過(guò)的triplet文件 。這樣通過(guò)vcpkg install安裝的所有庫(kù)的deployment target都是10.15 。 autoconf類型的工程比如libiconv庫(kù)是手動(dòng)執(zhí)行autoconf編譯的,需要在configure時(shí)增加參數(shù):./configure CFLAGS=-mmacos-version-min=10.15 CPPFLAGS=-mmacos-version-min=10.15 CMake工程在CMakeLists.txt里的project()語(yǔ)句之前增加一句:set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")或者set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "" FORCE) Xcode工程在界面的工程屬性中可以設(shè)置deployment target 。 Makefile工程在makefile里自行給clang傳遞參數(shù)-mmacos-version-min=10.15即可 。【clang在編譯時(shí)指定目標(biāo)文件所需的最低macOS版本】
經(jīng)驗(yàn)總結(jié)擴(kuò)展閱讀
- 生豬肉怎么腌制比較嫩
- 在 .NET 7上使用 WASM 和 WASI
- 屎卡在馬桶能軟化了嗎
- 2023大暑節(jié)氣是在幾月幾日
- 2 onps棧移植說(shuō)明——編譯器及os適配層移植
- 怎么洗面筋
- 豆豉的吃法
- 世界上飯量最小的狗排行榜
- 世界十大可怕的螞蟻排行榜
- 漢堡在冰箱可以放幾天
