g++编译,.o文件与.so文件顺序不对引起的 undefined reference ‘xxxxxx‘ 的错误

这周五呢,被一个 undefined reference 'xxxxx' 的编译错误折腾了一天时间,还好在下班之前找到了根本原因,事后反思呢,想想也算是自己给自己上了一课,也希望将这个经验教训记录一下,并分享给大家避免发生类似的问题。

按理来说执行 Makefile 文件编译的时候发生这样的错误,肯定就是需要用到的库文件没有配置正确,链接器将所有的 .o 文件链接成最终的可执行程序时没有找到相关库函数的定义所导致;但实际情况是,工程本身也就只用到了一个 .so 文件,而且清清楚楚,明明白白的都已经指定了相应的头文件路径,库文件路径以及需要的库文件名称,结果就是怎么编译,怎么试都是同样的错误:undefined reference 'xxxxxx' .

当时已经快崩溃了,实在想不出是哪儿的问题了,因为是通过 Makefile 来编译工程的,所以这里先贴出有 bug 的编译指令:

${TargetExeFile} : ${ObjectFiles}
	@echo "Linker all object files into target execute file..."
	${CXX} ${CSTANDARD} ${CXXFLAGS} ${IsLibFile} ${LIBRARY_DIR} ${LIBRARIES} $^ -o $@


${CXX} : g++ 
${CSTANDARD}: -std=c++17
${CXXFLAGS}: -Wall -O2 -fPIC  一些相关编译选项参数
${IsLibFile}:如果编译库文件就为 -shared, 否则就是空
${LIBRARY_DIR}:指定库文件所在路径 /usr/lib
${LIBRARIES}: 指定所需要用到的库文件  -lxxx
$^: 所有的依赖文件,这里为所有的 .o 文件
$@: 指定的可执行程序的文件

因为之前很多时候如果需要用 Makefile 编译代码时都是从别的地方拷贝一份写好的,然后改改里面的配置路径及相应库文件,源文件路径就可以了,很少动手亲自写一个完整的Makefile文件来使用。这样应了那句老话:纸上得来终觉浅,绝知此事要躬行。只有自己亲自动手去做一件事儿的时候,才会发现很多问题,同时也会暴露出很多自己不知道的点,正是这些点才恰恰是我们提升能力,快速成长的好时机;但现实情况是这些是我们最容易忽略轻视的点。

很巧的是,这个Makefile是自己从0到1写的一个完整的Makefile文件来使用,孰不知一个 bug 已经被我悄悄的安排进去了,就等着在某一天触发它后回头折磨我嘲笑我。正确的编译指令是下面这样子的,大家可以对比一下:

${TargetExeFile} : ${ObjectFiles}
	@echo "Linker all object files into target execute file..."
	${CXX} ${CSTANDARD} ${CXXFLAGS} ${IsLibFile} $^ ${LIBRARY_DIR} ${LIBRARIES} -o $@

产生bug的根本原因在于:对象文件(.o 文件)与 库文件(.so文件)的顺序写反了,一定要将 .o 文件写在 .so 文件之前,否则就会产生让人熟悉而又抓耳挠腮的错误。

这也算是众多导致 undefined reference 'xxxx' 错误的另一个特例原因了,在此记录分享与大家共勉。

你可能感兴趣的:(c++,g++,Makefile,undefined)