使用GHS数学库编译项目时遇TLS与非TLS定义不匹配错误
这个错误我之前帮同事排查过类似的情况,核心矛盾很清晰:系统libc里的errno是线程局部存储(TLS)变量,而你用的GHS数学库把errno当成了普通的全局非TLS变量来定义,链接器在合并符号时发现类型不匹配,直接报错。你尝试引入errno.h没用是正常的——头文件只是声明符号,冲突的是库文件里的实际定义,不是声明层面的问题。
结合你给出的编译参数,给你几个可行的解决方向:
重新编译GHS数学库,强制对齐TLS类型
如果你们有GHS数学库的源码,可以重新编译它,让它适配Linux/GCC的TLS规范。编译时添加-fthread-local-storage(GCC环境)或者GHS编译器对应的TLS启用参数(比如-mtls,具体参考GHS编译器文档),让库把errno定义成TLS变量,和系统libc的实现对齐。通过链接选项屏蔽GHS库中的
errno定义
在链接阶段添加参数-Wl,--exclude-libs=libghs_math.so,告诉链接器忽略libghs_math.so里的全局符号定义,这样就会优先使用系统libc提供的errno。如果需要更精准的控制,也可以用-Wl,--defsym=errno=__errno_location——Linux下GCC的errno本质是通过__errno_location()函数获取的线程局部存储指针,用这个选项可以强制把GHS库的errno符号映射到系统的实现上。查找GHS库的编译宏开关,禁用自定义
errno
去GHS数学库的头文件里找找有没有控制errno定义的宏,比如类似GHS_DISABLE_ERRNO_DEFINE这类的开关。如果有的话,把它加到你的C_DEFINES里,禁止库自己定义errno,转而使用系统标准的errno实现。
另外提个小细节:你的C_FLAGS里重复写了-fPIC,可以去掉其中一个,虽然不影响编译,但代码更整洁~
内容的提问来源于stack exchange,提问作者Rahul

