Cmake 之Linux库编译

这篇具有很好参考价值的文章主要介绍了Cmake 之Linux库编译。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一 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执行流程图

Cmake 之Linux库编译,cmake,linux

2.3 Cmake最简单且必须的3个文件,如开头那个CmakeLists.txt

  • cmake_minimum_required:
  • 指定使用的 cmake 的最低版本
  • 可选,非必须,如果不加可能会有警告
cmake_minimum_required(VERSION 3.0)
  • project:
  • 定义工程名称,并可指定工程的版本、工程描述、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:
  • 定义工程会生成一个可执行程序,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指令,生成如下日志

Cmake 之Linux库编译,cmake,linux

八 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文章来源地址https://www.toymoban.com/news/detail-809763.html

到了这里,关于Cmake 之Linux库编译的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 安装交叉编译工具链aarch64-linux-gnu-g++ 以及cmake测试

       测试文件结构    CMakeLists.txt  参考文章: linux 交叉编译 C和C++_aarch64-linux-gnu-gcc查看版本_weixin_45302027的博客-CSDN博客 ubuntu16.04 安装交叉编译工具aarch64-linux-gnu-gccg++_ubuntu 安装aarch64-linux-gnu-gcc_普通网友的博客-CSDN博客

    2024年02月12日
    浏览(51)
  • 4.Linux下Cmake交叉编译Qt项目到Jetson Orin Nano(arm)

    由于3:Ubuntu上配置QT交叉编译环境并编译QT程序到Jetson Orin Nano(ARM)_月上林梢的博客-CSDN博客  这一篇文章只用手动配置,一直在点、点、点。比较 LOW,现在在Ubuntu上使用Cmake实现交叉编译QT程序到Jetson Orin Nano上。 提醒: 我的工作环境是 Visual Studio+QT+arm 由于 Ubuntu 下没有V

    2024年02月12日
    浏览(46)
  • vs2017实现linux远程编译报错“CMake 缺少以下功能:serverMode“解决方案

    背景 window系统vs2017使用cmake实现linux远程调试和编译时,搭建的环境报 CMake 缺少以下功能:“serverMode”。请参阅 https://aka.ms/linuxcmakeconfig 了解详细信息 错误,如何解决? 经排查,发现远程开发环境的cmake版本不支持serverMode模式,因此,无法实现远程编译 解决方案 验证远程目

    2024年02月11日
    浏览(38)
  • Linux conan+cmake管理的项目如何进行多架构编译(x86_64及交叉编译arm64)

    Conan 和 CMake 是两个非常流行的跨平台开发工具,它们可以让开发者轻松管理依赖和构建项目,支持多种操作系统和架构。下面是一些关于 conan 和 cmake 的介绍: Conan Conan 是一个用于管理 C++ 依赖项的开源工具。它可以从公共或私有存储库中自动下载和安装依赖项。Conan 可以轻

    2024年02月09日
    浏览(48)
  • Linux下安装 CMake

     我们选择下载直接可以使用的版本,右键保存链接地址,打开Linux系统(以Ubuntu为例) 历史版本下载地址:Index of /files 注意: 这里不要装太老的cmake版本,因为后面make的时候没法做,要装 3.16 以上的 创建/opt/cmake目录,在该目录下执行 wget -c https://cmake.org/files/v3.22/cmake-3.

    2024年02月08日
    浏览(34)
  • Linux下CMake开发

    编写CMakeLists.txt 编写C++文件main.cpp 编译和运行 一般把CMakeLists.txt文件放在工程目录下,使用时,先创建一个叫build的文件夹(这个并非必须,因为cmake命令指向CMakeLists.txt所在的目录,例如cmake … 表示CMakeLists.txt在当前目录的上一级目录。cmake后会生成很多编译的中间文件以及

    2024年02月15日
    浏览(40)
  • Linux 系统下 CMake 示 例

    CMake 是一个开源的跨平台工具,可以构建、测试和打包软件。 它具有如下特性: 自动搜索可能需要的程序、库和头文件的能力; 独立的构建目录(如 build ),可以安全清理; 支持复杂的自定义命令(下载、生成各种文件); 自定义配置可选组件; 从简单的文本文件( C

    2024年02月09日
    浏览(28)
  • Linux下CMake安装遇到的问题

    在使用pip install cmake安装完cmake以后,想要检查一下cmake的版本,于是输入 结果出现如下报错: 这个问题是由于CMake无法找到正确的安装路径。 首先,卸载现有的cmake: 然后,使用Anaconda提供的CMake包来安装: 安装完成以后即可解决问题。

    2024年04月12日
    浏览(47)
  • Linux下安装CMake的两种方法

    方法一:使用包管理器安装CMake 在Linux系统中,可以使用包管理器来安装CMake。不同的Linux发行版可能使用不同的包管理器,下面以常见的Ubuntu系统为例: 打开终端,输入以下命令更新包管理器的软件源信息: 安装CMake: 输入管理员密码确认安装。包管理器将自动下载并安装

    2024年02月04日
    浏览(45)
  • CMake : Linux 搭建开发 - g++、gdb

    目录 1、环境搭建 1.1 编译器 GCC,调试器 GDB 1.2 CMake 2、G++ 编译 2.1 编译过程 编译预处理 *.i 编译 *.s 汇编 *.o 链接 bin 2.2 G++ 参数 -g -O[n] -l、-L -I -Wall、-w -o -D -fpic 3、GDB 调试器 3.1 调试命令参数 4、CMake 4.1 含义 4.2 构建树 4.3 常用命令 4.4 构建流程 编译预处理 *.i 主要对包含的*

    2023年04月25日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包