(Star this for CPP developers to enhance C/C++ skills)
Author: Zhu Jincan (This article is submitted by the author)
1. Basic Patterns of Makefiles in Windows Environment
From my observation, there is a basic pattern for makefiles in the Windows environment, which is as follows:
1. Set compiler flags
2. If the compiler flags are incorrect, prompt usage
3. If the clean command is executed, perform the cleaning command
4. Set compilation output (including output folder, exe file, or dll file, etc.)
5. Create output folders, etc. (this step is optional)
6. Run the compilation command to generate target files
7. Run resource compilation command (if there are no resource files, this step is unnecessary)
8. Run the link command to generate exe or dll files
2. A Makefile Template I Designed
Many open-source libraries set various compilation options. For example, the GDAL library has the following different compilation commands:
nmake -f makefile.vc DEBUG=1 // Compile 32-bit debug version
nmake -f makefile.vc // Compile 32-bit release version
nmake -f makefile.vc WIN64=1 DEBUG=1 // Compile 64-bit debug version
nmake -f makefile.vc WIN64=1 // Compile 64-bit release version
nmake -f makefile.vc clean // Clean compilation
nmake -f makefile.vc devinstall WIN64=1 // Compile release version and install development header and library files
# Include basic environment variables
!include <C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\Win32.Mak>
# Set compiler flags, initialize to FALSE
CFGSET = FALSE
!IF "$(option)"== "1"
# The following is the setup for compilation option 1
CFGSET = TRUE
Platform= x64
Configuration= Release
# Define preprocessor for release version
CC_OPTION = -D_WIN64 -D_NDEBUG -D_WINDOWS
TARGET_MACHINE = X64
!ELSE IF "$(option)"== "2"
# The following is the setup for compilation option 2
CFGSET = TRUE
Configuration= Debug
Platform= x64
# Define compilation options for debug version
CC_OPTION = -D_WIN64 -D_DEBUG -D_WINDOWS
TARGET_MACHINE = X64
!ELSE IF "$(option)"== "3"
# The following is the setup for compilation option 3
CFGSET = TRUE
Configuration= Release
Platform= Win32
CC_OPTION = -D_WIN32 -D_NDEBUG -D_WINDOWS
TARGET_MACHINE = X86
!ELSE IF "$(option)"== "4"
# The following is the setup for compilation option 4
CFGSET = TRUE
Configuration= Debug
Platform= Win32
CC_OPTION = -D_WIN32 -D_DEBUG -D_WINDOWS
TARGET_MACHINE = X86
!ELSE IF "$(option)"=="5"
CFGSET=TRUE
!ENDIF
# Prompt usage
!IF "$(CFGSET)"== "FALSE"!MESSAGE Usage: nmake /f makefile.vc option=1or2or3or4or5
!MESSAGE
!MESSAGE where is one of:!MESSAGE - option=1- build x64 release version
!MESSAGE - option=2- build x64 debug version
!MESSAGE - option=3- build x86 release version
!MESSAGE - option=4- build x86 debug version
!MESSAGE - option=5- clear temp file and output file
!MESSAGE
!MESSAGE
!ERROR please choose a valid configuration instead"
!ENDIF
# If the compilation option is 5, execute cleaning operation
!IF "$(option)"=="5"
CLEAN:
if exist "..\..\Intdir\Debug_x64\MyDepends" (del "..\..\Intdir\Debug_x64\MyDepends\*.obj") else echo Debug_x64 not exist
if exist "..\..\Intdir\Debug_Win32\MyDepends" (del "..\..\Intdir\Debug_Win32\MyDepends\*.obj") else echo Debug_Win32 not exist
if exist "..\..\Intdir\Release_x64\MyDepends" (del "..\..\Intdir\Release_x64\MyDepends\*.obj") else echo Release_x64 not exist
if exist "..\..\Intdir\Release_Win32\MyDepends" (del "..\..\Intdir\Release_Win32\MyDepends\*.obj") else echo Release_Win32 not exist
!ELSE
# Set output folder and temporary folder
OUTDIR =..\..\OutDir\$(Configuration)_$(Platform)
INDIR =..\..\Intdir\$(Configuration)_$(Platform)\MyDepends
# Here add multiple outputs
all: $(INDIR) $(INDIR)\MyDepends.res $(OUTDIR) $(OUTDIR)\MyDepends.exe
# If the $(INDIR) folder does not exist, create it
$(INDIR) :
if not exist "$(INDIR)" mkdir $(INDIR)
# If the $(OUTDIR) folder does not exist, create it
$(OUTDIR) :
if not exist "$(OUTDIR)" mkdir $(OUTDIR)
# Run the compilation command
CC = $(CC_OPTION)
$(INDIR)\MessageProcess.obj:MessageProcess.c
cl -c $(CC) /Fo"$(INDIR)\" /Fd"$(INDIR)\" MessageProcess.c
$(INDIR)\MyDepends.obj:MyDepends.c $(INDIR)\MessageProcess.obj
cl -c $(CC) /Fo"$(INDIR)\" /Fd"$(INDIR)\" MyDepends.c
# Compile resource script
$(INDIR)\MyDepends.res:MyDepends.rc
rc.exe /n /v /fo $(INDIR)\MyDepends.res MyDepends.rc
# Run the link command
$(OUTDIR)\MyDepends.exe: $(INDIR)\MyDepends.obj
link /machine:$(TARGET_MACHINE) /NOLOGO /subsystem:WINDOWS /out:$(OUTDIR)\MyDepends.exe $(INDIR)\MyDepends.obj $(INDIR)\MessageProcess.obj $(INDIR)\MyDepends.res kernel32.lib user32.lib comdlg32.lib Shell32.lib
!ENDIF
3. Notes for Writing Makefiles in Windows Environment
!IF "$(RUN_CLEAN)"== "TRUE"if exist "../../Intdir/Debug_x64/TestLog"(del"..\..\Intdir\Debug_x64\TestLog\*.obj") else echo Debug_x64不存在if exist "../../Intdir/Debug_Win32/TestLog"(del"..\..\Intdir\Debug_Win32\TestLog\*.obj") else echo Debug_Win32不存在!ELSE
It needs to be modified to:
!IF "$(RUN_CLEAN)"== "TRUE"
CLEAN:
if exist "..\..\Intdir\Debug_x64\TestLog"(del"..\..\Intdir\Debug_x64\TestLog\*.obj") else echo Debug_x64 not exist
if exist "..\..\Intdir\Debug_Win32\TestLog"(del"..\..\Intdir\Debug_Win32\TestLog\*.obj") else echo Debug_Win32 not exist
if exist "..\..\Intdir\Release_x64\TestLog"(del"..\..\Intdir\Release_x64\TestLog\*.obj") else echo Release_x64 not exist
if exist "..\..\Intdir\Release_Win32\TestLog"(del"..\..\Intdir\Release_Win32\TestLog\*.obj") else echo Release_Win32 not exist
!ELSE
1. A block name must be added, such as CLEAN:
2. There should be no blank lines between CLEAN: and if exist.
3. At least one tab must be inserted before if exist.
【Author of this article】
Author: Zhu Jincan, graduated with a bachelor’s degree in GIS from CUG (Wuhan). Currently engaged in software development and team management work in Beijing. He has won the second prize of the Nonferrous Metal Industry Science and Technology Progress Award. Personal blog: https://blog.csdn.net/clever101. WeChat public account: HiProgrammer
Recommended Reading
(Clicking the title will jump to read)
Introduction to Makefile
Microsoft’s new programming font is open-source, and one can accidentally curse while using it
Did this article help you? Please share it with more people
Follow ‘CPP developers’ and star it to enhance C/C++ skills
Good article, I’m reading ❤️