cmake及相关知识学习

编译的原理过程

源文件、目标文件、可执行文件

编写 C++ 程序中,由程序员编写的语句称为源代码,其保存的文件称为源文件。将源代码转换为机器语言的过程的第一阶段,为预处理器程序读取源代码。预处理程序将搜索以#符号开头的特殊行。这些行包含命令或指令,这些命令使预处理器以某种方式修改或处理源代码。

在下一阶段,编译器逐步通过预处理的源代码,将每个源代码指令转换为适当的机器语言指令。此过程将揭示程序中可能出现的任何语法错误。语法错误包括非法使用关键字、运算符、标点符号和其他语言元素等。如果程序没有语法错误,则编译器会将翻译后的机器语言指令,也就是所谓的目标代码,存储在目标文件中。

虽然目标文件包含机器语言指令,但它并不是一个完整的程序。因为C++把执行常规操作或困难任务的代码封装为库,称为运行时库,编译器在生成目标文件时不会包含运行时库例程中的机器代码。在翻译的最后阶段,一个名为链接器的程序会将目标文件与必需的运行时库例程相结合。完成后会创建一个可执行文件。可执行文件包含机器语言指令或可执行代码,可以在计算机上运行。

makefile

makefile制定整个工程的编译规则,包括文件编译的顺序,功能操作等,因为其中也有操作系统的执行命令。实现了“自动化编译”,写好即可以通过一个make命令,自动编译整个工程。

make是一个命令工具,可以解释makefile,大多数的IDE具有这个命令。

不同平台的make工具遵循着不同的规范和标准,因此对应的makefile的格式也有所不同,因此同一个工程在不同平台就对应不同的makefile。

而CMake可以根据CMakeList.txt文件,在不同平台生成本地化Makefile和工程文件。

GNU

GPL

GDB

IDE和编译器

IDE即集成开发环境,提供一整套开发环境的工具,一般包含:不同语言的编译器和链接器、SDK软件开发包等。

c++编译器是一个与标准化C++高度兼容的编译环境。这点对于编译可移植的代码十分重要。编译器对不同的CPU会进行不同的优化。

c++编译器主要有GCC家族、MS家族、Borland家族。

  • gcc是gnu c的编译器, g++是gnu c++的编译器, 而egcs(Enhanced GNU Compiler Suite)可以认为是gcc的改进版。目前gcc已经改名,从原来代表GNU C Compiler改变为代表GNU Compiler Collection。而MinGW或Cgywin,是在windows平台上的gnu c/c++编译器,以及库文件,运行环境的集合
    在GCC家族中GNU GCC是根本,其它的编译器版本都是从它导出的。其中,Cygwin和Mingw32都是WIN32平台下的编译器,DJGPP是DOS下的32位编译器。大家所熟知的DEV-C++充其量只是GCC的一个外壳,它所自带的编译器就是Mingw32的一个版本。这些GCC的版本中,Cygwin是最大的,它与其说是一个编译器,倒不如说是一套编程工具。它不仅有编译器,还有其它很多的工具。其实,它就是一个UNIX系统在WIN32平台上的实现。实现了大多常用的UNIX工具,最近的版本中连Apache这样的“工具”都集成进来的。不过,Cygwin虽然功能强大,但它却不是很易用(和UNIX相似,熟悉UNIX的人用它可以很快上手),因为太多其它的工具分散了人们的注意力。相比之下Mingw32就要好用得多,它只有最基本的几个编程工具(只可惜它不自带GDB)。GCC中并不只是C/C++编译器,其中还有很多其它的编译器如JAVA,Fortran,ADA等。它是一个编译器集合,不过有些编译器只能在UNIX系统上用。
    Cygwin和Mingw32生成的代码效率都很不错,编译的速度也很快,最值得一提的是它们对C++的特性的支持算是所有编译器中最完全的,而且它们还支持C++的大部分特性。这一点很是不错!
  • MS家族是Visual Studio、Visual Studio.net 2002、Visual Studio.net 2003、Visual Studio.net 2005的后台C++编译器。Visual C++ 7.1对标准C++的兼容性达到98.22%。
  • Borland家族以速度快、空间效率高而著称。它的5.5版本对标准化C++的支持达92.73%,而官方称100%符合ANSI/ISO的C++标准和C99标准。它是Borland公司开发的,是Borland C++ Builder和Borland C++ Builder X这两种IDE的后台编译器。
    Windows平台上,msvc对应的编译器文件为cl.exe,MingW对应g++.exe文件。

动态库及静态库

目标文件

目标文件有三种形式。

  • 可执行目标文件。即我们通常所认识的,可直接运行的二进制文件。
  • 可重定位目标文件。包含了二进制的代码和数据,可以与其他可重定位目标文件合并,并创建一个可执行目标文件。
  • 共享目标文件。它是一种在加载或者运行时进行链接的特殊可重定位目标文件。

