Visual Studio 环境配置

理解动态链接库和静态链接库的区别,lib 文件,dll 文件和头文件的各自作用,Debug 版本 & Release 版本,32 位版本 & 64 位版本,让以后编写任何 C++ 程序都不再迷惘。

链接库

在 Windows 上开发 C++ 程序,需要 头文件链接库,头文件大家都很熟,就是包含函数定义的 .h 文件,链接库就是编译好的代码库,供其它程序使用,分为 动态链接库静态链接库。关于动态链接库和静态链接库的区别,简单来说,就是下面几点

  1. 静态链接库把所有指令都编译到 .lib 文件中。使用时要把 lib 文件和头文件包含到项目中,生成项目时地把静态链接库的所有指令链接到应用程序 exe 中去;因此应用程序会比较大,但不需要其它库的支持,单独一个 exe 文件就能执行;
  2. 动态链接库把所有指令都编译到 .dll 文件中去,另外还会生成一个导入动态库的 lib 文件,这个文件只定义了 dll 文件中哪个指令可以使用,并不包含实际的指令内容,使用时要把 lib 文件和头文件包含到项目中,生成项目时不会把指令链接到 exe 文件中,而是在执行时动态从 dll 文件中加载,因此应用程序会比较小,但必须把 dll 文件放在可执行文件所在目录或程序能找到的系统目录;
  3. lib 文件有两种,一种是静态链接库本身,它包含了所有编译后的指令,文件比较大;另一种是动态链接库的导入库,它只声明了动态库中哪些有哪些导出的指令,不包含实际内容,文件比较小。

关于动态链接库和静态链接库更多的细节,可参考 动态链接库&静态链接库

  • 使用动态链接库:头文件 .h,库文件 .dll,导入库文件 .lib
  • 动态链接库:头文件 .h,库文件 .lib

C++ 配置

附加包含目录

