作者:隔壁老吴 | 来源:互联网 | 2023-05-19 11:16
编译器(Compiler)是指将一种语言翻译为另一种语言的工具,对于C++来讲,是将我们写的代码语言转换为二进制语言(EXE或者ELF),从而能够在Windows或者Linux下
编译器(Compiler) 是指将一种语言 翻译为另一种语言的工具,对于C++来讲,是将我们写的代码语言 转换为二进制语言(EXE或者ELF),从而能够在Windows或者Linux下运行。
很多新同学可能对编译器并不敏感,直接用 IDE(VS、Eclipse)编译一下就可以了,没有感觉到编译器的存在,这其实就是一个问题,作者建议对于初学者尽量不要直接就用 IDE,先用 Linux命令,然后 逐渐过渡到 Vim、Emacs、Sublime等,最后才考虑用 IDE。
我们先来看一下 GCC 和 G++ :
sudo apt-get install g++
sudo apt-get install gcc
一般来讲,GCC与G++打包在一起,对于 Ubuntu 14.04 默认安装的是 4.8.4 版本,当然也可以根据自己的需要进行升级。
GCC和G++有什么区别呢?
1. GCC是C程序编译器,将.C的后缀文件按照C语言格式编译,将.CPP文件按照C++语言格式编译;
G++是C++编译器,在编译.C文件时调用GCC,编译.CPP文件时按照C++编译;
错误观点:GCC只能编译C代码,G++只能编译C++代码。
2. 由于GCC无法链接C++库(但可以链接纯C),因此,对于C++链接这个工作就交给了G++;
错误观点:编译用GCC,链接用G++。
3. GCC不会定义__cplusplus宏,而G++会;
看一下Linux下的命令行编译的例子(sh文件build):
#!/bin/bashSRC=`ls *.cpp`LIBS=`ls /usr/local/lib/libopencv*.so`g++ -I./include $SRC -o main $LIBS
list所有的cpp文件,加载lib库(例子对应的是opencv),G++调用编译(-o 生成目标文件 main)。
> GCC Compile
gcc -o hello hello.c -I/home/include -L/home/lib -lworldCORE_LIBS="$CORE_LIBS -L/usr/lib64/mysql -Wl,-Bstatic -lmysqlclient \ -Wl,-Bdynamic -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto"
-static # to find .a
-shared # to find .o (default)
用到的两个选项: -Wl,-Bstatic 和 -Wl,-Bdynamic 告诉链接器,对接下来的-l选项使用静态链接 or 动态链接。
Make与CMake
Make是GNU 针对复杂的编译过程开发的一个调度器,通过MakeFile文件 实现编译选项的控制、用户交互等操作。
CC = g++SRC = `ls *.cpp`TARGET = main $(CC) -I./include $SRC -o $(TARGET)clean: rm main
这是一个简单的 makefile 例子,很容易看懂,在命令行输入make,调用g++进行编译,输入clean,完成清理。
虽然写 makefile 是程序员的必备技能,但是 有时候文件太多、逻辑太复杂,并不能够对Solution进行有效管理,基于这种考虑,CMake诞生了。
CMake 能够生成 makefile,所以我们把它看作是上层工具,目前CMake使用较广的原因作者认为有两点:
1. CMake 对大型工程的管理更为简单,虽然也需要借助 CMakeLists.txt 文件,但维护工作量大大减少;
2. CMake 有比较好的可视化工具,这堪称利器,不解释。
同样来看一个CMake的例子:
#////////////////////////////////////////////#project目录下的CMakeLists.txt#///////////////////////////////////////////CMAKE_MINIMUM_REQUIRED(VERSION 2.8)#工程名PROJECT(CMakeTest)#工程文件中使用相对路径SET(CMAKE_SUPPRESS_REGENERATION 1)SET(CMAKE_USE_RELATIVE_PATHS ON)#支持IF(A) ELSE()的写法SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)#定义工程的顶级路径SET(PROJDIR ${CMAKE_CURRENT_SOURCE_DIR})#定义源文件目录SET(SRCDIR ${PROJDIR}/src)#设置输出路径SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/build)SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/build)#设置安装路径SET(CMAKE_INSTALL_PREFIX ${PROJDIR}/build)#定义头文件安装目录SET(PROJ_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/headers)#根据操作系统不同而设置不同的路径IF(WIN32) SET(GDAL_HDRS "E:/lib/gdal/include")ELSE() SET(GDAL_HDRS "/home/sunsc/gdal/")ENDIF()#设置头文件的引用路径INCLUDE_DIRECTORIES( ${GDAL_HDRS})#设置引用库路径SET(LIBS ${LIBRARY_OUTPUT_PATH})LINK_DIRECTORIES(${LIBS})#宏,实现visio studio的目录分组(过滤器)功能macro(source_group_by_dir source_files) if(MSVC) set(sgbd_cur_dir ${CMAKE_CURRENT_SOURCE_DIR}) foreach(sgbd_file ${${source_files}}) string(REGEX REPLACE ${sgbd_cur_dir}//(.*/) //1 sgbd_fpath ${sgbd_file}) string(REGEX REPLACE "/(.*/)/.*" //1 sgbd_group_name ${sgbd_fpath}) string(COMPARE EQUAL ${sgbd_fpath} ${sgbd_group_name} sgbd_nogroup) string(REPLACE "/" "//" sgbd_group_name ${sgbd_group_name}) if(sgbd_nogroup) set(sgbd_group_name "//") endif(sgbd_nogroup) source_group(${sgbd_group_name} FILES ${sgbd_file}) endforeach(sgbd_file) endif(MSVC)endmacro(source_group_by_dir)#添加子目录ADD_SUBDIRECTORY(src)
除了 Make 和 CMake 之外,很多人也会用到 qmake,这里我们不再继续展开讨论,而对于 VS 对应的编译器,大家可以与 G++ 进行比较,发现其相同与不同之处,这对于编译器的理解很有好处。
当然 如果你有兴趣自己写一个编译器的话,那将是非常有挑战的!