Я столкнулся с undefined reference
ошибка при работе с automake, возникающая только при определенном локальном заголовочном файле (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?
Дополнительный вопрос: если это вызвано отсутствием внешней защиты, почему это работает при компиляции в разных каталогах?
Вот lmpiotest
выход успешного make check
беги, то есть без 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
Спасибо 🙂
Как указал Мэтт Макнабб, это связано с внешними охранниками:
В include/lmp2atomstyle.h
Я забыл добавить внешнюю защиту для C ++:
#ifdef __cplusplus
extern "C" {
#endif
[function headers]
#ifdef __cplusplus
}
#endif
Это исправило это для меня.
Дополнительный вопрос:
Почему это работает при компиляции в разных каталогах?