利用Visual Studio提供的编译工具进行代码开发

说明

当我们在Windows下开始学习编程的时候,通常会用到Visual Studio这个工具进行代码开发。

通常我们会打开Visual Studio(这里以Visual Studio Community 2015为例,因此Community版本是免费的),然后在下面创建项目,写代码,并进行编译和执行。下面是一个例子(创建项目的过程略):

在上述的界面选择"生成->生成解决方案"进行编译,然后选择"调试->开始执行(不调试)"就可以运行程序,结果如下:

通常到这里之后,我们会觉得在编程的道路上跨出了一大步,但是实际上呢,感觉什么也没有做。

这是因为Visual Studio为我们完成了几乎所有的操作,我们只是写了几行字,点了几个按键而已。

这对编程的学习并不是很有好。

所以通常作为初学者会被告知,要更好地学习编程,可以考虑在Linux下进行,从中我们可以学到预编译,编译,链接等种种操作,从而对软件开发有更深入的了解。

这当然是好的,但是为什么要在Linux下呢?实际上Visual Studio本身也提供了种种的工具,我们可以拿这些工具,自己进行编译相关的种种操作。

本文的目的就是介绍和使用这些工具来进行代码开发。

工具在哪里

首先我们当然需要找到Visual Studio提供的工具在哪里,由于Visual Studio隐藏了种种的细节,并没有给我们看工具在哪里(也有可能是Visual Studio提供的IDE界面太复杂了导致我没有找到),所以需要我们自己在安装目录中查找。

下面是具体的位置(还是以Visual Studio Community 2015为例):

上述的这些exe文件就是Visual Studio提供的编译相关工具。

比如cl.exe就是Visual Studio提供的C/C++编译器:

下面就是介绍如何使用这些工具来进行代码开发。

一个有点复杂和啰嗦的例子

首先我们创建一个目录,在里面存放相关的代码:

先来一个HelloWorld.c:

#include <stdio.h>

int main() {
	printf ("Hello world\n");
	
	return 0;
}

然后我们在当前目录下打开一个CMD窗口,并调用cl.exe文件:

先不管cl.exe的使用方式,这里的首要问题是找不到cl.exe。

当然我们是知道cl.exe在哪里的,前面已经讲过;但是系统并不知道,为了让系统知道,需要将cl.exe对应的路径加入到环境变量中,这个也不难,如下:

之后重新打开一个CMD窗口就可以找到:

之后再执行上述的操作:

结果还是报错了,原因在于我们的代码中包含了一个头文件<stdio.h>,而目前cl.exe并不知道去哪里找这个头文件。

那么这个头文件到底在哪里呢?

这似乎也不是什么难的问题,盲猜还是在Visual Studio安装目录下面,结果猜错了......实际上也跟Visual Studio有关,因为这个Windows Kits也是在安装Visual Studio的时候安装的(所以安装的时候需要注意选项):

不过问题来了,如何在执行cl.exe的时候指定相应的文件呢?

查看cl.exe的帮助(cl.exe /?),我们发现cl.exe下包含中断的参数,而其中恰好有跟头文件相关的内容:

那么就添加这个参数试试吧(注意需要引号将路径引用起来,否则会报错):

可以看到似乎有效,但是还是有问题,就是需要包含额外的头文件,找到这个文件再放到参数中:

看来头文件的问题解决了,但是还是有其它的问题,这个问题就在于printf()函数并没有在我们的代码中实现,所以必须要使用库函数,这需要通过链接来实现,这也是为什么这里打印错误的是LINK这一步。

那么如果链接到LIBCMT.lib这个库呢?

这个时候就需要看link.exe的帮助说明了:

似乎可以直接加上lib库就行:

这个时候发现又少其它lib,继续找,知道找到所有:

终于找到了,并成功生成了exe文件。

这当然太复杂了,下面使用了link.exe的一个参数/LIBPATH:

/LIBPATH指定目录而不是直接指定lib库,这让情况稍微简单了一点,但是还是太麻烦了。

有没有更简单的办法吗?

一种更简单的方法

当我们在安装Visual Studio的时候,会创建如下的一个系统变量(注意还是以Visual Studio Community 2015为例):

通过它我们就能够知道我们的系统安装了某个Visual Studio版本,并得到对应的bin目录:

因为我们的系统是x64的,所以这里指定64位的编译,所以对应到这里的目录是x86_amd64。

在这个目录下可以找到红框内的批处理文件,而执行它就可以直接为我们配置好一般环境,包括PATH,LIBPATH等,这也就不需要我们手动去指定。这里写了一个批处理:

@echo off

:: This is for Visual Stdio 2015.
if defined VS140COMNTOOLS (
   :: Make sure the Visual Stduio is default installed, or the path will be wrong.
   set "COMMONTOOLSx64=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64"
   goto VsFound
)

