理解Cmake

PS:仅记录个人学习历程,并非干货,如有错误或者不足,会在日后慢慢改正与添加。        

目录

一.C++程序编译

二、GCC

三、makefile

四、Cmake


一.C++程序编译

        在大学上实验课去机房学习汇编语言的时候,学习过一堆的汇编指令,如何移位,如何操纵存储等等,最终也就是点亮个跑马灯什么的,到现在也都忘完了(因为根本没用到过)。当时学的C++也是基于VC6.0的软件进行学习,也是只知道先点哪个箭头,后点哪个箭头,然后程序运行结果,“叭”,就出来了(记得当时学习的时候挺认真的,就是没有继续深入的学下去,非计算机专业),也就是说当时的学习很不系统,只知其然而不知其所以然。

        以下仅说下自己对其中的理解与看法(理解意思就行哈)。

        比如现在我们需要用计算机计算1+1,那么我们要双击打开计算器软件,在输入框中输入1,+,1,点击确定,然后计算机给我们返回了结果,显示在显示屏的软件中——当然,图像化界面的操作系统是这样。如果不是图像化界面的操作系统呢?那么可能会存在类似于一些的基础指令,如加法:add(1,2),命令行中返回3,就像这样:

>>add(1,2)
>>3

        是的,看起来就是这么简单!

        那么,计算机怎么就知道add(1,2) == 1+2呢,计算机又怎么知道1+2=3呢?add是什么?a是什么?(是什么?

        现在涉及到两个逻辑:1.表达逻辑,2.运算逻辑

        1.表达逻辑

                我们知道ASCLL就行了,类似上述的a,(,都有对应的ASCLL值,他对应着计算机系统的二进制。

        2.运算逻辑

                这个,只需要知道二进制就行了,01+01=10,这些运算过程伴随着电信号峰值的叠加。

        现在,我们会说话了,也会做简单运算了。

        正比如,我们定义"+"号为电信号+0.5,那么,“A+1”在一定意义上等于B(因为他们是按顺序排列,往下查就是B)。

        除了基础的ASCLL,我们在函数中常用的  def add()  也是这个作用,不管具体是怎么实现的,仅理解这个过程。

        现在,计算机知道add(1,3)是在"1"的基础上,加上3倍的单位的电平信号,并将最终电平返回,查表输出,即为4。

        个人理解这和linux中ls,mkdir,windows中cd ,ipconfig等等命令是一样的,只不过每个命令所操纵的内容有所不同,有的属于资源管理,有的属于配置查看,有的属于修改环境等等等等。但有一点,他们都与计算机有着时时刻刻的交互,硬盘、内存、触发、中断等等等等(说到这里,又想起了51单片机,但是51单片机已经是基于C语言了)。

        当然,直接在shell或者cmd中输入 cd,计算机也不是直接能够识别的,我们常配的环境变量就起这个作用,通常我们在配置环境的时候,按照步骤要加入什么环境变量,不然输入对应指令,计算机会提示找不到。

        当我们把环境变量加完,让计算机知道add这个指令,计算机调用add指令,add继续调用计算机硬件信息,直至电流层的操作,完成了1+1=2的过程,返回,反变换显示,那么我们这个过程结束了。

        假设上述都是基于汇编语言完成的,那么这个过程也可以理解为汇编语言->机器->操作->查表>返回->汇编(个人理解),可是汇编语言是枯燥的,那么高级语言就出来了,如C,C++,Python等。

        同样对于C++\Python,计算机会去解析高级语言,并将其指令一级一级翻译并且传递下去。但对于这二者而言,又分为了汇编型,解释型语言。

        对于汇编型语言,是把整个流程编译一遍,没有错误了才能运行,这个过程叫做编译。

        对于解释型语言,是解释一行执行一行,遇到了错误才停止运行,这个过程叫做解释。

        也就是常见的,C++总是编译不成功,原来是一个分号写错了,Python跑着跑着报出了数据类型不正确。

        对于Python,我们有python.exe,对应着不同的版本,不同的环境,直接去逐行解析Python代码。

        对于C++,我们有gcc,也对应着不同的版本,不同的环境,去整体编译C++代码。

        说了这么多,其实也就是一句话:编译是把C++代码和底层硬件的交互逻辑走通(个人理解)。

        若想知道的更多,可以参考开头的一篇文章<参考链接>,这里仅为理解与示意。

二、GCC

        首先,我们知道GCC是个编译器,能完成上述一种的内容。

        以下摘自百度百科:

GCC最基本的用法是∶gcc [options] [filenames]

其中options就是编译器所需要的参数,filenames给出相关的文件名称。

-c,只编译,不链接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。

-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。

-g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。

-O,对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、链接的速度就相应地要慢一些。

-O2,比-O更好的优化编译、链接,当然整个编译、链接过程会更慢。

-Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。C程序中的头文件包含两种情况∶

A)#include <myinc.h>

B)#include “myinc.h”

