2010-07-02 2 views
2

У меня есть небольшой проект, который создает несколько целей из тех же исходных файлов. Цели требуют создания исходных файлов с различными флагами компиляции. Это на самом деле на cygwin, поэтому я буду использовать это как конкретный пример, хотя, я полагаю, это общая проблема.Как обеспечить, чтобы объектные файлы скомпилированы с правильными настройками в Makefile с несколькими целями MAKE.

Таким образом, это будет пример Makefile:

a: CFLAGS = 

a: a.o c.o 

b: CFLAGS = -mno-cygwin 

b: b.o c.o 

Это работает в принципе построение будет компилировать с CFLAGS неустановленным, а здание б откомпилироваться CFLAGS набора для -mno-Cygwin. Но только если c.o еще не существует.

Так делают

> make a b 

в девственном каталоге первый будет компилировать a.c и к.ц с помощью пустого CFLAGS. Затем он попытается построить b, используя CFLAGS = -mno-cygwin. Но так как c.o уже существует, он не будет перекомпилировать c.c, что приведет к ошибкам компоновщика, поскольку объектные файлы должны иметь одинаковые настройки этого флага.

Опять же, cygwin-флаг - всего лишь один конкретный пример, и я ищу универсальное решение.

То, что я пытался это ввести дополнительную цель проверки текущего CFLAGS и удалить все объектные файлы, если он не соответствует:

ARCH = `echo $(CFLAGS)` 
checkTarget: 
[email protected] test "`cat .arch`" != "$(ARCH)"; then \ 
    rm *.o; \ 
    /bin/echo -n $(ARCH) > .arch; \ 
fi 

Установки этой цели в качестве зависимости для двух целей гарантирует, что весь объект при необходимости файлы перекомпилируются.

a: CFLAGS = 

a: checkTarget a.o c.o 

b: CFLAGS = -mno-cygwin 

b: checkTarget b.o c.o 

Это, однако перекомпилирует каждый файл объекта, который является ненужным, и становится проблемой в более крупном проекте.

Есть ли лучший способ сделать это?

EDIT: В комментарии к единому ответу добавлен подсказку о том, что вы можете сделать объектные файлы зависимыми от содержимого CFLAGS. Я не могу понять, как это сделать, за исключением того, что они копят их во временный файл и сравниваются с предыдущими, а затем копируют это через зависящий файл. Нет ли лучшего способа?

ответ

0

Хотя там, где некоторые предложения о том, как сделать то, что я изначально просил here (как указал по slowdog), я принял решение принять другую схему имен Beta на один шаг дальше и поместить все объекты для различных вариантов в подкаталоги, следуя описанию второго предложения предложения Beta в его ответе на вопрос this question.

В сущности, что сделал мой Makefile выглядеть следующим образом:

A : AOBJDIR = .a 
AOBJECTS = $(addprefix $(AOBJDIR)/,$(ASRCS:.c=.o)) 

$(AOBJECTS): $(AOBJDIR)/%o: %.c 
    $(CC) $(CFLAGS) -MMD -o [email protected] -c $< 

$(AOBJDIR) : 
    @mkdir $(AOBJDIR) 

-include $(AOBJECTS:.o=.d) 

a: $(AOBJDIR) $(AOBJECTS) 
    $(LINK) ... 

Таким образом, первые названия деталей подкаталог, которые будут использоваться для объектных файлов «а» и создает список объектных файлов в этом каталоге с помощью преобразования исходные имена файлов и добавление префикса подкаталога.

Далее следует правило по умолчанию для этих объектных файлов (с генерацией зависимостей, введенной для хорошей оценки).

Следующие два являются гарантией того, что этот подкаталог существует и что информация о зависимостях включена.

Наконец, правило ссылки с дополнительной зависимостью от самого подкаталога, чтобы убедиться, что оно создано, если оно не существует.

Этот блок может быть повторен для b, в моем примере, путем замены всех. Поэтому, если бы я только мог понять, как упаковать этот блок во что-то более общее, которое можно параметризовать, я был бы счастлив.

2

Нам нужны две (или более) версии c.o, скомпилированные с разными флагами и связанные с различными исполняемыми файлами. Вы можете сделать это с помощью выдуманных имен файлов, как c_for_a.o, но это аккуратнее, чтобы держать их в разных каталогах, for_a/ и for_b/:

a for_a/%: CFLAGS = 

a: a.o for_a/c.o 

b for_b/%: CFLAGS = -mno-cygwin 

b: b.o for_b/c.o 

(Если это не ясно, что я могу заполнить в остальной части Makefile.)

EDIT:
Если вы не хотите, чтобы держать несколько c.o «ы, вам придется перекомпилировать сотрудничества иногда. Существует небольшое улучшение в идее checkTarget.

Когда вы строите цель как b и c.o уже существует, то имеет ли что c.o был построен с CFLAGS подходит к b, и вы используете checkTarget, чтобы записать эту информацию. Но вам все равно, что использовали CFLAGS, только b's CFLAGS. Таким образом, вы не должны записывать ничего в файле checkTarget, просто обновите его, когда вы строите новую цель:

a: CFLAGS = 

b: CFLAGS = -mno-cygwin 

# You may be able to combine the a and b rules... 
a: a.o c.o checkTarget 
    # build c.o 
    touch checkTarget 
    # build the target 

b: b.o c.o checkTarget 
    # build c.o 
    touch checkTarget 
    # build the target 

# Need this to create checkTarget the first time 
checkTarget: 
    @touch [email protected] 
+0

Хороший ответ. Если проект большой, скажем, 50 объектных файлов, это будет работать, если количество файлов для перекомпиляции (c.c в примере) невелико. Если бы большинство потребовало перекомпиляции, эта стратегия стала бы неуклюжей, я думаю. Любые идеи для этого сценария? – thoni56

+0

@ Томас Нильссон: это зависит от того, что вы пытаетесь оптимизировать. Если вы не хотите перекомпилировать 'c.c' больше, чем нужно, тогда вы должны хранить разные версии, и это лучший способ. Если вы не хотите хранить несколько 'c.o', но вы хотите перекомпилировать' c.o' только тогда, когда это необходимо, есть другой способ, небольшое улучшение вашего checkTarget. Я отредактирую свой ответ, чтобы включить его. – Beta

+0

Хммм, если я правильно понимаю, checkTarget - это метка времени, чтобы, например, если вы создадите b, но b.o и c.o существует, checkTarget все равно вызовет правило сборки. Затем в командах вы устанавливаете сборку c.o в соответствии с CFLAGS. Если это ваше намерение, я не полностью удовлетворен (но опять же это может быть невозможно ;-), потому что мне постоянно нужно будет обновлять явные команды сборки по мере изменения моих требований. Я надеялся каким-то образом сделать каждый% .o зависимым от CFLAGS, используемого для его компиляции, и скомпилировать компиляцию, только если CFLAGS не совпадают. – thoni56

Смежные вопросы