Что касается первого вопроса, вы можете поставить фальшивую цель перед любыми другими, например:
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, но это поможет вам начать.
person
paxdiablo
schedule
20.01.2011