对make(Linux)和nmake使用相同的makefile(Windows)

我有一个简单的C-Programm(1源文件),我想在Linux上和Windows上通过make resp编译。 NMAKE。 是否有可能使用单个makefile实现此目的?

我想到了类似的东西

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

不幸的是,nmake似乎不理解ifeq ,所以我无法使用它。 我有一个工作的makefile,但会产生非常难看的结果:

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

这适用于两个系统。 问题是结果取决于各个编译器的默认行为。 在Linux下我得到一个可执行的名为’a.out’而不是’hello’。 在Windows下我得到’hello.exe’,但也有’hello.obj’,我不想拥有它。

有没有人知道另一种方式? 或者我正在尝试绝对不可能的事情?

这可能并非不可能,但最有可能的是,无论如何写两个makefile会更容易。

GNU make(在Linux中使用)和nmake都有include伪指令,因此一些常见的东西可以放在main makefile包含的公共makefile中。

您应该考虑使用CMake 。 有一个源文件应该很容易!

编辑:

以下是如何设置一个简单的项目:

 cmake_minimum_required(VERSION 2.8) project(Simple) include_directories("${PROJECT_BINARY_DIR}") add_executable(Simple simple.cpp) 

要构建简单项目,您将执行以下操作(假设您的源和CMakeLists.txt文件位于~/src/simple

 foo@bar~/src/simple$ mkdir build foo@bar~/src/simple$ cd build foo@bar~/src/simple$ cmake .. foo@bar~/src/simple$ make 

我想使用make和nmake使用的相同makefile include。 由于make在注释行上识别行继续但nmake没有,这意味着我们可以为make和nmake分别指定。 例如:

 # \ !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 

只需确保nmake特定代码被#终止

我无法找到一种方法来使用通用的makefile来同时使用GNU make和MS nmake,主要是因为它们具有“include”和/或“if”指令的不兼容语法。 MS nmake需要使用! 指令的前缀。 例如,!if,!include等…

但是,如果允许它具有单独的宏,则可能会被欺骗。 在这里,我提出了迄今为止我发现的最佳方法,通过观察以下内容使makefile兼容GNU make和MS nmake:

  1. MS nmake读取TOOLS.ini文件以获取默认宏。
  2. MS套件使用.obj作为目标文件扩展名。
  3. GNU make读取MAKEFILES环境变量中定义的文件。
  4. GNU套件使用.o作为目标文件扩展名。
  5. GNU make不需要为目标提供可执行的扩展名.exe。

注意:以下内容已使用MS Visual Studio 2015和MINGW32进行了测试。

步骤1:创建以下DOS批处理文件,并在调用CMD提示时让它运行。

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

步骤2:在您的工作目录下创建一个TOOLS.ini文件,如下所示:(此文件可能与您的项目依赖项无关)

 [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:$@ 

步骤3:在您的工作目录下创建一个TOOLS.gcc,如下所示:(此文件可能与您的项目依赖关系无关)

 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 $@ 

第4步:编辑您的makefile,如下所示(注意$(X)和$(O)),其中只指定了dependecies。

 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 *~ 

第5步:使用相同的makefile享受GNU make和MS nmake

 $ nmake $ make clean $ nmake clean $ make 

我只是想到了一些完全不同的东西。

如果您坚持使用非常简单的Makefile,您可以使用它,并将“标准”变量CC和CFLAGS放在各自的环境中,比如说

  export CC=gcc 

分别

  set CC=CL.EXE 

  export CFLAGS=-o myexecutable 

分别

  set CFLAGS=/out:myexecutable.exe 

它可能只是工作。

请注意,我不确定使用的确切选项,你必须自己解决它们。 但AFAIK都使变体识别同一组标志。 您甚至可以在相应的命令行中设置它们(但不在makefile中,因为NMAKE使用不同的’ifeq’语法……)

是的,您可以使用单个Makefile执行此操作。 这种材料的最佳来源是O’Reilly Book:

使用GNU Make管理项目,第三版作者:Robert Mecklenburg

请参阅第7章:便携式Makefile。

总结一下,该技术是测试环境变量ComSpec,它表示是否存在windows命令解释器:

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

我用一个便携式shell脚本包装它,它使用sed编辑Nmake或Gnu-make的makefile。