2011-11-25 10 views
11

Tengo un simple C-Programm (1 archivo fuente) que quiero compilar en Linux y en Windows a través de make resp. nmake. ¿Existe la posibilidad de lograr esto con un solo archivo MAKE?Utilice el mismo archivo make para make (Linux) y nmake (Windows)

pensé en algo así como

ifeq($(MAKE), nmake) 
    // nmake code here 
else 
    // make code here 
endif 

Desafortunadamente nmake parece no entender ifeq, así que no puedo usar eso. Tengo un archivo make que funciona pero que produce resultados muy feos:

hello: hello.c 
    $(CC) hello.c 

Eso funciona en ambos sistemas. El problema es que el resultado depende de los comportamientos predeterminados de los respectivos compiladores. Bajo Linux obtengo un ejecutable llamado 'a.out' en lugar de 'hola'. En Windows obtengo 'hello.exe' pero también 'hello.obj' que no quiero tener.

¿Alguien sabe de una manera alternativa? ¿O es lo que estoy tratando absolutamente imposible?

+1

Es posible construir o conseguir GNU make en el sistema Windows. –

+7

Para proyectos multiplataforma, puedo recomendar cmake (http://www.cmake.org). –

+0

Ya leí sobre cmake. Pero lo necesito para un ejercicio en la universidad donde se supone que debemos usar nmake. – j0ker

Respuesta

9

Probablemente no sea imposible, pero lo más probable es que sea tan difícil que sea más fácil escribir dos makefiles de todos modos.

Tanto GNU make (utilizado en Linux) como nmake tienen directivas de inclusión, por lo que algunas cosas comunes se pueden poner en un archivo make común que se incluye en el archivo make principal.

+0

Parece que no puedo encontrar un 'nmake' 'directiva include' en cualquier parte [MSDN] (http://msdn.microsoft.com/en-us/library/dd9y37ha.aspx)? –

+2

@JosephQuinsey http://msdn.microsoft.com/en-us/library/7y32zxwh.aspx –

1

Pensé en algo completamente diferente.

Si usted se pega a su Makefile extremadamente simple, que, se dice, funciona, y sólo hay que poner las variables 'estándar' CC y CFLAGS en sus respectivos entornos, dice

export CC=gcc 

respectivamente

set CC=CL.EXE 

y

export CFLAGS=-o myexecutable 

respectivamente

set CFLAGS=/out:myexecutable.exe 

podría funcionar.

Tenga en cuenta, no soy firme en las opciones exactas de usar, tendrá que resolverlas usted mismo. Pero AFAIK hace que las variantes reconozcan el mismo conjunto de banderas. Incluso puede establecerlos en las respectivas líneas de comando (pero no en el archivo MAKE, ya que NMAKE utiliza una sintaxis 'ifeq' diferente)

+1

Es probablemente una buena idea para escribir un archivo de secuencia de comandos shell y por lotes simple que configurar el entorno e invocar maquillaje ... – Christoph

6

Para esto, debe usar el CMake. ¡Con un archivo fuente debería ser bastante fácil!

EDIT:

Aquí es cómo se puede configurar un proyecto simple:

cmake_minimum_required(VERSION 2.8) 

project(Simple) 

include_directories("${PROJECT_BINARY_DIR}") 

add_executable(Simple simple.cpp) 

para construir el proyecto simple, usted haría lo siguiente (esto supone que su origen y CMakeLists.txt están en ~/src/simple:

[email protected]~/src/simple$ mkdir build 
[email protected]~/src/simple$ cd build 
[email protected]~/src/simple$ cmake .. 
[email protected]~/src/simple$ make 
+1

- 1 En comentario a la pregunta OP declara que necesita usar NMAKE. –

+2

@JohanBezem Cuando publiqué esta respuesta, ese comentario no estaba disponible. Sin embargo, creo que esta respuesta es la forma correcta de resolver el problema cuando no está bajo restricciones artificiales de una tarea ... – mevatron

+1

CMake puede generar nmake, así que no es descabellado _that_ utilizar CMake. Por lo menos vale la pena considerarlo. – ideasman42

1

sí, se puede hacer esto con un solo Makefile. La mejor fuente de este material es el libro de O'Reilly:

Managing Projects with GNU Make, Third Edition By Robert Mecklenburg

véase el capítulo 7: Portable Makefile.

En resumen, la técnica es poner a prueba la variable de entorno Comspec que dice si el intérprete de comandos de Windows está presente:

ifdef COMSPEC 
MV ?= move 
RM ?= del 
else 
MV ?= mv -f 
RM ?= rm -f 
endif 

envuelvo esto con un script de shell portátil que utiliza sed para editar el makefile para nAsegúrate o Gnu-make ..

+0

hm, afaict la sintaxis '? =' No es válida con 'nmake'. Creo que el ejemplo sólo se detecta si 'make' GNU está siendo ejecutado en W32 o no (en lugar de ser un nmake/gnumake políglota)) –

+0

@ Umlaute - Sí dice utilizo una secuencia de comandos sed para personalizar la sintaxis .... –

+0

lo suficientemente justo; Otoh, ya que el script de shell portátil es el pegamento mágico que en realidad responde a la pregunta, podría ser bueno para compartir, así que :-) –

4

Yo quería usar el mismo makefile para ser utilizado por make y nmake. Dado que make reconoce la continuación de línea en las líneas de comentario, pero nmake no, esto significa que podemos tener instrucciones separadas para make y nmake. por ejemplo:

# \ 
!ifndef 0 # \ 
# nmake code here \ 
MV=move # \ 
RM=del # \ 
CP=copy # \ 
!else 
# make code here 
MV=mv -f 
RM=rm -f 
CP=cp -f 
# \ 
!endif 

Sólo tiene que asegurarse de que nmake código específico es terminada por # \

+0

Esto funciona, aunque nmake no permite comentarios sobre comandos. Solo puede usar esta técnica para macros y comandos de * línea simple *. Sin embargo, puedes concatenar varios comandos usando ';' para mantenerlos en una sola línea. –

1

no soy capaz de encontrar una manera de utilizar un makefile común de trabajar tanto para GNU make y MS nmake, principalmente porque tienen una sintaxis incompatible para las directivas "incluir" y/o "si". MS nmake requiere usar! prefijo para directivas. por ejemplo,! if,! include, etc ...

Si se permite tener macros separadas, sin embargo, podría ser engañado. Aquí I presenta la mejor manera que he encontrado hasta ahora para la fabricación de archivo MAKE compatible tanto con GNU make y MS nmake mediante la observación de los siguientes:

  1. MS nmake lee el archivo TOOLS.ini de macros por defecto.
  2. MS suite utiliza .obj como extensión de archivo de objeto.
  3. GNU make lee archivos definidos en una variable de entorno MAKEFILES.
  4. GNU suite utiliza .o como extensión de archivo de objeto.
  5. GNU no necesita dar una extensión ejecutable .exe para un destino.

Nota: Se ha probado lo siguiente con MS Visual Studio 2015 y MINGW32.

Paso 1: cree un siguiente archivo de proceso por lotes de DOS y permita que se ejecute cada vez que se invoca el aviso de CMD.

set MAKEFILES=TOOLS.gcc 
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" 

Paso 2: Crear un archivo TOOLS.ini bajo el directorio de trabajo de la siguiente manera: (este archivo es independiente de sus dependencias del proyecto, excepto las bibliotecas posiblemente)

[NMAKE] 
LDLIBS = 
CDEBUG = /Zi 
LDEBUG = /debug:full 
WDFLAGS = /wd4996 /wd4774 /wd4018 /wd4710 /wd4820 
CFLAGS = /nologo $(CDEBUG) /EHsc /Wall $(WDFLAGS) 
LDFLAGS = /nologo $(LDEBUG) 
RM  = del /F /Q 
LINK = "$(VCINSTALLDIR)bin\link" $(LDFLAGS) 
CP = copy 
CC = cl 
CPP = $(CC) /P 
X = .exe 
O = .obj 

.obj.exe: 
    $(LINK) $** $(LOADLIBES) $(LDLIBS) /Out:[email protected] 

Paso 3: Crear una herramientas .gcc bajo el directorio de trabajo de la siguiente manera: (este archivo es independiente de sus dependencias del proyecto, excepto las bibliotecas posiblemente)

LD_LIBS = 
LDLIBS = 
CDEBUG = -g 
LDEBUG = -g 
CFLAGS = $(CDEBUG) 
LDFLAGS = $(LDEBUG) 
RM  = rm -f 
LINK = gcc $(LDFLAGS) 
CP  = cp 
CC  = gcc 
CPP  = $(CC) -E 
X  = 
O  = .o 

%: %.o 
    $(LINK) $^ $(LOADLIBES) $(LDLIBS) -o [email protected] 

Paso 4: Editar el Makefile de la siguiente manera (nota $ (X) y $ (O)) donde solo se especifican las dependencias.

SHELL = /usr/bin/sh 
app: app1$(X) app2$(X) 
app1$(X): app1$(O) 
app2$(X): app2$(O) 

clean: 
    $(RM) *.exe *.o *.obj *.ilk *.pdb *.tmp *.i *~ 

Paso 5: Disfrute de GNU make y MS nmake con el mismo archivo MAKE

$ nmake 
$ make clean 
$ nmake clean 
$ make