MacOS Sequoia 15.5构建RpcExplorer遇ncurses版本化符号缺失问题
构建RpcExplorer在macOS Sequoia 15.5上的符号缺失问题
问题背景
在Apple Silicon的macOS Sequoia 15.5上构建RpcExplorer时遇到链接错误,该项目曾在macOS 14及以上版本正常构建,不确定从哪个版本开始失败。
构建完依赖库后,用nm命令检查发现,提示缺失的符号实际存在于lib/ncurses-6.3/dist/lib/libncursesw_g.a中,推测Apple工具链未能正确识别静态库中的符号。
需要明确此次系统更新的改动点,以及可修复该错误的编译标志。
构建命令与错误日志
git clone git@github.com:square/RpcExplorer.git cd RpcExplorer make // 省略(成功的)库构建部分 // ... // ... g++ -std=c++17 -o RpcExplorer RpcExplorer.cc -Ilib/cdk-5.0-20230201/dist/include -Ilib/ncurses-6.3/dist/include -Ilib/protobuf-3.21.2/dist/include lib/protobuf-3.21.2/dist/lib/libprotobuf.a lib/cdk-5.0-20230201/dist/lib/libcdkw.a lib/ncurses-6.3/dist/lib/libncursesw_g.a Undefined symbols for architecture arm64: "_endwin$NCURSES60", referenced from: _endCDK in libcdkw.a[19](cdkscreen.o) _execCDKSwindow in libcdkw.a[42](swindow.o) "_init_pair$NCURSES60", referenced from: _initCDKColor in libcdkw.a[22](draw.o) _initCDKColor in libcdkw.a[22](draw.o) _initCDKColor in libcdkw.a[22](draw.o) _initCDKColor in libcdkw.a[22](draw.o) _initCDKColor in libcdkw.a[22](draw.o) _initCDKColor in libcdkw.a[22](draw.o) _initCDKColor in libcdkw.a[22](draw.o) _initCDKColor in libcdkw.a[22](draw.o) ... "_initscr$NCURSES60", referenced from: runCursesInterface(Options&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, google::protobuf::MethodDescriptor const*, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, google::protobuf::MethodDescriptor const*>>>) in RpcExplorer-eac14a.o _initCDKScreen in libcdkw.a[19](cdkscreen.o) "_keypad$NCURSES60", referenced from: _newCDKButton in libcdkw.a[11](button.o) _newCDKDialog in libcdkw.a[21](dialog.o) _newCDKEntry in libcdkw.a[23](entry.o) _newCDKEntry in libcdkw.a[23](entry.o) _newCDKFselect in libcdkw.a[24](fselect.o) _newCDKLabel in libcdkw.a[30](label.o) _popupLabel in libcdkw.a[36](popup_label.o) ... "_newwin$NCURSES60", referenced from: _newCDKButton in libcdkw.a[11](button.o) _newCDKButton in libcdkw.a[11](button.o) _newCDKDialog in libcdkw.a[21](dialog.o) _newCDKDialog in libcdkw.a[21](dialog.o) _newCDKEntry in libcdkw.a[23](entry.o) _newCDKEntry in libcdkw.a[23](entry.o) _newCDKFselect in libcdkw.a[24](fselect.o) _newCDKFselect in libcdkw.a[24](fselect.o) ... "_start_color$NCURSES60", referenced from: _initCDKColor in libcdkw.a[22](draw.o) "_subwin$NCURSES60", referenced from: _newCDKEntry in libcdkw.a[23](entry.o) _newCDKEntry in libcdkw.a[23](entry.o) _newCDKScroll in libcdkw.a[39](scroll.o) _newCDKScroll in libcdkw.a[39](scroll.o) _newCDKSelection in libcdkw.a[41](selection.o) _newCDKSwindow in libcdkw.a[42](swindow.o) "_use_default_colors$NCURSES60", referenced from: runCursesInterface(Options&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, google::protobuf::MethodDescriptor const*, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, google::protobuf::MethodDescriptor const*>>>) in RpcExplorer-eac14a.o "_waddch$NCURSES60", referenced from: __drawCDKButton in libcdkw.a[11](button.o) __focusCDKButton in libcdkw.a[11](button.o) __unfocusCDKButton in libcdkw.a[11](button.o) _drawCDKDialogButtons in libcdkw.a[21](dialog.o) _drawCDKDialogButtons in libcdkw.a[21](dialog.o) _drawCDKDialogButtons in libcdkw.a[21](dialog.o) _boxWindow in libcdkw.a[22](draw.o) _boxWindow in libcdkw.a[22](draw.o) _boxWindow in libcdkw.a[22](draw.o) _boxWindow in libcdkw.a[22](draw.o) ... "_wbkgd$NCURSES60", referenced from: __setBKattrButton in libcdkw.a[11](button.o) __setBKattrDialog in libcdkw.a[21](dialog.o) _setCDKEntryHighlight in libcdkw.a[23](entry.o) __setBKattrEntry in libcdkw.a[23](entry.o) __setBKattrEntry in libcdkw.a[23](entry.o) __setBKattrEntry in libcdkw.a[23](entry.o) _drawCDKEntryField in libcdkw.a[23](entry.o) ... "_wgetch$NCURSES60", referenced from: _getcCDKObject in libcdkw.a[10](binding.o) "_whline$NCURSES60", referenced from: _boxWindow in libcdkw.a[22](draw.o) _boxWindow in libcdkw.a[22](draw.o) _attrbox in libcdkw.a[22](draw.o) _attrbox in libcdkw.a[22](draw.o) _drawLine in libcdkw.a[22](draw.o) _drawShadow in libcdkw.a[22](draw.o) _cleanCDKEntry in libcdkw.a[23](entry.o) ... "_wrefresh$NCURSES60", referenced from: __drawCDKButton in libcdkw.a[11](button.o) __focusCDKButton in libcdkw.a[11](button.o) __unfocusCDKButton in libcdkw.a[11](button.o) _eraseCursesWindow in libcdkw.a[14](cdk.o) _deleteCursesWindow in libcdkw.a[14](cdk.o) _refreshCDKScreen in libcdkw.a[19](cdkscreen.o) _refreshCDKWindow in libcdkw.a[19](cdkscreen.o) ... "_wvline$NCURSES60", referenced from: _boxWindow in libcdkw.a[22](draw.o) _boxWindow in libcdkw.a[22](draw.o) _attrbox in libcdkw.a[22](draw.o) _attrbox in libcdkw.a[22](draw.o) _drawLine in libcdkw.a[22](draw.o) _drawShadow in libcdkw.a[22](draw.o) _drawCDKScrollList in libcdkw.a[39](scroll.o) _drawCDKScrollList in libcdkw.a[39](scroll.o) ... ld: symbol(s) not found for architecture arm64 clang++: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [RpcExplorer] Error 1
问题更新
- 移除ncurses库后重新链接,缺失符号数量增加,说明部分未版本化的符号可被ncurses库解析。
- 在所有源文件及
Makefile、configure等辅助文件中,均未找到NCURSES60字符串。
核心问题可简化为:
- macOS 15.5上的clang编译CDK时,为何要求部分curses符号带版本号,其他符号却不需要?如何禁用该行为,让cdk不依赖特定版本的curses符号?
解决方案
1. 重新构建ncurses并禁用符号版本化
ncurses默认会给符号添加版本后缀,重新构建时添加--disable-versioned-symbols选项:
cd lib/ncurses-6.3 ./configure --disable-versioned-symbols --prefix=$(pwd)/dist make clean && make && make install
2. 指定CDK使用本地ncurses库
CDK编译时可能被系统ncurses头文件影响,强制使用了版本化符号。在CDK的configure阶段指定本地ncurses路径:
cd lib/cdk-5.0-20230201 ./configure --prefix=$(pwd)/dist --with-ncurses=$(pwd)/../ncurses-6.3/dist make clean && make && make install
3. 调整链接顺序
将ncurses库放在CDK库之后,确保链接器优先从ncurses中查找符号:
修改Makefile中的链接命令,把lib/ncurses-6.3/dist/lib/libncursesw_g.a移到lib/cdk-5.0-20230201/dist/lib/libcdkw.a之后:
g++ -std=c++17 -o RpcExplorer RpcExplorer.cc -Ilib/cdk-5.0-20230201/dist/include -Ilib/ncurses-6.3/dist/include -Ilib/protobuf-3.21.2/dist/include lib/protobuf-3.21.2/dist/lib/libprotobuf.a lib/ncurses-6.3/dist/lib/libncursesw_g.a lib/cdk-5.0-20230201/dist/lib/libcdkw.a
4. 禁用链接器的严格符号版本检查
在链接时添加-Wl,-no_deduplicate标志,缓解符号版本匹配问题:
g++ -std=c++17 -o RpcExplorer RpcExplorer.cc -Ilib/cdk-5.0-20230201/dist/include -Ilib/ncurses-6.3/dist/include -Ilib/protobuf-3.21.2/dist/include lib/protobuf-3.21.2/dist/lib/libprotobuf.a lib/cdk-5.0-20230201/dist/lib/libcdkw.a lib/ncurses-6.3/dist/lib/libncursesw_g.a -Wl,-no_deduplicate
系统改动说明
macOS Sequoia 15.5中,Apple调整了clang链接器对符号版本的处理逻辑,默认更严格地检查符号版本匹配。旧版本可能自动兼容版本化与非版本化符号,但新版本强制要求符号完全匹配,导致原本兼容的链接逻辑失效。
内容的提问来源于stack exchange,提问作者merlin2011
相关产品推荐
相关产品推荐

