cmake & CMakeLists.txt

2023-05-16

文章目录

    • 前言
    • 先从体验开始
      • 1.一个最简单的例子:
      • 2.例子升级,将hello.c生成为一个库:
      • 3.例子升级,将源代码和库分开放:
      • 4.让可执行文件在 bin 目录,库文件在 lib 目录:
      • 5.动态库:
      • 6.应用:
    • 部分常用命令
      • include_directories,link_directories,link_libraries和target_link_libraries区别:
    • 工程路径
    • 各种参数
    • find_package
      • 基本使用
      • 如何编写自己的cmake module

前言

cmake官网:https://cmake.org/documentation/
其中的tutorial讲的很好:https://cmake.org/cmake/help/latest/guide/tutorial/index.html


先从体验开始

1.一个最简单的例子:

cmake执行的流程:

#其中directory为CMakeList.txt所在目录
$> ccmake directory		#配置编译选项,如VTK_DIR目录 ,一般这一步不需要配置,直接执行第二条语句即可,但当出现错误时,这里就需要认为配置了,这一步才真正派上用场;
$> cmake directory		#根据CMakeLists.txt生成Makefile文件;
$> make					#执行Makefile文件,编译程序,生成可执行文件;

hello.h 头文件

#ifndef DBZHANG_HELLO_
#define DBZHANG_HELLO_
void hello(const char* name);
#endif //DBZHANG_HELLO_

hello.c

#include <stdio.h>
#include "hello.h"
void hello(const char * name)
{
printf ("Hello %s!/n", name);
}

main.c

#include "hello.h"
int main()
{
hello("World");
return 0;
}

CMakeList.txt

project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})

由于执行cmake的时候会产生很多中间文件,我们采用out of source(外部编译)方式进行构建:建立一个build目录储存中间执行过程。

进入build目录,执行cmake . . ,cmake执行指向上一个目录,也就是存储CMakeLists.txt的目录,完成后就会看到makefile文件,make过后就会看到执行文件。

#第一个行project不是强制性的,最好加上,这会引入两个变量:
HELLO_BINARY_DIR, HELLO_SOURCE_DIR
#同时也会定义两个等价的变量:
PROJECT_BINARY_DIR, PROJECT_SOURCE_DIR
#外部编译要时刻区分这两个变量对应的目录:
#可以通过message进行输出

message(${PROJECT_SOURCE_DIR})
#set 命令用来设置变量

#add_exectuable 告诉工程生成一个可执行文件。
#add_library 则告诉生成一个库文件。
#注意:CMakeList.txt 文件中,命令名字是不区分大小写的,而参数和变量是大小写相关的。

2.例子升级,将hello.c生成为一个库:

改写一下前面的CMakeList.txt文件试试:

project(HELLO)
set(LIB_SRC hello.c)
set(APP_SRC main.c)
add_library(libhello ${LIB_SRC})
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)

和前面相比,我们添加了一个新的目标 libhello,并将其链接进hello程序

因为可执行程序占据了 hello 这个名字,所以 add_library 就不能使用这个名字了
然后,我们取了个libhello 的名字,这将导致生成的库为 libhello.lib(或 liblibhello.a),很不爽
想生成 hello.lib(或libhello.a) 怎么办?

添加一行

set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

就可以了
但是上面将源代码和库放在同一个目录下,工程变大后会很乱,怎么办?

3.例子升级,将源代码和库分开放:

顶层的CMakeList.txt 文件

project(HELLO)
add_subdirectory(src)
add_subdirectory(libhello)

src 中的 CMakeList.txt 文件

include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(APP_SRC main.c)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)

libhello 中的 CMakeList.txt 文件

set(LIB_SRC hello.c)
add_library(libhello ${LIB_SRC})
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

目录结构如下:

├── build
├── CMakeLists.txt
├── libhello
│   ├── CMakeLists.txt
│   ├── hello.c
│   └── hello.h
└── src
    ├── CMakeLists.txt
    └── main.c

编译之后生成的库文件在build/libhello中,生成的可执行文件在build/src中

回头看看,这次多了点什么,顶层的 CMakeList.txt 文件中使用 add_subdirectory 告诉cmake去子目录寻找新的CMakeList.txt 子文件
在 src 的 CMakeList.txt 文件中,新增加了include_directories,用来指明头文件所在的路径。
通常编译后生成的可执行文件放在bin目录下,库文件放在lib目录下,所以:

4.让可执行文件在 bin 目录,库文件在 lib 目录:

**一种办法:**修改顶级的 CMakeList.txt 文件,指定名字

