[转载]Makefile和Visual Studio

Visual Studio开发人员的Makefile简介

续前言Visual Studio开发人员的Makefiles

在您必须阅读/创建经典Makefile之前,Visual Studio提供的功能是理所当然的。 例如,Visual Studio自动神奇地执行以下操作。

  • 编译项目文件中的所有源代码
  • 创建一个输出目录,并将所有中间目标文件放入其中
  • 链接目标文件和外部依赖库以创建二进制文件
  • 管理源文件和目标文件之间的依赖关系
  • 管理目标文件和二进制文件之间的依赖关系

以上所有内容都必须在Makefile明确指定。 在某些方面, make实用程序等效于Visual Studio devenv.exe (没有精美的GUI)。

在Visual Studio的幕后 
相当于GNU / Linux 
Visual Studio制作实用程序映射 
 
源结构 
建立 
 
Makefile详细信息 
目标 
依赖 
内容 
NMAKE 
结论 
外部链接

在Visual Studio的幕后

Visual Studio本质上是编译和链接过程的GUI。 它利用基础命令行编译器和链接器。 此外,它提供了源代码编辑器,调试器和其他开发工具。

 c:\ tmp> cl.exe
适用于80x86的Microsoft(R)32位C / C ++优化编译器版本16.00.30319.01
版权所有(C)Microsoft Corporation。 版权所有。

用法:cl [选项...]文件名... [/ link linkoption ...]
 c:\ tmp> link.exe
 Microsoft(R)增量链接器版本10.00.30319.01
版权所有(C)Microsoft Corporation。 版权所有。

 用法:LINK [选项] [文件] [@commandfile]

下面显示了Visual Studio中的一个简单的win32控制台应用程序项目。 

测试溶液

在Visual Studio中的解决方案上调用构建会在幕后进行如下调用。

  C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC \ bin \ CL.exe / c / ZI / nologo / W3 / WX- / Od / Oy- / D WIN32 / D _DEBUG / D _CONSOLE / D _UNICODE / D UNICODE / Gm / EHsc / RTC1 / MDd / GS / fp:precise / Zc:wchar_t / Zc:forScope / Fo“ Debug \\” /Fd"Debug\vc100.pdb“ / Gd / TP / analyze- / errorReport:提示Test.cpp

 C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC \ bin \ link.exe / ERRORREPORT:PROMPT /OUT:"c:\tmp\Test\Debug\Test.exe“ / INCREMENTAL / NOLOGO kernel32.lib user32 .lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib / MANIFEST /ManifestFile:"Debug\Test.exe.intermediate.manifest“ / MANIFESTUAC :“ level ='asInvoker'uiAccess ='false'” / DEBUG /PDB:"c:\tmp\Test\Debug\Test.pdb“ / SUBSYSTEM:CONSOLE / TLBID:1 / DYNAMICBASE / NXCOMPAT / IMPLIB:” c: \ tmp \ Test \ Debug \ Test.lib“ / MACHINE:X86 Debug \ Test.exe.embed.manifest.res Debug \ Test.obj 

是的,看起来很丑! 但这就是将项目属性转换为编译器/链接器标志和选项。

相当于GNU / Linux

在GNU / Linux中非常相似。 gcc是GNU工程C和C ++编译器,等效于编译器和链接器。 它进行预处理,编译,组装和链接。

  $ gcc-帮助
用法:gcc [选项]文件... 

下面显示的是一个非常简单的Makefile ,可以从GitHub https://github.com/cognitivewaves/Simple-Makefile访问该Makefile 。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

# 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

调用make命令进行构建将输出以下内容。

  〜/ src /简单的Makefile $ make
 gcc -c main.cpp -o main.o
 gcc -o应用程序main.o -lstdc ++

Visual Studio制作实用程序映射

下表是将Visual Studio方面与Makefile相关的表。

 视觉工作室使效用
命令devenv.exemake
源文件列表项目( .vcproj )Makefile
源结构解决方案( .sln )的项目文件可能位于子目录中从根目录开始,每个Makefile都可以指示其他Makefile (通常是子目录)的位置
源到对象的依赖项目( .vcproj )Makefile
库构建依赖解决方案( .sln )具有项目和构建订单Makefile
编译和链接选项项目( .vcproj )Makefile
编译器cl.exegcc, g++, c++ (或任何其他编译器,甚至cl.exe )
链接link.exegcc, ld (或任何其他链接程序)

