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

# Build all target
.PHONY : all
all : app

# Link the object files and dependent libraries 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 and dependent libraries 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 need to be ported to NMake format.

In summary, Linux Makefiles require some manual effort to run on Windows. Some of the options are,

  • Port to Windows NMake format.
  • Use a Linux like environment with Cygwin or MinGW to run “as is” on Windows (i.e. without NMake).
  • Create an equivalent Visual Studio Solution.
  • Create an equivalent CMake project. This is a more elegant alternative as the cross-platform build system CMake can generate Makefiles for Linux and Visual Studio solutions for Windows.
If you are not familiar with Makefile and/or CMake, see the following for a Visual Studio friendly introduction.
Makefiles and Visual Studio
CMake and Visual Studio