Perché le build incrementali in "make" non usano algoritmi di hashing?


10

Sono un principiante makee mi chiedo quando utilizzare make clean.

Un collega mi ha detto che le build incrementali si makebasano sui timestamp dei file. Quindi, se fai il checkout di una vecchia versione di un file nel tuo VCS, avrà un "vecchio" timestamp e sarà contrassegnato come "non è necessario ricompilare questo file". Quindi, quel file non verrebbe incluso nella prossima build.
Secondo quello stesso collega, sarebbe un motivo da usare make clean.

Ad ogni modo, ho ottenuto approssimativamente la risposta alla domanda "quando usare make clean" da altre domande StackExchange ma la mia altra domanda è:

Perché le build incrementali che utilizzano si makebasano sui timestamp dei file e non su SHA-1 per esempio? Git, ad esempio, mostra che possiamo determinare con successo se un file è stato modificato usando SHA-1.
È per problemi di velocità?


5
makeè stato creato negli anni '70. SHA-1 è stato creato negli anni '90. Git è stato creato negli anni 00. L'ultima cosa che vuoi è che alcune build oscure che funzionavano da 30 anni fallissero improvvisamente perché qualcuno ha deciso di diventare tutto moderno con un sistema collaudato.
Ordous,

1
L'hashing dei file è sempre lento. Penso che git usi anche metadati del filesystem per ottimizzare i suoi controlli per i file modificati.
CodesInChaos,

4
La soluzione originale basata sulle date dei file è molto semplice, non necessita di file aggiuntivi per l'archiviazione dei codici hash e ha funzionato notevolmente per diversi decenni. Perché qualcuno dovrebbe sostituire una soluzione ben funzionante con una più complicata? Inoltre, la maggior parte del sistema VFA di AFAIK assegna i file di checkout la "data di checkout", quindi i file modificati causeranno correttamente una ricompilazione senza "rendere pulito".
Doc Brown,

@Ordous: divertente, ma è rilevante qui? Il software non si arrugginisce; dà perché qualcuno ha cambiato qualcosa nell'ambiente circostante. A meno che non abbiano funzionato, nel qual caso dovrebbe comunque funzionare.
Robert Harvey,

1
@RobertHarvey Certo che lo è! Certo, se non aggiorni il maketuo software, il tuo software non si romperà, ma makefa piuttosto uno sforzo per avere la retrocompatibilità nelle nuove versioni. Cambiare il comportamento di base senza una buona ragione è praticamente l'opposto di quello. E le date mostrano perché non è stato originariamente creato per utilizzare SHA-1 o perché non è stato facile modificarlo quando è diventato disponibile ( makeormai aveva decenni).
Ordous,

Risposte:


7

Un ovvio (e probabilmente superficiale) problema sarebbe che il sistema di compilazione dovrebbe tenere traccia degli hash dei file che sono stati usati per l'ultima build. Sebbene questo problema possa certamente essere risolto, richiederebbe l'archiviazione laterale quando le informazioni di marca temporale sono già presenti nel file system.

Più seriamente, tuttavia, l'hash non trasmetterebbe la stessa semantica. Se sai che il file T è stato creato dalla dipendenza D con l'hash H 1 e poi scopri che D ora ha un hash su H 2 , dovresti ricostruire T ? Probabilmente sì, ma potrebbe anche essere che H 2 si riferisca effettivamente a una versione precedente del file. I timestamp definiscono un ordine mentre gli hash sono paragonabili solo per l'uguaglianza.