附加包含目录 存放项目需要用到的额外头文件,在代码中包含一个不属于项目本身的头文件时(一般会写 #include <xxx.h>,而包含项目内的头文件则写 #include "xxx.h"),VS 会去 附加包含目录 查找有没有这个头文件,如果找不到则会报语法错误。

VS 默认会有一个 附加包含目录,位于 VS 安装目录下,所有 C++ 项目都会默认包含这个目录,所以如果我们把头文件放这个目录下,则所有的项目都无需再另外配置,这种方式暂且称之为 系统级配置;另外的方式就是为每个程序单独那个目录存放头文件,然后手动把这个目录包含进来,这种方式暂且称之为 程序级配置

系统级配置

这种方式很简单,只需要把头文件放在系统定义的附加包含目录 %VS_ROOT%\VC\include 中去即可,可建子目录存放,然后使用的时候加上子目录即可,比如 #include <gl/glew.h>

程序级配置

随便找个目录存放头文件,但遵循规范一般都是在工程目录下建个 include 目录,然后打开 项目属性页,在 配置属性 –> C/C++ –> 常规 –> 附加包含目录 中添加我们新建的目录即可,可使用绝对路径和相对路径,推荐使用相对路径,方便项目移植。相对路径是相对于项目文件 xxx.vcxproj 的路径,如果 include 目录和项目文件同层级,则使用 .\include,如果在项目文件上一层,比如多个项目使用同一个头文件库,通常会这样放,则使用 ..\include

include

上图中的 %(AdditionalIncludeDiretories) 就是指系统定义的附加包含目录,VS 自动加上的,即使你把它删了也没关系,VS 还是会找到 %VS_ROOT%\VC\include 这个目录。

附加库目录

库文件在链接的时候使用,如果使用的是静态链接库,则是库文件本身,如果是动态链接库,则是导入库文件,即无论使用哪种库,需要包含的都是 .lib 文件。这些 .lib 文件统一放在 附加库目录 下,和头文件一样,VS 在安装目录下有一个系统的 附加库目录,所有 C++ 项目都会包含这个库目录。

系统级配置

和头文件不同,库文件有 32 位和 64 位之分,如果是 32 位库文件则放在 %VS_ROOT%\VC\lib 目录下,如果是 64 位库文件则放在 %VS_ROOT\VC\lib\amd64 目录下。

程序级配置

同样找个目录存放库文件,一般在工程目录下建个 lib 目录,然后打开 项目属性页,在 配置属性 –> 链接器 –> 常规 –> 附加库目录 添加新建的目录即可。

lib-include

附加依赖项

库文件和头文件不同,头文件只要放在 附加包含目录 下即可,而库文件不仅要放在 附加库目录 下,还要告诉 VS 这个库需要链接到程序中去,VS 不会把 附加库目录 下所有的库都链接到程序中去,而是指明要链接的库才会进行链接,这些要链接的库称为 附加依赖项。VS 同样会指明一些默认的附加依赖项,这些库是 Windows 程序必须包含的库,比如 kernel32.lib, user32.lib, gdi32.lib 等等。这些库 VS 默认会进行链接,但如果是我们自己添加的库,即使放在系统的 附加库目录,VS 也不会自动链接,而是需要手动添加到 附加依赖项,所以附加依赖项没有系统配置和程序级配置之分。打开 项目属性页,在 配置属性 –> 链接库 –> 输入 –> 附加依赖项 中填入要链接的库文件名即可。

lib

%(AdditionalLibraryDirectories) 为系统 包含库目录%(AdditionalDependencies) 为系统 附加依赖项,都是 VS 默认配置的。

动态链接库

如果使用的是静态链接库,则不需要这一步,因为所有库代码都被链接到可执行程序 .exe 中去了,单个文件即可执行。反之则需要把动态链接库 .dll 文件放在可执行文件能自动找到的目录下,系统目录或可执行文件所在目录。系统目录在 32 位系统和 64 位系统上有所不同,

  • 如果是 32 位操作系统,系统目录只有 C:\\Windows\\System32 这个目录,32 位系统可以运行 32 位和 16 位程序,不能运行 64 位程序,但只有 System32 这一个系统目录,Windows 是如何兼容这两种程序的,我们就不深入研究了,毕竟 16 位程序已经很少见了,32 位系统也将逐步淘汰。

  • 如果是 64 位操作系统,32 位程序放在 C:\\Windows\\SysWOW64 目录下,而 64 位程序正常放在 System32 目录下。可能你会奇怪为什么是反过来的,这是为了兼容性,因为以前在 32 位系统开发的程序,引用的都是 System32 目录下的库,为了保持习惯,不管是新开发的 64 位程序还是由 32 位程序升级而来的 64 位程序,仍旧引用 System32 目录下的库,另外把 32 位程序升级到 64 位程序,也不用作任何代码修改。至于在 64 位系统运行的 32 位程序,只能屈尊引用 SysWOW64 目录下的库了,SysWOW64 的全称是 32bit Windows on 64bit Windows(Windows on Windows64),即 64 位系统上的 32 位系统,由此可见其是专门为 32 位程序准备的,而不是为 64 位准备的。

配置平台

VS 生成的程序分为 Debug 版本和 Release 版本,平台有 Win32, x64, ARM 三种。ARM 是指使用 ARM 架构的平台,Windows 平台使用的是 X86 架构,一般我们不会涉及到 ARM,所以先不管它。Win32 和 x64 则是 32 位和 64 位的区别,如果发布到 Win32 平台,则必须使用 32 位的库,反之必须使用 64 位的库。根据版本不同和平台不同,有 4 种组合的配置项,

  • Win32-Debug
  • Win32-Release
  • x64-Debug
  • x64-Release

项目属性页 的顶部,可选择配置版本和平台,之后我们编辑的所有配置都只对当前选中的版本和平台生效,点击 配置管理器 可打开配置管理器,查看所有配置项或者新建配置项。

配置版本和平台

生成项目的时候也需要选择对应的发布版本和发布平台,比如 DebugWin32,则本次生成会使用 Win32-Debug 配置项的配置。

选择版本和平台

当前选中的版本和平台会在属性页显示 活动,如果想一次配置对所有版本和平台都生效,在属性页选择 所有配置所有平台 即可。

全部配置

属性管理器

VS 有一个属性管理器的窗口,方便我们对属性表进行管理,默认属性管理器窗口是没有打开的,通过”视图“或”视图-其它窗口“可以找到它。

打开属性管理器窗口,可以看到每个项目下面都有 4 个目录,分别是 Debug | Win32Debug | x64Release | Win32Release | x64。右键目录可以添加新的属性表或添加现有的属性表,右键属性表可以添加子属性表及保存属性表。新添加的属性表保存在项目文件夹下,命名为 ***.props,可以把属性表拷贝一份放在一个公共的地方,然后其它项目通过添加”现有属性表“来引用它,这样对于一些复杂的属性配置就可以复用,而不用每新建一个项目都要配置一次。