XuSenfeng

个人站

复读了,更新随缘,有的文件不全或者图片缺失具体看我的笔记库(https://github.com/XuSenfeng/note)


补充知识2

目录

补充知识2

CMake

注释

注释行

CMake 使用 # 进行行注释,可以放在任何位置。

# 这是一个 CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.0.0)

注释块

CMake 使用 #[[ ]] 形式进行块注释

#[[ 这是一个 CMakeLists.txt 文件。
这是一个 CMakeLists.txt 文件
这是一个 CMakeLists.txt 文件]]
cmake_minimum_required(VERSION 3.0.0)

命令

  • cmake_minimum_required : 所需要的最低的版本, 这个是非必要的
cmake_minimum_required(VERSION 3.0.0)
  • project:定义工程名称,并可指定工程的版本、工程描述、web主页地址、支持的语言(默认情况支持所有语言),如果不需要这些都是可以忽略的,只需要指定出工程名字即可。
# PROJECT 指令的语法是:
project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
       [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
       [DESCRIPTION <project-description-string>]
       [HOMEPAGE_URL <url-string>]
       [LANGUAGES <language-name>...])
  • add_executable:定义工程会生成一个可执行程序
add_executable(可执行程序名 源文件名称)

在指定原文件的时候可以使用空格或者使用;进行间隔

基本使用

cmake_minimum_required(VERSION 3.0.0)
project(jiao)
add_executable(result main.c add.c sub.c)

在想要生成文件的文件夹里面使用命令cmake CMakeList.txt所在的文件夹的路径, 之后会生成Makefile文件, 然后使用命令make就可以生成目标文件

命令2

  • set: 定义变量, 这时候存储的数据都是字符串
# SET 指令的语法是:
# [] 中的参数为可选项, 如不需要可以不写
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

VAR:变量名VALUE:变量值

set(SRC_LIST main.c add.c sub.c)
add_executable(result ${SRC_LIST})
  • 指定c++的标准
#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)
#增加-std=c++14
set(CMAKE_CXX_STANDARD 14)
#增加-std=c++17
set(CMAKE_CXX_STANDARD 17)

直接设置使用的版本

#增加-std=c++11
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=11
#增加-std=c++14
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=14
#增加-std=c++17
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=17

在执行 cmake 命令的时候指定出这个宏的值, 使用-D再加上要改变的变量名字就可以

  • 指定输出的路径也对应一个宏,叫做EXECUTABLE_OUTPUT_PATH,它的值还是通过set命令进行设置
set(HOME /home/robin/Linux/Sort)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)

这个只有最终生成的文件才会放在这里面, 路径不存在的时候会进行创建

  • 搜索指定目录下的文件

使用aux_source_directory 命令可以查找某个路径下的所有源文件

aux_source_directory(< dir > < variable >)

dir:要搜索的目录

variable:将从dir目录下搜索到的源文件列表存储到该变量中

cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
# 搜索 src 目录下的源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
add_executable(app  ${SRC_LIST})

在CMake中为我们提供了搜索文件的命令,他就是file(当然,除了搜索以外通过 file 还可以做其他事情)

message(${CMAKE_CURRENT_BINARY_DIR})
message(${CMAKE_CURRENT_SOURCE_DIR})
jiao@LAPTOP-BJF9EUQH:~/c_language/2023-9-27-cmake/output$ cmake ../src/
/home/jiao/c_language/2023-9-27-cmake/output
/home/jiao/c_language/2023-9-27-cmake/src
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)

GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。

GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。

file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
  • 添加头文件include_directories(头文件所在的路径)

制作库

制作静态库

在linux里面为lib+库名字+.a, Windows为.lib

add_library(库名称 STATIC 源文件1 [源文件2] ...) 

在这里不需要给出生生的库文件的后缀名, 只需要给出库文件的名字就行了

动态库

add_library(库名称 SHARED 源文件1 [源文件2] ...) 

同上面

指定生成的路径

由于在Linux下生成的动态库默认是有执行权限的,所以可以按照生成可执行程序的方式去指定它生成的目录

# 设置动态库生成路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

在Linux下生成的静态库默认不具有可执行权限,所以在指定静态库生成的路径的时候就不能使用EXECUTABLE_OUTPUT_PATH宏了,而应该使用LIBRARY_OUTPUT_PATH,这个宏对应静态库文件和动态库文件都适用。

