我看到这篇文件感觉非常的赞,虽然现在用不到但是以后会很有用,所以留下来。谢谢作者!
摘自:https://www.cnblogs.com/kekec/archive/2013/04/21/3007277.html
1. 如果已经有vc6的dsp工程,可直接导出nmake脚本文件(.mak)
“Project - Export Makefile...”
nmake -f nMakeTest.mak CFG="nMakeTest - Win32 Debug"
nmake -f nMakeTest.mak CFG="nMakeTest - Win32 Debug" all
nmake -f nMakeTest.mak CFG="nMakeTest - Win32 Release" clean
注:如果未指定/F选项,则使用当前目录下的名为makefile的文件
【nmake /?】 获取更多帮助! vc6:【D:\program files\Microsoft Visual Studio\VC98\Bin】
vs2008:【D:\program files\Microsoft Visual Studio 9.0\VC\bin】
为了能正确地使用命令行工具及vc6或vs2008下的函数库,需要对一些环境变量进行设置,最快捷地方式是通过如下方式打开命令行窗口(以vs2008为例):
2. vs的c++工程没有提供导出nmake脚本文件的功能,我们只有借助工具或手动编写nmake脚本文件了
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3. rc.exe 【将.rc资源文本转变成.res二进制文件】
所在路径:C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\rc.exe
/l 0x804 // 默认语言ID(十六进制数表示) 0x804:简体中文 0x409:美国 更多...
/fo"nMakeTest.res" // 指定rc文件输出的res名称
例:rc.exe /l 0x804 /fo"nMakeTest.res" /d "_DEBUG" /d "_AFXDLL" “nMakeTest.rc”
4. cl.exe 常见选项 【将.c,.cpp,.cxx编译成obj文件】 更多...
vs2008版本所在路径:D:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\cl.exe
命令行长度说明:
windows上整个命令行的长度不能超过260个字符,然而编译命令行往往会超过这个限制,微软提供的解决方案是:将命令行参数写入一个response文件,然后将其传入编译器。
不过要注意的是:response文件仍然有32KB的限制。
如:"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\cl.exe" @"C:\UE4_15_0_Release\Build\Win64\PhysXVehicles.generated.cpp.obj.response"
/nologo // 不打印版权申明信息
/I "../include" // 添加头文件查找路径(如果路径中带有空格,一定要用引号括起来)
/DWIN32 // 预编译宏定义(win32程序)
/D_CONSOLE // 预编译宏定义(控制台程序)
/D "_DEBUG" // 预编译宏定义(Debug版本)
/D_CRT_SECURE_NO_DEPRECATE // 预编译宏定义(关闭C4996警告。使用strcpy、strcat等不安全函数时会报C4996警告)
/D_CRT_NONSTDC_NO_DEPRECATE // 预编译宏定义(关闭C4996警告。使用strcpy、strcat等不安全函数时会报C4996警告)
/DLIB_VER=0x2000 // 预编译自定义宏LIB_VER为0x2000 等价于#define LIB_VER 0x2000
/Od // 优化选项:带入Debug信息
/O2 // 优化选项:最快速度
/O1 // 优化选项:最小尺寸
/Oy // 启用帧指针省略【Frame pointer omission (FPO)】优化
// FPO是一种二进制程序代码优化方法,它压缩或者省略了在栈上为该函数创建框架指针的过程。这个选项加速了函数调用,因为不需要建立和移除框架指针(ESP,EBP)了。
// 同时,它还解放出了EBP寄存器,用来存储使用频率较高的变量。只在Intel CPU的架构上才有这种优化。
// 在Vista之前的os中,开启编译优化就会默认进行FPO优化,在Vista以后默认就没有FPO优化了,它所带来的优化效果比起它所带来的函数调用堆栈回溯的问题可以忽略。
/W3 // 设置3级警告级别
/WX // 将Warining视为error
/Fp"nMakeTest.pch" // 指定预编译文件名
/Yu"stdafx.h" // 在生成期间使用预编译头文件
/FI "myheader.h" // 在每个源文件的第一行上的#include该文件
/Fd"vcpdb/testpdb" // 会将vc辅助编译的idb及pdb文件(见下面的/Gm选项)输入到vcpdb目录中,
并重命名为testpdb.idb与testpdb.pdb(这里的pdb为project database文件,用于存工程的数据库信息)
/Fo"objFiles" // 将obj文件输出到objFiles目录中
/c // 编译但不链接
/feMyTest // 编译后,输出MyTest.exe可执行文件
/EHsc // 打开"C++例外(Exceptions)",以免出现编译器警告
/LD // 创建动态链接库
/LDd // 创建调试动态链接库
/ML // 使用 libc.lib 创建单线程可执行文件
/MLd // 使用 libcd.lib 创建调试单线程可执行文件
/MT // 使用 libcmt.lib 创建多线程可执行文件
/MTd // 使用 libcmtd.lib 创建调试多线程可执行文件
/MD // 使用 msvcrt.lib/msvcrt.dll 创建多线程可执行文件
/MDd // 使用 msvcrtd.lib/msvcrtd.dll创建调试多线程可执行文件
/Z7 //生成与 C7.0兼容的调试信息
/Zd //生成行号
/Zi //生成完整的调试信息
/Za // 禁用语言扩展(不支持ANSI C89 及 C++11) --使用该参数时,编译器会自动定义__STDC__宏
/Ze // 启用语言扩展(默认)
/Zl // ZL 非ZI; 告诉编译器从.obj文件中移除默认C库链接指令(注:该链接指令会被传给连接器 形如:/DEFAULTLIB:'LIBCMT')
/Gm // 启用最小重新生成
编译器在.idb文件中存储源文件和类定义之间的依赖关系。
使用.idb 文件的信息来确定是否需要编译某个源文件。
而不是该源文件只要包含了被修改的.h文件,就必须重新编译。
/link // 将/link后指定的选项传递给link.exe
// 默认情况下,cl.exe编译完后,会自动调用link.exe进行连接,
// 所以直接用cl.exe编译带main函数的.c或.cpp后,会生成obj与exe文件。
例:cl /c test1.cpp test2.cpp // 编译test1.cpp,test2.cpp
例:cl *.cpp /MD /c /I"G:\Visual C++\VC98\PlatformSDK\Include"
5. link.exe常见选项 【将obj、lib、res链接成dll或exe等可执行文件】
vs2008版本所在路径:D:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\link.exe
/dll // 输出dll文件
-lib // 生成lib静态库文件 例:link -lib *.obj /out:test.lib
/libpath:"..\PublicSDK\lib" // 指定外部lib查找路径(路径中不能带有空格,否则链接时会报LNK1181的错误)
/subsystem:windows[console] // 指定子系统
/machine 指定目标平台{AM33|ARM|EBC|IA64|M32R|MIPS|SH3|SH3DSP|SH4|SH5|THUMB|X86|X64},等
/NODEFAULTLIB:libcd.lib // 链接时,忽略libcd.lib库
/debug // 生成调试信息
/export:myAdd=_Add,@1 // 导出extern "C" Add函数,并将符号名修改为myAdd,同时将导出序号设为1(一种dll动态库导出符号的方法)
/export:_g_isTest,@2 // 导出extern "C" g_isTest变量,并将导出序号设为2(一种dll动态库导出符号的方法)
/def:"nMakeTest.def" // 模块导出文件(另外一种dll动态库导出符号的方法)
注1:def文件名不要求与dll文件名或工程名一致
注2:一个dll工程最多只允许使用一个def文件
注3:vc:只需将def文件添加到工程中即可
注4:vs2008:项目 - 属性 - 连接器 - 输入 - 模块定义文件,填入def文件名(def文件要放在当前工程目录之下,def文件可不添加到工程中)
;nMakeTest.lib 导出DLL函数
;作者:kekec
LIBRARY nMakeTest.def
EXPORTS
Add @ 1
g_isTest @ 2
注:还可以在代码中使用__declspec(dllexport)进行符号的导出
#ifdef WIN32DLL_EXPORTS
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif
/************** export.c ***************/
#ifdef __cplusplus
extern "C"
{
#endif
WIN32DLL_API int __stdcall Add(int a, int b)
{
return (a + b);
}
WIN32DLL_API int g_isTest = 0;
#ifdef __cplusplus
}
#endif
/pdb:"nMakeTest.pdb" // 重命名生成的pdb文件(Program Debug Database),保存调试符号等信息
/map:"nMakeTest.map" // 重命名生成的map文件
/out:"nMakeTest.exe" // 重命名生成的exe文件
/implib:"test.lib" // 生成名为test.lib的导出库
/stack:0x300000 // 设置线程栈Reserve内存大小为3MB windows缺省是1MB -- 格式:/STACK:reserve[,commit]
/stack:0x500000,0x200000 // 设置线程栈Reserve内存大小为5MB,Commit内存大小为2MB windows缺省是1MB -- 格式:/STACK:reserve[,commit]
/entry:_DllMainCRTStartup@12 // 指定_DllMainCRTStartup函数dll的起始地址
/release // 生成checksum
/incremental:yes // 开启增量链接
incremental开关默认是开启的。
开启增量链接产生的exe或dll文件的size要大一些。
因为有代码和数据的填充,增量链接的exe或dll文件会包含跳转trunk来处理函数重定位到新地址。
MSDN上明确指出:为确保最终发布版本不包含填充或者trunk,请关闭增量链接。
例:link gdiplus.lib /subsystem:windows /out:test.exe file1.obj file2.lib file3.res // 生成名为test.exe的windows可执行程序
例:link gdiplus.lib /subsystem:console /out:test.exe *.obj file2.lib file3.res // 生成名为test.exe的控制台可执行程序
例:link gdiplus.lib /subsytem:windows /dll /out:test.dll /implib:test.lib /def:test.def *.obj file2.lib file3.res // 生成名为test.dll动态库
例:link *.obj rc.res /LIBPATH:"G:\Visual C++\lib" /SUBSYSTEM:WINDOWS /MACHINE:X86 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib OpenGL32.Lib
例:"D:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin/link.exe" /MANIFEST:NO /NOLOGO /DEBUG /errorReport:prompt /MACHINE:x86 /SUBSYSTEM:WINDOWS /FIXED:No /LARGEADDRESSAWARE /NXCOMPAT /STACK:5000000,5000000 /SAFESEH /DEF:UnrealEngine3.def /DELAY:UNLOAD /RELEASE /OPT:REF /OPT:ICF /INCREMENTAL:NO /DELAYLOAD:"dxgi.dll" /DELAYLOAD:"d3d10.dll" /LIBPATH:"../External/zlib/Lib" /LIBPATH:"D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\/Lib/x86" /NODEFAULTLIB:"MSVCRTD" /NODEFAULTLIB:"MSVCPRTD" /NODEFAULTLIB:"LIBC" /NODEFAULTLIB:"LIBCMT" /NODEFAULTLIB:"LIBCPMT" /NODEFAULTLIB:"LIBCP" /NODEFAULTLIB:"LIBCD" /NODEFAULTLIB:"LIBCMTD" /NODEFAULTLIB:"LIBCPMTD" /NODEFAULTLIB:"LIBCPD" @"g:\svn\MyGame\Binaries\Win32\MyGameRelease.exe.response" /OUT:"g:\svn\MyGame\Binaries\Win32\MyGameRelease.exe" /IMPLIB:"g:\svn\MyGame\Binaries\Win32\MyGameRelease.lib" /PDB:"g:\svn\MyGame\Binaries\Win32\MyGameRelease.pdb" /CLRTHREADATTRIBUTE:STA /FILEALIGN:0x1000
6. nmake指令说明
(1) 符号说明
# // 注释符(命令所在行不能使用注释符,命令应该与注释都独立使用一行进行书写;如:erase nMakeTest.obj # 删除nMakeTest.obj文件【非法】)
^#abc // 表示#abc这个字符串
\ // 连接符,用于将两行合并为一行;在宏中,分多行写时,一定要用"\"进行连接
% // 文件说明符,表示其后的字符串为一文件名
---------------------
若文件名为 c:\prog.exe
%s 将为 c:\prog.exe
%:F 将为 c:\prog.exe
%:dF 将为 c
%:pF 将为 c:\
%:fF 将为 prog
%:eF 将为 exe
---------------------
@ // 命令修饰符;防止修饰的命令的结果,被打印出来
! // 命令修饰符
$ // 宏引用符
: // 依赖符号
?【*】 // 通配符支持
++++++++++++++++++++++++++++++++++++
$@ // 表示所有目标全名(路径+文件名称+扩展名)的挨个值
$$@ // 与$@用法含义一致,但仅在作为依赖项中的依赖项时有效
$< // 表示所有依赖目标的挨个值,仅在推理规则的命令中有效
$^ // 表示所有依赖目标的集合,以空格分隔,若有重复,会被去重;
$+ // 与$^含义一致,只是不进行去重处理。
$? // 表示所有比目标心的依赖目标的集合,以空格分隔
$* // 当前目标的路径和文件名称,没有文件扩展名
$** // 当前目标的所有依赖项
----------------------------
修饰符 说明
D 驱动器和目录
B 文件名称
F 文件名称和扩展名
R 驱动器、目录和文件名称
----------------------------
(2) 长文件名用双引号引起来
例:ALL : nMakeTest.dll // 文件名较短时,可不需要引号
例:ALL : "$(OUTDIR)\nMakeTest.exe" // 文件名较长时,特别是路径中有空格的情况,一定要用引号
(3) 预定义规则
.c.obj // 默认操作:cl /c $*.c
也可对默认操作显示地重写:
.c.obj:
cl /c /Ox /DWIN32 $<
(4) 包含文件
!INCLUDE nmake.opt
include makefile.mak
(5) 条件判断 - 01
!IF "$(CFG)" == ""
CFG=nMakeTest - Win32 Debug
!MESSAGE No configuration specified. Defaulting to nMakeTest - Win32 Debug.
!ELSE
!MESSAGE Be specified.
!ENDIF
(6) 条件判断 - 02 【!IFNDEF !IFDEF】
!IFNDEF PRIVATE_RUNTIMEMODE_DEBUG
RUNTIMEMODE_DEBUG = /MDd
!ELSE
RUNTIMEMODE_DEBUG = $(PRIVATE_RUNTIMEMODE_DEBUG)
!ENDIF
(7) 输出消息日志
!MESSAGE Invalid configuration "$(CFG)" specified.
(8) 描述块 - makefile的核心 【注:在依赖项(或规则)和命令块之间不能出现空行,commands之前为一个tab字符,多条command之间用;分割】
只要dependences中任意一个文件比targets新,就执行commands命令
targets... : dependences...
commands...
(9) ALL / CLEAN
OUTDIR=.\Release
INTDIR=.\Release
ALL : "$(OUTDIR)\nMakeTest.exe"
CLEAN :
-@erase "$(INTDIR)\nMakeTest.obj"
-@erase "$(INTDIR)\nMakeTest.pch"
-@erase "$(INTDIR)\nMakeTest.res"
-@erase "$(INTDIR)\nMakeTestDlg.obj"
-@erase "$(INTDIR)\StdAfx.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\nMakeTest.exe"
-@erase "$(OUTDIR)\nMakeTest.map"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
(10) 编译
CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)\nMakeTest.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
(11) 链接
LINK32=link.exe
LINK32_FLAGS=/nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)\nMakeTest.pdb" /map:"$(INTDIR)\nMakeTest.map" /machine:I386 /out:"$(OUTDIR)\nMakeTest.exe"
LINK32_OBJS= \
"$(INTDIR)\nMakeTest.obj" \
"$(INTDIR)\nMakeTestDlg.obj" \
"$(INTDIR)\StdAfx.obj" \
"$(INTDIR)\nMakeTest.res"
"$(OUTDIR)\nMakeTest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
(12) 文件依赖
SOURCE=.\nMakeTest.cpp
"$(INTDIR)\nMakeTest.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\nMakeTest.pch"
SOURCE=.\nMakeTest.rc
"$(INTDIR)\nMakeTest.res" : $(SOURCE) "$(INTDIR)"
$(RSC) $(RSC_PROJ) $(SOURCE)
(13) 预编译文件
SOURCE=.\StdAfx.cpp
!IF "$(CFG)" == "nMakeTest - Win32 Release"
CPP_SWITCHES=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)\nMakeTest.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
"$(INTDIR)\StdAfx.obj" "$(INTDIR)\nMakeTest.pch" : $(SOURCE) "$(INTDIR)"
$(CPP) @<<
$(CPP_SWITCHES) $(SOURCE)
<<
!ELSEIF "$(CFG)" == "nMakeTest - Win32 Debug"
CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)\nMakeTest.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
"$(INTDIR)\StdAfx.obj" "$(INTDIR)\nMakeTest.pch" : $(SOURCE) "$(INTDIR)"
$(CPP) @<<
$(CPP_SWITCHES) $(SOURCE)
<<
!ENDIF
# 参考
1. http://msdn.microsoft.com/zh-cn/library/dd9y37ha(v=vs.80).aspx
2. http://c2.com/cgi/wiki?UsingNmake
3. http://zh.wikipedia.org/wiki/Make
5. http://blog.codingnow.com/2008/09/replacement_of_ide_1.html
6. http://blog.codingnow.com/2008/09/replacement_of_ide_2
7. http://blog.codingnow.com/2008/09/replacement_of_ide_3
8. http://blog.codingnow.com/2008/09/replacement_of_ide_4
相关推荐
编写Makefile时,可以参考Linux的Makefile语法,但需要注意Windows下的路径和命令格式。使用Makefile的优点在于可以方便地管理和维护复杂的项目,通过简单的命令就能完成编译、链接和清理等一系列操作。
**nmake命令语法** - `nmake /?`:显示nmake的帮助信息。 - `/F <makefile>`:指定要使用的Makefile文件。 - `/I`:忽略Makefile中的错误,继续执行。 - `/NOLOGO`:不显示nmake的版权信息。 - `/A`:无论目标是否...
windows下安装perl模块方法和必备软件nmake dmake devcpp: 方式一: 将 nmake.exe 放到system32目录下 用一下方式: perl Makefile.pl nmake nmake test nmake install 如果成功,将不用看下面内容。 方式二:...
Makefile是构建程序的重要工具,特别是在Unix/Linux环境下广泛使用,但也可以在Windows系统中配合Microsoft的NMAKE工具进行程序构建。NMAKE是Microsoft Program Maintenance Utility的缩写,它是一个解释器,负责...
当用户输入 nmake 命令后,首先 nmake 会读取 makefile,然后解析 makefile,并根据 makefile 的规则来确定要编译哪些代码。然后 nmake 会调用编译器、链接器等一些开发工具,完成对代码的编译链接。最终会生成可...
一旦Makefile准备就绪,只需在命令行中运行nmake并指定Makefile的名称,nmake就会自动处理其余的工作。 **示例Makefile** ```makefile TARGET = my_program.exe SOURCES = main.asm utility.asm all: $(TARGET) ...
NMAKE工具遵循Makefile文件的规则来决定哪些文件需要重新编译,然后按照指定的命令执行编译和链接任务。 **NMAKE工作原理** NMAKE基于Makefile文件,这是一个文本文件,包含了构建项目所需的所有指令。Makefile...
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
通过阅读“Nmake.doc”、“nmakefile的使用.doc”和“NMake参考.pdf”这三份文档,你可以深入理解Nmake的工作机制,掌握编写和使用Makefile的技巧,以及在Windows环境下如何利用Nmake高效地管理编译工程。...
1. **启动NMAKE**:在命令行窗口,通过输入`nmake`命令,然后跟随Makefile的路径,例如`nmake -f Makefile`。 2. **目标指定**:若Makefile中定义了多个目标,可以通过`nmake target`指定要构建的具体目标。 3. **...
- **语法差异**:`make`的语法更加灵活,支持Gnu Make的扩展,而`nmake`遵循较简单的传统Makefile规则,对Windows路径和命令的支持更佳。 - **性能比较**:由于`nmake`针对Windows环境进行了优化,它在处理本地项目...
最后,Makefile不仅适用于Unix/Linux环境,在Windows环境下的IDE(如Visual Studio)中也有类似make的工具(如nmake)。了解makefile能够帮助程序员更好地掌握软件构建的过程,提升编程的专业水平。 通过对makefile...
1. **平台兼容性**:Nmake主要在Windows环境下使用,而Make是跨平台的。 2. **语法差异**:虽然两者的基本概念相似,但具体语法和功能有所区别,如Nmake使用宏,而Make使用变量。 3. **隐含规则**:Make有丰富的预定...
该包只限用于WINDOWS下编译PHP缺少LDAP相关依赖包时使用。只编译了liblber和libldap二个部分。 代码参考了https://github.com/winlibs/openldap中源码。但是,该源码中的工程文件中,预处理器的宏定义有错,不能正确...
不同的IDE或编译环境都有自己的make命令,例如Delphi的make、Visual C++的nmake等。在Linux下,最常见的是GNU的make,其版本为3.80,广泛应用于多种环境。 #### 编译和链接的基础 要理解Makefile,首先需要了解C/...
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 ...
【Makefile文件写法】和【手工生成VC++工程需要用到的Makefile】是关于在Windows环境下,使用nmake工具和Makefile进行C++程序编译的主题。Makefile是描述项目构建规则的文件,用于自动化编译和链接过程,极大地提高...
在各种IDE中,如Delphi的make、Visual C++的nmake和Linux下的GNU make,都有类似的命令工具来解析并执行Makefile。 在讲解如何编写Makefile之前,我们需要理解程序的编译和链接过程。编译阶段,源代码(如C/C++)会...
对于许多 Windows 平台的程序员而言,由于集成开发环境(IDE)已经提供了自动构建项目的功能,因此可能对 Makefile 缺乏了解。然而,为了成为一名优秀的程序员,掌握 Makefile 是十分必要的。正如 HTML 编辑器可以帮助...
Makefile是一个在Linux下用于编译和链接程序的重要工具,它能够指导make命令如何进行编译和链接操作。Makefile的作用是定义源文件之间的依赖关系,自动检测源文件的改动,并且只重新编译改动过的源文件,然后链接...