come può un makefile rilevare se un comando è disponibile nel computer locale?


11

Ho iniziato a utilizzare la modalità org per pianificare le mie attività nel sistema in stile GTD . Mettendo tutti i file dell'organizzazione in una directory di una cartella Dropbox , eseguo emacs per modificare / gestire questi file da tre diversi computer locali: Cygwin, Mac OS X e Debian. Dato che utilizzo anche MobileOrg per accedere a questi file organizzativi dal mio iPad, un checksums.datfile deve essere tenuto aggiornato quando vengono apportate modifiche. Questo può essere fatto eseguendo md5sum *.org > checksums.dat.

Il problema è che ci sono tre diversi comandi per il md5sumcomando: md5sum.exein Cygwin, md5in Mac OS X e md5sumin Debian. La situazione ideale è un makefile, memorizzato in un foder Dropbox, rileva quale comando è disponibile nella macchina corrente ed esegue quel comando per eseguire l'operazione di checksum md5.



1
@Kevin Sembra un eccessivo. Non voglio installare un programma in tre sistemi distinti. In ogni sistema, una cartella Dropbox è accessibile come directory locale. Quando corro make checksumper generare dati di checksum in una cartella Dropbox, desidero che il makefile utilizzi un comando appropriato dopo aver rilevato quale comando di checksum è disponibile nella macchina corrente.
Federico Magallanez,

Se hai intenzione di fare una quantità significativa di script e il progetto è piccolo, suggerirei scons.
Faheem Mitha,

Risposte:


7

Possibili comandi per generare un checksum

Sfortunatamente, non esiste un'utilità standard per generare un checksum crittografico. C'è un programma di utilità standard per generare un CRC: cksum; questo può essere sufficiente per il tuo scopo di rilevare cambiamenti in un ambiente non ostile.

Consiglierei di utilizzare SHA1 anziché MD5. Non ci sono molti sistemi che dispongono di un'utilità MD5 ma non di SHA1, e se utilizzerai checksum crittografici, potresti anche utilizzare un algoritmo senza un metodo noto per trovare le collisioni (supponendo che tu controlli anche le dimensioni).

Uno strumento non standard ma comune e in grado di calcolare i digest è OpenSSL . È disponibile per Cygwin, Debian e OSX, ma sfortunatamente non fa parte dell'installazione predefinita su OSX.

openssl dgst -sha1

Su OSX 10.6, c'è shasumun'utilità, che è presente anche su Debian (fa parte del perlpacchetto) e credo anche su Cygwin. Questo è uno script Perl. La maggior parte dei sistemi unix hanno installato Perl, quindi potresti raggruppare quello script insieme al tuo makefile se sei preoccupato che questo script non sia disponibile ovunque.

Selezione del comando giusto per il tuo sistema

Ok, diciamo che davvero non riesci a trovare un comando che funzioni ovunque.

Nel guscio

Usa il typebuilt-in per vedere se un comando è disponibile.

sum=
for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do
  if type "${x%% *}" >/dev/null 2>/dev/null; then sum=$x; break; fi
done
if [ -z "$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi
$sum *.org

GNU make

È possibile utilizzare la shellfunzione per eseguire uno snippet di shell quando viene caricato il makefile e archiviare l'output in una variabile.

sum := $(shell { command -v sha1sum || command -v sha1 || command -v shasum; } 2>/dev/null)
%.sum: %
        $(sum) $< >$@

Marca portatile (POSIX)

È possibile eseguire solo comandi shell nella regola, quindi ogni regola che calcola un checksum deve contenere il codice di ricerca. Puoi inserire lo snippet in una variabile. Ricorda che le righe separate nelle regole vengono valutate in modo indipendente. Ricorda inoltre $che è necessario sfuggire ai segni che devono essere passati alla shell $$.

determine_sum = \
        sum=; \
        for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do \
          if type "$${x%% *}" >/dev/null 2>/dev/null; then sum=$$x; break; fi; \
        done; \
        if [ -z "$$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi

checksums.dat: FORCE
    $(determine_sum); \
    $$sum *.org

Ho dovuto usare l' -Popzione del typecomando per far funzionare correttamente il metodo "GNU make" descritto sopra, quindi ho finito con sum := $(shell { type -P sha1sum || type -P sha1 || type -P shasum; } 2>/dev/null).
Sean,

@Sean Grazie per la segnalazione di bug. type -PFunziona solo se la tua shell è bash, non se è ad esempio ksh o dash (che è il caso di Ubuntu tra gli altri). È possibile utilizzare command -vper la portabilità.
Gilles 'SO- smetti di essere malvagio' il

Sembra che tu sia passato dall'uso typeall'utilizzo command. Anche gli altri metodi dovrebbero essere aggiornati?
Sean,

@Sean Gli altri metodi vanno bene: typeè un modo corretto e portatile per testare la presenza di un comando, il problema è che produce output come sha1sum is /usr/bin/sha1sumpiuttosto che solo il nome del programma. Questo è stato l'unico posto in cui ho usato l'output typepiuttosto che solo il suo valore di ritorno.
Gilles 'SO- smetti di essere malvagio' il

5

È una specie di hack, ma potresti testare se ognuno esiste ed eseguirli se lo fanno:

[ -x "`which md5 2>/dev/null`" ] && md5 newfile >>sums
[ -x "`which md5sum 2>/dev/null`" ] && md5sum newfile >>sums

Sono abbastanza sicuro che Cygwin riconosca i comandi (incluso md5sum) senza il .exe, ma includilo se devi.


4
whichi valori di uscita non sono portatili. Utilizzare typeinvece (e probabilmente si desidera utilizzare if; then; elifper evitare problemi in più eseguibili). whiche typecerca solo gli eseguibili, quindi il tuo test con -x è inutile.
Chris Down,

ulteriori informazioni sull'uso di "type": cmd = $ (per cmd in foo md5 md5sum bar; digitare $ cmd> / dev / null 2> & 1 && echo $ cmd && break; done); $ cmd file1 file2 file3> md5.txt
michael


1

O autotools GNU (come menzionato in un commento), o anche CMake è un'opzione.

Gli autotools GNU sono l'approccio più tradizionale, ma (e forse parlando solo per me stesso) non penso che le persone siano davvero troppo entusiaste della prospettiva di iniziare inizialmente un progetto usando loro. Bene, in ogni caso è una curva di apprendimento. CMake è il bambino più recente del blocco, e forse meno comune (e ha ancora una curva di apprendimento). Ha una sua sintassi e genera makefile per la tua piattaforma. CMake ha il netto vantaggio di non essere così * x-centrico; funziona in modo affidabile anche su unix, windows e mac (ad esempio, può generare progetti msvc, ad esempio, anziché makefile).

Modifica: e naturalmente da quando sono stati suggeriti i "makefile", questa risposta si accompagna a quella presunzione. Ma forse solo uno script python o (gasp) un semplice programma Java sarebbe più appropriato per questo compito; il linguaggio di programmazione / scripting farebbe lo stesso su tutte le piattaforme.

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.