По первому вопросу вы можете поставить поддельную цель перед любым другим по следующим направлениям:
preamble:
-mkdir obj
main.o: preamble main.c
blah blah blah
Это автоматически выполнит все в преамбуле (вы должны сделать это первымзависимость в каждом правиле), прежде чем он строит что-либо еще.-
в начале mkdir
игнорирует сбои, если, например, каталог уже существует.
Для второго вопроса вы можете указать что-то вроде:
all: debug release
debug: blah blah blah
release: blah blah blah
и фактически поместить код отладки и выпуска в отдельные подкаталоги.Таким образом, вы можете собрать либо с помощью make release
или make debug
и построить их и с make all
.
Третий вопрос: ваш make-файл собирается каждый раз, потому что правила говорят ему,Например, Output: main.o Base64.o
всегда будет пытаться построить, поскольку Output
никогда не существует (правильная цель, по-видимому, Output.exe
).
Точно так же ваши правила объектного файла всегда будут выполняться, поскольку ни main.o
, ни Base64.o
обновляются в соответствии с их утверждениями (вместо этого они обновляют файлы в каталоге obj
).
Вы можете исправить это, установив цель $(OBJPATH)/main.o
, но, если честно, я необычно не беспокоятся о разделении объектов и исполняемых файлов на отдельные каталоги.Я просто собираю их все в один каталог и позволяю make -clean
очистить их.
Итак, make-файл, с которого я бы начал, был бы:
COMPILER=gcc
# Meta rules
all: release debug
release: Output.exe
debug: Output-d.exe
# Release stuff
Output.exe: main.o Base64.o
$(COMPILER) -o Output.exe main.o Base64.o
strip Output.exe
main.o: main.c main.h
$(COMPILER) -c main.c -o main.o
Base64.o: Base64.c Base64.h
$(COMPILER) -c Base64.c -o Base64.o
# Debug stuff
Output-d.exe: main-d.o Base64-d.o
$(COMPILER) -g -o Output-d.exe main-d.o Base64-d.o
main-d.o: main.c main.h
$(COMPILER) -g -DDEBUG -c main.c -o main-d.o
Base64-d.o: Base64.c Base64.h
$(COMPILER) -g -DDEBUG -c Base64.c -o Base64-d.o
В ответ на ваш вопрос-комментарий:
Можно ли в любом случае переустановить переменную на основе выбранной цели?например, если выбранная версия OBJPATH будет "./obj/Release", если выбрана отладка OBJPATH = "./obj/Debug"?
GNU Make может быть более мощным, чем те, которые я использовално вы можете сделать это, установив переменную окружения, а затем повторно запустите make согласно следующему:
all: release debug
release:
( export zzvar=release ; $(MAKE) zz_Output.exe )
debug:
( export zzvar=debug ; $(MAKE) zz_Output-d.exe )
zz_Output.exe:
echo $(zzvar)
touch zz_Output.exe
zz_Output-d.exe: zz_main-d.o zz_Base64-d.o
echo $(zzvar)
touch zz_Output-d.exe
, который выдает:
( export zzvar=release ; make zz_Output.exe )
make[1]: Entering directory '/home/pax'
echo release
release <==
touch zz_Output.exe
make[1]: Leaving directory '/home/pax'
( export zzvar=debug ; make zz_Output-d.exe )
make[1]: Entering directory '/home/pax'
echo debug
debug <==
touch zz_Output-d.exe
make[1]: Leaving directory '/home/pax'
Вы можете увидеть две отдельные переменные, помеченныес <==
выше.
Как я уже сказал, возможно, есть более простой способ сделать это с помощью GNU Make, но это поможет вам начать работу.