Pergunta

Eu tenho um makefile que constrói e depois chama outro makefile.Como esse makefile chama mais makefiles que fazem o trabalho, ele realmente não muda.Assim fica pensando que o projeto está construído e atualizado.

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

Como faço para forçar 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

Observação:Nomes removidos para proteger os inocentes

Editar:Versão fixa final:

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
Foi útil?

Solução

Você pode declarar um ou mais de seus alvos para serem falso.

Um alvo falso é aquele que não é realmente o nome de um arquivo; Em vez disso, é apenas um nome para uma receita a ser executada quando você fizer uma solicitação explícita. Há duas razões para usar um alvo falso: evitar um conflito com um arquivo com o mesmo nome e melhorar o desempenho.

...

Um alvo falso não deve ser um pré -requisito de um arquivo de destino real; Se for, sua receita será executada toda vez que a fabricação será atualizada para atualizar esse arquivo. Enquanto um alvo falso nunca for um pré -requisito de um alvo real, a receita falsa de alvo será executada somente quando o alvo falso for uma meta especificada

Outras dicas

o -B mudar para fazer, cuja forma longa é --always-make, diz make Para desconsiderar os registros de data e hora e fazer as metas especificadas. Isso pode derrotar o objetivo de usar, mas pode ser o que você precisa.

Um truque que costumava ser documentado em um manual do sol para make é usar um alvo (inexistente) '.force'. Você pode fazer isso criando um arquivo, force.mk, que contém:

.FORCE:
$(FORCE_DEPS): .FORCE

Então, assumindo que seu makefile existente é chamado makefile, você pode correr:

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

Desde .FORCE Não existe, qualquer coisa que depende disso estará desatualizada e reconstruída.

Tudo isso funcionará com qualquer versão de make; No Linux, você tem o GNU e, portanto, pode usar o alvo .Phony conforme discutido.

Também vale a pena considerar o porquê make Considera a liberação para estar atualizada. Isso pode ser porque você tem um touch 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. Então há a razão real ...

Alguém sugeriu .PHONY, o que é definitivamente correto..PHONY deve ser usado para qualquer regra para a qual uma comparação de data entre a entrada e a saída seja inválida.Como você não tem nenhum alvo no formato output: input você deve usar .PHONY para TODOS eles!

Dito isso, você provavelmente deve definir algumas variáveis ​​no topo do seu makefile para os vários nomes de arquivos e definir regras reais de make que tenham seções de entrada e saída para que você possa usar os benefícios do make, ou seja, que você só compilará de fato coisas que são necessárias para copmile!

Editar:exemplo adicionado.Não testado, mas é assim que você faz .PHONY

.PHONY: clean    
clean:
    $(clean)

Se bem me lembro corretamente, 'Make' usa timestamps (tempo de modificação de arquivo) para determinar se um destino está ou não atualizado. Uma maneira comum de forçar uma reconstrução é atualizar esse registro de data e hora, usando o comando 'Touch'. Você pode tentar invocar o 'toque' no seu Makefile para atualizar o registro de data e hora de um dos alvos (talvez um desses subfiles), que pode forçar fazer para executar esse comando.

Essa técnica simples permitirá que o Makefile funcione normalmente quando a força não é desejada. Crie um novo alvo chamado força No final do seu makefile. o força O Target tocará um arquivo do qual seu destino padrão depende. No exemplo abaixo, eu adicionei Toque em myProgram.cpp. Eu também adicionei uma chamada recursiva para faço. Isso fará com que o alvo padrão seja feito toda vez que você digitar fazer força.

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

force:
       touch yourProgram.cpp
       make

Eu tentei isso e funcionou para mim

Adicione essas linhas para makefile

clean:
    rm *.o output

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

salvar e agora ligue

make new 

E vai recompilar tudo de novo

O que aconteceu?

1) 'Novas' chamadas limpas. 'limpo' do 'rm', que remove todos os arquivos de objeto que têm a extensão de '.o'.

2) 'Novas chamadas' fazem '. 'Faça' ver que não há arquivos '.o', por isso cria todos os '.o' novamente. Em seguida, o vinculador vincula todo o arquivo .o em uma saída executável

Boa sorte

Conforme Miller's Recursive tornar considerado prejudicial você deve evitar ligar $(MAKE)! No caso de você mostrar, é inofensivo, porque isso não é realmente um script de makefile, apenas um script de wrapper, que poderia muito bem ter sido escrito em Shell. Mas você diz que continua assim em níveis mais profundos de recursão, então provavelmente encontrou os problemas mostrados naquele ensaio revelador.

É claro que com a GNU torna pesado evitar. E mesmo que estejam 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 de diretório, mas todos são atraídos para uma visão completa do seu projeto.

Mas os makefiles legados são escritos recursivamente. Então há uma solução alternativa onde $(MAKE) Não faz nada além de canalizar as sub -calças de volta ao processo Makepp principal. Somente se você fizer coisas redundantes ou, pior, --traditional-recursive-make (o que obviamente quebra essa vantagem do Makepp). Não conheço seus outros makefiles, mas se eles estiverem escritos de maneira limpa, com o Makepp necessários as reconstruções necessárias devem acontecer automaticamente, sem a necessidade de nenhum hacks sugerido aqui por outras pessoas.

Se você não precisa preservar nenhuma das saídas que você já compilou com sucesso

nmake /A 

reconstruir tudo

Na verdade, depende do que é 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 alvo falso, mas você apenas deseja reconstruí -lo por algum motivo (um exemplo é quando você usa a macro __time__ pré -processamento), você deve usar o esquema de força descrito nas respostas aqui.

Já foi mencionado, mas pensei que poderia adicionar ao uso touch

Se você touch Todos os arquivos de origem a serem compilados, o touch o comando altera os registros de data e hora de um arquivo para o tempo do sistema touch O comando foi executado.

O arquivo de origem timstamp é o que make usos para "saber" um arquivo mudou e precisa ser recompensado

Por exemplo: se o projeto foi um projeto C ++, então faça touch *.cpp, então corra make Novamente, e make deve recompilar todo o projeto.

make clean Exclui todos os arquivos de objeto já compilados.

No meu sistema Linux (CentOS 6.2), há uma diferença significativa entre declarar o alvo .Phony e criar uma dependência falsa da força, quando a regra realmente cria um arquivo que corresponde ao destino. Quando o arquivo deve ser regenerado sempre, exigia a força de dependência falsa do arquivo e .Phony para a dependência falsa.

errado:

date > $@

certo:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top