说明:(1)转载请注明出处:http://www.cnblogs.com/opangle/p/4298155.html

(2)以下以VS2013为例,并假设VC安装路径为%VC_INSTALL_PATH%(本人的安装目录为D:\Program Files (x86)\Microsoft Visual Studio 12.0)。

一、环境配置

■ 方法一:使用MS提供的Developer Command Prompt快捷方式

“开始” => “Visual Studio 2013” => “Visual Studio Tools” => “Developer Command Prompt for VS2013”。

■  方法二:使用MS提供的vcvarsall.bat脚本

在命令行窗口中进入%VC_INSTALL_PATH%目录,执行“vcvarsall.bat”脚本。

■  方法三:手动配置环境变量

手动配置环境变量,至少要设置一下三个环境变量:

※  PATH:默认情况下cl命令(微软编译器)是不可以使用的,需要将cl.exe文件所在的路径(即%VC_INSTALL_PATH%\bin目录)添加到PATH环境变量中。

※  INCLUDE:默认情况下cl命令不知道从何处查找系统头文件的,该环境变量告诉cl命令从何处查找系统头文件。

※  LIB:与INCLUDE环境变量类似,LIB环境变量用来告诉链接器:从何处查找库文件、目标文件等。

本人试过的最小配置如下:

环境变量

配置说明(多个路径之间用分号分隔)

PATH

将以下路径加入PATH环境变量中:

%VC_INSTALL_PATH%\bin

INCLUDE

将以下路径加入INCLUDE环境变量中:

%VC_INSTALL_PATH%\include

C:\Program Files (x86)\Windows Kits\8.1\include\shared

C:\Program Files (x86)\Windows Kits\8.1\include\um

LIB

将以下路径加入到LIB环境变量中:

%VC_INSTALL_PATH%\lib

C:\Program Files (x86)\Windows Kits\8.1\lib\winv6.3\um\x86

注:最完整的配置方式可以参考“方法一”、“方法二”中的环境变量配置方式。

■  测试环境配置

写一个简单的“Hello World”程序(假设为hello.cpp),在命令行下执行:cl hello.cpp,如果能成功生成hello.exe可执行文件,即说明配置成功!

二、常用的命令行选项

下表列出了一些常用的命令行选项,并同时列出了gcc中相对应的选项,熟悉gcc的朋友可以不用看“说明”应该也能明白各选项的含义和作用。

MSVC

gcc

说明

/E

-E

输出预处理结果

/Dname

/Dname=value

-Dname

-Dname=value

定义一个宏

/Idirecotry

-Idirecotry

指定头文件搜索路径

/c

-c

编译、汇编生成目标文件

/libpath:direcotry

-Ldirecotry

指定库文件搜索路径(MSVC的/libpath属于链接选项,第一个链接选项之前要指定/link选项,用来告诉编译器驱动,后续选项传给链接器使用)

另外,如果觉得每次编译都要使用同样的选项,敲太长的命令实在是一件累人的事,微软同样为大家提供了省事的方式:仍然是设置环境变量。详细说明如下:

※  CL环境变量:其中可以指定多个常用的选项,cl命令会自动将该环境变量的内容加入编译命令。

※  LINK环境变量:链接器会自动将该环境变量中的内容加入到链接命令中。

三、静态库的创建与使用

■  创建静态库

linux下创建静态库(*.a)通常需要借助ar命令,例如:“ar -r mylib.a foo.o bar.o”。微软也提供了类似的命令——lib命令,该命令的详细使用方法可参考其帮助文档“lib /?”,下面仅给出一个简单的示例:

cl /c foo.cpp
cl /c bar.cpp
lib foo.obj bar.obj /out:mylib.lib

注:其中“/out选项”用于指定生成的静态库文件名。

■ 使用静态库

测试目录结构如下:

.
+-- lib
| +-- mylib.lib
| +-- mylib.h
+-- test
+-- test.cpp

测试代码如下:

// mylib.h
extern "C" void foo(); // test.cpp
#include <mylib.h>
int main() {
foo();
return ;
}

