jak plik makefile może wykryć, czy polecenie jest dostępne na komputerze lokalnym?

11

Zacząłem używać trybu org do planowania moich zadań w systemie GTD . Umieszczając wszystkie pliki org w katalogu folderu Dropbox , uruchamiam emacsa, aby edytować / zarządzać tymi plikami z trzech różnych lokalnych komputerów: Cygwin, Mac OS X i Debian. Ponieważ korzystam również z MobileOrg, aby uzyskać dostęp do tych plików org z mojego iPada, checksums.datplik musi być aktualizowany po wprowadzeniu jakichkolwiek zmian. Można to zrobić, uruchamiając md5sum *.org > checksums.dat.

Problem polega na tym, że istnieją trzy różne polecenia do md5sumpolecenia: md5sum.exew Cygwin, md5w Mac OS X i md5sumw Debianie. Najbardziej idealną sytuacją jest plik makefile zapisany w foderze Dropbox, wykrywa, które polecenie jest dostępne w bieżącej maszynie i uruchamia to polecenie, aby wykonać operację sumy kontrolnej md5.

Federico Magallanez
źródło
gnuautotools
Kevin
1
@Kevin To brzmi jak przesada. Nie chcę instalować programu w trzech różnych systemach. W każdym systemie folder Dropbox jest dostępny jako katalog lokalny. Kiedy uruchamiam, make checksumaby wygenerować dane sumy kontrolnej w folderze Dropbox, chcę, aby plik makefile używał odpowiedniego polecenia po wykryciu, które polecenie sumy kontrolnej jest dostępne na bieżącym komputerze.
Federico Magallanez
Jeśli zamierzasz wykonać znaczną ilość skryptów, a projekt jest niewielki, sugerowałbym scons.
Faheem Mitha

Odpowiedzi:

7

Możliwe polecenia do wygenerowania sumy kontrolnej

Niestety nie ma standardowego narzędzia do generowania kryptograficznej sumy kontrolnej. Jest to standardowe narzędzie do generowania CRC: cksum; może to być wystarczające do wykrycia zmian w nieprzyjaznym środowisku.

Polecam używanie SHA1 zamiast MD5. Nie ma wielu systemów, które mają narzędzie MD5, ale nie ma SHA1, a jeśli zamierzasz użyć kryptograficznych sum kontrolnych, równie dobrze możesz użyć algorytmu bez znanej metody znajdowania kolizji (zakładając, że również sprawdzasz rozmiar).

Jednym z nietypowych, ale powszechnych narzędzi, które mogą obliczać skróty, jest OpenSSL . Jest dostępny dla Cygwin, Debian i OSX, ale niestety nie jest częścią domyślnej instalacji w OSX.

openssl dgst -sha1

W OSX 10.6 jest shasumnarzędzie, które jest również obecne w Debianie (jest to część perlpakietu) i wierzę również w Cygwin. To jest skrypt Perla. Większość systemów uniksowych ma zainstalowanego Perla, więc możesz spakować ten skrypt razem z plikiem makefile, jeśli martwisz się, że ten skrypt nie będzie dostępny wszędzie.

Wybór właściwego polecenia dla twojego systemu

Ok, powiedzmy, że naprawdę nie możesz znaleźć polecenia, które działa wszędzie.

W skorupce

Użyj typewbudowanego, aby sprawdzić, czy polecenie jest dostępne.

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

Marka GNU

Możesz użyć tej shellfunkcji do uruchomienia fragmentu powłoki, gdy plik makefile jest załadowany i zapisać dane wyjściowe w zmiennej.

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

Marka przenośna (POSIX)

Komendy powłoki można uruchamiać tylko w regule, więc każda reguła obliczająca sumę kontrolną musi zawierać kod odnośnika. Możesz umieścić fragment kodu w zmiennej. Pamiętaj, że osobne wiersze w regułach są oceniane niezależnie. Pamiętaj również, że $znaki, które mają być przekazane do powłoki, muszą być zabezpieczone $$.

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
Gilles „SO- przestań być zły”
źródło
Musiałem użyć -Popcji typepolecenia, aby opisana powyżej metoda „GNU make” działała poprawnie, więc skończyłem z sum := $(shell { type -P sha1sum || type -P sha1 || type -P shasum; } 2>/dev/null).
Sean
@Sean Dzięki za zgłoszenie błędu. type -Pdziała tylko wtedy, gdy twoja powłoka jest bash, a nie, jeśli jest to np. ksh lub dash (co ma miejsce między innymi w Ubuntu). Możesz użyć command -vdo przenoszenia.
Gilles „SO- przestań być zły”
Wygląda na to, że przeszedłeś z używania typena używanie command. Czy inne metody również powinny zostać zaktualizowane?
Sean
@Sean Inne metody są w porządku: typejest poprawnym, przenośnym sposobem na przetestowanie obecności polecenia, problem polega na tym, że generuje on dane wyjściowe, sha1sum is /usr/bin/sha1suma nie tylko nazwę programu. To było jedyne miejsce, w którym użyłem wyjścia, typea nie tylko jego wartości zwracanej.
Gilles „SO- przestań być zły”
5

To coś w rodzaju włamania, ale możesz sprawdzić, czy każdy istnieje, i wykonać je, jeśli:

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

Jestem pewien, że cygwin rozpoznaje polecenia (w tym md5sum) bez .exe, ale dołącz je, jeśli musisz.

Kevin
źródło
4
whichwartości wyjściowe nie są przenośne. Użyj typezamiast tego (i prawdopodobnie chcesz użyć, if; then; elifaby uniknąć problemów z wieloma plikami wykonywalnymi). whichi i tak typeszukaj tylko plików wykonywalnych, więc twój test z -x jest bezcelowy.
Chris Down
więcej o używaniu „type”: cmd = $ (dla cmd w pasku foo md5 md5sum; wpisz $ cmd> / dev / null 2> & 1 && echo $ cmd && break; done); $ cmd plik1 plik2 plik3> md5.txt
Michał
1

Albo GNU autotools (jak wspomniano w komentarzu), albo CMake jest opcją.

Narzędzia automatyczne GNU są bardziej tradycyjnym podejściem, ale (i być może mówię tylko dla siebie) nie sądzę, aby ludzie byli naprawdę podekscytowani perspektywą rozpoczęcia projektu z ich wykorzystaniem. W każdym razie jest to krzywa uczenia się. CMake jest nowszym dzieckiem na bloku i być może rzadziej (i wciąż ma krzywą uczenia się). Ma własną składnię i generuje makefile na twoją platformę. CMake ma tę wyraźną zaletę, że nie jest tak nie * x-centryczny; działa niezawodnie również na systemach Unix, Windows i Mac (np. może generować projekty msvc, na przykład, zamiast plików makefile).

Edycja: i oczywiście od kiedy zaproponowano „makefile”, ta odpowiedź jest zgodna z tym domniemaniem. Ale być może po prostu skrypt Pythona lub (wstrzymujący oddech) prosty program Java byłby bardziej odpowiedni do tego zadania; język skryptowy / programistyczny zrobiłby to samo na różnych platformach.

Michał
źródło