Rutinariamente trabajo en varias computadoras y sistemas operativos diferentes, que son Mac OS X, Linux o Solaris. Para el proyecto en el que estoy trabajando, extraigo mi código de un repositorio de git remoto.
Me gusta poder trabajar en mis proyectos sin importar en qué terminal estoy. Hasta ahora, he encontrado formas de sortear los cambios del sistema operativo cambiando el archivo MAKE cada vez que cambio de computadora. Sin embargo, esto es tedioso y causa muchos dolores de cabeza.
¿Cómo puedo modificar mi archivo MAKE para que detecte qué sistema operativo estoy usando y modifique la sintaxis en consecuencia?
Aquí está el archivo MAKE:
cc = gcc -g
CC = g++ -g
yacc=$(YACC)
lex=$(FLEX)
all: assembler
assembler: y.tab.o lex.yy.o
$(CC) -o assembler y.tab.o lex.yy.o -ll -l y
assembler.o: assembler.c
$(cc) -o assembler.o assembler.c
y.tab.o: assem.y
$(yacc) -d assem.y
$(CC) -c y.tab.c
lex.yy.o: assem.l
$(lex) assem.l
$(cc) -c lex.yy.c
clean:
rm -f lex.yy.c y.tab.c y.tab.h assembler *.o *.tmp *.debug *.acts
PROCESSOR_ARCHITECTURE
entorno parece estar virtualizado dependiendo de si el proceso es de 32 bits o de 64 bits. Entonces, si sumake
es de 32 bits y está tratando de construir una aplicación de 64 bits, fallará. Usarlo en combinación conPROCESSOR_ARCHITEW6432
funcionó para mí (ver esto y aquello )make
equipo agrega un par de variables mágicas con os y arch, probablemente demasiados problemas.OS
está configurado en sistemas que no sean Windows. Haga que las golosinas no estén configuradas como vacías, lo que provocará un salto aluname
bloque basado. Solo necesita agregar un cheque de FreeBSD allí./bin/sh: -c: line 0: syntax error near unexpected token
, Windows_NT '/ bin / sh: -c: línea 0:ifeq (,Windows_NT)' make: *** [os] Error 2
El comando uname ( http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html ) sin parámetros debería indicarle el nombre del sistema operativo. Usaría eso, luego haría condicionales basados en el valor de retorno.
Ejemplo
fuente
Detecta el sistema operativo usando dos trucos simples:
OS
uname
comandoO una forma más segura, si no está en Windows y
uname
no está disponible:Ken Jackson propone una alternativa interesante si desea distinguir Cygwin / MinGW / MSYS / Windows. Vea su respuesta que se ve así:
Luego puede seleccionar las cosas relevantes dependiendo de
detected_OS
:Notas:
El comando
uname
es el mismo queuname -s
porque la opción-s
(--kernel-name
) es la predeterminada. Mira por quéuname -s
es mejor queuname -o
.El uso de
OS
(en lugar deuname
) simplifica el algoritmo de identificación. Todavía puede usar únicamenteuname
, pero debe lidiar conif/else
bloques para verificar todas las variaciones de MinGW, Cygwin, etc.La variable de entorno
OS
siempre se establece"Windows_NT"
en diferentes versiones de Windows (consulte%OS%
la variable de entorno en Wikipedia ).Una alternativa
OS
es la variable de entornoMSVC
(verifica la presencia de MS Visual Studio , ver ejemplo usando Visual C ++ ).A continuación proporciono un ejemplo completo usando
make
ygcc
para construir una biblioteca compartida:*.so
o*.dll
dependiendo de la plataforma. El ejemplo es lo más simple posible para ser más comprensible.Para instalar
make
ygcc
en Windows, vea Cygwin o MinGW .Mi ejemplo se basa en cinco archivos.
Recordatorio:
Makefile
se sangra con tabulación . Precaución al copiar y pegar debajo de archivos de muestra.Los dos
Makefile
archivos1)
lib/Makefile
2)
app/Makefile
Para obtener más información, lea la documentación de Variables automáticas según lo indicado por cfi .
El código fuente
-
lib/hello.h
-
lib/hello.c
-
app/main.c
La construcción
Arregle el copiar y pegar de
Makefile
(reemplazar espacios iniciales por una tabulación)El
make
comando es el mismo en ambas plataformas. La salida dada es en sistemas operativos tipo Unix:La carrera
La aplicación requiere saber dónde está la biblioteca compartida.
En Windows, una solución simple es copiar la biblioteca donde está la aplicación:
En sistemas operativos tipo Unix, puede usar la
LD_LIBRARY_PATH
variable de entorno:Ejecute el comando en Windows:
Ejecute el comando en sistemas operativos tipo Unix:
fuente
uname
no es Linux. Solo doy un ejemplo que puede que no necesite, pero esto puede ayudar a alguien que busca (en la web) una forma de implementar unaMakefile
para ambas plataformas ;-) ¿Qué debo cambiar en mi respuesta? Saludoslib/Makefile
ejemplo,target
se utiliza para.so
vs.dll
. Un ejemplo paralelo para elapp/makefile
sería útil para la comparaciónempty string
vs.exe
para el nombre de archivo de la aplicación. Por ejemplo, generalmente no veoapp.exe
en sistemas operativos tipo Unix. ;-)Hace poco estuve experimentando para responder a esta pregunta que me hacía. Aquí están mis conclusiones:
Dado que en Windows, no puede estar seguro de que el
uname
comando esté disponible, puede usarlogcc -dumpmachine
. Esto mostrará el objetivo del compilador.También puede haber un problema al usarlo
uname
si desea hacer una compilación cruzada.Aquí hay una lista de ejemplos de posibles resultados de
gcc -dumpmachine
:Puede verificar el resultado en el archivo MAKE de esta manera:
Funcionó bien para mí, pero no estoy seguro de que sea una forma confiable de obtener el tipo de sistema. Al menos es confiable sobre MinGW y eso es todo lo que necesito, ya que no requiere tener el
uname
comando o el paquete MSYS en Windows.En resumen,
uname
le da el sistema en el que está compilando ygcc -dumpmachine
le da el sistema para el que está compilando.fuente
uname
viene con deMinGW
todos modos? Sin embargo, la nota adicional con respecto a la compilación cruzada es excelente.$(shell $(CC) -dumpmachine)
. A partir de OS X Sierra, el comando -dumpmachine funciona en Clang.x86_64-apple-darwin16.6.0
y que las obras ya sea que se lo llamagcc
,cc
oclang
, pero nocl
El archivo make de git contiene numerosos ejemplos de cómo administrar sin autoconf / automake, pero aún funciona en una multitud de plataformas unixy.
fuente
if (!usesAutotools(git)) aversionTo(autotools) = justified;
también aclararé que solo son las herramientas a las que no me gusta. Estoy seguro de que las personas de Autotools son buenas personas.Actualización: ahora considero que esta respuesta es obsoleta. Publiqué una nueva solución perfecta más abajo.
Si su archivo MAKE puede estar ejecutándose en Windows
uname
que no sea Cygwin, es posible que no esté disponible. Eso es incómodo, pero esta es una solución potencial. Primero debe verificar Cygwin para descartarlo, porque también tiene WINDOWS en suPATH
variable de entorno.fuente
uname
emito desde un terminal cmd normal, me da MINGW. Lo que quiero decir es que todavía tengouname
sin usar Cygwin. También tengo git bash, pero no he probado uname en él (ahora estoy en Linux). ¿Me puede decir cómo se pueden incorporar estos dos en su código?uname
no se pudiera ejecutar, entenderíamos que estamos en Windows?Ese es el trabajo que el automake / autoconf de GNU está diseñado para resolver. Es posible que desee investigarlos.
Alternativamente, puede establecer variables de entorno en sus diferentes plataformas y hacer que Makefile sea condicional contra ellas.
fuente
make
a hacer lo que quiero. ¿Ahora quiero entrar también en automake / autoconf? - NO. Lo que se puede hacer en el archivo MAKE, sin duda, debe hacerse en el archivo MAKE, aunque solo sea para que no tenga varios puntos de parada cada vez que quiera modificar la compilación y el enlace.Finalmente encontré la solución perfecta que resuelve este problema para mí.
La variable UNAME está configurada en Linux, Cygwin, MSYS, Windows, FreeBSD, NetBSD (o presumiblemente Solaris, Darwin, OpenBSD, AIX, HP-UX) o Desconocido. Luego se puede comparar en el resto del Makefile para separar las variables y comandos sensibles al sistema operativo.
La clave es que Windows usa punto y coma para separar las rutas en la variable PATH, mientras que todos los demás usan dos puntos. (Es posible hacer un directorio de Linux con un ';' en el nombre y agregarlo a PATH, lo que rompería esto, pero ¿quién haría algo así?) Este parece ser el método menos riesgoso para detectar Windows nativo porque no necesita una llamada de shell. Cygwin y MSYS PATH usan dos puntos, por lo que se llama a uname .
Tenga en cuenta que la variable de entorno del sistema operativo se puede utilizar para detectar Windows, pero no para distinguir entre Cygwin y Windows nativo. La prueba de eco de comillas funciona, pero requiere una llamada de shell.
Desafortunadamente, Cygwin agrega información de la versión a la salida de uname , así que agregué las llamadas 'patsubst' para cambiarlo solo a 'Cygwin'. Además, uname para MSYS en realidad tiene tres salidas posibles que comienzan con MSYS o MINGW, pero también uso patsubst para transformar todo a solo 'MSYS'.
Si es importante distinguir entre sistemas nativos de Windows con y sin uname.exe en la ruta, esta línea se puede usar en lugar de la simple asignación:
Por supuesto, en todos los casos se requiere la marca GNU u otra marca que admita las funciones utilizadas.
fuente
Me encontré con este problema hoy y lo necesitaba en Solaris, así que aquí hay una forma estándar POSIX de hacer esto (algo muy parecido).
fuente
Aquí hay una solución simple que comprueba si está en un entorno Windows o similar a posix (Linux / Unix / Cygwin / Mac):
Aprovecha el hecho de que el eco existe tanto en entornos de posix como en Windows, y que en Windows el shell no filtra las comillas.
fuente
$PATH
podría referirse a otroecho
(el mío sí ...)-mwindows
bandera o elegir entre un.dll
o.so
, esto fallará.Tenga en cuenta que los Makefiles son extremadamente sensibles al espaciado. Aquí hay un ejemplo de un Makefile que ejecuta un comando adicional en OS X y que funciona en OS X y Linux. En general, sin embargo, autoconf / automake es el camino a seguir para cualquier cosa que no sea trivial.
fuente
Otra forma de hacerlo es mediante el uso de un script "configurar". Si ya está usando uno con su archivo MAKE, puede usar una combinación de uname y sed para que todo funcione. Primero, en tu guión, haz:
Luego, para poner esto en su Makefile, comience con Makefile.in que debería tener algo como
en eso.
Use el siguiente comando sed en su script de configuración después del
UNAME=uname
bit.Ahora su archivo MAKE debería haberse
UNAME
definido como se desea. ¡Si las declaraciones / elif / else son todo lo que queda!fuente
Tuve un caso en el que tuve que detectar la diferencia entre dos versiones de Fedora, para ajustar las opciones de línea de comandos para Inkscape:
- en Fedora 31, el Inkscape predeterminado es 1.0beta que usa
--export-file
- en Fedora <31, el Inkscape predeterminado es 0.92 que utiliza
--export-pdf
Mi Makefile contiene lo siguiente
Esto funciona porque
/etc/os-release
contiene una líneaentonces el comando de shell en el Makefile devuelve la cadena
VERSION_ID=<value>
, luego el comando eval actúa sobre esto para establecer la variable MakefileVERSION_ID
. Obviamente, esto puede modificarse para otros sistemas operativos dependiendo de cómo se almacenan los metadatos. Tenga en cuenta que en Fedora no hay una variable de entorno predeterminada que proporcione la versión del sistema operativo, de lo contrario, ¡lo habría usado!fuente