在test目录下编译test.cpp文件:

cl /I..\lib test.cpp /link /libpath:..\lib mylib.lib

其中/link选项用于告诉cl命令:后续选项为链接选项,请从..\lib目录查找mylib.lib库文件!

除了使用命令行选项告诉链接器应该链接的库、从何处查找库,还可以使用“#pragma comment”指令。

例1(编译命令cl /I..\lib test.cpp /link /libpath:..\lib):

#include <mylib.h>
#pragma comment(lib, "mylib.lib") // 此处包含库名信息,因此命令行选项中不需指定库名
int main() {
foo();
return ;
}

例2(编译命令cl /I..\lib test.cpp):

#include <mylib.h>
#pragma comment(lib, "..\\lib\\mylib.lib") // 此处包含库名及路径信息,注意转义符用“\\”
int main() {
foo();
return ;
}

四、动态库的创建与使用

与静态库的创建相比,动态库的创建相对复杂。为了更容易理解,这里先介绍一些关于windows动态链接库(DLL)基本概念,然后再介绍动态库的创建和使用方法。

■ 基本概念一:动态库的分类

微软将动态库分为四类:

※ 非MFC动态链接库(Non-MFC DLL)

※ 静态链接MFC的正规DLL(Regular DLLs statically linked to MFC)

※ 动态链接MFC的正规DLL(Regular DLLs dynamically linked to MFC)

※ 扩展DLL(Extension DLLs)

其中只有第一种动态库不需要链接微软的MFC,后三种都需要链接MFC(不管你是否使用MFC),个人感觉微软这样做,似乎有点将自己的产品强加于人的感觉,当然,这纯属本人的个人想法,也许有人真的需要MFC吧。这里需要特别说明的是:下文中所提到的“动态库”,特指上述第一种动态库,而不再赘述成“非MFC动态链接库(Non-MFC DLL)”了。

■ 基本概念二:符号的导出与导入

符号的导出与导入的分两个方向:

※ 从动态库导出符号:生成导出符号表;

※ 向应用程序导入符号:告知链接器——我需要的符号来自某个动态库。

下面首先介绍符号的导出,再介绍符号的导入。

windows下的动态库文件(.dll)与可执行文件(.exe)在文件的组织结构上最大的区别在于:动态库文件中包含一个导出符号表。只有存在于该导出符号表中的符号(名字)才可以被其它程序直接访问,我们可以使用dumpbin命令来查看一个动态库的导出符号表,例如:

dumpbin /exports mylib.dll

在动态库中导出符号有两种方式:

(1) 创建模块定义文件(.def)(Exporting a symbol from DLL by ordinal):

优点:可以减小导出符号表的大小;

缺点:当导出C++函数时,需要使用名字修饰后的符号名。

(2) 使用__declspec(dllexport)关键字(Exporting a symbol from DLL by name)。

优点:不用考虑名字修饰的问题;

缺点:将符号名存储在导出符号表中,当导出内容较多时,会导致符号表变得非常庞大。

■ 创建动态库

示例1:创建模块定义文件来导出函数

// foo.cpp
#include <stdio.h>
extern "C" void foo() { printf("foo()\n"); } // bar.cpp
#include <stdio.h>
extern "C" void bar() { printf("bar()\n"); } // mylib.def
LIBRARY mylib
EXPORTS
foo @
bar @

编译生成动态库:

cl foo.cpp bar.cpp /link /dll /def:mylib.def /out:mylib.dll

示例2:使用__declspec(dllexport)关键字来导出函数

// foo.cpp
__declspec(dllexport) void foo() { printf("foo()\n"); } // bar.cpp
__declspec(dllexport) void __stdcall bar() { printf("foo()\n"); }

编译生成动态库:

cl foo.cpp bar.cpp /link /dll /out:mylib.dll

注:上述两个示例中,无论使用哪种方式来导出符号,最终都会生成以下三个文件:

※  mylib.dll:动态链接库;

※  mylib.lib:导入库,后面“使用动态库”一节中“使用加载时动态链接”的示例中会用到。

