补充知识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