Как динамически переименовать объектный файл в makefile

#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 на их реальные эквиваленты, поскольку я тогда забыл…

Я понимаю, что это может быть не очень полезно, но, по крайней мере, это идея, которую стоит рассмотреть.