从GitHub下载示例资源, 网址https://github.com/cognitivewaves/Makefile-Example 。 
请注意,使用了非常基本的Makefile构造,因为重点是概念,而不是make本身的功能。

源结构

生成文件-实施例
    |-应用
    |  | -Makefile
    |  |-main.cxx
    |-数学
    |  |-高级
    |  |  |-AdvancedFunctions.cxx
    |  |  |-AdvancedFunctions.h
    |  |-简单
    |  |  |-SimpleFunctions.cxx
    |  |  |-SimpleFunctions.h
    |  | -Makefile
    | -Makefile

建立

视觉工作室使效用
通过IDE中的菜单项或在命令提示符下调用.sln文件上的devenv.exe来在Visual Studio中进行构建。 这将自动创建必要的目录,并仅构建上次构建后修改的文件。使用makefiles启动构建是在shell提示符下调用make命令。 必须在Makefile或外部显式地创建输出目录。

在此示例中,为使makefile保持简单,将在shell提示符下创建目录。

  〜/ src / Makefile-示例$ mkdir -p app / bin app / obj math / bin math / obj 

make实用程序语法如下所示。 有关详细信息,请参见make手册页。

 制作[-f制作文件] [选项] ... [目标] 

执行命令make并指定“ root” Makefile 。 但是,更常见的是更改到“根” Makefile存在的目录并调用make 。 这将读取当前目录中名为Makefile ,并默认调用all目标。 
注意make如何进入要构建的子目录。 这是因为嵌套的Makefiles ,这将在后面的“ Makefiles详细信息”部分中说明。

  〜/ src / Makefile-示例$ make

进行-C数学 make [1]:进入目录`/ home / user / src / Makefile-Example / math' g ++ -fPIC -I。 -c -o obj / AdvancedFunctions.o高级/AdvancedFunctions.cxx g ++ -fPIC -I。 -c -o obj / SimpleFunctions.o simple / SimpleFunctions.cxx g ++ -fPIC -shared -o bin / libmath.so obj / AdvancedFunctions.o obj / SimpleFunctions.o make [1]:离开目录`/ home / user / src / Makefile-Example / math' 制作-C app make [1]:进入目录`/ home / user / src / Makefile-Example / app' g ++ -I ../ math -c -o obj / main.o main.cxx g ++ obj / main.o -L ../ math / bin -o bin / app.exe -lmath make [1]:离开目录`/ home / user / src / Makefile-Example / app'

构建代码后,运行可执行文件。 这不是makefile所特有的,但已作了详细说明,以防您不熟悉Linux,因为您会注意到默认情况下它将无法运行并显示错误消息。

 〜/ src / Makefile-示例$ app / bin / app.exe 4

app / bin / app.exe:加载共享库时出错:libmath.so:无法打开共享库文件:没有这样的文件或目录

这是因为可执行文件app.exe需要共享对象libmath.so ,该对象位于其他目录中,并且不在系统路径中。 设置LD_LIBRARY_PATH以指定其路径。

 〜/ src / Makefile-示例$ export LD_LIBRARY_PATH =〜/ src / Makefile-Example / math / bin /

 〜/ src / Makefile-示例$ app / bin / app.exe 4

4和4的总和是8 4的平方根是2

生成文件详细信息

Makefile的基础具有非常简单的结构。

 目标:依赖
 [tab]系统命令 

[tab]分隔符非常重要! 空格而不是[tab]是不一样的。 您将看到相当模糊的错误消息,如下所示。 
Makefile:12: *** missing separator. Stop.

目标

target在这里是磁盘上的物理文件。 当target更多地是标签时,则必须将其标记为.PHONY以指示该目标不是实际文件。

视觉工作室使效用
默认情况下,Visual Studio提供了用于清理和重建项目或解决方案的选项。清理和重建必须明确地写在makefile中作为targets ,然后才能调用它们。

典型的情况是在重建之前进行clean 。

 〜/ src / Makefile-示例$ make clean

使-C数学干净 make [1]:进入目录`/ home / api / src / Makefile-Example / math' rm -fv bin / * obj / * 删除了bin / libmath.so 删除了obj / AdvancedFunctions.o 删除了obj / SimpleFunctions.o make [1]:离开目录`/ home / api / src / Makefile-Example / math' 使-C app干净 make [1]:进入目录`/ home / api / src / Makefile-Example / app' rm -fv bin / * obj / * 删除了``bin / app.exe'' 删除了obj / main.o make [1]:离开目录`/ home / api / src / Makefile-Example / app'

