【发布时间】:2017-12-27 04:51:05
【问题描述】:
我正在开发一个最终将开源的 C 静态库,因此我在 Windows 和 Ubuntu 上进行交叉编译,以支持任何可移植性问题。
我遇到的问题是 Linux 构建中省略了其中一个目标文件中的符号。当我在 Windows 上使用 VS2015 构建库时,所有符号都存在。
我主要习惯于为 Windows 进行开发,因此对于大多数构建场景我都非常喜欢使用 IDE。在 Ubuntu 上,我使用的是 NetBeans ,我不确定问题出在我对 gcc 的理解上还是我没有正确设置 NetBeans。
详情
Ubuntu 16.04LTS 使用 gcc(Ubuntu) 5.4.0
NetBeans IDE 8.1 C/C++
该库由3个源文件和2个头文件组成:
queue.c --> queue implementation
memutil.c --> memory utilities
mylib.c --> main library implementation
queue.h --> included by queue.c and mylib.c
mylib.h --> header file for the static library
mylib.h 标头包含memutil.c 源文件的标头信息,包含在取决于命令行上MEMCHECK 符号的条件中。 memutil.c 源文件中的代码也是如此。 MEMCHECK 符号是在构建库时定义的,但是当我在 Linux 构建后在 libmylib.a 上运行 nm 时,没有为 memutil.o 目标文件列出任何符号。当我在 Windows 上查看 mylib.lib 文件时,列出了 memutil.obj 的所有符号。
现在,如果我添加一个仅包含 mylib.h 标头的存根源文件,则所有符号都存在于 libmylib.a 库中。我猜有某种头文件交互故障正在发生,但我不知道去哪里找出它是什么或如何修复它。我已经用谷歌搜索出了我能想到的尽可能多的不同措辞,但没有任何乐趣。
这是 NetBeans 构建输出,减去所有目录噪音:
gcc -c -g -Wall -DMEMCHECK -MMD -MP -MF "build/queue.o.d" -o build/queue.o queue.c
gcc -c -g -Wall -DMEMCHECK -MMD -MP -MF "build/memutil.o.d" -o build/memutil.o memutil.c
gcc -c -g -Wall -DMEMCHECK -MMD -MP -MF "build/mylib.o.d" -o build/mylib.o mylib.c
ar -rv dist/Debug/GNU-Linux/libmylib.a build/queue.o build/memutil.o build/mylib.o
ar: creating dist/Debug/GNU-Linux/libmylib.a
a - build/queue.o
a - build/memutil.o
a - build/mylib.o
ranlib dist/Debug/GNU-Linux/libmylib.a
BUILD SUCCESSFUL (total time: 3s)
在头文件包含中存根不能解决这个问题,可以吗?它有效,但看起来非常粗糙。此外,我真的不能相信它对 gcc 是必要的,而对 VS2015 是不必要的。
【问题讨论】:
-
它可能会有点麻烦,但您可以考虑使用
-E选项进行编译。这将在预处理器运行后显示源代码,因此您应该能够看到-DMEMCHECK是否在做您认为应该做的事情。您的代码将在#includes 之后接近尾声。您可以将输出重定向到一个文件,gcc -E code.c > ppCode.cstackoverflow.com/questions/3742822/preprocessor-output -
还建议使用
-Wextra标志进行编译以打开更多警告。 -
@yano:在我看来,如果条件有问题,Windows 构建也会很不稳定。
-
这当然是最有意义的,但显然有些事情正在发生。 IDE 可以在幕后#define 东西,谁知道呢?不会打赌我的下一张薪水是问题所在,但值得一看 IMO。只是链中要消除的另一个变量。
标签: c gcc netbeans-8