project(HELLO)
add_subdirectory(src bin)
add_subdirectory(libhello lib)

可是这样除了 hello.exe,中间产物也进来了。还不是我们最想要的。
另一种办法:
不修改顶级的文件,修改其他两个文件
src/CMakeList.txt 文件

include_directories(${PROJECT_SOURCE_DIR}/libhello)
#link_directories(${PROJECT_BINARY_DIR}/lib)
set(APP_SRC main.c)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello ${APP_SRC})target_link_libraries(hello libhello)

libhello/CMakeList.txt 文件

set(LIB_SRC hello.c)
add_library(libhello ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

上面的例子中都是生成的静态库,下面用动态库代替静态库

5.动态库:

如果不考虑windows下,这个例子应该是很简单的,只需要在上个例子的 libhello/CMakeList.txt 文件中的
add_library命令中加入一个SHARED参数:

add_library(libhello SHARED ${LIB_SRC})

通过例子我们已经学习到了以下变量:

HELLO_BINARY_DIR, HELLO_SOURCE_DIR
PROJECT_BINARY_DIR, PROJECT_SOURCE_DIR

EXECUTABLE_OUTPUT_PATH
LIBRARY_OUTPUT_PATH 

SHARED 

6.应用:

(1)添加版本号和配置头文件 :
在源代码中提供版本号如果要修改就很麻烦,可以写到CMakeLists.txt中:

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
 
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  )
 
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
 
# add the executable
add_executable(Tutorial tutorial.cxx)

另创建“TutorialConfig.h.in”文件,内容如下:

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

tutorial.cxx:

// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
 
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"%s Version %d.%d\n",
            argv[0],
            Tutorial_VERSION_MAJOR,
            Tutorial_VERSION_MINOR);
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
  double inputValue = atof(argv[1]);
  double outputValue = sqrt(inputValue);
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}

(2)”EXTRA_LIBS”变量是用来收集每一个可选库的,以便他们链接到可执行程序中.这是一个保持大项目工程可选库清洁的通用方法

# add the MathFunctions library?
#
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
  add_subdirectory (MathFunctions)
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial  ${EXTRA_LIBS})

部分常用命令

set
SET( VAR value [CACHE TYPE DOCSTRING [FORCE]])
#set(VAR ${VAR} value)相当于VAR = VAR + value

add_executable

add_library
#添加SHARED可将目标作为动态库

message

project(<PROJECT-NAME>
        [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
        [DESCRIPTION <project-description-string>]
        [HOMEPAGE_URL <url-string>]
        [LANGUAGES <language-name>...])
#项目名称、版本

add_subdirectory()#可指定输出目录的名字:
add_subdirectory(输入目录名,输出目录名)

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])  
#将input文件复制到output文件中    
  
INCLUDE_DIRECTORIES( "dir1" "dir2" ... )
#头文件路径,相当于编译器参数 -Idir1 -Idir2

LINK_DIRECTORIES("dir1" "dir2")
#库文件路径。注意:
#由于历史原因,相对路径会原样传递给链接器。
#尽量使用FIND_LIBRARY而避免使用这个。

AUX_SOURCE_DIRECTORY( “sourcedir” variable)
#收集目录中的文件名并赋值给变量

ADD_CUSTOM_TARGET
#自定义目标

ADD_DEPENDENCIES( target1 t2 t3 )
#目标target1依赖于t2 t3

ADD_DEFINITIONS( "-Wall -ansi")
#本意是供设置 -D... /D... 等编译预处理需要的宏定义参数,对比 REMOVE_DEFINITIONS()

TARGET_LINK_LIBRARIES( target-name lib1 lib2 ...)
#设置单个目标需要链接的库

LINK_LIBRARIES( lib1 lib2 ...)
#设置所有目标需要链接的库

SET_TARGET_PROPERTIES( ... )
#设置目标的属性 OUTPUT_NAME, VERSION, ....

MESSAGE(...)

INSTALL( FILES “f1” “f2”DESTINATION . )
#DESTINATION 相对于 ${CMAKE_INSTALL_PREFIX}

LIST( APPEND|INSERT|LENGTH|GET| REMOVE_ITEM|REMOVE_AT|SORT ...)
#列表操作

STRING( TOUPPER|TOLOWER|LENGTH| SUBSTRING|REPLACE|REGEX ...)
#字符串操作

SEPARATE_ARGUMENTS( VAR )
#转换空格分隔的字符串到列表

FILE( WRITE|READ|APPEND|GLOB| GLOB_RECURSE|REMOVE|MAKE_DIRECTORY ...)
#文件操作

