Написание makefile для создания динамических библиотек

#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.