CMake基础

目录结构

.
├── build
├── CMakeLists.txt
├── include
│     └── Hello.h
└── src
      ├── Hello.cpp
      └── main.cpp
  • CMakeList.txt文件不区分命令的大小写。

  • 变量使用${}方式取值,但是在IF控制语句中是直接使用变量名。

CMake构建系统步骤

项目文件一般包含

  • 第三方头文件(*.h)
  • 第三方库(*.so)
  • 项目头文件(*.h)
  • 项目源文件(*.cpp)、main.cpp

标准库的文件位置已知,需要提供给cmake其他所有文件的位置。

#cmake版本
cmake_minimum_required(VERSION 3.0.0)
#项目名、项目版本
project(test_ VERSION 0.1.0)
# 使用给定的源文件(包含main.cpp等项目源文件),为工程引入一个可执行文件
add_executable(test_ main.cpp src/a.cpp)
#设置变量表示头文件路径及库文件路径
set(OPENCV_DIR /usr/local/include/opencv4)
set(OPENCV_LIB_DIR /usr/local/lib)
#添加opencv头文件路径及库文件路径
include_directories(${OPENCV_DIR})
link_directories(${OPENCV_LIB_DIR})
#将库文件链接到目标文件
target_link_libraries(
    ${PROJECT_NAME} 
    PUBLIC
    libopencv_core.so
)
#添加项目头文件路径
include_directories(${PROJECT_SOURCE_DIR}/include)
  • 进阶一:
    将源文件生成静态库/动态库,并链接到目标文件。
add_executable(test_ main.cpp)

add_library(a_shared SHARED src/a.cpp)
add_library(a src/a.cpp)

target_link_libraries(
    ${PROJECT_NAME} 
    PUBLIC
    libopencv_core.so
    a
)

生成了静态库及动态库文件
生成了静态库及动态库文件

  • 进阶二
  1. 将源文件批量放入可执行文件中