Una caratteristica che supporta i timestamp è che puoi semplicemente aggiornare il timestamp (ad esempio, usando l'utilità della riga di comando POSIX touch) per indurre makea pensare che una dipendenza è cambiata o - cosa più interessante - un target è più recente di quanto non sia in realtà. Mentre giocare con questa è una grande opportunità per spararti nel piede, è utile di volta in volta. In un sistema basato su hash, è necessario il supporto del sistema di build stesso per aggiornare il suo database interno di hash utilizzati per l'ultima build senza effettivamente creare nulla.

Mentre una discussione potrebbe certamente essere fatta per usare gli hash nei timestamp, il mio punto è che non sono una soluzione migliore per raggiungere lo stesso obiettivo, ma una soluzione diversa per raggiungere un obiettivo diverso. Quale di questi obiettivi è più desiderabile potrebbe essere aperto al dibattito.


1
Sebbene la semantica differisca tra hash e timestamp, in questo caso è normalmente irrilevante in quanto è molto probabile che si desideri una build basata sui file correnti, indipendentemente dalla loro età.
axl

Gran parte di ciò che dici è corretto. Tuttavia, un sistema di build ben implementato che utilizza hash come Google blaze / bazel (la versione interna di blaze, quella open source è bazel) batte i pantaloni di un sistema con timestamp come Make. Detto questo, devi fare molto sforzo per costruire ripetibili in modo che sia sempre sicuro usare manufatti di vecchia costruzione piuttosto che ricostruire.
btilly

Il mapping qui non è molti a uno, è uno a uno. Se Dora hash per H2, e non si dispone di un output T2costruito D@H2, è necessario produrre e memorizzarlo. Successivamente, indipendentemente dall'ordine in cui si Dalternano gli stati H1e H2, sarà possibile utilizzare l'output memorizzato nella cache.
Asad Saeeduddin,

1

L'hash di un intero progetto è molto lento. Devi leggere ogni singolo byte di ogni singolo file. Git non esegue l'hashing di ogni file ogni volta che si esegue uno dei git statusdue. Né i checkout VCS normalmente impostano l'ora di modifica di un file sull'ora di creazione originale. Un ripristino di backup lo farebbe, se ti prendi cura di farlo. L'intero motivo per cui i filesystem hanno i timestamp è per casi d'uso come questi.

Uno sviluppatore di solito viene eseguito make cleanquando cambia una dipendenza non tracciata direttamente dal Makefile. Ironia della sorte, questo di solito include il Makefile stesso. Di solito include anche le versioni del compilatore. A seconda di come è scritto il tuo Makefile, potrebbe includere versioni di librerie esterne.

Questi sono i tipi di cose che tendono ad essere aggiornati quando si esegue un aggiornamento del controllo versione, quindi la maggior parte degli sviluppatori ha l'abitudine di eseguirne uno make cleancontemporaneamente, quindi sai che stai iniziando da una tabula rasa. Puoi scappare senza farlo per la maggior parte del tempo, ma è davvero difficile prevedere le volte che non puoi.


Puoi usare filesystem come ZFS in cui il costo dell'hashing viene ammortizzato nel momento in cui i file vengono modificati, anziché essere pagati tutti in una volta durante la creazione.
Asad Saeeduddin,

1

Alcuni punti sugli hash contro i timestamp nei sistemi di build:

  1. Quando esegui il checkout di un file, il timestamp deve essere aggiornato all'ora corrente, il che innesca una ricostruzione. Ciò che il tuo collega descrive non è di solito una modalità di errore dei sistemi di data e ora.
  2. I timestamp sono leggermente più veloci degli hash. Un sistema timestamp deve solo controllare il timestamp, mentre un sistema hash deve controllare il timestamp e quindi potenzialmente l'hash.
  3. Make è progettato per essere leggero e autonomo. Per superare (2), i sistemi basati su hash di solito eseguono un processo in background per il controllo degli hash (ad esempio Watchman di Facebook ). Questo è in contrasto con gli obiettivi di progettazione (e la storia) di Make.
  4. Gli hash impediscono ricostruzioni inutili quando un timestamp è cambiato ma non il contenuto. Spesso, questo compensa il costo del calcolo dell'hash.
  5. Gli hash consentono alle cache degli artefatti di essere condivise tra i progetti e su una rete. Ancora una volta, questo più che compensa il costo del calcolo degli hash.
  6. I moderni sistemi di build basati su hash includono Bazel (Google) e Buck (Facebook).
  7. La maggior parte degli sviluppatori dovrebbe considerare l'utilizzo di un sistema basato su hash, dal momento che non hanno gli stessi requisiti di quelli in cui è stato progettato Make.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.