FIND_FILE
#注意 CMAKE_INCLUDE_PATH

FIND_PATH
#注意 CMAKE_INCLUDE_PATH

FIND_LIBRARY
#注意 CMAKE_LIBRARY_PATH

FIND_PROGRAM
 
FIND_PACKAGE
#注意 CMAKE_MODULE_PATH

EXEC_PROGRAM( bin [work_dir] ARGS <..> [OUTPUT_VARIABLE var] [RETURN_VALUE var] )
#执行外部程序

OPTION( OPTION_VAR “description” [initial value] )
#选择是否添加可选项
#多数情况会有大量的依赖第三方的库文件.添加一个可选库等
#一般在最高层的CMakeLists.txt

include_directories,link_directories,link_libraries和target_link_libraries区别:

1.INCLUDE_DIRECTORIES(添加头文件目录)
它相当于g++选项中的-I参数的作用,也相当于环境变量中增加路径到CPLUS_INCLUDE_PATH变量的作用(这里特指c++。c和Java中用法类似)。比如:

include_directories("/opt/MATLAB/R2012a/extern/include")
export CPLUS_INCLUDE_PATH=CPLUS_INCLUDE_PATH:$MATLAB/extern/include

2.LINK_DIRECTORIES(添加需要链接的库文件目录)
语法:link_directories(directory1 directory2 …)
它相当于g++命令的-L选项的作用,也相当于环境变量中增加LD_LIBRARY_PATH的路径的作用。比如:

LINK_DIRECTORIES("/opt/MATLAB/R2012a/bin/glnxa64")
export LD_LIBRARY_PATH=LD_LIBRARY_PATH:MATLAB/bin/glnxa64

3.LINK_LIBRARIES (添加需要链接的库文件路径,注意这里是全路径)
List of direct link dependencies.
比如:

LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" “/opt/MATLAB/R2012a/bin/glnxa64/libmx.so”)

4.TARGET_LINK_LIBRARIES (设置要链接的库文件的名称)
语法:TARGET_LINK_LIBRARIES(targetlibrary1 <debug | optimized> library2 …)
比如(以下写法(包括备注中的)都可以):

TARGET_LINK_LIBRARIES(myProject hello),连接libhello.so库
TARGET_LINK_LIBRARIES(myProject libhello.a)
TARGET_LINK_LIBRARIES(myProject libhello.so)

再如:

TARGET_LINK_LIBRARIES(myProject libeng.so)  #这些库名写法都可以。
TARGET_LINK_LIBRARIES(myProject eng)
TARGET_LINK_LIBRARIES(myProject -leng)

下面是具体的例子:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

include_directories("/opt/MATLAB/R2012a/extern/include")

#directly link to the libraries.
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")

#equals to below
#LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" “/opt/MATLAB/R2012a/bin/glnxa64/libmx.so”)

工程路径

CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
<projectname>_SOURCE_DIR

这三个变量指代的内容是一致的,是工程顶层目录

CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
<projectname>_BINARY_DIR

这三个变量指代的内容是一致的,如果是in source编译,指得就是工程顶层目录,如果 是out-of-source编译,指的是工程编译发生的目录

CMAKE_CURRENT_SOURCE_DIR

指的是当前处理的CMakeLists.txt所在的路径。

CMAKE_CURRRENT_BINARY_DIR

如果是in-source编译,它跟CMAKE_CURRENT_SOURCE_DIR一致,如果是out-ofsource 编译,他指的是target编译目录。

CMAKE_CURRENT_LIST_FILE

输出调用这个变量的CMakeLists.txt的完整路径

各种参数

1.CMAKE_BUILD_TYPE
控制 Debug 和 Release 模式的构建
CMakeList.txt文件:

SET(CMAKE_BUILD_TYPE Debug)

命令行参数:

cmake DCMAKE_BUILD_TYPE=Release

2.编译器参数
CMAKE_C_FLAGS
CMAKE_CXX_FLAGS
也可以通过指令ADD_DEFINITIONS()添加

3.CMAKE_INCLUDE_PATH
配合 FIND_FILE() 以及 FIND_PATH() 使用。如果头文件没有存放在常规路径(/usr/include, /usr/local/include等),
则可以通过这些变量进行弥补。如果不使用 FIND_FILE 和 FIND_PATH的话,CMAKE_INCLUDE_PATH,没有任何作用。

4.CMAKE_LIBRARY_PATH
配合 FIND_LIBRARY() 使用。否则没有任何作用

