专栏名称: saka
目录
相关文章推荐
51好读  ›  专栏  ›  saka

cmake使用教程(十)-关于file

saka  · 掘金  ·  · 2018-07-06 02:27

正文

阅读 10

cmake使用教程(十)-关于file

【cmake系列使用教程】

cmake使用教程(一)-起步

cmake使用教程(二)-添加库

cmake使用教程(三)-安装、测试、系统自检

cmake使用教程(四)-文件生成器

cmake使用教程(五)-cpack生成安装包

cmake使用教程(六)-蛋疼的语法

cmake使用教程(七)-流程和循环

cmake使用教程(八)-macro和function

cmake使用教程(九)-关于安卓的交叉编译

cmake使用教程(十)-关于file

这个系列的文章翻译自官方cmake教程: cmake tutorial

示例程序地址: github.com/rangaofei/t…

不会仅仅停留在官方教程。本人作为一个安卓开发者,实在是没有linux c程序开发经验,望大佬们海涵。教程是在macos下完成,大部分linux我也测试过,有特殊说明的我会标注出来。本教程基于cmake-3.10.2,同时认为你已经安装好cmake。

简介

cmake中的file使用也很简单,与c语言的文件io相似。file命令属于脚本命令,可以卸载脚本中。后边讲到的 aux_source_directory 属于工程命令,不能用在脚本中。

首先来说一个我在编写程序的时候遇到的问题,在学习apue的过程中,有许多实例小程序,因为IDE用的是Clion,所以需要在cmake脚本中生成执行文件,最开始的时候是简单的添加 add_executable 命令来不断的增加新的程序构建,随着学习的深入,手动添加太麻烦了,于是写了一个简单的脚本来半自动构建程序,目录结构如下:

  apue git:(master) ✗ cd src
➜  src git:(master) ✗ tree
.
├── CmakeLists.txt
├── part1
│   ├── CmakeLists.txt
│   ├── copytest.c
│   ├── groupid.c
│   ├── mycopy.c
│   ├── myerror.c
│   ├── myls.c
│   ├── myshell.c
│   ├── mystdcopy.c
│   ├── newshell.c
│   └── processid.c
├── part11
│   ├── CmakeLists.txt
│   ├── pthread1.c
│   ├── pthread2.c
│   ├── pthread3.c
│   └── pthread4.c
├── part3
│   ├── CmakeLists.txt
│   ├── holetest.c
│   └── seektest.c
├── unp_1
│   ├── CMakeLists.txt
│   ├── daytimetcpcli.c
│   ├── daytimetcpcliv6.c
│   └── daytimetcpsrv.c
└── unp_3
    ├── CMakeLists.txt
    └── byteorder.c

src是apue的源代码目录,包含多个章节对应的文件夹和一个主cmakelist文件,章节文件夹下是具体的c和h文件和一个cmakelist文件,看一下part3章节文件夹中的cmakelist文件:

AUX_SOURCE_DIRECTORY(. PART_THREE)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
FOREACH (FILE ${PART_THREE})
    MESSAGE(STATUS ${FILE})
    STRING(REPLACE "./" "" LIB_NAME ${FILE})
    STRING(REPLACE ".c" "" LIB_NAME ${LIB_NAME})
    add_executable(${LIB_NAME} ${FILE})
    target_link_libraries(${LIB_NAME} apue.a)
ENDFOREACH ()

这段代码首先将当前章节的所有文件收入到PART_THREE变量中,以list形式存储,下边两行代码设置了可执行文件和库文件的存储路径,然后FOREACHE循环中输出了所有的可执行文件和链接库,可执行文件名称是用.c文件用正则替换无用信息后生成的。

然后在主cmakelist中添加 add_subdirectory(part3) 后直接执行即可。这也是今天要讲的主要内容。

文件写入与追加

file(WRITE <filename> <content>...)
file(APPEND <filename> <content>...)

将content的内容写入filename中,假如文件不存在则会创建文件,假如filename中包含路径,则相应的文件夹也会被创建。WRITE会擦出文件内容,重新写入content,APPEND会在文件末尾追加内容。写一个最简单的测试:

file(WRITE test.txt "this is a test to wirte\n")
file(APPEND test/test.txt "this is a test to append")
file(APPEND test.txt "this is a test to append")

此时目录结构如下:

.
└── write.cmake

0 directories, 1 file

执行该脚本后:

➜  Stepfile git:(master) ✗ cmake -P write.cmake
➜  Stepfile git:(master) ✗ tree
.
├── test
│   └── test.txt
├── test.txt
└── write.cmake

1 directory, 3 files

前边介绍过configure_file这个命令,是用来在构建工程时替换文件内容的,注意一下区别。

文件的读取

file(READ <filename> <variable>
     [OFFSET <offset>] [LIMIT <max-in>] [HEX])

这个也比较简单: 将filename文件中的内容读取到variable总,可以指定OFFSET的值,也就是开始读取的位置,指定LISTMI的值,读取的长度,HEX是否以16进制形式读取。

file(STRINGS <filename> <variable> [<options>...])

类似于读取字符码,而不读取字节码。这个命令会将filename中的字符串读取到variable中,并且variable是一个list,每个元素保存每行的内容。二进制文件不会被读取,并且换行符会被忽略。举个例子,我们刚才写入的 test.txt 的文件内容是:

this is a test to wirte
this is a test to append
    have tab #这个是我手动添加的

我们读取这个文件并打印结果,编写 string.cmake 文件如下:

file(STRINGS test.txt strings)
foreach(str IN LISTS strings)
    message(STATUS ${str})
endforeach(str)

因为结果会用list保存,所以用foreach循环来查看结果:

-- this is a test to wirte
-- this is a test to append
-- have tab

关于一些选项,用的不太多:

OPTION 说明
LENGTH_MAXIMUM 读取字符的最大个数
LENGTH_MINIMUM 读取的字符的最少个数
LIMIT_COUNT 提取的不同字符的最大数量
LIMIT_INPUT 限制读取的最大字节
LIMIT_OUTPUT 限制写入变量的最大字节
NEWLINE_CONSUME 不忽略换行符
NO_HEX_CONVERSION 不需要自动转换为16进制
REGEX 提取匹配正则表达式的字符串
ENCODING 重新编码UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE

文件的hash码

file(<HASH> <filename> <variable>)

利用这个命令可以提取出文件的hash码







请到「今天看啥」查看全文


推荐文章
看懂经济  ·  金融安全的底线
7 年前
A963设计网  ·  有一种优雅,来自女设计师
7 年前
妙法佛音  ·  【素食养生】夏季7种养生食材
7 年前