Makefiles in Windows

A commonly asked question is, “can I use Linux makefiles to build on Windows?”
Often, the simple (and rather naive) answer is “use NMake”. This post explains the nuanced differences between a Linux and Windows Makefile.

NMake is the native Windows alternative to the Linux make utility and the syntax is very similar too. However, let’s see if it can handle the following simple Linux Makefile. The example code can be accessed via GitHub at https://github.com/cognitivewaves/Simple-Makefile.

# Specify compiler
CC=gcc
 
# Specify linker
LINK=gcc
 
.PHONY : all
all : app
 
# Link the object files into a binary
app : main.o
    $(LINK) -o app main.o -lstdc++
 
# Compile the source files into object files
main.o : main.cpp
    $(CC) -c main.cpp -o main.o
 
# Clean target
.PHONY : clean
clean :
    rm main.o app 

Start a command prompt which can execute NMake. An easy way is to start a command prompt from Visual Studio (Tools->Visual Studio Command Prompt), so that all the necessary environment variables are set. Change directory to where the Makefile exists and run NMake.

D:\tmp\Simple-Makefile>nmake

Microsoft (R) Program Maintenance Utility Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

        gcc -c main.cpp -o main.o
'gcc' is not recognized as an internal or external command,
operable program or batch file.
NMAKE : fatal error U1077: 'gcc' : return code '0x1'
Stop.

The error points to the first problem. It’s easy to fix though as shown in the snippet.

  • Compilers are different on Linux and Windows.
# Specify compiler
CC=cl.exe

# Specify linker
LINK=link.exe

Run NMake again after the change.

D:\tmp\Simple-Makefile>nmake

Microsoft (R) Program Maintenance Utility Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

        cl.exe -c main.cpp -o main.o
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

cl : Command line warning D9035 : option 'o' has been deprecated and will be removed in a future release
main.cpp
        link.exe -o app main.o -lstdc++
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : warning LNK4044: unrecognized option '/o'; ignored
LINK : warning LNK4044: unrecognized option '/lstdc++'; ignored
LINK : fatal error LNK1181: cannot open input file 'app.obj'
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\BIN\link.exe"' : return code '0x49d'
Stop.

These warnings and errors indicate the next set of problems, which are more perverse. To fix it, adjust the file as shown in the snippet.

  • Libraries are never the same
  • Linux uses dash (-) to specify compiler options. Fortunately, Visual Studio allows options to be specified by either a forward slash (/) or a dash (–). But the compiler and linker flags are not exactly the same. There are more differences than similarities.
# Link the object files into a binary
app : main.o
	$(LINK) /OUT:app.exe main.o 

# Compile the source files into object files
main.o : main.cpp
	$(CC) /c main.cpp /Fomain.o

Run NMake again.

D:\tmp\Simple-Makefile>nmake

Microsoft (R) Program Maintenance Utility Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

        link.exe /OUT:app.exe main.o
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

        rm main.o app.exe
'rm' is not recognized as an internal or external command,
operable program or batch file.
NMAKE : fatal error U1077: 'rm' : return code '0x1'
Stop.

These indicate further problems.

  • It doesn’t recognize the Linux built in target names like .PHONY
  • Linux commands are obviously not valid in Windows



Finally, to make it work, the following changes have to be made. So Linux makefiles needs to be ported to NMake format.

Notes

  1. An alternative to porting the makefile is to create an equivalent Visual Studio Solution.
  2. A more elegant alternative is to use a cross-platform build system like CMake which will generate Makefiles for Linux and Visual Studio solutions for Windows.
  3. To use a Makefile “as is” on Windows (i.e. without NMake), a Linux like environment with Cygwin or MinGW is required.
  4. If you are not familiar with makefiles, see Makefiles and Visual Studio for a Visual Studio friendly introduction to the Make utility.
Advertisements