Конечные комментарии после подстановки переменных - PullRequest
0 голосов
/ 31 марта 2012

В GNU make завершающие комментарии, добавленные к присваиванию переменных, не позволяют корректно работать последующему сравнению (через ifeq).

Вот Makefile ...

  A = a
  B = b ## trailing comment
  C = c

  RESULT :=

ifeq "$(A)" "a"
  RESULT += a
endif

ifeq "$(B)" "b"
  RESULT += b
endif

ifeq "$(C)" "c"
  RESULT += c
endif

rule:
    @echo RESULT=\"$(RESULT)\"
    @echo A=\"$(A)\"
    @echo B=\"$(B)\"
    @echo C=\"$(C)\"

Вот вывод...

$ make
RESULT=" a c"
A="a"
B="b "
C="c"

Как видно из отображаемого значения RESULT, на ifeq оказало влияние наличие комментария в назначении B.Повторяющаяся переменная B показывает, что проблема не в комментарии, а в пробелах .

Очевидным решением является явное удаление пробела досравнение вот так ...

ifeq "$(strip $(B))" "b"
  RESULT += b
endif

Однако это кажется подверженным ошибкам.Поскольку операция strip не требуется, если / пока не используется комментарий, вы можете опустить strip, и все изначально будет работать просто отлично - так что, скорее всего, вы не всегда будете помнить о добавлении strip.Позже, если кто-то добавит комментарий при установке переменной, Makefile больше не будет работать, как ожидалось.

Примечание: есть тесно связанная проблема, как продемонстрировано в этот вопрос , этот завершающий пробелможет прервать сравнение строк, даже если нет комментариев.

Вопрос: Есть ли более надежный способ справиться с этой проблемой?

Ответы [ 3 ]

5 голосов
/ 31 марта 2012

Это не что-то особенное для GNU Make; скорее, make - это , определенный POSIX для работы таким образом :

string1 = [string2]

Макрос с именем string1 определяется как имеющий значение string2 , где string2 определяется как все символы, если они есть, после <equals-sign> , вплоть до символа комментария (#) или без экранирования <newline>. Любые символы <blank> непосредственно перед или после <equals-sign> должны игнорироваться.

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

FOO = stuff  # this macro has two trailing spaces
BAR = something else# and this one has none

хотя, вероятно, обычно было бы яснее реорганизовать места, которые вы используете $(FOO), чем зависеть от того, что у него есть неясные пробелы.

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

A = a # list of apples
B = b # list of bananas
C = c # list of carrots

напишите это:

# list of apples
A = a
# list of bananas
B = b
# list of carrots
C = c

Это, как правило, стиль в проектах GNU (см., Например, внизу этой страницы ), хотя я не помню, документировано ли это где-либо.

Кстати, при изучении пробелов вы, вероятно, хотите заключить в кавычки свои переменные в вашей команде echo more:

rule:
   @echo 'RESULT="$(RESULT)"'

В вашей версии echo RESULT=\"$(RESULT)\", $(RESULT) не заключено в кавычки из оболочки, поэтому вкладки и несколько пробелов вводятся в заблуждение как отдельные пробелы.

0 голосов
/ 11 августа 2017

Гадкий, но, возможно, более надежный. Любой, кто редактирует это в будущем, может, по крайней мере, заметить, что вы, возможно, сделали это уродливо нарочно.

A = $(strip a )##
B = $(strip b )## trailing comment
C = $(strip c )##
0 голосов
/ 01 апреля 2012

Вот несколько необработанных идей, которые у меня есть:

  • Сделать политику всегда использовать strip с ifeq
    • Не использовать strip будет редким исключением и потребует объяснения в комментариях.
  • Не устанавливайте вручную переменные конфигурации внутри Makefile
    • Найдите или создайте несколько другихинструмент для этого.
    • возможно, оболочки POSIX будет достаточно (хотя я думаю, что нюансы переменных оболочки могут быть хуже, чем у make).
    • Я подозреваю, что сборка GNUsystem (Autoconf / Automake / etc.) решает эту проблему, но я чувствую, что для большинства целей это излишне.
  • Используйте какой-нибудь инструмент "lint", чтобы найти этивиды проблем
    • Я не знаю о существовании какого-либо такого инструмента.
  • Измените GNU make, чтобы исправить эту проблему.
    • Желательно минимизировать влияние на существующие файлы Makefile.
    • Измените язык make так, чтобы по умолчанию пробелы в конце были удалены
  • Используйте более современныйинструмент сборки вместо GNU make
...