#c #makefile #dynamic-linking
#c #makefile #динамическое связывание
Вопрос:
У меня есть makefile в моем каталоге src. Makefile должен создать структуры данных, которые находятся в DataStructures/, а затем выполнить итерацию по всем cpp-файлам в calculations/ и создать соответствующий файл .so в ../bin/calculations
Я попробовал следующий синтаксис:
DAST = DataStructures/
COMPS = computations/
BIN = ../bin/
OBJECTS = ${DAST}Atom.o ${DAST}Molecule.o
COMPILE = g -Wall -g -c -std=c 0x -I/usr/local/include/openbabel-2.0 LINK = g -Wall -g -std=c 0x ${OBJECTS} -lopenbabel -I/usr/local/include/openbabel-2.0
all: ${BIN}main ${DAST}Molecule.o ${DAST}Atom.o ${BIN}${COMPS}%.so
${BIN}main: ${OBJECTS} main.cpp
${LINK} main.cpp -o ${BIN}main
${DAST}Molecule.o: ${DAST}Molecule.h ${DAST}Molecule.cpp
${COMPILE} ${DAST}Molecule.cpp -o ${DAST}Molecule.o
${DAST}Atom.o: ${DAST}Atom.h ${DAST}Atom.cpp
${COMPILE} ${DAST}Atom.cpp -o ${DAST}Atom.o
${BIN}${COMPS}%.o: ${COMPS}%.cpp
gcc -Wall -fPIC -c -lopenbabel $< -I/usr/local/include/openbabel-2.0 -std=c 0x
${BIN}${COMPS}%.so: ${COMPS}%.o
gcc -shared -Wl,-soname,libcsmtest.so.1 -o libcsmtest.so $@
clean:
rm -rf ${OBJECTS}
.PHONY: all clean
Но это, очевидно, не работает, поскольку я получаю следующий вывод:
shai@ubuntu:~/csm/csm2/src$ make all
make: *** No rule to make target `../bin/computations/%.so', needed by 'all'. Stop.
Спасибо
Комментарии:
1. Я не использую Make, поэтому это не ответ на ваш вопрос. Однако я бы предположил, что обучение использованию кроссплатформенного конструктора, такого как CMake или Bjam, стоит вложений. Обычно они синтаксически проще, их легче настраивать и обслуживать, и они работают как в Linux, так и в Windows.
Ответ №1:
Вам нужно явно указать в all:
цели предварительные условия.
На языке Makefile % — это подстановочный знак, который можно использовать в автоматических правилах. Однако all:
цель — это простая цель без такого подстановочного знака, поэтому ${BIN}${COMPS}%.so
в этом контексте она неверна.
Пожалуйста, обратите внимание, что когда я говорю «подстановочный знак» в этом контексте, этот подстановочный знак сопоставляет цель с предварительными условиями, а не с файловой системой, как *
это делается в выражениях glob.
Кроме того, хотя ваш hart находится в нужном месте, с точки зрения стиля ваш Makefile может быть лучше:
- Промежуточные объекты не должны быть предварительными условиями
all
цели, а только конечными целями, которые вы хотите отправить. - Существует набор автоматических и простых правил, определяющих создание объектов.
- Обычно для
%.so
не пишется автоматическое правило, потому что библиотека часто создается из более чем одного объекта. - Зависимости между объектом и файлами заголовков — сложная проблема. Короче говоря, вам нужно указать, что результирующий объект зависит от
*.cpp
(или.c
), а также от всех заголовков, включенных (прямо или косвенно) в*.cpp
файл. - По соглашению, которое хорошо поддерживается GNU make, вместо использования,
${COMPILE}
как вы делаете, следует использовать$(CXX)
для вашего компилятора C и$(CXXFLAGS)
для стандартных флагов, которые вы хотите передать этому компилятору.
Ответ №2:
Вам нужно что-то вроде
SOBJECTS = ... все: ${BIN}main ${SOBJECTS} ...
Вам нужен способ собрать все имена * .so в переменной SOBJECTS
. Вы можете сделать это вручную или использовать некоторые внутренние функции make
для сканирования исходного каталога.
Также обратите внимание, что я удалил два *.o
файла как зависимости от all
целевого объекта. Они не являются конечными целями сборки (я полагаю), поэтому вам не нужно упоминать их там.
Помимо этого есть другие стилистические моменты, которые я бы сделал по-другому, но на данный момент они не вызывают немедленных проблем, поэтому я не буду отвлекаться, но я советую вам взглянуть на некоторые руководства, чтобы увидеть, как все делается в целом.
Для начала ознакомьтесь с Правилами Пола для Makefiles и как не использовать VPATH.