:: No Visual Studio is intalled on this system.
echo.
echo Visual Studio not found.
echo.
exit /B 1

:VsFound
:: Visual Studio is found, just call the bat in the the directory of %COMMONTOOLSx64%.
if exist "%COMMONTOOLSx64%\vcvarsx86_amd64.bat" (
	@call "%COMMONTOOLSx64%\vcvarsx86_amd64.bat"
	@if errorlevel 1 (
		@echo. ERROR setting Microsoft Visual Studio %1
		@set COMMONTOOLSx64=
		@exit /B 1
	)
)

@echo on

:: Open a prompt where Visual Studio tools can be used.
@cmd

这样只需要点击个脚本,就可以完成需要的配置,并进入到编译的状态,点击上述脚本之后的结果如下:

显然这要比之前的一大堆操作简单很多。

当然这里的实现依赖于一点,即HelloWorld.c中调用的接口是Visual Studio本身就提供的,如果是其它的库,还是需要自己添加库,当然也可以修改上述的脚本来添加库和头文件,这样会更方便一些。

vcvarsx86_amd64.bat做了什么

为什么在执行了vcvarsx86_amd64.bat之后就可以直接使用cl.exe了呢?

原因可以在这个脚本中找到,实际上它就是设置了一堆系统变量,比如PATH,INCLUDE,LIB,LIBPATH等等:

@rem INCLUDE
@rem -------
@if exist "%VCINSTALLDIR%ATLMFC\INCLUDE" set INCLUDE=%VCINSTALLDIR%ATLMFC\INCLUDE;%INCLUDE%
@if exist "%VCINSTALLDIR%INCLUDE" set INCLUDE=%VCINSTALLDIR%INCLUDE;%INCLUDE%

@rem LIB
@rem ---
@if "%1" == "store" goto setstorelib
@if exist "%VCINSTALLDIR%ATLMFC\LIB\amd64" set LIB=%VCINSTALLDIR%ATLMFC\LIB\amd64;%LIB%
@if exist "%VCINSTALLDIR%LIB\amd64" set LIB=%VCINSTALLDIR%LIB\amd64;%LIB%
@goto setlibpath
:setstorelib
@if exist "%VCINSTALLDIR%LIB\store\amd64" set LIB=%VCINSTALLDIR%LIB\store\amd64;%LIB%

:setlibpath
@rem LIBPATH
@rem -------
@if "%1" == "store" goto setstorelibpath
@if exist "%VCINSTALLDIR%ATLMFC\LIB\amd64" set LIBPATH=%VCINSTALLDIR%ATLMFC\LIB\amd64;%LIBPATH%
@if exist "%VCINSTALLDIR%LIB\amd64" set LIBPATH=%VCINSTALLDIR%LIB\amd64;%LIBPATH%
@goto appendlibpath
:setstorelibpath
@if exist "%VCINSTALLDIR%LIB\store\amd64" set LIBPATH=%VCINSTALLDIR%LIB\store\amd64;%VCINSTALLDIR%LIB\store\references;%LIBPATH%
:appendlibpath
@if exist "%FrameworkDir%%Framework40Version%" set LIBPATH=%FrameworkDir%%Framework40Version%;%LIBPATH%
@if exist "%FrameworkDir%%FrameworkVersion%" set LIBPATH=%FrameworkDir%%FrameworkVersion%;%LIBPATH%
@if exist "%FrameworkDir64%%Framework40Version%" set LIBPATH=%FrameworkDir64%%Framework40Version%;%LIBPATH%
@if exist "%FrameworkDir64%%FrameworkVersion64%" set LIBPATH=%FrameworkDir64%%FrameworkVersion64%;%LIBPATH%

这样我们就不需要额外的指定了,编译器和链接器会根据这些环境变量找到需要的头文件和库函数。

一个完整的例子

有了上面的基本只是,我们就可以开始实际的开发了,不过真正的项目开发,一般不会直接通过执行cl.exe之类的来完成,而是使用Makefile文件,然后通过nmake(相当于Linux下的make)来进行编译。同样以HelloWorld.c为例,下面是对应的一个简单的Makefile文件:

all: 
  cl.exe HelloWorld.c

clean:
  @if exist HelloWorld.obj del /f /q HelloWorld.obj
  @if exist HelloWorld.exe del /f /q HelloWorld.exe

之后执行VS_COMPILE.cmd。现在文件的目录结构如下:

然后进入到HelloWorld目录下,执行nmake命令:

编译成功并顺利执行。

以上就是一个较为完整的通过Visual Studio提供的编译工具进行代码开发的例子。

关于Makefile可以在参看Makefile基础Makefile基础——函数

上面的脚本和代码可以在https://gitee.com/jiangwei0512/VisualStudioProject下载到。

发布了197 篇原创文章 · 获赞 193 · 访问量 60万+

猜你喜欢

转载自blog.csdn.net/jiangwei0512/article/details/102908139