Post

Makefile Introduction

Makefile Introduction

1 Makefile Introduction

Windows CE’s build system heavily uses Nmake and makefiles. Most Microsoft software and driver development kits include Nmake. So it’s necessary to introduce makefiles and the Nmake tool.

1.1 Makefile Overview

For many Windows programmers, makefile might be unfamiliar. Windows IDEs (like Visual Studio and Borland C++ Builder) handle what makefiles do. Usually, just press a button in the IDE and the tool automatically compiles and links the project. Without an IDE, you need another way to manage project building.

Simply put, makefiles help developers simplify compilation, linking, and other build tasks. For simple projects with a few files, you can manually control the compiler and linker. But imagine a large project with hundreds or thousands of files — doing everything manually would be unmanageable. That’s where makefiles shine.

Makefiles define the compilation rules for the entire project. Source files are organized in directories by type, function, or module. Makefiles specify which files to compile first, which later, which need recompilation, and even more complex operations — makefiles are like automation scripts that can execute OS commands.

The biggest benefit of makefiles is “automated building.” After writing a makefile, a single command automatically compiles and links the entire project, greatly improving development efficiency.

A makefile is essentially a text file that can’t run itself. An external program interprets and executes it. NMake.exe is the tool that parses and executes makefiles.

When you type nmake, Nmake reads the makefile, parses it, determines which code to compile based on the rules, then calls the compiler and linker to compile and link the code, ultimately generating executables.

Figure: Makefile workflow

Notably, makefiles aren’t specific to Windows CE or Microsoft. They’re a universal automation build method widely used on Unix/Linux platforms. Many development tools provide NMake-like tools: Delphi’s make, Visual C++’s nmake, GNU’s make on Linux.

1.2 Makefile Rules

Makefiles consist of derivation rules (called Description Blocks in NMake). Basic syntax:

targets... : dependents... commands...

targets — target files, can be object files, executables, or labels. Must be at the start of a line. dependents — files needed to generate the target. Separated from targets by a colon. commands — commands NMake executes. Can be any Windows command-line command.

This defines a file dependency: if any dependent file is newer than the target file, the commands execute. This is the core concept of makefiles.

1.3 A Working Makefile Example

Create a hello directory under %_WINCEROOT%\PBWorkspaces\MyPlatform, then create hello.cpp:

#include <windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MessageBox(NULL, L"Hello", L"bb", 0); }

Create a file named makefile (no extension) in the hello directory:

#This is a demo makefile hello.exe: hello.obj @echo linking... link -MACHINE:x86 -NODEFAULTLIB -subsystem:windowsce,5.00 -entry:WinMainCRTStartup -LIBPATH:E:\WINCE500\PBWorkspaces\MyPlatform\priv\... hello.obj: hello.cpp @echo compiling... cl -nologo -c -I. -IE:\WINCE500\public\common\sdk\inc -DUNICODE -D_UNICODE -DUNDER_CE=500 -D_WIN32_WCE=500 -DWIN32 -DSTRICT -Dx86 -D_X86_ -DINTERNATIONAL -DL0804 -DINTLMSG_CODEPAGE=1252 hello.cpp clean: del hello.obj, hello.exe

Open the Windows CE console from Start → Programs → Microsoft Windows CE 5.0, cd to hello, type nmake.

1.4 Using Variables

To make makefiles easier to maintain, use variables (like C macros):

TARGETNAME = hello SOURCES = hello.cpp TARGETLIBS = $(TARGETNAME).obj coredll.lib corelibc.lib CPPFLAGS = -nologo -c -I. -IE:\WINCE500\public\common\sdk\inc -DUNICODE -D_UNICODE ... LFLAGS = -MACHINE:x86 -NODEFAULTLIB -subsystem:windowsce,5.00 -entry:WinMainCRTStartup ... $(TARGETNAME).exe: $(TARGETNAME).obj @echo linking... $(LINK) $(LFLAGS) $(TARGETLIBS) $(TARGETNAME).obj: $(SOURCES) @echo compiling... $(CPP) $(CPPFLAGS) $(SOURCES)

1.5 Using Preprocessing

NMake supports preprocessing for conditional processing, error messages, including other makefiles, etc.

!IFDEF EXEENTRY ! MESSAGE EXEENTRY: $(EXEENTRY) EXEENTRYOPTION=-entry:$(EXEENTRY) !ELSE EXEENTRYOPTION=-entry:WinMainCRTStartup !ENDIF

1.6 Including Other Files

Use !INCLUDE to split makefiles into reusable parts:

sources file:

TARGETNAME = hello SOURCES = hello.cpp EXEENTRY = WinMain TARGETLIBS = coredll.lib corelibc.lib

makefile file:

!INCLUDE makefile.def
This post is licensed under CC BY 4.0 by the author.