makefile: как связать объектные файлы из разных подкаталогов и включить разные пути поиска

Я хочу изменить местоположение моего тестового кода (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.

ОБНОВИТЬ:
Спасибо Майку Кингхану за ответ на мой вопрос.

3

Решение

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, как ‘: -спунктированный список имен каталогов.

11

Другие решения

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 $@ $^
0

По вопросам рекламы [email protected]