некоторые вопросы о сборочных файлах GNU - PullRequest
1 голос
/ 20 января 2011

Мне было интересно, есть ли у кого-нибудь ответы на некоторые вопросы о сборочных файлах GNU ...

  1. как создать каталог, если он не существует ("./obj") для вывода?
  2. У меня есть один make-файл, но у меня есть 2 метода сборки: «Debug» и «Release», могу ли я иметь оба в 1 make-файле и как узнать, какой из них собрать?
  3. я былиспользуя Code :: Blocks, который создает только измененные файлы, но мой make-файл создает их каждый раз, когда я вызываю команду make, не касаясь каких-либо файлов.как мне сделать так, чтобы он строил только измененные файлы?

вот мой текущий make-файл

OBJPATH=./obj
COMPILER=gcc

Output: main.o Base64.o
 $(COMPILER) -o Output.exe $(OBJPATH)/main.o $(OBJPATH)/Base64.o
 strip Output.exe

main.o: main.c main.h
 $(COMPILER) -c main.c -o $(OBJPATH)/main.o

Base64.o: Base64.c Base64.h
 $(COMPILER) -c Base64.c -o $(OBJPATH)/Base64.o

спасибо.

Ответы [ 3 ]

2 голосов
/ 20 января 2011

По первому вопросу вы можете поставить поддельную цель перед любым другим по следующим направлениям:

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, но это поможет вам начать работу.

1 голос
/ 20 января 2011

как создать каталог, если он не существует ("./obj") для вывода?

rm -Rf ./obj && mkdir ./obj

У меня есть один make-файл, но у меня есть 2 метода сборки «Debug» и «Release», могу ли я иметь оба в 1 make-файле и как сказать ему, какой из них собрать?

Вы можете иметь несколько целей сборки верхнего уровня. Output в вашем make-файле является целью высшего уровня. Сделай два. Один называется «Debug», а другой «Release». Затем вы можете сказать make Debug для сборки отладки и make Release для сборки выпуска.

Я использовал Code :: Blocks, который создает только измененные файлы, но мой make-файл создает их каждый раз, когда я вызываю команду make, не касаясь каких-либо файлов. как мне сделать так, чтобы он строил только измененные файлы?

Я не использовал Code::Blocks (я не знаю, что это такое), но если ваши Make-файлы написаны правильно (т.е. с правильно заданными зависимостями), он будет перестраивать только необходимые цели.

0 голосов
/ 13 февраля 2013

В ответ на ваш комментарий вопрос:

Можно ли в любом случае переустановить переменную на основе выбранной цели? например, если выбранный выпуск OBJPATH будет "./obj/Release", если выбранная отладка OBJPATH = "./obj/Debug"?

Вот как вы делаете это без рекурсии:

COMPILER=gcc

release: OBJPATH = obj
release: Output.exe

debug: OBJPATH = obj-dbg
debug: Outputd.exe

Output%.exe: main.o Base64.o
 $(COMPILER) -o $@ $(OBJPATH)/main.o $(OBJPATH)/Base64.o
 strip $@

main.o: main.c main.h
 $(COMPILER) -c main.c -o $(OBJPATH)/main.o

Base64.o: Base64.c Base64.h
 $(COMPILER) -c Base64.c -o $(OBJPATH)/Base64.o
...