其中,A类使用尖括号(< >),B类使用双引号(“ ”)。对于A类,预处理程序cpp在系统预设包含文件目录(如/usr/include)中搜寻相应的文件,而B类,预处理程序在目标文件的文件夹内搜索相应文件。

        上述我们常用的就是

                1.g++ test.cpp -o test

                2.g++ -c test.cpp -o test.o

                3.g++ -S test.i -o test.s

        需要注意的是g++ 在AB类的处理过程,与 本文 一 中描述的一段有相近之处,即需要知道指令add的指令目录。

        通常,我们用g++ test.c -o test,即可在当前平台生成可执行程序。(g++会默认链接c++标准库,而gcc不会)

        这个过程,无论是在windows还是Linux操作都是相同的,都只需要一条命令将cpp程序编译成可执行的文件(中间的编译不用我们去考虑)

三、makefile

        说实话,这个东西我不会,听网上说这个makefile不像是人学的东西,所以我也对之望而却步,因为已经有了更好的方法Cmake去做这个事情,所以也不再关注(个人觉得:能用就行呗。。。)

        对于二中所述,我们用g++编译了一个程序,那么如果碰到庞大的项目或者复杂的情况,我们需要一个一个个地去进行g++编译,如果改动了其中的某个环节,可能整体都要重新编译一遍,这个在效率方面使我们不希望看到的。那么makefile就是处理这个事情的,makefile会告诉机器如何去编译这个代码。所以写了Makefile只会编译你做出改动的部分,其他的部分保持原样,而且你也不用再一个个 地去编译,只需在命令行中输入 make  就行了,这就是makefile的作用。

四、Cmake

        虽然Makefile很强大, 但是,不同平台下的makefile编写方法还不太一样,这就导致在移植的时候,可能需要重复性编译,也是个麻烦事。Cmake就是做了这么一件事:在不同的平台下,去生成对应平台的makefile!

        而需要操作的,就是编写CMakeLists.txt!

        也就是,你写CMakeLists.txt,CMakeLists.txt去写makefile,最后你直接去make就行啦!

        也就是说,只要你的源码包里面,写好了CMakeLists.txt,那么在任何平台下,都可以通过cmake进行编译,生成对应的应用程序,并直接运行,想想都很不错。

        那么现在看下CMakeLists.txt是如何起作用的:

        1.在项目的根目录创建CMakeLists.txt

        2.编写CMakeLists.txt

        3.cmake .(注意"."代表了当前文件夹,cmake去这个路径下搜索CMakeLists.txt,并把Makefile输出在当前文件夹,通常会在根目录创建build文件夹,cd 到文件夹,进行cmake ..,注意是..,对上层目录进行cmakelists.txt搜索)

        4.make (make当前文件夹的makefile)

        5.编译完成

        那么该如何编写CMakeLists.txt呢?

        下面举例:

# 声明要求的cmake最低版本
cmake_minimum_required(VERSION 2.8)

# 声明cmake工程
project(hello)

# 添加一个可执行程序
add_executable(hello hello.cpp)

        这三行只有最终的add_executable是等于g++ hello.cpp -o hello,也就是输出最终程序。

        细看之下,其实cmakelists.txt没有那么难,只是声明,声明,生成。

        下面看下更多的cmakelists.txt命令:

        //生成库文件

        - - add_library(common STATIC util.cpp) # 生成静态库(windows:.lib,linux:.a)

        - - add_library(common SHARED util.cpp) # 生成动态库或共享库(windows:.dll,linux:.so)

        - - add_library(demo demo.cpp test.cpp util.cpp) # 制定编译库包含的代码

        // 将当前文件夹下所有的cpp打成包

        aux_source_directory(. SRC_LIST) # 搜索当前目录下的所有.cpp文件
        add_library(demo ${SRC_LIST})

       //指定链接库

        target_link_libraries(demo libface.a) # 链接libface.a
        target_link_libraries(demo libface.so) # 链接libface.so

        //等等

        网上有大量关于如何写cmakelists.txt的,也比较全,这里推荐一个:cmakelists.txt细节

        个人觉得这东西也算是工具,一下子也记不住,只能在平时不断的练习并增加记忆感,实在不行搜起来对着照搬也不是不行,只要知道怎么用就行了。

总的来说,整个过程是为了工作学习中有更好的理解,见识浅薄,请见谅!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值