#makefile #gnu-make #multiple-makefiles
#makefile #gnu-make #несколько makefiles
Вопрос:
Я очень, очень новичок в makefiles. Самой сложной задачей, которую я выполнял до этого, было включение новых .h и .cpp или .c в уже созданные makefile.
Мне нужно перенести процесс компиляции проекта из Visual Studio в gcc, и для этого уже есть готовое решение, написанное коллегой, но он использовал 4 bash-скрипта и makefile для компиляции решения.
Вместо этого я искал решения, упрощающие обслуживание. Признаю, мой вопрос может быть очень глупым, но я нигде не смог его найти и не смог все правильно понять.
В целевом объекте ниже:
$(OBJECTS): %.o: %.cpp
$(CC) $(CPPFLAGS) -c $< -o $@
Я хотел бы проверить, существует ли уже создаваемый файл .o, и переименовать его во что-то другое. Это необходимо, потому что в проекте есть несколько исходных файлов с одинаковым именем, но они отличаются по содержанию.
Например, если вызывается текущий .cpp, который компилируется file.cpp и объект, который будет сгенерирован, будет file.o, правило должно проверять, является ли file.o уже существует и переименуйте текущий файл.o во что-то другое.
Если вы знаете какой-нибудь хороший учебник, объясняющий это, пожалуйста, дайте мне знать. Я нашел множество примеров, которые показывают, как создавать тесты для текущего файла, компилируемого по этому правилу, но ни одного, который бы переименовывал объект .o.
Заранее спасибо и извините за любую «тупость», написанную здесь. 🙂
Комментарии:
1. Что я делал в прошлом, так это помещал объектные файлы в ту же иерархию каталогов, что и исходные файлы. Я предполагаю, что у вас есть файлы на разных уровнях с одинаковыми именами?
2. @Max, да. Существуют два разных каталога с исходными файлами, названными как file1.cpp file2.cpp и т.д.
Ответ №1:
Прежде всего, мы выражаем вам наше глубокое сочувствие.
Make на самом деле не предназначен для обработки такой двусмысленности, поэтому нам придется использовать kludge. Вы не сказали, в что вы хотите переименовать файл, поэтому сейчас давайте предположим, что мы переходим file.o
к file_save.o
.
# This tells Make that these are not real targets, so that it will
# proceed even if file.o already exists.
.PHONY: $(OBJECTS)
$(OBJECTS): %.o: %.cpp
# If file.o exists, move it to file_save.o
@if [ -f $@ ]; then mv $@ $*_save.o; fi
$(CC) $(CPPFLAGS) -c $< -o $@
Комментарии:
1. Привет, большое спасибо. Этот код, похоже, работает, однако файлы *_save.o не генерируются. Я думаю, это потому, что мой исходный cpp-файл определен в переменной,
SOURCE = file1.cpp file2.cpp file1.cpp
а затем я использовалOBJECTS = $(SOURCES:.cpp=.o)
для создания правила OBJECTS.2. Действительно? Это не должно иметь значения… Замените
if
строку на эту и посмотрите, что получится:mv $@ $*_save.o
. В первый раз он пожалуется, когда нетfile.o
возможности переместить, но в остальном он сделает то же самое и сообщит вам, что он делает.3. Спасибо за помощь! Когда я пытаюсь это сделать, make прерывает компиляцию сразу после первого .o не найден.
4. @xlogdan: Подтверждение! Извините, я должен был сказать
-mv $@ $*_save.o
. И попробуйтеfile.o
сначала только с одним, а не со всемOBJECTS
списком.5. @Beta, большое спасибо за помощь! Он по-прежнему не показывает никакого эффекта, make жалуется, что я включил две одинаковые цели в одно и то же правило, и он не будет выполнять вышеуказанную команду, потому что нет .o. В любом случае, я приношу извинения за весь этот беспорядок, но я заставил его работать, собирая исходные файлы с одинаковыми именами в пакетном файле, я просто указываю, что у каждого файла будет другое имя .o. Затем я вызываю makefile, который объединит все в статическую библиотеку. У меня больше нет на это времени, поэтому, к сожалению, мне придется оставить все как есть, по крайней мере, я сократил его с 5 bash-скриптов до 1 плюс make-файл.
Ответ №2:
Расширение моего комментария к вопросу:
Возможно, вам следует рассмотреть возможность размещения объектных файлов в той же иерархии каталогов, что и исходные файлы, чтобы предотвратить конфликты именования.
Чтобы src/network/client.cpp компилируется для сборки/obj/network/client.o.
Я очень устал, когда дело доходит до makefiles, но я полагаю, что решил это, сделав что-то вроде:
$SRC= src/network/client.cpp src/main.cpp .....
$OBJ= makefile_replace_function($SRC, .o)
$(OBJ) : $(SRC)
compile_instructions
Где вам придется заменить makefile_replace_function
и compile_instructions
на их реальные эквиваленты, поскольку я тогда забыл…
Я понимаю, что это может быть не очень полезно, но, по крайней мере, это идея, которую стоит рассмотреть.