Как заставить make-файл пересобрать цель

StackOverflow https://stackoverflow.com/questions/816370

  •  03-07-2019
  •  | 
  •  

Вопрос

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

dnetdev11 ~ # make
make: `release' is up to date.

Как заставить make-файл пересобрать цель?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

Примечание:Имена удалены, чтобы защитить невиновных

Редактировать:Финальная фиксированная версия:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib
Это было полезно?

Решение

Вы можете объявить одну или несколько ваших целей фальшивый.

Ложная цель — это цель, которая на самом деле не является именем файла;Скорее, это просто имя для рецепта, который должен быть выполнен, когда вы делаете явный запрос.Есть две причины использовать фальшивую цель:Чтобы избежать конфликта с одним и тем же именем и повысить производительность.

...

Ложная цель не должна быть обязательным условием для настоящего целевого файла;Если это так, его рецепт будет запущен каждый раз, когда будет обновлять этот файл.Пока фальшивая цель никогда не является предпосылкой реальной цели, рецепт фальшивой цели будет выполняться только тогда, когда фальшивая цель является указанной целью

Другие советы

Переключатель -B для создания, длинная форма которого - always-make , указывает make игнорировать временные метки и делать указанные цели. Это может победить цель использования make, но это может быть то, что вам нужно.

Одна хитрость, которая раньше документировалась в руководстве Sun для make , - это использование (несуществующей) цели «.FORCE». Вы можете сделать это, создав файл force.mk, который содержит:

.FORCE:
$(FORCE_DEPS): .FORCE

Затем, если ваш существующий make-файл называется makefile , вы можете запустить:

make FORCE_DEPS=release -f force.mk -f makefile release

Поскольку .FORCE не существует, все, что от него зависит, будет устаревшим и перестроено.

Все это будет работать с любой версией make ; в Linux у вас есть GNU Make, и поэтому вы можете использовать цель .PHONY, как обсуждалось.

Стоит также подумать, почему make считает выпуск актуальным. Это может быть потому, что у вас есть команда touch release среди выполненных команд; это может быть связано с тем, что существует файл или каталог с именем 'release', который существует и не имеет зависимостей и поэтому является актуальным. Тогда есть настоящая причина ...

Кто-то еще предложил .PHONY, что определенно правильно. .PHONY следует использовать для любого правила, для которого сравнение даты между входом и выходом недопустимо. Поскольку у вас нет целей в виде output: input , вы должны использовать .PHONY для ВСЕХ из них!

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

Изменить: добавлен пример. Не проверено, но это то, как вы делаете .PHONY

.PHONY: clean    
clean:
    $(clean)

Если я правильно помню, make использует временные метки (время изменения файла), чтобы определить, актуальна ли цель. Распространенным способом принудительного пересоздания является обновление этой временной метки с помощью команды «touch». Вы можете попробовать вызвать «touch» в вашем make-файле, чтобы обновить временную метку одной из целей (возможно, одного из этих подфайлов), что может заставить Make выполнить эту команду.

Этот простой метод позволит make-файлу нормально функционировать, когда форсирование нежелательно. Создайте новую цель с именем force в конце своего файла сборки . Цель force коснется файла, от которого зависит цель по умолчанию. В приведенном ниже примере я добавил touch myprogram.cpp . Я также добавил рекурсивный вызов в make . Это приведет к тому, что цель по умолчанию будет выполняться каждый раз, когда вы нажимаете make force .

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

Я попробовал это, и это сработало для меня

добавьте эти строки в Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

сохраните и теперь звоните

make new 

и он снова все перекомпилирует

Что случилось?

1) «новые» звонки чистые. 'clean' do 'rm', который удаляет все объектные файлы с расширением '.o'.

2) «новые» звонки «сделать». 'make' видит, что нет файлов '.o', поэтому он снова создает все '.o'. затем компоновщик связывает все файлы .o в одном исполняемом выводе

Удачи

Согласно рекурсивной программе «Считать вредной» Миллера, вам следует избегать вызова $ (MAKE) ! В случае, если вы показываете, это безвредно, потому что на самом деле это не make-файл, а просто скрипт-обертка, который с таким же успехом мог бы быть написан в Shell. Но вы говорите, что продолжаете в том же духе на более глубоких уровнях рекурсии, так что вы, вероятно, столкнулись с проблемами, показанными в этом открывающем эссе.

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

OTOH, makepp был создан как решение этой проблемы , Вы можете писать свои make-файлы на уровне каталогов, но все они объединяются в полный обзор вашего проекта.

Но устаревшие make-файлы пишутся рекурсивно. Так что есть обходной путь, когда $ (MAKE) ничего не делает, кроме как направляет подзапросы обратно в основной процесс makepp. Только если вы делаете избыточные или, что еще хуже, противоречивые вещи между вашими подмаками, вы должны запросить - Traditional-recursive-make (что, конечно, лишает это преимущество makepp). Я не знаю других ваших make-файлов, но если они написаны правильно, с makepp необходимые перестройки должны происходить автоматически, без необходимости каких-либо хаков, предложенных здесь другими.

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

nmake /A 

перестраивает все

Это на самом деле зависит от цели. Если это фальшивая цель (то есть цель НЕ связана с файлом), вы должны объявить ее как .PHONY.

Если, однако, цель не является фальшивой целью, но вы просто хотите по какой-то причине ее перестроить (например, когда вы используете макрос предварительной обработки __TIME__), вам следует использовать схему FORCE, описанную в ответах здесь.

Это уже упоминалось, но я подумал, что могу добавить в touch

Если вы коснитесь всех исходных файлов для компиляции, команда touch изменит временные метки файла на системное время touch . Команда была выполнена.

Исходный файл timstamp - это то, что make использует для " знать " файл изменился, и его необходимо заново скомпилировать

Например: если проект был проектом c ++, выполните touch * .cpp , затем снова запустите make , и make должна перекомпилировать весь проект.

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

В моей системе Linux (Centos 6.2) существует существенная разница между объявлением цели .PHONY и созданием фиктивной зависимости от FORCE, когда правило действительно создает файл, соответствующий цели. Когда файл должен быть восстановлен каждый раз, это требовало поддельная зависимость FORCE от файла и .PHONY для поддельной зависимости.

неправильно:

date > $@

справа:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top