#将项目路径下src文件夹中所有的.cpp文件放入TEST_SRC变量中
file(GLOB TEST_SRC ${PROJECT_SOURCE_DIR}/src/*.cpp) 
#将TEST_SRC放入可执行文件中
add_executable(test_ main.cpp ${TEST_SRC})
${PROJECT_SOURCE_DIR}

表示包含PROJECT()的最近一个CMakeLists.txt文件所在的文件夹。

file(GLOB variable [RELATIVE path] [globbing expressions]...)

GLOB 会产生一个由所有匹配globbing表达式的文件组成的列表,并将其保存到变量中。Globbing 表达式与正则表达式类似,但更简单。如果指定了RELATIVE 标记,返回的结果将是与指定的路径相对的路径构成的列表。 (通常不推荐使用GLOB命令来从源码树中收集源文件列表。原因是:如果CMakeLists.txt文件没有改变,即便在该源码树中添加或删除文件,产生的构建系统也不会知道何时该要求CMake重新产生构建文件。globbing 表达式包括:

*.cxx - match all files with extension cxx
*.vt? - match all files with extension vta,…,vtz
f[3-5].txt - match files f3.txt,f4.txt, f5.txt

  1. 将源文件批量生成单个库文件
file(GLOB TEST_SRC ${PROJECT_SOURCE_DIR}/src/*.cpp) 

add_executable(test_ main.cpp)
add_library(a_shared SHARED ${TEST_SRC})

target_link_libraries(
    ${PROJECT_NAME} 
    PUBLIC
    libopencv_core.so
    a_shared
)

常用语句:

  1. set指令详解 link
  2. add_definitions(-Dxxx)
    -D表示定义xxx,可以控制源代码。
  3. option
  4. message
  5. install
  6. source_group
  7. aux_source_directory

Bash编译命令

编写CMakeLists.txt后

#用cmake生成makeFile文件
deploy@deploy:~/workspace/zqz/c++/build$ cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/deploy/workspace/zqz/c++/build
#用makeFile生成编译文件及可执行文件
deploy@deploy:~/workspace/zqz/c++/build$ make
Scanning dependencies of target test_
[ 50%] Linking CXX executable test_
[100%] Built target test_
#运行可执行文件
deploy@deploy:~/workspace/zqz/c++/build$ ./test_
Hello, world!

进阶:选择generator(make、ninja),指定c、c++编译器路径(选择版本)

#删除之前的cmake文件、make(ninja文件)、编译文件、可执行文件等
#-G 指定gengerator,这里使用vscode默认的ninja
#-D 指定c、c++编译器路径,注意没有空格
#ninja,生成编译文件及可执行文件
deploy@deploy:~/workspace/zqz/c++/build$ rm -rf * && cmake -G Ninja -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7 .. && ninja
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/gcc-7
-- Check for working C compiler: /usr/bin/gcc-7 -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/g++-7
-- Check for working CXX compiler: /usr/bin/g++-7 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/deploy/workspace/zqz/c++/build
[3/3] Linking CXX executable test_
#运行可执行文件
deploy@deploy:~/workspace/zqz/c++/build$ ./test_
Hello, world!
A_T()
~A_T()
  • 路径前面的为家目录,区别于根目录/。家目录为用户目录。
  • .为当前目录,结尾没有/,因此如果指定子目录(文件)需要组合/使用,即./ ,也可以不使用任何符号开头,即为相对目录,开头添加""则为根目录。..为上级目录。
  • linux(Bash)中的&和&&,|和||:
    1. & 表示任务在后台执行,如要在后台运行redis-server,则有 redis-server &
    2. && 表示前一条命令执行成功时,才执行后一条命令 ,如 echo '1‘ && echo ‘2’
    3. | 表示管道,上一条命令的输出,作为下一条命令参数,如 echo ‘yes’ | wc -l
    4. || 表示上一条命令执行失败后,才执行下一条命令,如 cat nofile || echo “fail”
  • Bash,Unix shell的一种,在1987年由布莱恩·福克斯为了GNU计划而编写。1989年发布第一个正式版本,原先是计划用在GNU操作系统上,但能运行于大多数类Unix系统的操作系统之上,包括Linux与Mac OS X v10.4都将它作为默认shell。
  • Shell,在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(命令解析器)。它类似于DOS下的command.com和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。
    传统意义上的shell指的是命令行式的shell,以后如果不特别注明,shell是指命令行式的shell。
    文字操作系统与外部最主要的接口就叫做shell。shell是操作系统最外面的一层。shell管理你与操作系统之间的交互:等待你输入,向操作系统解释你的输入,并且处理各种各样的操作系统的输出结果。
    shell提供了你与操作系统之间通讯的方式。这种通讯可以以交互方式(从键盘输入,并且可以立即得到响应),或者以shell script(非交互)方式执行。shell script是放在文件中的一串shell和操作系统命令,它们可以被重复使用。本质上,shell script是命令行命令简单的组合到一个文件里面。
    Shell基本上是一个命令解释器,类似于DOS下的command。它接收用户命令(如ls等),然后调用相应的应用程序。较为通用的shell有标准的Bourne shell (sh)和C shell (csh)。
  • DOS,磁盘操作系统(Disk Operating System),是早期个人计算机上的一类操作系统DOS是Diskette Operating system的缩写,意思是磁盘操作系统。
    DOS是1981~1995年的个人电脑上使用的一种主要的操作系统。由于早期的DOS系统是由微软公司为IBM的个人(PC)电脑开发的,故而即称之为PC-DOS,又以其公司命名为MS-DOS,因此后来其他公司开发的与MS-DOS兼容的操作系统,也延用了这种称呼方式,如:DR-DOS、Novell-DOS …,以及国人开发的汉字DOS(CC-DOS)等等。
    MS-DOS发展,从早期1981年不支持硬盘分层目录的DOS1.0,到当时广泛流行的DOS3.3,再到非常成熟支持CD-ROM的DOS6.22,以及后来隐藏到Windows9X下的DOS7.X,前前后后已经经历了20年,至今仍然活跃在PC舞台上,扮演着重要的角色。
    DOS是在直接内存下运行,程序设计员只能在1MB以下的存储器上操作。DOS容许使用的内存空间只有640KB(其他的348KB为ROM BIOS和其他卡所保留),在DOS下无法运行超过640KB的大程序。DOS系统是字符式的操作系统,所有操作都通过键盘输入“命令行”来执行。
    微软公司推出它的Windows操作系统以后,由于Windows操作系统的几乎所有操作都可以通过鼠标的点击来完成,不必再去记忆繁杂的命令,也省去了键盘输入“命令行”的操作。这种对用户友好的操作界面,使得Windows操作系统很快的就占据了PC舞台上主角位置,而把DOS推倒了舞台的边缘。
    但是为了一些特定的需要,Windows操作系统里保留了DOS命令形式,在需要时在系统的内存中拿出640K的内存,开辟出虚拟一个DOS运行的环境(“虚拟机”)来执行DOS命令。这种Windows操作系统里开辟的DOS运行环境,只不过是Windows操作系统里面的许多窗口中的一个窗口而已,它与Windows操作系统出现之前dos独占系统的全部资源的情况已大不相同。
    “纯DOS”就是相对于这种情况而言的:不打开windows系统,只用软盘或其他媒体(如光盘、U盘等)启动机器,进入DOS系统,这时的DOS独享系统的全部资源,这时的环境状态就叫“纯DOS”状态。由于没有打开windows系统,所以与windows有关的一切软件、病毒、木马…,都不能起作用,不能控制你的任何资源
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值