使用本地头文件时未定义的引用
Posted
技术标签:
【中文标题】使用本地头文件时未定义的引用【英文标题】:undefined reference when using local header file 【发布时间】:2014-04-28 12:23:39 【问题描述】:我在使用 automake 时遇到了undefined reference
错误,该错误仅在存储库中存在某个本地头文件(include/lmp2atomstyle.h
,同一存储库中的库需要)时发生。
为了方便起见,我正在努力将多个 automake 项目源文件夹 lmpio
和 lmp2atomstyle
合并到一个文件夹中。这两个项目都是库,每个库都提供了一个用于测试的小程序。
手动合并Makefile.am
后,lmp2atomstyle
编译就好了,但是lmpio
找不到liblmp2atomstyle.so
的符号:
$ make check
make lmpiotest
make[1]: Entering directory `/home/e.lorenz/code/lmputils'
/bin/sh ./libtool --tag=CXX --mode=link g++ -g -O2 -lfftw3 -llmpio -llmp2atomstyle -o lmpiotest src/lmpiotest.o -llammps_custom -lmpi_stubs
libtool: link: g++ -g -O2 -o .libs/lmpiotest src/lmpiotest.o -lfftw3 /home/e.lorenz/code/lmputils/.libs/liblmpio.so /cluster/gcc/gcc-4.8.2/lib/../lib64/libstdc++.so -lm /home/e.lorenz/code/lmputils/.libs/liblmp2atomstyle.so -llammps_custom -lmpi_stubs -Wl,-rpath -Wl,/usr/local/lib -Wl,-rpath -Wl,/cluster/gcc/gcc-4.8.2/lib/../lib64
/home/e.lorenz/code/lmputils/.libs/liblmpio.so: undefined reference to `lmp2atomstyle_parse_file(void*, char const*)'
/home/e.lorenz/code/lmputils/.libs/liblmpio.so: undefined reference to `lmp2atomstyle_get_style(void*, char*, unsigned long)'
/home/e.lorenz/code/lmputils/.libs/liblmpio.so: undefined reference to `lmp2atomstyle_create()'
collect2: error: ld returned 1 exit status
make[1]: *** [lmpiotest] Error 1
make[1]: Leaving directory `/home/e.lorenz/code/lmputils'
make: *** [check-am] Error 2
这里是Makefile.am
:
AUTOMAKE_OPTIONS = subdir-objects
ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -Iinclude
lib_LTLIBRARIES = liblmp2atomstyle.la liblmpio.la
include_HEADERS = include/lmpio.h include/lmp2atomstyle.h
liblmp2atomstyle_la_SOURCES = src/lmp2atomstyle.c
liblmp2atomstyle_la_LDFLAGS = -version-info 1:0:0
liblmpio_la_SOURCES = src/lmpio.cpp
liblmpio_la_LDFLAGS = -version-info 1:0:0 -llmp2atomstyle
bin_PROGRAMS = lmp2atomstyle
lmp2atomstyle_SOURCES = src/lmp2atomstyle_main.c
lmp2atomstyle_LDFLAGS = -llmp2atomstyle
check_PROGRAMS = lmpiotest
lmpiotest_SOURCES = src/lmpiotest.cpp
lmpiotest_LDADD = -llammps_custom -lmpi_stubs
lmpiotest_LDFLAGS = -lfftw3 -llmpio -llmp2atomstyle
首先,我假设了一个错误的链接顺序,但是在仔细评估了所有库的依赖关系之后,链接顺序似乎没问题。无论如何,它在存储库合并之前工作。我也只使用了LDADD
,但没有帮助。
跟踪更改后,我发现lmpio
编译良好,只要include/lmp2atomstyle.h
不存在,而是从/usr/local/include 自动包含。此时未安装这些库。一旦我将lmp2atomstyle.h
复制到include/
,就会出现错误。
我错过了什么?对本地头文件和库有什么要求吗?使用 automake 时,头文件的路径如何导致链接错误?
追问:如果是缺少extern guard造成的,为什么在不同目录下编译会起作用?
这是成功运行make check
的lmpiotest
输出,即没有include/lmp2atomstyle.h
:
make lmpiotest
make[1]: Entering directory `/home/e.lorenz/code/lmputils'
depbase=`echo src/lmpiotest.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
g++ -DHAVE_CONFIG_H -I. -Iinclude -g -O2 -MT src/lmpiotest.o -MD -MP -MF $depbase.Tpo -c -o src/lmpiotest.o src/lmpiotest.cpp &&\
mv -f $depbase.Tpo $depbase.Po
/bin/sh ./libtool --tag=CXX --mode=link g++ -g -O2 -lfftw3 -llmpio -llmp2atomstyle -o lmpiotest src/lmpiotest.o -llammps_custom -lmpi_stubs
libtool: link: g++ -g -O2 -o .libs/lmpiotest src/lmpiotest.o -lfftw3 /home/e.lorenz/code/lmputils/.libs/liblmpio.so /cluster/gcc/gcc-4.8.2/lib/../lib64/libstdc++.so -lm /home/e.lorenz/code/lmputils/.libs/liblmp2atomstyle.so -llammps_custom -lmpi_stubs -Wl,-rpath -Wl,/usr/local/lib -Wl,-rpath -Wl,/cluster/gcc/gcc-4.8.2/lib/../lib64
make[1]: Leaving directory `/home/e.lorenz/code/lmputils'
我的configure.ac
:
AC_INIT([lmputils], [1.0], [(email...)])
LT_INIT
AM_INIT_AUTOMAKE()
AC_CONFIG_HEADERS([config.h])
AC_PROG_CXX
AM_PROG_CC_C_O
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
最后,这是导致错误的最小目录树:
./include
./include/lmpio.h
./include/lmp2atomstyle.h
./src
./src/lmp2atomstyle.c
./src/lmp2atomstyle_main.c
./src/lmpio.cpp
./src/lmpiotest.cpp
./Makefile.am
./configure.ac
./autogen.sh
谢谢:)
【问题讨论】:
另外,如果您的.cpp
文件应该链接到在 .c
文件中定义的函数,请确保标头包含在 extern "C"
保护中。
@Matt 在发布问题后不久就闪过我的脑海。再次感谢您指出。
【参考方案1】:
正如马特麦克纳布所指出的,这与外部后卫有关:
在include/lmp2atomstyle.h
中,我忘记为 c++ 添加外部保护:
#ifdef __cplusplus
extern "C"
#endif
[function headers]
#ifdef __cplusplus
#endif
这为我解决了问题。
后续问题: 为什么在不同目录下编译会起作用?
【讨论】:
更多信息:如果您不想“污染” .h 文件,另一种选择是在 .cpp 文件中转到extern "C"
#include "header.h"
以上是关于使用本地头文件时未定义的引用的主要内容,如果未能解决你的问题,请参考以下文章