Eu tenho um makefile que cria e depois chama outro makefile. Como esse makefile chama mais makefiles que fazem o trabalho, ele realmente não muda. Assim, continua pensando que o projeto foi construído e atualizado.
dnetdev11 ~ # make
make: `release' is up to date.
Como forço o makefile a reconstruir o destino?
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
Nota: Nomes removidos para proteger os inocentes
Editar: Versão final fixa:
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
.PHONY
não era o seu único problema, e você não está realmente deveria editar a solução para a questão, ou pelo menos não mais.)Respostas:
Você pode declarar que um ou mais de seus alvos são falsos .
fonte
:
, não apenas ao resultado final que você deseja criar (por exemplo, seu arquivo binário). Na pergunta,release
,debug
,clean
, einstall
são os alvos marca, nãoxxx_util
ouxxxcore.so
ou qualquer outra coisa.A
-B
opção de fazer, cuja forma longa é--always-make
, indicamake
para desconsiderar os carimbos de data e hora e fazer os destinos especificados. Isso pode anular o objetivo de usar o make, mas pode ser o que você precisa.fonte
Um truque que costumava ser documentado em um manual da Sun
make
é usar um destino (inexistente) '.FORCE'. Você pode fazer isso criando um arquivo, force.mk, que contém:Supondo que seu makefile existente seja chamado
makefile
, você pode executar:Como
.FORCE
não existe, tudo o que depende será desatualizado e reconstruído.Tudo isso funcionará com qualquer versão do
make
; no Linux, você possui o GNU Make e, portanto, pode usar o destino .PHONY conforme discutido.Também vale a pena considerar por que o
make
release está atualizado. Isso pode ocorrer porque você possui umtouch release
comando entre os comandos executados; pode ser porque existe um arquivo ou diretório chamado 'release' que existe e não tem dependências e, portanto, está atualizado. Depois, há a verdadeira razão ...fonte
Alguém sugeriu .PHONY, o que é definitivamente correto. .PHONY deve ser usado para qualquer regra para a qual uma comparação de datas entre a entrada e a saída é inválida. Como você não possui nenhum alvo no formulário
output: input
, use .PHONY para TODOS eles!Tudo isso dito, você provavelmente deve definir algumas variáveis na parte superior do seu makefile para os vários nomes de arquivos e definir regras reais de make que possuem seções de entrada e saída para que você possa usar os benefícios do make, ou seja, que você só irá compilar coisas que são necessárias para copmile!
Editar: exemplo adicionado. Não testado, mas é assim que você faz .PHONY
fonte
.PHONY
alvo não importa. Pode estar em qualquer lugar doMakefile
.Se bem me lembro, 'make' usa carimbos de data e hora (hora da modificação do arquivo) para determinar se um destino está ou não atualizado. Uma maneira comum de forçar uma recriação é atualizar esse carimbo de data / hora, usando o comando 'touch'. Você pode tentar chamar 'touch' no seu makefile para atualizar o registro de data e hora de um dos destinos (talvez um desses sub-makefiles), o que pode forçar o Make a executar esse comando.
fonte
Essa técnica simples permitirá que o makefile funcione normalmente quando forçar não é desejado. Crie um novo alvo chamado force no final do seu makefile . O alvo de força tocará em um arquivo do qual seu alvo padrão depende. No exemplo abaixo, adicionei touch myprogram.cpp . Também adicionei uma ligação recursiva a fazer . Isso fará com que o alvo padrão seja criado toda vez que você digita make force .
fonte
make
dentro de um Makefile. Use em$(MAKE)
vez disso.Eu tentei isso e funcionou para mim
adicione estas linhas ao Makefile
salve e ligue agora
e recompilará tudo novamente
O que aconteceu?
1) 'novas' chamadas limpas. 'clean' do 'rm', que remove todos os arquivos de objeto com a extensão '.o'.
2) 'novas' chamadas 'fazem'. 'make' veja que não há arquivos '.o', então ele cria todo o '.o' novamente. o vinculador vincula todo o arquivo .o em uma saída executável
Boa sorte
fonte
new
melhor uso do$(MAKE)
quemake
De acordo com a Recursiva de Miller Tornar Considerável Prejudicial, você deve evitar ligar
$(MAKE)
! No caso de você mostrar, é inofensivo, porque esse não é realmente um makefile, apenas um script de wrapper, que poderia muito bem ter sido escrito no Shell. Mas você diz que continua assim em níveis de recursão mais profundos, e provavelmente encontrou os problemas mostrados nesse ensaio revelador.Obviamente, com o GNU, é difícil evitar isso. E mesmo estando cientes desse problema, é a maneira documentada de fazer as coisas.
OTOH, makepp foi criado como uma solução para esse problema. Você pode escrever seus makefiles em um nível por diretório, mas todos eles são atraídos para uma visualização completa do seu projeto.
Mas makefiles legados são escritos recursivamente. Portanto, há uma solução alternativa em
$(MAKE)
que nada faz além de canalizar as sub-solicitações de volta ao processo principal do makepp. Somente se você fizer coisas redundantes ou, pior, contraditórias entre seus submakes, deverá solicitar--traditional-recursive-make
(o que obviamente quebra essa vantagem do makepp). Eu não conheço seus outros makefiles, mas se eles estiverem escritos de maneira limpa, com o makepp, as reconstruções necessárias deverão ocorrer automaticamente, sem a necessidade de hacks sugeridos aqui por outras pessoas.fonte
:
), ela sempre será reconstruída quando necessário.Se você não precisar preservar nenhuma das saídas que você já compilou com sucesso
reconstrói tudo
fonte
Na verdade, depende de qual é o alvo. Se for um alvo falso (ou seja, o alvo NÃO está relacionado a um arquivo), você deve declará-lo como .PHONY.
Se, no entanto, o destino não for um destino falso, mas você apenas deseja reconstruí-lo por algum motivo (um exemplo é quando você usa a macro de pré-processamento __TIME__), você deve usar o esquema FORCE descrito nas respostas aqui.
fonte
http://www.gnu.org/software/make/manual/html_node/Force-Targets.html#Force-Targets
fonte
Já foi mencionado, mas achei que poderia adicionar ao uso
touch
Se
touch
todos os arquivos de origem a serem compilados, otouch
comando alterará os carimbos de data e hora de um arquivo para a hora em que otouch
comando foi executado.O registro de data e hora do arquivo de origem é o que é
make
usado para "saber" que um arquivo foi alterado e precisa ser recompiladoPor exemplo: Se o projeto era um projeto c ++, execute
touch *.cpp
, executemake
novamente e make deve recompilar o projeto inteiro.fonte
Como Abernier apontou, há uma solução recomendada no manual de criação do GNU, que usa um alvo 'falso' para forçar a reconstrução de um destino:
Isso funcionará limpo, independentemente de outras dependências.
Eu adicionei o ponto e vírgula à solução do manual, caso contrário, uma linha vazia é necessária.
fonte
No meu sistema Linux (Centos 6.2), há uma diferença significativa entre declarar o destino .PHONY e criar uma dependência falsa do FORCE, quando a regra realmente cria um arquivo correspondente ao destino. Quando o arquivo deve ser regenerado todas as vezes, é necessária a dependência falsa FORCE no arquivo e .PHONY para a dependência falsa.
errado:
certo:
fonte
make clean
exclui todos os arquivos de objetos já compilados.fonte