链接库文件

在cmake中,链接静态库的命令如下:

link_libraries(<static lib> [<static lib>...])

可以是库的名字, 也可以是lib名字.a

如果不是系统提供的库, 需要指定路径, 这个路径不只适用于静态库

link_directories(<lib path>)

: 这两个的连接顺序是先添加库之后增加库的位置

# 链接对应的库文件
link_libraries(calc)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
  • 链接动态库
target_link_libraries(
    <target> 
    <PRIVATE|PUBLIC|INTERFACE> <item>... 
    [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
  • target:指定要加载动态库的文件的名字
    • 该文件可能是一个源文件
    • 该文件可能是一个动态库文件
    • 该文件可能是一个可执行文件
**PRIVATE PUBLIC INTERFACE**:动态库的访问权限,默认为PUBLIC
  • 如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可。
  • 动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。(public状态时候的连接方式)

当有多个动态库的时候, 只需要包含其中一个库, 这个库链接的其他库也会被加入到整个程序中

  • PUBLIC:在public后面的库会被Link到前面的target中,并且里面的符号也会被导出,提供给第三方使用。可以使用你以及你调用的库里面的所有函数
  • PRIVATE:在private后面的库仅被link到前面的target中,并且终结掉,第三方不能感知你调了啥库, 只能调用你本身的函数
  • INTERFACE:在interface后面引入的库不会被链接到前面的target中,只会导出符号。target只知道有一个函数, 但是不知道这个函数的所在的库, 连接的属性是最差的

: 动态库文件的添加一般放在文件的最后, 因为加载动态库与加载应用时间不同, 首先生成文件之后再进行连接

link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
add_executable(app ${SRC_LIST})
target_link_libraries(app calc)

消息

在CMake中可以用用户显示一条消息,该命令的名字为message

message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
  • (无) :重要消息
  • STATUS :非重要消息
  • WARNING:CMake 警告, 会继续执行
  • AUTHOR_WARNING:CMake 警告 (dev), 会继续执行
  • SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤
  • FATAL_ERROR:CMake 错误, 终止所有处理过程

CMake的命令行工具会在stdout上显示STATUS消息,在stderr上显示其他所有消息。CMake的GUI会在它的log区域显示所有消息。

CMake警告和错误消息的文本显示使用的是一种简单的标记语言。文本没有缩进,超过长度的行会回卷,段落之间以新行做为分隔符。

使用内敛汇编实现显示字符串

基本格式

asm(汇编语句
:输出操作数(可选)
:输入操作数(可选)
:被破坏的寄存器(可选)
);
  • 示例
int a = 10, b;
asm("movl %1, %%eax; movl %%eax, %0;"
   :"=r"(b)		/*输出*/
   :"r"(a)		/*输入*/
   :"%eax"		/*破坏的寄存器*/
   )

实现的是b=a的功能

具体格式说明

  • 只有一条汇编语句
asm("hlt")		//CPU进行休眠
  • 多条汇编
asm("sti;hlt");
asm("sti\n\thlt");
asm("sti\n\t"
	"hlt");

多条语句的时候使用\n\t或者使用;进行分割

  • 有输出操作数

有些时候有的数据需要将数据输出到C语言里面的某一些变量里面, 可以使用输出操作数

char c;
asm("mov $3, %[out]":[out]"=r"(c));

%[out]是定义的一个输出约束, 名称和后面的out相同, “=r”(c)制定了c变量映射到某一个寄存器

  • r: 任意寄存器
  • a: %eax, %ax, %al
  • b:
  • c:
  • d:
  • S: %esi, %si
  • D: %edi, %di
  • 有输入操作数

当需要从C语言中读取变量的值到汇编语句中时,则需要使用输入操作数。例如,下面的代码中,mov %[ch], %%al用于将c变量中的字符写到al中。因此,在输入操作数中使用了[ch]”r”(c),即c变量映射到某个寄存器上(见上文中输出操作数的类似设置)。最终的效果为: mov$0xe,%%ah、mov %[c], %%al

char c = 'a';
asm("mov $0xe, %%ah\n\t"
   "mov %[ch], %%al\n\t"
    "int $0x10"::[ch]"r"(c));

在这个时候所有的寄存器前面使用的是%%

避免优化

使用__asm__ __volatile__代替原来的asm