命令⾏编译C++(Linux下、Windows下)
C++ 编译过程
⼀般⽽⾔,对于 C++ 程序编译有以下4个阶段:
预处理(preprocessing)
对源程序中的伪指令(以#开头的指令)和特殊符号进⾏处理。伪指令包括宏定义、条件编译指令、头⽂件包含指令等。
编译(compilation)
将预处理后的⽂件编译⽣成后缀为 .s 的汇编语⾔⽂件,。编译程序所要做的⼯作是通过记法分析和语法分析,在确认所有指令都符合语法规则后,将其翻译成等价的中间代码或汇编代码。
汇编(assembly)
将汇编⽂件汇编⽣成后缀为 .o 的⽬标⽂件(⼆进制)。汇编过程实际上是指把汇编语⾔代码翻译成⽬标机器指令的过程。
链接(linking)
将多个⽬标⽂件和库连接⽣成后缀为 .out 或 .exe 的可执⾏⽂件。链接程序的主要⼯作就是将有关的⽬标⽂件彼此相连接,即将在⼀个⽂件中引⽤的符号现该符号在另外⼀个⽂件中的定义连接起来,使得所有的这些⽬标⽂件成为⼀个能够被操作系统装⼊执⾏的统⼀整体。
链接处理分为两种:
静态链接(static linking)
简单说,指链接器在链接时将库(静态库)的内容拷贝到可执⾏程序中。
动态链接(dynamic linking)
简单说,指程序运⾏时才将库(动态链接库)连接到程序中。
Linux系统
参考《An Introduction to GCC》
使⽤gcc(GNU编译器套件)
gcc 最开始的时候是 GNU C Compiler,就是⼀个 c 编译器。但是后来因为这个项⽬⾥边集成了更多其他不同语⾔的编译器, GCC 就代表 the GNU Compiler Collection,所以表⽰⼀堆编译器的合集。g++ 则是GCC的 c++ 编译器。
现在调⽤ gcc 的时候,已经不是当初那个 c 语⾔编译器了,更确切地说它是⼀个驱动程序,根据代码的后缀名来判断调⽤ c 编译器还是c++ 编译器(g++)。即代码后缀是 .c,则调⽤ c 编译器和 linker 去链接 c 的 library,代码后缀是 .cpp,则调⽤ g++ 编译器,但是这⾥ gcc 不会⾃动和 c++ 库链接。
基本参数
shell 窗⼝中执⾏ gcc –help 列出基本参数:
$ gcc --help
# 省略⼀部分输出
-E Preprocess only; do not compile, assemble or link
-S Compile only; do not assemble or link
-c Compile and assemble, but do not link
-o <file> Place the output into <file>
# 省略⼀部分输出
例
$ cd ~/design-pattern/factory/
$ ls
Factory.cpp Factory.h main.cpp Product.cpp Product.h
编译
如上所述,gcc 不会⾃动和 c++ 库链接,所以这⾥只编译,否则会有⼀堆链接错误
$ gcc *.cpp -c
$ ls # 可以看到编译⽣成 *.o 对象⽂件(⼆进制)
Factory.cpp Factory.o main.o Product.h
Factory.h main.cpp Product.cpp Product.o
链接
上⾯强调 gcc 不会⾃动链接 c++ 库,这⾥我们可以⼿动链接 c++ 库
$ gcc *.o -lstdc++
$ ls
a.out Factory.h main.cpp Product.cpp Product.o
Factory.cpp Factory.o main.o Product.h
$ ./a.out
Concrete Facotry
因 gcc 不会⾃动链接 c++ 库,所以可直接⽤ g++ 链接 .o ⽂件⽣成 .out 可执⾏⽂件
$ g++ *.o
$ ls
a.out Factory.h main.cpp Product.cpp Product.o
Factory.cpp Factory.o main.o Product.h
$ ./a.out
Concrete Facotry
综上,可直接使⽤ g++ 编译链接 c++ 程序⽣成可执⾏⽂件
$ g++ *.cpp
$ ls
a.out Factory.cpp Factory.h main.cpp Product.cpp Product.h
$ ./a.out
Concrete Facotry
include 包含⽂件搜索路径
include 包含⽂件在编译的时候使⽤,GCC 搜索头⽂件路径的顺序:
1. 当前⽬录(#include “” ⽅式会搜索当前⽬录,#include <> ⽅式不会搜索当前⽬录)
2. -I 选项指定的⽬录
3. gcc 环境变量 CPLUS_INCLUDE_PATH 指⽰的⽬录(c 程序使⽤的是 C_INCLUDE_PATH)
4. gcc 的默认⽬录
/usr/local/include
/usr/include
/
usr/lib/x86_64-linux-gnu/5.4.0/include
gcc 的默认⽬录,不是由 $PATH 环境变量指定的,⽽是由 g++ 的配置 prefix 指定。
lib 库⽂件搜索路径
链接的时候使⽤,搜索顺序:
静态库⽂件
1. -L 选项指定的路径
2. gcc 的环境变量 LIBRARY_PATH
3. gcc 的默认⽬录
/lib
/usr/local/lib
/usr/lib
动态库⽂件
1. 编译代码时指定的路径(gcc 的参数 -Wl, -rpath 指定)
2. 环境变量 LD_LIBRARY_PATH 指定的路径(多个路径⽤冒号 : 分隔)
3. 配置⽂件 /etc/f 指定的路径
4. 默认的动态库路径 /lib,/usr/lib
-I(⼤写的i)、 -include、 -L、 -l(⼩写的L)参数说明
-I 扩展 gcc 在编译时对包含⽂件的搜索路径,即不使⽤ -I 参数时,只会在上述默认路径下搜索。
$ cd ~/design-pattern/factory/
$ ls
Factory.cpp Factory.h main.cpp Product.cpp Product.h
$ mv *.h ../
$ gcc -c -I ../ *.cpp
$ ls
Factory.cpp Factory.o main.cpp main.o Product.cpp Product.o
$ gcc
-include 指定包含头⽂件,很少⽤,因为⼀般头⽂件都在源代码中⽤ #include xxx实现了。
-L 扩展 gcc 在链接时对库⽂件的搜索路径,即不使⽤ -L 参数时,只会在上述默认路径下搜索。
$ gcc *.cpp -I ../ -L /usr/lib/gcc/x86_64-linux-gnu/5.4.0 -lstdc++
# or
$ g++ *.cpp -I ../ -L /usr/lib/gcc/x86_64-linux-gnu/5.4.0
$ ./a.out
Concrete Facotry
-l 紧接库名,指定程序要链接的库。
这⾥注意库名与库⽂件名的区别,以⽂件 ./usr/lib/gcc/x86_64-linux-gnu/5/libstdc++.so 为例,libstdc++.so 为库⽂件名,⽽库名则是 stdc++。如
$ gcc *.cpp -I ../ -lstdc++
$ ls
a.out Factory.cpp Factory.o main.cpp main.o Product.cpp Product.o
$ ./a.out
Concrete Facotry
-shared 参数说明
⽤于编译⽣成动态库。
Windows系统
cl.exe 和 分别是 visual studio IDE 中的编译器和链接器。
visual studio和vs code的区别使⽤cl.exe编译器
⽤法
usage: cl [ ] [ /]
基本参数
-I: 指定第⼀个寻头⽂件的⽬录(如果指定多个⽬录,则使⽤多个-I)
-c: 只编译不链接
-EHsc: 指⽰编译器启⽤ C++ 异常处理
例:
Windows下命令中使⽤路径时,注意特殊字符要使⽤转义字符”\”,如下路径中包含\,空格和括号,前⾯均加转义符”\”,或者将路
径⽤引号括起来。
gitbash窗⼝:
$ cl *.cpp -c -EHsc -I C:\\Program\ Files\ \(x86\)\\Microsoft\ Visual\ Studio\ 14.0\\VC\\include -I C:\\Program\ Files\ \(x86\)\\Windows\ Kits\\10\\Include # or
$ cl *.cpp -c -EHsc -I "C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt" -I "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC 使⽤链接器
⽤法
usage: LINK[options][files][@commandfile]
基本参数(以下参数在windows cmd窗⼝中执⾏有效,在bash中不过)
/LIBPATH: 指定要在环境库路径之前搜索的路径
/OUT: 指定输出⽂件名
例:
windows cmd 窗⼝(bash下测试不过):
$ link *.obj /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib" /LIBPATH:"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A 编译器控制的LINK选项
除⾮指定 -c 选项,否则 cl.exe 会⾃动调⽤ 。以下为 cl 中影响链接的常⽤功能(注意当参数有指定输出⽂件时,要带冒号:):/Fo: filename: 指定⽣成的 .obj ⽂件名
/Fe: filename: 传递 /OUT:filename 给 , 指定⽣成的 .exe ⽂件名
环境变量
CL 和 LINK ⽤到的环境变量有:
<
INCLUDE: 指⽰ C/C++ 源⽂件中使⽤ #include 包含的⽂件,如头⽂件等。标准 C/C++ 开发,会使⽤ Visual C++ 的安装路径下 vc\include ⼦⽬录中的包含⽂件, Windows API 开发,会使⽤Platform SDK 的安装路径下 vc\include ⼦⽬录中的包含⽂件。
LIBPATH: 指定⽤于搜索使⽤ #using 引⽤的元数据⽂件的⽬录。
<
LIB: 指定搜索对象、库或其他⽂件的路径。标准 C/C++ 开发,会使⽤ Visual C++ 的安装路径下 vc\lib ⼦⽬录中的包含⽂件,Windows API 开发,会使⽤Platform SDK 的安装路径下 vc\lib ⼦⽬录中的包含⽂件会从如下路径搜索对象⽂件和库⽂件:
当前路径
命令⾏上由 /BASE 指定的路径
使⽤ LIB环境变量中的路径。
TMP: 链接时寻 OMF 或 .res ⽂件时,会从这个路径中寻。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论