5.CMAKE_MODULE_PATH
cmake 为上百个软件包提供了查找器(finder):FindXXXX.cmake

当使用非cmake自带的finder时,需要指定finder的路径,这就是CMAKE_MODULE_PATH,配合 FIND_PACKAGE()使用

6.CMAKE_INSTALL_PREFIX
控制make install是文件会安装到什么地方。默认定义是/usr/local 或 %PROGRAMFILES%

7.BUILD_SHARED_LIBS
如果不进行设置,使用ADD_LIBRARY且没有指定库类型,默认编译生成的库是静态库。

8.UNIX 与 WIN32
UNIX,在所有的类UNIX平台为TRUE,包括OS X和cygwin
WIN32,在所有的win32平台为TRUE,包括cygwin

find_package

基本使用

FIND_PACKAGE( <name> [version] [EXACT] [QUIET] [NO_MODULE] [ [ REQUIRED | COMPONENTS ] [ componets... ] ] )

功能::帮助我们取找头文件和库文件。

find_package()命令首先会在模块路径中寻找Find.cmake,这是查找库的一个典型方式。具体查找路径依次为CMake:变量$ {CMAKE_MODULE_PATH}中的所有目录。如果没有,然后再查看它自己的模块目录/share/cmake-x.y/Modules/($CMAKE_ROOT的具体值可以通过CMake中message命令输出)。这称为模块模式。

例如:我们要使用bzip2库时:

include_directiories(/usr/include/curl)
target_link_libraries(myprogram path/curl.so)

当我们使用find_package查找bzip2时:

project(helloworld)
add_executable(helloworld hello.c)
find_package (BZip2 REQUIRED)	//库文件 选项
if (BZIP2_FOUND)
    include_directories(${BZIP_INCLUDE_DIRS})		//库文件自己定义的变量
    target_link_libraries (helloworld ${BZIP2_LIBRARIES})
endif (BZIP2_FOUND)

为了能支持各种常见的库和包,CMake自带了很多模块。可以通过命令 cmake –help-module-list (输入cmake –help,然后双击Tab会有命令提示)得到你的CMake支持的模块的列表: 直接查看模块路径。比如Ubuntu linux上,模块的路径是 ls /usr/share/cmake/Modules/
以bzip2库为例。CMake中有个 FindBZip2.cmake 模块。只要使用 find_package(BZip2) 调用这个模块,cmake会自动给一些变量赋值,然后就可以在CMake脚本中使用它们了。变量的列表可以查看cmake模块文件,或者使用命令:

root@xy:~/cmake_practice/cmake_build/build_demo10# cmake --help-module FindBZip2
FindBZip2
---------

Try to find BZip2

Once done this will define
::
BZIP2_FOUND - system has BZip2
BZIP2_INCLUDE_DIR - the BZip2 include directory
BZIP2_LIBRARIES - Link these to use BZip2
BZIP2_NEED_PREFIX - this is set if the functions are prefixed with BZ2_
BZIP2_VERSION_STRING - the version of BZip2 found (since CMake 2.8.8)

如何编写自己的cmake module

如上所说,find是根据库提供的.cmake等文件来查找,那么就需要制作此.cmake文件

以上内容参考自:
https://blog.csdn.net/alan711/article/details/86171103
https://blog.csdn.net/yanchuang1/article/details/69683236
https://blog.csdn.net/alan711/article/details/86171103
https://blog.csdn.net/dbzhang800/article/details/6329068
继续学习可看文章:
https://blog.csdn.net/dbzhang800/article/details/6329314
https://blog.csdn.net/dbzhang800/article/details/6340102
https://blog.csdn.net/dbzhang800/article/details/6341029
https://blog.csdn.net/dbzhang800/article/details/6341803

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cmake & CMakeLists.txt 的相关文章

