Я хочу изменить местоположение моего тестового кода (tsnnls_test_DKU.c
) и я не могу внести изменения в make-файл, чтобы правильно отразить изменение этой папки. Некоторая помощь будет оценена.
У меня есть два вопроса:
1) Как связать объектные файлы из другого подкаталога
2) включить разные пути поиска (в моем примере 3 пути поиска).
В моей первоначальной настройке, где makefile работает нормально, я поставил свой тестовый код tsnnls_test_DKU.c
в следующем месте (внутри сторонних библиотек):
Dir1 = /home/dkumar/libtsnnls-2.3.3/tsnnls
Все объектные файлы, на которые я ссылаюсь, находятся на
OBJDir = /home/dkumar/libtsnnls-2.3.3/tsnnls
Кроме того, некоторые включают файл, содержащийся в tsnnls_test_DKU.c
находятся в следующих трех местах (три пути поиска):
Dir1 = /home/dkumar/libtsnnls-2.3.3/tsnnls
Dir2 = /home/dkumar/libtsnnls-2.3.3
Dir3 = /home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic
и мой make-файл работает нормально.
Тем не менее, я хотел бы изменить расположение тестового кода на:
Dir4 = /home/dkumar/CPP_ExampleCodes_DKU/Using_tsnnls_DKU/
Вот как выглядит мой make-файл (обновлен после ввода данных от другого пользователя:
# A sample Makefile
VPATH = -L/home/dkumar/libtsnnls-2.3.3/tsnnls
INC_PATH = -I/home/dkumar/libtsnnls-2.3.3/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/
# Here is a simple Make Macro.
LINK_TARGET = tsnnls_test_DKU
OBJS_LOC = tsnnls_test_DKU.o
# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS = libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o \
$(OBJS_LOC)
REBUILDABLES = $(LINK_TARGET)
all : $(LINK_TARGET)
echo All done
clean :
rm -f $(REBUILDABLES)
echo Clean done
#Inclusion of all libraries
RANLIB = ranlib
STATICLIB= /usr/local/lib/taucs_full/lib/linux/libtaucs.a
tsnnls_test_LDADD = $(LDADD)
LIBS = -largtable2 -llapack -lblas -lquadmath -lm
$(LINK_TARGET) : $(OBJS) $(tsnnls_test_LDADD) $(LIBS) $(STATICLIB)
gcc -g ${INC_PATH} -o $@ $^
Ошибка, которую я получаю при попытке запустить «$ make»
make: *** No rule to make target `libtsnnls_la-taucs_malloc.o', needed by `tsnnls_test_DKU'. Stop.
Очевидно, я не смог правильно использовать VPATH.
ОБНОВИТЬ:
Спасибо Майку Кингхану за ответ на мой вопрос.
Q1: Как связать объектные файлы из другого подкаталога?
Допустим, ваша программа prog
это программа на C, которая будет связана с объектом file0.o
, file1.o
который
должны быть скомпилированы в подкаталог obj
, Вот то, что вам обычно нужно в вашем
makefile для выполнения этой связи.
$(OBJS) = $(patsubst %.o,obj/%.o,file0.o file1.o)
prog: $(OBJS)
gcc -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
Это делает $(OBJS)
знак равно obj/file0.o, obj/file1.o
и вы просто передаете объект
такие файлы в команду link. Документация patsubst
Нотабене Этого недостаточно для Создайте obj
подкаталог, если он не существует, когда вы хотите
скомпилировать объектный файл в него. Вам придется создать его самостоятельно или научиться делать make
сделай это.
Q2: Как включить разные пути поиска?
Это неоднозначный вопрос — двусмысленность сбивает вас с толку — и мы должны разбить его на Q2.a, Q2.b, Q2.c:
Q2.a: Как указать разные пути поиска, где препроцессор будет искать заголовочные файлы, которые #include
в исходном коде?
По умолчанию препроцессор будет искать заголовочные файлы, используя встроенный список стандартных путей поиска. Вы можете увидеть их по
запуск препроцессора в подробном режиме, например,cpp -v
(CTRL-C, чтобы прекратить). Вывод будет содержать что-то вроде:
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/4.8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
Предположим, у вас есть несколько собственных заголовочных файлов в подкаталогах.
inc
а также inc/foo/bar
и хотите, чтобы препроцессор искал эти каталоги
также. Затем вам нужно передать параметры препроцессора:
-I inc -I inc/foo/bar
к вашей команде компиляции. Параметры препроцессора обычно назначаются
переменная make CPPFLAGS
например,
CPPFLAGS = -I inc -I inc/foo/bar
(вместе с любыми другими параметрами препроцессора, которые вам требуются) и передаются через него
переменная в рецепте команды компиляции, например
gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
Нотабене Это распространенная ошибка думать, что CPPFLAGS
является обычной переменной make для флагов компилятора C ++.
Обычная переменная make для флагов компилятора C ++: CXXFLAGS
,
Вы можете увидеть эффект от -I
вариант, запустив:
mkdir -p inc/foo/bar # Just to create the path
cpp -v -I inc -I inc/foo/bar
(CTRL-C, чтобы прекратить). Теперь вывод будет содержать как:
#include "..." search starts here:
#include <...> search starts here:
inc
inc/foo/bar
/usr/lib/gcc/x86_64-linux-gnu/4.8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
Q2.b: Как указать разные пути поиска, где компоновщик будет искать библиотеки?
Предположим, у вас есть библиотека, libfoobar.a
что вам нужно связать с prog
а также
что он находится в каталоге lib
это на 2 уровня выше вашего make-файла. Затем вы
нужно передать параметры компоновщика:
-L ../../lib
а также
-lfoobar
на вашу команду ссылки. Первый из них скажет компоновщику, что ../../lib
это одно из мест, где можно посмотреть
для библиотек. Обычно вы передаете эту опцию в рецепт команды компоновщика через LDFLAGS
, Второй рассказывает
компоновщик для поиска какой-либо библиотеки под названием libfoobar.a
(статическая библиотека) или libfoobar.so
(динамическая библиотека). Обычно вы передаете эту опцию в рецепт команды компоновщика через LDLIBS
Так же, как есть список путей поиска по умолчанию для препроцессора, существует
список путей поиска для компоновщика. Вы можете увидеть их, запустив:
gcc -v -Wl,--verbose 2>&1 | grep 'LIBRARY_PATH'
Вывод будет примерно таким:
Library_path = / USR / Библиотека / GCC / x86_64-Linux-ГНУ / 4,8 /: / USR / Библиотека / GCC / x86_64-Linux-ГНУ / 4.8 /../../../ x86_64-Linux-ГНУ /:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:
/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib /: / USR / Библиотека /
Когда вам нужно связать одну из стандартных библиотек, например, libm
(математическая библиотека), которая находится в одном из
пути поиска библиотеки по умолчанию, вам не нужно передавать какие-либо -L
вариант. -lm
один сделает.
Q2.c: Как указать разные пути поиска, где make
буду искать предпосылки
из целей?
Нотабене Это вопрос о make
, а не вопрос о препроцессоре, компиляторе или
линкер.
Мы предполагали, что все ваши объектные файлы будут скомпилированы в подкаталог obj
,
Чтобы их скомпилировать, было бы просто и просто использовать шаблонное правило:
obj/%.o:%.c
gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
которые говорят make
что, например obj/file0.o
сделан из file0.c
по рецепту:
gcc -c -o obj/file0.o $(CPPFLAGS) $(CFLAGS) file0.c
и аналогично для любого файла obj/*.o
и соответствующий файл *.c
Это хорошо, как долго file0.c
находится в том же каталоге, что и make-файл, но
Предположим, у вас есть *.c
файлы где-то еще? Скажем, ваши исходные файлы организованы
в подкаталогах, foo/file0.c
а также bar/file1.c
, затем make
не сможет
выполнить это шаблонное правило и сказать, что «нет правила создавать целевой объект obj / file0.o»,
и т.п.
Для решения этой проблемы используйте VPATH
, make
переменная, которая имеет особое значение.
Если вы назначите список имен каталогов, отмеченных ‘:’, VPATH
, затем
make
будет искать необходимое условие в каждом из перечисленных каталогов всякий раз, когда
он не может найти его в текущем каталоге. Так:
VPATH = foo:bar
вызовет make
посмотреть в текущем каталоге, а затем foo
а также bar
когда
он пытается найти .c
файлы, соответствующие этому шаблону правил. Это удастся удовлетворить
Правило и скомпилирует необходимые исходные файлы.
Нотабене Вы использовали VPATH
неправильно в вашем размещенном коде:
VPATH = -L/home/dkumar/libtsnnls-2.3.3/tsnnls
Вы назначили линкер поиск пути к нему, с опцией компоновщика -L
, который не имеет
бизнес там.
Нижняя линия:
Пути поиска препроцессора для поиска файлов заголовков указываются с помощью
препроцессор -I<dirname>
вариант. Передайте эти параметры рецепту компиляции в CPPFLAGS
Пути поиска компоновщика для поиска библиотек указываются с помощью
компоновщика -L<dirname>
вариант. Передайте эти параметры рецепту связи в LDFLAGS
Пути поиска для предварительных условий make
правила указаны в
make
переменная VPATH
, как ‘: -спунктированный список имен каталогов.
My answer to part of question
Я мог бы узнать, как связать object files from different subdirectory/ subdirectories
; но до сих пор could not figure out how to use different search path
:
Мой текущий make-файл:
# A sample Makefile
OBJS_PATH = /home/dkumar/libtsnnls-2.3.3/tsnnls/
C_INCLUDE_PATH = -I/home/dkumar/libtsnnls-2.3.3/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/
CPATH = -I/home/dkumar/libtsnnls-2.3.3/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/
# Here is a simple Make Macro.
LINK_TARGET = tsnnls_test_DKU
OBJS_LOC = tsnnls_test_DKU.o
# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS = libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o
## adding "$(OBJS_PATH)" to each word in "$(OBJS)"# which in our case is basically to add the same folder in front of all "*.o" object files.
OBJS2 = $(addprefix $(OBJS_PATH)/, $(OBJS))# OBJS_LOC is in current working directory,
OBJS_ALL = $(OBJS2) \
$(OBJS_LOC)
## DKU IS COPING THIS FROM ORIGINAL MAKEFILE THAT ARE GENERATED USING /home/dkumar/libtsnnls-2.3.3/tsnnls/MAKEFILE.AM
RANLIB = ranlib
STATICLIB= /usr/local/lib/taucs_full/lib/linux/libtaucs.a
tsnnls_test_LDADD = $(LDADD)
LIBS = -largtable2 -llapack -lblas -lquadmath -lmREBUILDABLES = $(OBJS_LOC) $(LINK_TARGET)all : $(LINK_TARGET)
echo All done
clean :
rm -f $(REBUILDABLES)
echo Clean done
# Here is a Rule that uses some built-in Make Macros in its command:
$(LINK_TARGET) : $(OBJS_ALL) $(tsnnls_test_LDADD) $(LIBS) $(STATICLIB)
gcc -g -o $@ $^