¿Cómo puede un archivo MAKE detectar si un comando está disponible en la máquina local?

11

Comencé a usar el modo org para planificar mis tareas en el sistema de estilo GTD . Al colocar todos los archivos de organización en un directorio de una carpeta de Dropbox , ejecuto emacs para editar / administrar estos archivos desde tres máquinas locales diferentes: Cygwin, Mac OS X y Debian. Como también uso MobileOrg para acceder a estos archivos de organización desde mi iPad, un checksums.datarchivo debe mantenerse actualizado cuando se realicen cambios. Esto se puede hacer corriendo md5sum *.org > checksums.dat.

El problema es que hay tres comandos diferentes para el md5sumcomando: md5sum.exeen Cygwin, md5en Mac OS X y md5sumen Debian. La situación más ideal es un archivo MAKE, almacenado en un buscador de Dropbox, detecta qué comando está disponible en la máquina actual y ejecuta ese comando para realizar la operación de suma de comprobación md5.

Federico Magallanez
fuente
GNUautotools
Kevin
1
@ Kevin Eso suena como una exageración. No quiero instalar un programa en tres sistemas distintos. En cada sistema, se puede acceder a una carpeta de Dropbox como un directorio local. Cuando ejecuto make checksumpara generar datos de suma de verificación en una carpeta de Dropbox, quiero que el archivo MAKE use un comando apropiado después de detectar qué comando de suma de verificación está disponible en la máquina actual.
Federico Magallanez
Si va a realizar una gran cantidad de secuencias de comandos y el proyecto es pequeño, le sugiero scons.
Faheem Mitha

Respuestas:

7

Posibles comandos para generar una suma de comprobación

Desafortunadamente, no hay una utilidad estándar para generar una suma de verificación criptográfica. Hay una utilidad estándar para generar una CRC: cksum; Esto puede ser suficiente para su propósito de detectar cambios en un entorno no hostil.

Recomendaría usar SHA1 en lugar de MD5. No hay muchos sistemas que tengan una utilidad MD5 pero no SHA1, y si va a usar sumas de verificación criptográficas, también podría usar un algoritmo sin método conocido para encontrar colisiones (suponiendo que también verifique el tamaño).

Una herramienta que no es estándar pero sí común y puede calcular resúmenes es OpenSSL . Está disponible para Cygwin, Debian y OSX, pero desafortunadamente no forma parte de la instalación predeterminada en OSX.

openssl dgst -sha1

En OSX 10.6, hay una shasumutilidad, que también está presente en Debian (es parte del perlpaquete) y también creo en Cygwin. Este es un script de Perl. La mayoría de los sistemas Unix tienen instalado Perl, por lo que puede agrupar ese script junto con su archivo MAKE si le preocupa que este script no esté disponible en todas partes.

Seleccionar el comando correcto para su sistema

Ok, digamos que realmente no puedes encontrar un comando que funcione en todas partes.

En la cáscara

Use el typeincorporado para ver si hay un comando disponible.

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

Puede usar la shellfunción para ejecutar un fragmento de shell cuando se carga el archivo MAKE y almacenar la salida en una variable.

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

Marca portátil (POSIX)

Solo puede ejecutar comandos de shell en la regla, por lo que cada regla que calcule una suma de verificación debe contener el código de búsqueda. Puedes poner el fragmento en una variable. Recuerde que las líneas separadas en las reglas se evalúan de forma independiente. También recuerde que las $señales que se deben pasar al shell deben escaparse $$.

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- deja de ser malvado'
fuente
Tuve que usar la -Popción del typecomando para que el método "GNU make" descrito anteriormente funcionara correctamente, así que terminé con sum := $(shell { type -P sha1sum || type -P sha1 || type -P shasum; } 2>/dev/null).
Sean
@Sean Gracias por el informe de error. type -Psolo funciona si su shell es bash, no si es, por ejemplo, ksh o dash (que es el caso en Ubuntu, entre otros). Puedes usar command -vpara portabilidad.
Gilles 'SO- deja de ser malvado'
Parece que has cambiado de usar typea usar command. ¿Deberían actualizarse también los otros métodos?
Sean
@Sean Los otros métodos están bien: typees una forma correcta y portátil de probar la presencia de un comando, el problema es que produce un resultado similar sha1sum is /usr/bin/sha1sumal nombre del programa. Este fue el único lugar donde utilicé el resultado en typelugar de solo su valor de retorno.
Gilles 'SO- deja de ser malvado'
5

Es algo así como un truco, pero puedes probar si cada uno existe y ejecutarlos si lo hacen:

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

Estoy bastante seguro de que Cygwin reconoce los comandos (incluidos md5sum) sin el .exe, pero inclúyalo si es necesario.

Kevin
fuente
44
whichlos valores de salida no son portables. Use en su typelugar (y probablemente quiera usar if; then; elifpara evitar tener problemas porque hay múltiples ejecutables). whichy typesolo busque ejecutables de todos modos, por lo que su prueba con -x no tiene sentido.
Chris Down
más sobre el uso de "type": cmd = $ (para cmd en foo md5 md5sum bar; escriba $ cmd> / dev / null 2> & 1 && echo $ cmd && break; done); $ cmd archivo1 archivo2 archivo3> md5.txt
michael
1

O las herramientas automáticas GNU (como se menciona en un comentario), o también CMake es una opción.

Las herramientas automáticas GNU son el enfoque más tradicional, pero (y tal vez hablando solo por mí) no creo que la gente esté realmente entusiasmada con la perspectiva de establecer inicialmente un proyecto usándolas. Bueno, es una curva de aprendizaje, en cualquier caso. CMake es el chico más nuevo en el bloque, y quizás menos común (y aún tiene una curva de aprendizaje). Tiene su propia sintaxis y genera archivos MAKE para su plataforma. CMake sí tiene la clara ventaja de no estar tan centrado en x; también funciona de manera confiable en Unix, Windows y Mac (por ejemplo, puede generar proyectos de msvc, por ejemplo, en lugar de archivos MAKE).

Editar: y, por supuesto, como se sugirieron 'makefiles', esta respuesta va junto con esa presunción. Pero quizás solo un script de Python o (jadeo) un simple programa Java sería más apropiado para esta tarea; el lenguaje de programación / scripting haría lo mismo en todas las plataformas.

Miguel
fuente