Как создать цель, которая создает каталог, если он не существует? - PullRequest
2 голосов
/ 29 мая 2019

В моей конфигурации make-файла все объектные файлы компилируются в определенный каталог. Компилятор жалуется, если его не существует. Я хотел бы создать цель makefile, которая распознает любой объектный файл и создает этот каталог до запуска любой другой цели и фактически компилирует объектные файлы.

До сих пор я экспериментировал с правилами сопоставления с образцом и двумя двоеточиями.

obj: 
    mkdir obj

obj/%.o :: | obj

obj/example.o :: src/example.cc includes/example.hh
    $(build_obj_file) # macro to do the actual job

С этим кодом только последняя цель запускается для obj/example.o. Я ожидал, что обе цели объекта будут выполняться отдельно.

Когда я заменяю сопоставление с шаблоном на статический obj/example.o, я получаю желаемый результат. Также, когда я использую статическое сопоставление с образцом, как obj/example.o : obj/%.o :: obj.

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

Что бы вы предложили для решения такой задачи?

Ответы [ 2 ]

2 голосов
/ 29 мая 2019

Вы не можете использовать шаблонные правила для «добавления дополнительных предпосылок» к набору целей. Шаблонные правила должны предоставить рецепт; если они этого не делают, то считается, что они удаляют правило шаблона .

.

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

Если вы хотите использовать предварительные условия только для заказа, вам нужно либо добавить их в правило шаблона, которое будет соответствовать вашей цели:

obj/%.o : src/%.cc | obj
         $(build_obj_file)

или отдельно определите обязательное отношение:

obj/example.o: | obj
1 голос
/ 16 июня 2019

С помощью (GNU) делают и легко понять правила, более или менее адаптированные из набора правил, который готовит automake:

MKDIR_P = mkdir -p

obj/%.o: src/%.cc
    @$(MKDIR_P) $(@D)
    $(COMPILE.cc) -o $@ -c $<

obj/example.o : includes/example.hh

Это создаст каталог назначения $(@D) для каждого объектного файла $@, и если место назначения уже существует, mkdir -p все равно завершится с 0 и, таким образом, не прервет набор целевых правил.

С (GNU) make и немного более сложными для понимания, но более эффективными правилами (каталог obj только mkdir -p ed один раз):

MKDIR_P = mkdir -p

obj:
    @$(MKDIR_P) $@

obj/%.o: src/%.cc | obj
    $(COMPILE.cc) -o $@ -c $<

obj/example.o : includes/example.hh

Часть | obj гарантирует, что целевой объектный файл не будет перестроен только потому, что кто-то добавил или удалил файл в obj/ и, таким образом, изменил метку времени каталога obj.

Строка $(COMPILE.cc) была взята в основном из вывода GNU make -p.

Обратите внимание, что ручное ведение зависимостей заголовка довольно подвержено ошибкам, поэтому оно должно быть автоматически сгенерировано, предпочтительно MadScientist всесторонне спроектированным надежным методом .

Также, если ваш Makefile использует GNUmakeism, попробуйте переименовать его GNUmakefile.

С automake вы не можете скомпилировать объектные файлы, помещенные в определенный каталог, но тогда тег automake для этого вопроса, похоже, был ошибкой.

...