一 camake第一列,C编译为so库
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
对应的CmakeList文件
cmake_minimum_required(VERSION 3.27)
project(test C)
set(CMAKE_C_STANDARD 11)
add_executable(test main.c)
二 Cmake介绍
2.1?CMake 是一个跨平台的项目构建工具,CMake可以生成各种构建系统的配置文件,包括Makefile、Visual Studio项目文件、Xcode项目文件等,可以帮助开发人员简化项目的构建过程,提高开发效率
2.2?CMake执行流程图
2.3 Cmake最简单且必须的3个文件,如开头那个CmakeLists.txt
- 指定使用的 cmake 的最低版本
- 可选,非必须,如果不加可能会有警告
cmake_minimum_required(VERSION 3.0)
- 定义工程名称,并可指定工程的版本、工程描述、web主页地址、支持的语言(默认情况支持所有语言)
- 如果不需要这些都是可以忽略的,只需要指定出工程名字即可
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(可执行程序名 源文件名称)
- 源文件名可以是一个也可以是多个,如有多个可用空格或
;
间隔
# 方式1
add_executable(app add.c div.c main.c mult.c sub.c)
# 方式2
add_executable(app add.c;div.c;main.c;mult.c;sub.c)
三 执行Cmake命令编译C/C++文件
3.1 安装Cmake,最新版
sudo apt install cmake
安装失败错误解决:
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
解决:需要更新apt
$ apt-get update
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
解决:无权限,切换root用户
$ su root
Password:
su: Authentication failure
解决:设置root密码
$ sudo passwd root
New password:
Retype new password:
passwd: password updated successfully
再次安装Cmake
# sudo apt install cmake
Reading package lists... Done
3.2 创建项目文件夹,里面包含C文件和CMakeLists.txt?
cmaketest
├── test1.c
├── test2.c
├── main.c
├── CMakeLists.txt
test.h
#ifndef HEAD_H
#define HEAD_H
int add(int a ,int b);
int sub(int a ,int b);
int mult(int a ,int b);
int div(int a ,int b);
#endif
test1.c
#include "test.h"
int add(int a ,int b){
return a+b;
}
int sub(int a ,int b){
return a-b;
}
test2.c
#include "test.h"
int mult(int a ,int b){
return a*b;
}
int div(int a ,int b){
return a/b;
}
mian.c
#include <stdio.h>
#include "test.h"
int main(){
int a=20;
int b=10;
int value1 = add(a,b);
int value2 = sub(a,b);
int value3 = mult(a,b);
int value4 = div(a,b);
printf("a , b is%d,%d\n", a, b);
printf("a + b = %d\n", value1);
printf("a - b = %d\n", value2);
printf("a * b = %d\n", value3);
printf("a / b = %d\n", value4);
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
add_executable(app test1.c test2.c main.c)
3.3 进入项目目录,执行cmake命令,cmaketest
# cd /mnt/d/VSProject/cmaketest
执行cmake,注意要加.,表示当前目录
# cmake .
可能会报错
root@LAPTOP-G67LH5N6:/mnt/d/VSProject/cmaketest# cmake .
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is unknown
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
CMake Error at CMakeLists.txt:2 (project):
? No CMAKE_CXX_COMPILER could be found.? Tell CMake where to find the compiler by setting either the environment
? variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
? to the compiler, or to the compiler name if it is in the PATH.
需要安装C++编译器:
sudo apt-get install build-essential
再次执行cmake命令,可以看到这次成功了
root@LAPTOP-G67LH5N6:/mnt/d/VSProject/cmaketest# cmake .
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/VSProject/cmaketest?
此时项目目录会增加一些makefile相关文件
maketest
├── CMakeCache.txt? ? ? ? ? ?# new add file
├── CMakeFiles? ? ? ? ? ? ? ? ? # new add dir
├── cmake_install.cmake ? ?# new add file
├── CMakeLists.txt
├── Makefile? ? ? ? ? ? ? ? ? ? ? ? # new add file
├── test1.c├── test2.c
└── main.c
?3.4 执行make命令?
# make
?编译成功会出现以下信息:
# make
[ 25%] Building C object CMakeFiles/app.dir/test1.c.o
[ 50%] Building C object CMakeFiles/app.dir/test2.c.o
[ 75%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
[100%] Built target app
此时的文件目录
cmaketest
├── app? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 生成的可执行程序
├── CMakeCache.txt? ? ? ? ?# CMake缓存
├── CMakeFiles? ? ? ? ? ? ? ? ?# app.dir里面是生成的so库
├── cmake_install.cmake
├── CMakeLists.txt
├── main.c
├── Makefile
├── test.h
├── test1.c
└── test2.c
3.5 注意,必须写入口文件,mian方法入口 ,否则可能出现以下错误
# make
[ 25%] Building C object CMakeFiles/app.dir/test1.c.o
[ 50%] Building C object CMakeFiles/app.dir/test2.c.o
[ 75%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/app.dir/build.make:129: app] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/app.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
3.6 注意,mian.c里面最好引用头部文件,可以避免被多次包含
#ifndef HEAD_H
#define HEAD_H
……(头文件内容)
#endif
否则可能在编译的时候出现以下错误,意思出现多次方法加载,重复加载
# make
[ 25%] Building C object CMakeFiles/app.dir/test1.c.o
[ 50%] Building C object CMakeFiles/app.dir/test2.c.o
[ 75%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `add':
main.c:(.text+0x0): multiple definition of `add'; CMakeFiles/app.dir/test1.c.o:test1.c:(.text+0x0): first defined here
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `sub':
main.c:(.text+0x18): multiple definition of `sub'; CMakeFiles/app.dir/test1.c.o:test1.c:(.text+0x18): first defined here
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `mult':
main.c:(.text+0x2e): multiple definition of `mult'; CMakeFiles/app.dir/test2.c.o:test2.c:(.text+0x0): first defined here
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `div':
main.c:(.text+0x45): multiple definition of `div'; CMakeFiles/app.dir/test2.c.o:test2.c:(.text+0x17): first defined here
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/app.dir/build.make:129: app] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/app.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
3.7 上面都在同一个文件夹,看着乱,我们可以新建一个文件夹,来放编译生成的目录。
cmake 用两个..,来切换到源码目录编译
# mkdir build
# cd build
# cmake ..
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/VSProject/cmaketest/build
这时我们的目录就简洁了很多
cmaketest
├── CMakeLists.txt
├── main.c
├── test.h
├── test1.c
├── test2.c
├── build? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # cmake,make后生成的文件夹
├──├── app? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 生成的可执行程序
├──├── CMakeCache.txt? ? ? ? ?# CMake缓存
├──├── CMakeFiles? ? ? ? ? ? ? ? ?# app.dir里面是生成的so库
├──├── cmake_install.cmake
├── ├──Makefile
四 Cmake配置参数
4.1 定义变量:SET指令
# NAME :变量名
# VALUE:变量值
SET(NAME VALUE)
?这样我们就可以把上面的那些源文件放在一个SRC_LIST变量中
# 各个源文件之间使用空格间隔,有可用分号隔开
# SRC_LIST 是源文件存储的变量名
set(SRC_LIST test1.c test2.c main.c)
add_executable(app ${SRC_LIST})
4.2? 其它常用变量
指定C++标准,如通过C++标准对应的宏DCMAKE_CXX_STANDARD,指定C++标准为C++11
shell语法
$ g++ *.cpp -std=c++11 -o app
cmake语法
set(CMAKE_CXX_STANDARD 11)
指定输出路径,宏?EXECUTABLE_OUTPUT_PATH
# 定义一个变量用于存储一个绝对路径
# 从根目录开始完整路径-可执行程序目录
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
#?将拼接好的路径值设置给宏
set(EXECUTABLE_OUTPUT_PATH ${MYPATH}/bin)
搜索文件:aux_source_directory命令
# 上面只是简单配置,生成可执行程序。但只适用于文件少的情况,文件上百个就不合适了,所以需要通过搜# 索文件配置来简化和提高执行效率。
# dir:要搜索的目录
# variable:将从dir目录下搜索到的源文件列表存储到该变量中
aux_source_directory(dir variable)
# 示例:
# 设置源文件路径变量SOURCE_DIR
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 搜索 src 目录下的源文件
aux_source_directory(${SOURCE_DIR}/src SRC_LIST)
# 添加程序编译
add_executable(app ${SRC_LIST})
?搜索文件:file命令
#?GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。
#?GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中
# name:变量名
# path:源文件路径
file(GLOB/GLOB_RECURSE name path);
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmakeList)
file(GLOB MAIN_SRC ${SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${SOURCE_DIR}/include/*.h)
包含头文件:include_directories命令
#?path头文件目录
include_directories(path)
#?示例
set(SOURCE_DIR /mnt/d/VSProject/cmakeList)
include_directories(${SOURCE_DIR}/include)
4.3上面提到的set用法完整示例
# 最小cmake版本
cmake_minimum_required(VERSION 3.0)
# 项目名字
project(cmaketest)
# C++标准
set(CMAKE_CXX_STANDARD 11)
# 定义输出路径
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
# 输出路径
set(EXECUTABLE_OUTPUT_PATH ${MYPATH}/bin/)
# 设置源文件路径变量
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 搜索头文件目录
include_directories(${SOURCE_DIR}/include)
# 搜索源文件目录
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# 添加执行目录
add_executable(app ${SRC_LIST})
执行命令,则会生成上面目录的文件
# mkdir build
# cd build
# cmake ..?# make
文件目录
cmaketest
├── build
├── CMakeLists.txt
├── include
│???└── test.h
└── src
? ? ├── test1.c
? ? ├── test2.
? ? └── main.cpp?
五?编译静态,动态库
5.1 前面操作都是生成的可执行程序,把可执行程序进行安装打包,可以生成Linux的安装包程序。但如果我们想要生成三方库供其它平台使用,就要编译成静态(.a),或者动态(.so)库文件
5.2 生成三方库只需要在上面CMakeLists.txt基础上增加下面指令就可以:
把?add_executable (执行程序命令)换为 add_library(库命令)
#?库名称,自定义就可以,如mylib
#?库类型,STATIC(静态)/ SHARED?(动态)
#?源文件,一个或多个,
add_library(库名称? 库类型? 源文件1 [源文件2] ...)?
# 示例
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST "${SOURCE_DIR}/src/*.c")
add_library(calc STATIC ${SRC_LIST})
5.3 输出目录要注意下,根上面不同
EXECUTABLE_OUTPUT_PATH 宏 ,用于静态目录
# 只能用于动态so库
set(EXECUTABLE_OUTPUT_PATH ${SOURCE_DIR}/lib)
LIBRARY_OUTPUT_PATH?宏 ,用于动/静态目录
# 适用于动态库/静态库路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
示例:
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 输出目录
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
set(LIBRARY_OUTPUT_PATH ${MYPATH}/lib)
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 包含头文件
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# add_executable(app ${SRC_LIST})
# add_library(app STATIC ${SRC_LIST})
add_library(calc SHARED ${SRC_LIST})
执行
# mkdir build
# cd build
# cmake ..?# make
这样就会在outpath/lib 目录下生成libcalc.a文件,动态的话就是libcalc.o文件
$ make
[ 25%] Building C object CMakeFiles/app.dir/src/main.c.o
[ 50%] Building C object CMakeFiles/app.dir/src/test1.c.o
[ 75%] Building C object CMakeFiles/app.dir/src/test2.c.o
[100%] Linking C static library ../outpath/lib/libcalc.a
[100%] Built target calc
5.4 静态库,动态库的区别和优缺点
静态库
优点:
- 静态库被打包到应用程序中加载速度快
- 发布程序无需提供静态库,移植方便
缺点
- 相同的库文件数据可能在内存中被加载多份, 消耗系统资源,浪费内存
- 库文件更新需要重新编译项目文件, 生成新的可执行程序, 浪费时间。
?动态库
优点:
- 可实现不同进程间的资源共享
- 动态库升级简单, 只需要替换库文件, 无需重新编译应用程序
- 可以自由控制何时加载动态库, 不调用库函数动态库不会被加载
缺点:
- 加载速度比静态库慢,但随着计算机性能的提升可以忽略
- 发布程序需要提供依赖的动态库
六 链接库文件
6.1 上面已经生成了库文件,那怎样用这个库呢?这时候就需要用链接指令来加载需要的库。当然链接的库可以是自己的库,也可以是其它三方提供的库。
6.2 链接静态库?link_libraries 指令
# 参数是多个静态库的名字
#?可以是全名 libxxx.a
#?也可以是掐头去掉lib后的名字,xxx.a
link_libraries(<static lib> <static lib>...)
我们把源码删掉,保留头文件,库文件和CMakeLists.txt,测试入口main.cpp也可以保留
cmaketest
├── build
├── CMakeLists.txt
├── include
│? ? ?└── head.h
├── outpath
│? ? ?└──?lib
│?? ? ? ??? ?└── libcalc.a ? ? #静态库的名字
└── src
? ? ? ?└── main.cpp
?CMakeLists修改如下:
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 输出库文件目录
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
# set(LIBRARY_OUTPUT_PATH ${MYPATH}/lib)
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 包含头文件
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# 包含静态库路径
link_directories(${MYPATH}/lib)
# 链接静态库
link_libraries(calc)
add_executable(apptest ?${SRC_LIST})
# add_library(app STATIC ${SRC_LIST})
# add_library(app SHARED ${SRC_LIST})
执行后可以看到生成执行程序apptest成功
$ make
[ 50%] Building C object CMakeFiles/apptest.dir/src/main.c.o
[100%] Linking C executable apptest
[100%] Built target apptest
6.3 链接动态库?target_link_libraries 指令,也可以链接静态库
# target:指定要加载动态库的文件的名字(源文件/动态库文件/可执行文件)
# PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为PUBLIC
# 如果各个动态库之间没有依赖关系,用哪个权限都可以
# 动态库的链接具有传递性,也可以说继承性。
# PUBLIC:库会暴露出去,三方可以看到全部库
# PRIVATE:库仅被link到前面的target中,第三方不能感知你调了啥库
# INTERFACE:库不会被链接到前面的target中,只会导出符号
target_link_libraries(
? ? libname
? ? <PRIVATE|PUBLIC|INTERFACE> ...?)
同样保留动态库so目录如下:
cmaketest
├── build
├── CMakeLists.txt
├── include
│? ? ?└── head.h
├── outpath
│? ? ?└──?lib
│?? ? ? ??? ?└── libcalc.so? ? ?# 动态库的名字
└── src
? ? ? ?└── main.cpp
?CMakeLists修改:?注意程序启动后再去链接动态库
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 输出库文件目录
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
# set(LIBRARY_OUTPUT_PATH ${MYPATH}/lib)
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 包含头文件
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# 包含静态库路径
# link_directories(${MYPATH}/lib)
# 链接静态库
# link_libraries(calc)
# 启动程序
add_executable(apptest ${SRC_LIST})
# add_library(app STATIC ${SRC_LIST})
# add_library(app SHARED ${SRC_LIST})
# 程序启动后链接动态库
target_link_libraries(apptest calc)
执行make命令,生成可执行程序
$ make
[ 50%] Building C object CMakeFiles/apptest.dir/src/main.c.o
[100%] Linking C executable apptest
[100%] Built target apptest
6.4 测试静态和动态库是否可用
这时候在build目录下已经生成了一个可执行程序apptest,我们怎样运行这个程序呢
第一步需要给apptest 赋予修改文件的权限
build$ chmod +x apptest
第二步执行" ./ ",来运行该程序 ,,可以看到程序能够正常打印
build$ ./apptest
a , b is20,10
a + b = 30
a - b = 10
a * b = 200
a / b = 2
七 日志 message 命令
7.1 日志用来显示消息
#?type 日志类型:
#?空:重要消息
#?STATUS :非重要消息
#?WARNING:CMake 警告, 会继续执行
#?AUTHOR_WARNING:CMake 警告 (dev), 会继续执行
#?SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤
#?FATAL_ERROR:CMake 错误, 终止所有处理过程
# message文本消息
message(type message...)
示例:
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 输出一般日志信息
message(STATUS "STATUS Message")
# 输出警告信息
message(WARNING "WARNING Message")
# 输出错误信息
message(FATAL_ERROR "FATAL_ERROR Message")
执行cmake指令,生成如下日志
八 List 集合指令操作
8.1 Cmake用法不止上面作用,当然也支持多级嵌套,也支持条件表达式和循环表达式。这里不再细讲,下面说下字符串拼接和List操作相关用法。
8.2 链接字符串
set命令拼接字符串
# 将字符串拼接后赋值给RESULT
set(RESULT ${STRING_1} ${STRING_2} ${STRING_3})
list APPEND 追加字符串
list(APPEND RESULT ${STRING_1} ${STRING_2} ${STRING_3})
8.3?list? REMOVE_ITEM?字符串移除
list(REMOVE_ITEM RESULT ${STRING_1}/main.cpp)
8.4 list??LENGTH 获取长度
list(LENGTH ${STRING_1} RESULT )?
8.5 list用法非常多就不一一演示了,下面常用指令
- INSERT? ? ? ? ? ? ? ? ? 增
- REMOVE_ITEM? ? ?删
- JOIN? ? ? ? ? ? ? ? ? ? ? ?改
- FIND? ? ? ? ? ? ? ? ? ? ? 查
- REVERSE? ? ? ? ? ? ?翻转
- SORT? ? ? ? ? ? ? ? ? ? 排序
- POP_BACK? ? ? ? ? 移除末尾元素
- POP_FRONT? ? ? ? 移除开头元素
九 宏定义
9.1 自定义宏:add_definitions(-D宏名称)
cmake_minimum_required(VERSION 3.0)
project(cmaketeat3)
# 自定义 DEBUG 宏
add_definitions(-DDEBUG)
add_executable(app main.c)
main.c文件,?如果定义了DEBUG宏,则会打印出debug消息...
#include <stdio.h>
int main()
{
int a = 10;
#ifdef DEBUG
printf("debug消息...\n");
#endif
printf("hello,word\n");
return 0;
}
cmake ->?make生成可执行程序app
cmaketest3$ cmake .
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/VSProject/cmaketest3
$ make
[ 50%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
[100%] Built target app
执行app程序
./app
可以看到走到了定义debug消息的地方
$ ./app
debug消息...
hello,word?
对应C++编译方式为
cmaketest3$ gcc main.c -DDEBUG -o app
cmaketest3$ ./app
debug消息...
hello,word
C/C++常用的宏
# | 空指令无任何效果 |
#include | 包含源文件 |
#define | 宏定义 |
#undef | 取消已定义的宏 |
#if | 条件判断,如果给定条件为真,则编译下面代码 |
#ifdef | 如果宏已定义,则编译下面代码 |
#ifudef | 如果宏没有定义,则编译下面代码 |
#elif | 条件判断,else if,如果前面条件不为真,当前条件为真,则编译下面代码 |
#endif | 结束条件编译块,#if.....#elif |
9.2 CMake中的常见预定义宏
- PROJECT_SOURCE_DIR :使用cmake命令后紧跟的目录,一般是工程的根目录
- PROJECT_BINARY_DIR:执行cmake命令的目录
- CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt所在的路径
- CMAKE_CURRENT_BINARY_DIR?:target 编译目录
- EXECUTABLE_OUTPUT_PATH: 重新定义目标二进制可执行文件的存放位置
- LIBRARY_OUTPUT_PATH?:重新定义目标链接库文件的存放位置
- PROJECT_NAME:返回通过PROJECT指令定义的项目名称
- CMAKE_BINARY_DIR:项目实际构建路径,假设在build目录进行的构建,那么得到的就是这个目录的路径
十 调试库
10.1 调试库需要先生成可执行程序
10.1 调试库方式
- 通过cmake编译生成的可执行程序
- 当然也可以通过C/C++编译器,来编译main.c入口文件,生成可执行程序
?10.2 我们把库文件,头文件和main.c入口文件放在一个文件夹?
cmaketest2
├── head.h
├── libcalc.a
└── main.c
?编译测试程序main.c
# gcc 编译器
# main.c 测试入口文件
# -o 输出可执行程序
# app可执行程序名字
gcc main.c -o app
但直接执行是有问题的:找不到库里面的方法
$ gcc main.c -o calc
/usr/bin/ld: /tmp/ccG7UGl3.o: in function `main':
main.c:(.text+0x25): undefined reference to `add'
/usr/bin/ld: main.c:(.text+0x37): undefined reference to `sub'
/usr/bin/ld: main.c:(.text+0x49): undefined reference to `mult'
collect2: error: ld returned 1 exit status
所以需要改下,指定库的绝对或者相对路径?
# 编译的时候指定库信息
# -L: 指定库所在的目录(相对或者绝对路径)
# -l: 指定库的名字, 掐头(lib)去尾(.a),这里即app
# -L -l, 参数和参数值之间可以有空格, 也可以没有
gcc main.c -o app -L ./ -l calc
执行上面指令后就看到目录多了个app可执行程序文件
cmaketest2
├── app? ? ? ? ? ? #生成的可执行程序
├── head.h
├── libcalc.a
└── main.c
执行程序
./app
可以看到也可以执行成功
cmaketest2$ ./app
a , b is20,10
a + b = 30
a - b = 10
a * b = 200
a / b = 2