#include "../include/b.h"
double cal_sqrt(double value) { return sqrt(value); }
main.c主函数,如下所示:
#include "../include/b.h" #include <stdio.h> int main(int argc, char** argv) { double a = 49.0; double b = 0.0;
printf("input a:%f\n",a);
b = cal_sqrt(a);
printf("sqrt result:%f\n",b);
return 0;
}
**b.编写CMakeLists.txt**
接下来编写CMakeLists.txt文件,该文件放在和src,include的同级目录,实际放在哪里都可以,只要里面编写的路径能够正确指向就好了。其语法支持大小写混编,如:
cmake_minimum_required CMAKE_MINIMUM_REQUIRED cmake_MINUMUM_required
CMakeLists.txt文件,如下所示:
1 #1.cmake verson,指定cmake版本 2 cmake_minimum_required(VERSION 3.2) 3 4 #2.project name,指定项目的名称,一般和项目的文件夹名称对应 5 PROJECT(test_sqrt) 6 7 #3.head file path,头文件目录 8 INCLUDE_DIRECTORIES( 9 include 10 ) 11 12 #4.source directory,源文件目录 13 AUX_SOURCE_DIRECTORY(src DIR_SRCS) 14 15 #5.set environment variable,设置环境变量,编译用到的源文件全部都要放到这里,否则编译能够通过,但是执行的时候会出现各种问题,比如"symbol lookup error xxxxx , undefined symbol" 16 SET(TEST_MATH 17 {DIR_SRCS} 18 ) 19 20 #6.add executable file,添加要编译的可执行文件 21 ADD_EXECUTABLE({PROJECT_NAME} {TEST_MATH}) 22 23 #7.add link library,添加可执行文件所需要的库,比如我们用到了libm.so(命名规则:lib+name+.so),就添加该库的名称 24 TARGET_LINK_LIBRARIES({PROJECT_NAME} m)
CMakeLists.txt主要包含以上的7个步骤,为了方便还可以添加很多预定义变量.
文章引用: <https://blog.csdn.net/wzzfeitian/article/details/40963457?utm_source=blogxgwz13>
**更简单版本:**
只一个main2.cpp文件
cmake_minimum_required (VERSION 2.6) project (test) add_executable(test main2.cpp)
从这个更简单的版本可以看出,一个cmake文件至少有这三行组成
常碰到的问题可以参考这里:<https://blog.csdn.net/whahu1989/article/details/82078563>
#### **cmake中一些预定义变量**
cmake中一些预定义变量
PROJECT\_SOURCE\_DIR 工程的根目录
PROJECT\_BINARY\_DIR 运行cmake命令的目录,通常是${PROJECT\_SOURCE\_DIR}/build
CMAKE\_INCLUDE\_PATH 环境变量,非cmake变量
CMAKE\_LIBRARY\_PATH 环境变量
CMAKE\_CURRENT\_SOURCE\_DIR 当前处理的CMakeLists.txt所在的路径
CMAKE\_CURRENT\_BINARY\_DIR target编译目录
使用ADD\_SURDIRECTORY(src bin)可以更改此变量的值
SET(EXECUTABLE\_OUTPUT\_PATH <新路径>)并不会对此变量有影响,只是改变了最终目标文件的存储路径
CMAKE\_CURRENT\_LIST\_FILE 输出调用这个变量的CMakeLists.txt的完整路径
CMAKE\_CURRENT\_LIST\_LINE 输出这个变量所在的行
CMAKE\_MODULE\_PATH 定义自己的cmake模块所在的路径
SET(CMAKE\_MODULE\_PATH ${PROJECT\_SOURCE\_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
EXECUTABLE\_OUTPUT\_PATH 重新定义目标二进制可执行文件的存放位置
LIBRARY\_OUTPUT\_PATH 重新定义目标链接库文件的存放位置
PROJECT\_NAME 返回通过PROJECT指令定义的项目名称
CMAKE\_ALLOW\_LOOSE\_LOOP\_CONSTRUCTS 用来控制IF ELSE语句的书写方式
系统信息
CMAKE\_MAJOR\_VERSION cmake主版本号,如2.8.6中的2
CMAKE\_MINOR\_VERSION cmake次版本号,如2.8.6中的8
CMAKE\_PATCH\_VERSION cmake补丁等级,如2.8.6中的6
CMAKE\_SYSTEM 系统名称,例如Linux-2.6.22
CAMKE\_SYSTEM\_NAME 不包含版本的系统名,如Linux
CMAKE\_SYSTEM\_VERSION 系统版本,如2.6.22
CMAKE\_SYSTEM\_PROCESSOR 处理器名称,如i686
UNIX 在所有的类UNIX平台为TRUE,包括OS X和cygwin
WIN32 在所有的win32平台为TRUE,包括cygwin
开关选项
BUILD\_SHARED\_LIBS 控制默认的库编译方式。如果未进行设置,使用ADD\_LIBRARY时又没有指定库类型,默认编译生成的库都是静态库 (可在t3中稍加修改进行验证)
**CMAKE\_BUILD\_TYPE** 设置模式是Debug还是Release模式
SET(CMAKE_BUILD_TYPE "Debug”) or SET(CMAKE_BUILD_TYPE "Release")
也可以在执行cmake命令式在外部执行:
cmake -DCMAKE_BUILD_TYPE=Release ..
**CMAKE\_C\_FLAGS** 设置C编译选项
**CMAKE\_CXX\_FLAGS** 设置C++编译选项
**编译选项具体说明:**
在CMakeLists.txt中可能会看到这样的命令设置C或者C++的编译选项:
#SET(CMAKE_CXX_FLAGS_DEBUG "{CMAKE_CXX_FLAGS} -std=c++11 -O3 -Wall")
后面跟随的-O3 -Wall的是什么意思?这个参数是[gcc或者g++进行编译时](https://gitee.com/vip204888)设置的参数;
gcc中常用的编译选项有:
-c 只编译并生成目标文件:将汇编代码编译成目标文件,即二进制代码。-c 可以直接把 C/C++ 代码编译成机器代码,注意此时并没有链接生成可执行文件这样的步骤,因此,对于链接中的错误是无法发现的。
-g 生成调试信息。GNU 调试器可利用该信息。
-S 只是编译不汇编,生成汇编代码
-shared 生成共享目标文件。通常用在建立共享库时。
-W 开启所有 gcc 能提供的警告。
-w 不生成任何警告信息。
-Wall 生成所有警告信息。
-O0 -O1 -O2 -O3 [四级优化选项](https://gitee.com/vip204888):
-O0 不进行优化处理: 不做任何优化,这是默认的编译选项
-O 或 -O1 优化生成代码。 优化会消耗少多的编译时间,它主要对代码的分支,常量以及表达式等进行优化
-O2 进一步优化。会尝试更多的寄存器级的优化以及指令级的优化,它会在编译期间占用更多的内存和编译时间
-Os 相对语-O2.5。相当于-O2.5。是使用了所有-O2的优化选项,但又不缩减代码尺寸的方法。
-O3 比 -O2 更进一步优化,包括 inline 函数。在O2的基础上进行更多的优化
#### CMake常用命令
**1)project 命令**
命令语法:project(<projectname> [languageName1 languageName2 … ] )
命令简述:用于指定项目的名称
使用范例:project(Main)
**2)cmake\_minimum\_required命令**
命令语法:cmake\_minimum\_required(VERSION major[.minor[.patch[.tweak]]][FATAL\_ERROR])
命令简述:用于指定需要的 CMake 的最低版本
使用范例:cmake\_minimum\_required(VERSION 2.8)
**3)aux\_source\_directory命令**
命令语法:aux\_source\_directory(<dir> <variable>)
命令简述:用于将 dir 目录下的所有源文件的名字保存在变量 variable 中
使用范例:aux\_source\_directory(. **DIR\_SRCS**),将当前目录下的所有源文件加入到DIR\_SRCS,如果多个源文件,则DIR\_SRCS试一个list。
**4)add\_executable 命令**
命令语法:add\_executable(<name> [WIN32] [MACOSX\_BUNDLE][EXCLUDE\_FROM\_ALL] source1 source2 … sourceN)
命令简述:用于指定从一组源文件 source1 source2 … sourceN 编译出一个可执行文件且命名为 name
使用范例:add\_executable(Main ${**DIR\_SRCS**})
**5)add\_library 命令**
命令语法:add\_library([STATIC | SHARED | MODULE] [EXCLUDE\_FROM\_ALL] source1source2 … sourceN)
命令简述:用于指定从一组源文件 source1 source2 … sourceN 编译出一个库文件且命名为 name
使用范例:add\_library(Lib ${DIR\_SRCS}),和add\_executable相比,这里是成的库,而add\_executable是生成可执行文件。因此,这里的STATIC、SHARED分别表示在生成的是静态库还是动态库。
6)add\_dependencies 命令
命令语法:add\_dependencies(target-name depend-target1 depend-target2 …)
命令简述:用于指定某个目标(可执行文件或者库文件)依赖于其他的目标。这里的目标必须是 add\_executable、add\_library、add\_custom\_target 命令创建的目标
**7)add\_subdirectory 命令**
命令语法:add\_subdirectory(source\_dir [binary\_dir] [EXCLUDE\_FROM\_ALL])
命令简述:用于添加一个需要**进行构建**的子目录,意味着该目录下也有个CMakeLists.txt 文件
使用范例:add\_subdirectory(Lib)
8)**target\_link\_libraries与link\_libraries命令**
两则关系: link\_libraries用在add\_executable之前,target\_link\_libraries用在add\_executable之后; link\_libraries用来链接静态库,target\_link\_libraries用来链接导入库,即按照header file + .lib + .dll方式隐式调用动态库的.lib库
命令语法:target\_link\_libraries(<target> [item1 [item2 […]]][[debug|optimized|general] ] …)
命令简述:用于指定 target 需要链接 item1 item2 …。这里 target 必须已经被创建,链接的 item 可以是已经存在的 target(依赖关系会自动添加)
使用范例:target\_link\_libraries(Main Lib);link\_libraries(/home/myproject/libs)
解释:为Main项目(可以为执行文件,也可以为库)添加依赖库Lib。Lib可以为多个。比如:动态库所在目录为/home/myproject/libs,那么在add\_executable之前使用link\_libraries(/home/myproject/libs)指明动态库位置,在add\_executable之后,只需给出动态链接库的库名字就行。target\_link\_libraries(Main -lcurl)
**9)set 命令**
命令语法:set(<variable> <value> [[CACHE <type><docstring> [FORCE]] | PARENT\_SCOPE])
命令简述:用于设定变量 variable 的值为 value。如果指定了 CACHE 变量将被放入 Cache(缓存)中。
使用范例1:set(ProjectName Main);
使用范例2:set(var a;b;c) <=> set(var a b c) #定义变量var并赋值为a;b;c这样一个string list
**10)unset 命令**
命令语法:unset(<variable> [CACHE])
命令简述:用于移除变量 variable。如果指定了 CACHE 变量将被从 Cache 中移除。
使用范例:unset(VAR CACHE)
**11)message 命令**
命令语法:message([STATUS|WARNING|AUTHOR\_WARNING|FATAL\_ERROR|SEND\_ERROR] “message todisplay”…)
命令简述:用于输出信息,STATUS表示正常提示,WARNING就是警告 提示,FATAL\_ERROR重大错误提示...
使用范例:message(STATUS “Hello World”),STATUS可以不添加。
**12)include\_directories 命令**
命令语法:include\_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
命令简述:用于设定目录,这些设定的目录将被编译器用来查找 include 文件
使用范例:include\_directories(${PROJECT\_SOURCE\_DIR}/lib),添加在工程目录下的lib子文件夹目录
13)find\_path 命令
命令语法:find\_path(<VAR> name1 [path1 path2 …])
命令简述:用于查找包含文件 name1 的路径,如果找到则将路径保存在 VAR 中(此路径为一个绝对路径),如果没有找到则结果为 <VAR>-NOTFOUND。默认的情况下,VAR 会被保存在 Cache 中,这时候我们需要清除 VAR 才可以进行下一次查询(使用 unset 命令)。
使用范例:
find\_path(LUA\_INCLUDE\_PATH lua.h${LUA\_INCLUDE\_FIND\_PATH})
if(NOT LUA\_INCLUDE\_PATH)
message(SEND\_ERROR "Header file lua.h not found")
endif()
14)find\_library 命令
命令语法:find\_library(<VAR> name1 [path1 path2 …])
命令简述:用于查找库文件 name1 的路径,如果找到则将路径保存在 VAR 中(此路径为一个绝对路径),如果没有找到则结果为 <VAR>-NOTFOUND。一个类似的命令 link\_directories 已经不太建议使用了
15)add\_definitions 命令
命令语法:add\_definitions(-DFOO -DBAR …)
命令简述:用于添加编译器命令行标志(选项),通常的情况下我们使用其来添加预处理器定义
使用范例:add\_definitions(-D\_UNICODE -DUNICODE), 使用细节参考[这里](https://gitee.com/vip204888)
16)execute\_process 命令
命令语法:
execute\_process(COMMAND <cmd1>[args1...]]
[COMMAND <cmd2>[args2...] [...]]
[WORKING\_DIRECTORY<directory>]
[TIMEOUT <seconds>]
[RESULT\_VARIABLE<variable>]
[OUTPUT\_VARIABLE<variable>]
[ERROR\_VARIABLE<variable>]
[INPUT\_FILE <file>]
[OUTPUT\_FILE <file>]
[ERROR\_FILE <file>]
[OUTPUT\_QUIET]
[ERROR\_QUIET]
[OUTPUT\_STRIP\_TRAILING\_WHITESPACE]
[ERROR\_STRIP\_TRAILING\_WHITESPACE])
命令简述:用于执行一个或者多个外部命令。每一个命令的标准输出通过管道转为下一个命令的标准输入。WORKING\_DIRECTORY 用于指定外部命令的工作目录,RESULT\_VARIABLE 用于指定一个变量保存外部命令执行的结果,这个结果可能是最后一个执行的外部命令的退出码或者是一个描述错误条件的字符串,OUTPUT\_VARIABLE 或者 ERROR\_VARIABLE 用于指定一个变量保存标准输出或者标准错误,OUTPUT\_QUIET 或者 ERROR\_QUIET 用于忽略标准输出和标准错误。
使用范例:execute\_process(COMMAND ls)
18)file 命令
命令简述:此命令提供了丰富的文件和目录的相关操作(这里仅说一下比较常用的)
使用范例:
# 目录的遍历
# GLOB 用于产生一个文件(目录)路径列表并保存在variable 中
# 文件路径列表中的每个文件的文件名都能匹配globbing expressions(非正则表达式,但是类似)
# 如果指定了 RELATIVE 路径,那么返回的文件路径列表中的路径为相对于 RELATIVE 的路径
# file(GLOB variable [RELATIVE path][globbing expressions]...)
# 获取当前目录下的所有的文件(目录)的路径并保存到 ALL\_FILE\_PATH 变量中


**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**