Como é que a compilação continua?

11

Eu sei que posso interromper um processo make a qualquer momento sem ter que recompilar novamente a árvore fonte inteira. Como eu sei, make apenas compila um destino se ele ainda não estiver compilado ou o código-fonte é modificado após a última compilação.
Mas se eu interromper make , certamente haverá um ou mais (dependendo do nível de simultaneidade) binários semiprontos. O que isso faz com eles na próxima vez que eu executar make ? Ou termina o alvo atual quando pressiono Ctrl + C para evitar binários parcialmente compilados?

    
por psimon 18.06.2014 / 22:41

3 respostas

12

Em termos simples, você pode pensar em make como tendo um número (possivelmente grande) de etapas, em que cada etapa usa vários arquivos como entrada e cria um arquivo como saída.

Uma etapa pode ser "compilar file.c a file.o " ou "usar ld para vincular main.o e file.o a program ". Se você interromper make com Ctrl C , então a etapa atualmente em execução será terminada, o que irá (ou deverá) remover o arquivo de saída em que estava trabalhando. Geralmente, não há nenhum "binóculo incompleto" deixado para trás.

Quando você reinicia o make , ele irá ver os registros de data e hora de todos os arquivos de entrada e saída e executará novamente as etapas em que:

  • um arquivo de entrada possui um registro de data e hora mais recente que o arquivo de saída
  • o arquivo de saída não existe

Isso geralmente significa que se uma etapa levar muito tempo para ser executada (é raro em computadores modernos, mas a ld para programas grandes pode levar muitos minutos quando make foi criada), parando e reiniciando make iniciará esse passo desde o começo.

A realidade do seu Makefile médio é consideravelmente mais complicada do que a descrição acima, mas os fundamentos são os mesmos.

    
por 18.06.2014 / 23:19
8

Ctrl + C faz com que SIGINT seja enviado para o processo em execução. Este sinal pode ser capturado pelo processo. No código fonte, você pode encontrar uma armadilha para este sinal em commands.c :

  /* If we got a signal that means the user
     wanted to kill make, remove pending targets.  */

  if (sig == SIGTERM || sig == SIGINT

  ... remove childrens ...

  /* Delete any non-precious intermediate files that were made.  */

  remove_intermediates (1);

remove_intermediates() é a função de limpeza de make , veja sua definição aqui:

/* Remove all nonprecious intermediate files.
   If SIG is nonzero, this was caused by a fatal signal,
   meaning that a different message will be printed, and
   the message will go to stderr rather than stdout.  */

Mais tarde, na função que você vê, eles serão efetivamente excluídos:

status = unlink (f->name);

Conclusão: Geralmente não tenha medo de interromper uma compilação com make . Se não for um sinal não rastreável ( SIGKILL, SIGSEGV, SIGSTOP ), ele fará uma limpeza de arquivos intermediários.

    
por 18.06.2014 / 23:23
1

Quando algo para make (seja ctrl-C, shutdown ou até mesmo um comando que falha), o trabalho já feito permanece. Quando reapresentado, make faz como sempre: descobre o que ainda precisa ser feito (porque um arquivo foi alterado ou make nunca conseguiu processá-lo não importa) e continua com o trabalho.

A descrição acima claramente presume que os Makefile s relevantes descrevem as dependências e os comandos para executar corretamente, então tudo o que precisa ser (re) feito é.

    
por 19.06.2014 / 09:34