随机推荐

  • 我的创作纪念日

    初心未改 xff0c 继续向前
  • 最新激光雷达闭环检测/地点识别算法CVTNet(2023)

    CVTNet以激光点云多类投影生成的二维图为输入 xff0c 利用cross transformer将多类信息交叉融合 xff0c 为激光点云提取强特异性描述子 xff0c 实现SLAM闭环检测或全局定位功能 此外 xff0c CVTNet
  • python使用ffmpeg推流出现OSError: [Errno 2] No such file or directory

    python使用ffmpeg推流出现OSError Errno 2 No such file or directory 具体错误如下 xff1a Traceback span class token punctuation span mos
  • GDB调式工具学习笔记---单步执行和跟踪函数调用

    GDB调式工具学习笔记 单步执行和跟踪函数调用 简介1 单步执行和跟踪函数调用1 1 示例程序1 2 常用命令1 2 1 help1 2 2 list l 1 2 3 quit1 2 4 start1 2 5 next xff08 n xf
  • GDB调式工具学习笔记---断点

    GDB调式工具学习笔记 断点 2 断点2 1 示例代码2 2 常用命令2 2 1 display和undisplay2 2 2 break b 2 2 3 continue xff08 c xff09 2 2 4 disable2 2 6
  • C语言网络编程——UDP

    C语言网络编程 UDP 2 1 基于UDP的网络编程2 2 1 服务端实现2 2 2 客户端实现 2 1 基于UDP的网络编程 2 2 1 服务端实现 使用socket函数 xff0c 创建一个socket使用bind 函数 xff0c 绑
  • STM8S电源管理-重点活跃停机模式

    http blog sina com cn s blog 542bad910101qkru html
  • 多态的定义

    多态是什么 xff1f 多态 polymorphism 是面向对象编程 OOP object oriented programming 的一个重要特征 xff0c 顾名思义为多种形态 xff0c 详细解释为一个接口 xff0c 多种实现 x
  • 虚函数实现多态的原理

    1 C 43 43 中如何实现多态 基类中先声明一个虚函数至少有一个继承该基类的子类 2 虚函数实现多态的原理 当一个类中出现虚函数或着子类继承了虚函数时 xff0c 就会在该类中产生一个虚函数表 xff08 virtual table x
  • 停车场车牌识别项目

    停车场车牌识别项目 简介开发环境技术栈1 Sqlite2 TTS3 摄像头使用教程 实现效果图源码 简介 该项目的应用场景为停车场 xff0c 记录车辆的进出时间 xff0c 对车辆进行收费 开发环境 Windows 下的 QT 技术栈 Q
  • STM32串口输出字符串

    目录 串口步骤1 确定 IO 口并初始化2 初始化 UATR3 UART 中断配置4 编写 UART 中断服务函数5 1 方法一 xff1a 重定向 fputc 5 2 方法二 xff1a 将字符串分割成一个一个字符发送出去 效果附源码 串
  • 常用Linux命令

    目录 Shell常用Shell命令1 目录操作类2 文本操作类3 用户管理4 文件权限类5 磁盘管理类6 网络操作类7 控制终端类8 开关机类 Shell小技巧 Shell shell是一个应用程序 xff0c 作为用户与内核信息传递的桥梁
  • VSCode与Keil联合开发STM32

    目录 1 为什么要联合开发2 配置VSCode的环境1 安装c c 43 43 2 安装Embedded IDE3 设置编译工具4 导入 STM32 工程5 配置编译器选项6 烧录工具选择 3 附 1 为什么要联合开发 Keil容易出现中文
  • 8.类的继承

    目录 1 继承的定义2 继承的作用3 继承的语法4 类继承成员属性的访问权限5 利用参数列表 xff0c 初始化父类的私有成员6 继承中的构造函数与析构函数7 总结共继承的权限问题8 类中的隐藏问题9 类中的多继承10 类中多级继承11 菱
  • 14.数据成员属性

    目录 1 静态属性 xff1a 2 类中的静态成员 xff1a 3 类中的静态函数 xff1a 4 类中的const成员5 类中的常量成员6 类中的常量函数 xff1a 7 常量对象 xff1a 1 静态属性 xff1a 回顾C语言的静态变
  • 15.异常处理

    目录 1 为什么需要异常处理 xff1f 2 在c 43 43 中异常处理的方法 xff1f xff1f 3 异常的抛出4 异常的类型捕捉5 系统预定义的异常类型6 异常的再抛出 1 为什么需要异常处理 xff1f 用 new 运算符动态分
  • 我的创作纪念日

    一周年纪念
  • SD卡无法格式化怎么办的解决方法

    SD卡无法格式化怎么办的解决方法 http www upantool com jiaocheng neicunka 5399 html 每次SD卡受损都要格卡的朋友 xff0c 一大堆游戏 相片 视频 xff0c 还有导航地图要重新上传 x
  • cmake --Cannot specify link libraries for target" XX" which is not built by this project.

    cmake Cannot specify link libraries for target 34 XX 34 which is not built by this project 原CMakeLists txt内容 xff1a find
  • cmake & CMakeLists.txt

    文章目录 前言先从体验开始1 一个最简单的例子 xff1a 2 例子升级 xff0c 将hello c生成为一个库 xff1a 3 例子升级 xff0c 将源代码和库分开放 xff1a 4 让可执行文件在 bin 目录 xff0c 库文件在