Makefile.Как исключить один конкретный файл из компиляции? - PullRequest
7 голосов
/ 04 марта 2011

Я пытаюсь исключить файл main.cpp из списка файлов для компиляции, определяемых по следующему правилу:

$(TMPDIRPATH)%.o: %.cpp
    @echo compile $<
ifneq ($(notdir $<), main.cpp)
        @$(COMPILE.cpp) $(OUTPUT_OPTION) $<
endif

Это условие 'ifneq' всегда оценивается как истинное, что странно.Что я делаю неправильно?Есть ли лучший способ исключить один файл из явного правила?

Ответы [ 4 ]

11 голосов
/ 02 декабря 2014

Почему бы вам не попробовать использовать текстовую функцию filter-out , если вы используете GNU Make.

Возвращает все разделенные пробелом слова в тексте, которые несоответствует любому из шаблонных слов, удаляя слова, которые соответствуют одному или нескольким.Это полная противоположность функции фильтра.

Например, с учетом:

objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o 

следующее генерирует список, который содержит всеобъектные файлы не в сети:

$(filter-out $(mains),$(objects))
5 голосов
/ 04 марта 2011

Строка ifneq оценивается только один раз, когда make запускается и анализирует make-файл. В этом контексте $< пусто.

Чтобы получить различное поведение для каждой из целей, соответствующих вашему шаблонному правилу, вы можете сделать что-то вроде

$(TMPDIRPATH)%.o: %.cpp
    @echo compile $<
    @$(if $(filter main.cpp,$<),$(COMPILE.cpp) $(OUTPUT_OPTION) $<)

Это может помочь вам представить разницу между ifneq и $(if) в make-файле как разницу между #if и if() в коде C.

Делая шаг назад, хотя: если вы не хотите, чтобы main.cpp компилировалось по этому правилу, то вы, вероятно, захотите предоставить явное правило с $(TMPDIRPATH)main.o в качестве цели, которое будет предпочтительнее шаблона править всегда. Или, если вы не хотите, чтобы $(TMPDIRPATH)main.o был сделан на всех , вы должны искать правила, которые имеют его на правом глазу :, и удалять его оттуда.

5 голосов
/ 04 марта 2011

Это не лучший способ сделать это, но если вы делаете это в соответствии с этим, запишите это как условие оболочки, не используя GNU make conditionals:

$(TMPDIRPATH)%.o: %.cpp
    @echo compile $<
    @if [ $(notdir $<) != main.cpp ]; \
    then $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \
    fi

Требуются маркеры продолжения (обратная косая черта). Как и точки с запятой. Значения с префиксом $ будут расширены на make до вызова оболочки для их интерпретации. Вы, вероятно, не хотите, чтобы эхо там, где оно есть. Вам, вероятно, нужно:

$(TMPDIRPATH)%.o: %.cpp
    @if [ $(notdir $<) != main.cpp ]; \
    then echo compile $<; \
         $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \
    fi

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


Комментарий гласит: «Но Руководство по сборке GNU говорит, что ifneq должно работать».

ifneq будет работать, если он будет правильно расположен, что означает «не отступать как часть команд, связанных с правилом». Таким образом, вы могли бы написать что-то вроде (ужасно плохой пример, но мой мозг на фритюре):

ifneq (${CFLAGS}, -Wall)
CFLAGS += -Wall
endif

file1.o: file1.c
    ${CC} ${CFLAGS} -c $<

Но когда ifneq имеет отступ, как в вопросе, это просто команда, которая на самом деле не найдена в системе, когда make запускает оболочку для обработки команды.

2 голосов
/ 04 марта 2011

Make не имеет хорошего способа обработки условных выражений в правиле.Вы могли бы поместить условное в команду, но в этом случае есть более чистый способ:

$(TMPDIRPATH)main.o:
    @echo compile $< (but not really)

$(TMPDIRPATH)%.o: %.cpp
    @echo compile $<
    @$(COMPILE.cpp) $(OUTPUT_OPTION) $<

РЕДАКТИРОВАТЬ:
Я не знал, что вы не иметь а main.cpp.Решение простое: удалите main.cpp в качестве предпосылки правила main.o (я удалил его выше).Теперь make-файлу это не нужно, и он не будет пытаться его собрать.

Но вы все еще используете правило, которое означает, что что-то все еще пытается собрать main.o, как явныйцель или предпосылка чего-то еще.Это признак путаницы, который это исправление в make-файле не исправит.Если вы расскажете нам больше о ситуации, возможно, мы сможем предложить лучшее решение.Что требует main.o?У вас есть main.o?Какую цель вы указываете при вызове Make?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...