依赖

Dependencies可以是磁盘或其他目标(包括伪目标)上的文件。

视觉工作室使效用
默认情况下,Visual Studio支持项目中的隐式依赖关系(源文件到目标文件)。 库(项目)依赖项必须在解决方案文件中指定每个依赖项都必须在makefiles明确定义

例如,目标all取决于app.exe ,而app.exe又取决于libmath.so 。 如果删除app.exe ,make将能够识别libmath.so无需再次构建。

 〜/ src / Makefile-示例$ rm -v app / bin / *

删除了'app / bin / app.exe'

〜/ src / Makefile-示例$ make

制作-C app make [1]:进入目录`/ home / api / src / Makefile-Example / app' g ++ obj / main.o -L ../ math / bin -o bin / app.exe -lmath make [1]:离开目录`/ home / api / src / Makefile-Example / app'

内容

文件: Makefile

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

# all is the default target

.PHONY : all

all : app/bin/app.exe

 

# Invoke the Makefile in the sub-directory "app"

app/bin/app.exe : math/bin/libmath.so

    $(MAKE) -C app

 

# Invoke the Makefile in the sub-directory "math"

math/bin/libmath.so :

    $(MAKE) -C math

 

# Invoke the clean target in the "math" and "app" sub-directory Makefile

.PHONY : clean

clean :

    $(MAKE) -C math clean

    $(MAKE) -C app  clean

文件: math/Makefile

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

# The shared object libmath.so depends on the object files

# The command is to link and create the .so if the dependencies are up to date

# Note the .so is put in a sub-directory 'bin' by specifying 'g++ -o' option

bin/libmath.so : obj/AdvancedFunctions.o obj/SimpleFunctions.o

    g++ -fPIC -shared -o bin/libmath.so obj/AdvancedFunctions.o obj/SimpleFunctions.o

 

# The object file depends on the source

# The command is to compile the .cxx to .o

obj/AdvancedFunctions.o : advanced/AdvancedFunctions.cxx

    g++ -fPIC -I. -c -o obj/AdvancedFunctions.o advanced/AdvancedFunctions.cxx

 

# The object file depends on the source

# The command is to compile the .cxx to .o

obj/SimpleFunctions.o : simple/SimpleFunctions.cxx

    g++ -fPIC -I. -c -o obj/SimpleFunctions.o simple/SimpleFunctions.cxx

 

# clean target for this sub-directory Makefile

.PHONY : clean

clean :

    rm -fv bin/* obj/

档案: app/Makefile

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# The executable depends on the main.o object file

# Generate the exe if the object file dependencies are up to date

# The exe is put in a sub-directory 'bin' by specifying 'g++ -o' option

bin/app.exe : obj/main.o

    g++ obj/main.o -L../math/bin -o bin/app.exe -lmath

 

# The object file depends on the source

# The command is to compile the .cxx to .o

# The object file is put in sub-directory 'obj' by specifying 'g++ -o' option

obj/main.o : main.cxx

    g++ -I../math -c -o obj/main.o main.cxx

 

# clean target for this sub-directory Makefile

.PHONY : clean

clean :

    rm -fv bin/* obj/

NMAKE

NMake是* nix make实用程序的本机Windows替代品。 语法与* nix makefiles非常相似。 但是,这并不意味着* nix makefile可以在Windows上无缝执行。 有关讨论,请参见Windows中的Makefile 。

结论

与Visual Studio相比,Makefile具有非常强大的功能,并且具有很多控制能力和灵活性,但是其内容不容易理解。 作为替代方案,CMake也采用了类似的概念,但是该脚本更加容易并且更具可读性。 请参阅CMake和Visual Studio 。

初学者详细的Makefile

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