※  mylib.exp:暂未知。

■ 使用动态库

示例1:加载时动态链接(Using Load-Time Dynamic Linking)

extern "C" __declspec(dllimport) void foo();
extern "C" void bar(); // __declspec(dllimport)并不是必须的
int main() {
foo();
bar();
return ;
}

编译链接上述代码时需要链接导入库mylib.lib,例如:

cl test.cpp /link /libpath:..\lib mylib.lib

示例2:运行时动态链接(Using Run-Time Dynamic Linking)

#include <windows.h>
typedef void (FunType)(void);
int main() {
FunType* pfoo, *pbar;
HINSTANCE dll = LoadLibrary(TEXT("mylib.dll"));
pfoo = (FunType*)GetProcAddress(dll, "foo");
pbar = (FunType*)GetProcAddress(dll, "bar");
pfoo();
pbar();
FreeLibrary(dll);
return ;
}

编译链接上述代码时需要链接导入库mylib.lib,例如:

cl test.cpp

注:在运行上述两个示例中生成的test.exe可执行文件时,都需要拷贝一份mylib.dll到test目录下,或者将mylib.dll所在的路径加入PATH环境变量中,否则操作系统不知道从何处查找mylib.dll。

五、关于nmake和Makefile

与GNU make类似,VC安装目录下还自带了nmake工具,Makefile的书写形式也与linux下类似。下面给出一个简单的示例(示例文件名为Makefile):

CXX     = cl.exe
LD = link.exe
default: mylib.dll
mylib.dll: foo.obj bar.obj
$(LD) foo.obj bar.obj /dll /out:mylib.dll
foo.obj: foo.cpp
$(CXX) /c foo.cpp
bar.obj: bar.cpp
$(CXX) /c bar.cpp

执行:  nmake,即可编译生成mylib.dll动态库文件。关于nmake的更多说明可参考:“nmake /?”。

六、参考文档

Setting the Path and Environment Variables for Command-Line Builds
    https://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx
    
CL Environment Variables
    https://msdn.microsoft.com/en-us/library/kezkeayy.aspx
    
LINK Environment Variables
    https://msdn.microsoft.com/en-us/library/6y6t9esh.aspx
    
Compiler Options Listed by Category
    https://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
    
Kinds of DLLs
    https://msdn.microsoft.com/en-us/library/9se914de.aspx

Importing and Exporting
    https://msdn.microsoft.com/en-us/library/9h658af8.aspx

Exporting from a DLL
    https://msdn.microsoft.com/en-us/library/z4zxe9k8.aspx
    
Importing into an Application
    https://msdn.microsoft.com/en-us/library/kh1zw7z7.aspx
    
Using Load-Time Dynamic Linking
    https://msdn.microsoft.com/en-us/library/ms686923.aspx
    
Using Run-Time Dynamic Linking
    https://msdn.microsoft.com/en-us/library/ms686944.aspx
    
NMAKE Reference
    https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx

命令行下玩VC的更多相关文章

  1. 转 命令行下玩VC

    说明:(1)转载请注明出处:http://www.cnblogs.com/opangle/p/4298155.html (2)以下以VS2013为例,并假设VC安装路径为%VC_INSTALL_PAT ...

  2. 命令行下的C++程序转换成VC的MFC程序需要注意的问题

    在将命令行下的C++程序转换成MFC窗口程序时一般会提示下面这种错误: fatal error C1010: unexpected end of file while looking for prec ...

  3. VS2015——命令行下编译、静态库动态库制作以及断点调试

    c程序编译流程 程序的基本流程如图: 1. 预处理 预处理相当于根据预处理指令组装新的C/C++程序.经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的 ...

  4. windos命令行下的程序编写

    1.命令行下写程序. 写程序一定要用IDE?不,我还可以用记事本呢.呵呵,写程序一定要用记事本?? ———————————————— 命令行下输入copy con test.txt后回车可在相应目录下 ...

  5. VS2017自带VS2015编译器等在命令行下无法使用问题

    1.起因 早前把VS2015卸了,安装了VS2017.因为VS2017安装的时候可以选择安装VS2015编译套件,也就安装了.使用上一直没有什么问题,所以也没有注意到这个细节. 后来使用cmake生成 ...

  6. 转:开启命令行下的社交-webqq脚本

    最近一直在命令行下工作,除了 Google Chrome,几乎很少接触 GUI 相关的软件.前段时间把手机上的 QQ 给卸载了,希望可以把时间凝聚在更加有价值的位置,今天突然又想起了这个软件,突发奇想 ...

  7. JNI之——在cmd命令行下编译执行C/C++源文件

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46604269 一直用java来敲代码,java配置好jre路径之后.在cmd下编译 ...

  8. Linux系统——28个命令行下的工具

    Unix/Linux下的28个命令行下的工具 下面是Kristóf Kovács收集的28个Unix/Linux下的28个命令行下的工具(原文链接),有一些是大家熟悉的,有一些是非常有用的,有一些是不 ...

  9. 详解Linux命令行下常用svn命令

    1.Linux命令行下将文件checkout到本地目录 svn checkout path(path是服务器上的目录) 例如:svn checkout svn://192.168.1.1/pro/do ...

随机推荐

  1. jQuery自己编写插件()

    引言: 在项目中不同页面经常要用到已经写好的交互,比如弹窗,比如下拉菜单,比如选项卡,比如删除... 此时如果每次都把代码copy一份无疑是一件比较麻烦并且无趣的事情,而且个人认为有些low了,我们可 ...

  2. JavaScript的语法要点 4 - 面向对象的基础

    在传统的面向对象语言如C++.C#.Java中有类.对象.继承等概念.在JavaScript中又如何表示呢?JavaScript中没有class关键字,JavaScript中的类.对象.继承的概念是通 ...

  3. Linux下面对于VIM编辑器的代码折叠使用与screen

    VIM设置代码折叠 1. 折叠方式 可用选项 'foldmethod' 来设定折叠方式:set fdm=*****.有 6 种方法来选定折叠:          manual           手工 ...

  4. sublime 设置localhost 2

    最近sidebar用不了了,提示更新然后就自动卸载了: 研究了下其他方式实现: Sublime Text 2 Sublime Text 3 都可以使用: 菜单 --> Tools --> ...

  5. hibernate的n+1问题

    下面选自<精通Hibernate:Java对象持久化技术详解>作者:孙卫琴 在Session的缓存中存放的是相互关联的对象图.默认情况下,当Hibernate从数据库中加载Customer ...

  6. Spark Streaming揭秘 Day6 关于SparkStreaming Job的一些思考

    Spark Streaming揭秘 Day6 关于SparkStreaming Job的一些思考 Job是SparkStreaming的重要基础,今天让我们深入,进行一些思考. Job是什么? 首先, ...

  7. 浏览器内核-Webkit

    关键字:浏览器内核,浏览器引擎,Browser,Webkit,Blink,Chromium. 本文简单介绍一下各种浏览器内核.着种介绍一下Webkit.顾名思义,浏览器内核就是浏览器的核心部分,也可以 ...

  8. 2016年辛星less教程发布了

    首先简介一下less吧,它是一个css预处理器.当我们的项目比较大的时候,我们的css的代码量也会急剧的膨胀,因此就有很多方案来让编程更加容易,没错,less就是这样一种技术. 在百度网盘的下载地址为 ...

  9. ORA-27102: out of memory并伴随OSD-00031的处理

    刚才客户电话过来说有个数据库起不来了,开发商搞了好久搞不掂,得要让我们去帮忙看看.过去到现场,发现数据库无法打开,连nomount模式都不可以.报错的内容大致如下: ORA-27102: out of ...

  10. 传统ASP.NET开发和MVC的设计思想

    传统ASP.NET开发 第一步:客户端请求服务器: 第二步:服务器从数据库取得数据处理后响应给客户端页面. MVC的设计思想 第一步:客户端请求控制器(里面的一个方法): 第二步:控制器从数据库里取得 ...