关于cmake:CMake-LLVM-JIT-build-usrbinld-undefined-reference-to

TL;DR(EN): Open CMakeLists.txtFind this line, then add the required component: llvm_map_components_to_libnames(LLVM_LIBS core <Component>)If you don't know what component is required, then check this: llvm-config-<LLVM_Version> --components2024-02-26 自己于昨日为编译器前端增加 ORC JIT 的时候遇到这个问题, 初步判断是链接器问题, 可能的起因如下: LLVM 局部模块缺失, 须要装置 LLVM 框架中对应的模块.LLVM 链接器出错, 须要降级版本或重新安装CMake 链接器出错因为应用了 LLVM 提供的装置脚本, 所以应该是曾经装置了全副的模块, 十分惋惜, 我不晓得 ORC JIT 对应的是哪个模块, 甚至无从查起. wget https://apt.llvm.org/llvm.shchmod +x llvm.shsudo ./llvm.sh <version number>在网络搜寻的过程中, 发现 llvm-config 的链接:https://llvm.org/docs/CommandGuide/llvm-config.html 在 /usr/bin 目录下确定 llvm-config-18 的存在, 且以后应用的 LLVM 版本为 18 . 而后应用 llvm-config-18 –components, 取得如下后果: ...

February 26, 2024 · 1 min · jiezi

关于cmake:测试链接库的cmakelist模板

最近好几次须要本人写CMakeLists测试一个模块的应用,很多步骤是反复的,所以总结一下通用的模板。 假如当初有一个编译好的共享库libxxx.so,我想本人写些代码去测试它的接口应用,编译成可执行文件,能够应用相似如下的模板。 CMakeList.txt: message("start building...")#指定编译工具链SET(TOOLCHAIN_HOME "/usr")#SET(CMAKE_SYSTEM_NAME Linux)SET(CMAKE_C_COMPILER ${TOOLCHAIN_HOME}/bin/aarch64-linux-gnu-gcc)SET(CMAKE_CXX_COMPILER ${TOOLCHAIN_HOME}/bin/aarch64-linux-gnu-g++)#指定编译选项#add_compile_options(-DLINUX)set(CMAKE_CXX_FLAGS "-std=c++11 -O2 -pthread")cmake_minimum_required(VERSION 2.8)project(test)set(DEMO_NAME ${PROJECT_NAME})#编译的源文件门路,测试代码的源文件set(DEMO_SRCS srcFile1.cc srcFile2.cc main.cc)#编译的头文件门路,包含测试代码的头文件和援用模块的头文件include_directories( /your_test_file_path/ /lib_include_path/)#须要链接的库门路set(LIB_PATH /path_to_lib/libxxx.so)#增加可执行文件add_executable(${DEMO_NAME} ${DEMO_SRCS})#动态链接库target_link_libraries(${DEMO_NAME} ${LIB_PATH})而后能够再写个shell脚本一键编译 cmake-linux.sh: #!/bin/bash#编译输入目录BUILD_DIR=build_linuxBINARY_DIR=$BUILD_DIR/bin#每次编译时删除从新创立rm -rf $BUILD_DIRmkdir -p $BUILD_DIRmkdir -p $BINARY_DIRpushd $BUILD_DIR#开始编译,如果想要增加本人的库能够加installecho "Default mode"cmake -DCMAKE_INSTALL_PREFIX=install \ ..make#make installpopd

April 12, 2023 · 1 min · jiezi

关于cmake:Y-分钟速成-CMake

源代码下载: CMake-cn CMake 是一个跨平台且开源的自动化构建零碎工具。通过该工具你能够对你的源代码进行测试、编译或创立安装包。 CMake 试图去解决Makefile 跨平台的主动配置问题(不同的make解释器有不同的命令),以及链接第三方库时的易用性问题。 CMake 是一个可扩大的开源零碎,它以操作系统和与编译器无关的形式治理构建过程。与其余许多跨平台零碎不同的是,CMake 被设计为与本机的构建环境联合应用。它通过被搁置于每个源文件目录下的简略配置文件(名为 CMakeLists.txt 的文件)来生成惯例应用的规范构建文件(比方:Unix 下的 makefiles 文件或 Windows MSVC 中的 projects/workspaces)。 # 在 CMake 中, 这是一条命令# 要运行咱们的代码,请执行以下命令:# - mkdir build && cd build# - cmake ..# - make# # 通过上述命令,咱们将遵循最佳实际在子目录中进行编译# 在第二行命令中咱们申请Cmake 生成新的依赖于零碎的Makefile文件。# 最初,咱们运行本地的make 命令。#------------------------------------------------------------------------------# 根底局部#------------------------------------------------------------------------------## Cmake文件必须被命令为 “CMakeLists.txt” 。# 设置生成Makefile的CMake所需最低版本要求cmake_minimum_required (VERSION 2.8)# 当版本小于2.8时,须要退出关键字 FATAL_ERROR。cmake_minimum_required (VERSION 2.8 FATAL_ERROR)# 在这里定义了我的项目的名称,同时会影响Cmake 生成的目录命名约定。# 咱们能够将代码的语言作为第二个参数传入。project (learncmake C)# 设置我的项目的源目录(仅仅是因为常规)set( LEARN_CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )set( LEARN_CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )# 在构建零碎中用“semver”格调为咱们代码设置以后版本是很有用的。set (LEARN_CMAKE_VERSION_MAJOR 1)set (LEARN_CMAKE_VERSION_MINOR 0)set (LEARN_CMAKE_VERSION_PATCH 0)# 将变量(版本号)发送到源代码头configure_file ( "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" "${PROJECT_BINARY_DIR}/TutorialConfig.h")# 蕴含目录# 在 GCC中, 该语句等同于 "-I" 命令include_directories( include )# 在哪里装置其余库?留神:在此处提供includes门路,后续查看将解决所有其余问题set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake/modules/" )# 条件if ( CONDITION ) # 输入! # 附带信息 message(STATUS "My message") # CMake 正告,持续解决 message(WARNING "My message") # CMake 正告 (dev),持续解决 message(AUTHOR_WARNING "My message") # CMake 谬误,持续解决然而会跳过生成 message(SEND_ERROR "My message") # CMake 谬误,进行解决和生成 message(FATAL_ERROR "My message")endif()if( CONDITION )elseif( CONDITION )else( CONDITION )endif( CONDITION )# 循环foreach(loop_var arg1 arg2 ...) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ...endforeach(loop_var)foreach(loop_var RANGE total)foreach(loop_var RANGE start stop [step])foreach(loop_var IN [LISTS [list1 [...]]] [ITEMS [item1 [...]]])while(condition) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ...endwhile(condition)# 逻辑运算if(FALSE AND (FALSE OR TRUE)) message("Don't display!")endif()# 将惯例,缓存或环境变量设置为给定值。# 如果指定了PARENT_SCOPE选项,则将在以后作用域上的作用域中设置变量# `set(<variable> <value>... [PARENT_SCOPE])`# 如何在带引号和不带引号的参数中援用变量?How to reference variables inside quoted and unquoted arguments?# 如果未设置变量,变量援用由变量值或空字符串替换。${variable_name}# 清单# 设置源文件列表set( LEARN_CMAKE_SOURCES src/main.c src/imagem.c src/pather.c)# 调用编译器## ${PROJECT_NAME} 即 Learn_CMake add_executable( ${PROJECT_NAME} ${LEARN_CMAKE_SOURCES} )# 链接库target_link_libraries( ${PROJECT_NAME} ${LIBS} m )# 在哪里装置其余库?留神:在此处提供includes门路,后续查看将解决所有其余问题set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake/modules/" )# 编译条件 (gcc ; g++)if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" ) message( STATUS "Setting the flags for ${CMAKE_C_COMPILER_ID} compiler" ) add_definitions( --std=c99 )endif()# 查看 OSif( UNIX ) set( LEARN_CMAKE_DEFINITIONS "${LEARN_CMAKE_DEFINITIONS} -Wall -Wextra -Werror -Wno-deprecated-declarations -Wno-unused-parameter -Wno-comment" )endif()资源CMake tutorialCMake documentationMastering CMakeAn Introduction to Modern CMake有倡议?或者发现什么谬误?在Github上开一个 issue ,或者发动 pull request ! ...

December 16, 2022 · 2 min · jiezi

关于cmake:CMake系列CMAKE的hello-world

 (ps:本博客建设在cmake装置好的根底上) 本文抉择一个最简略的例子,HelloWorld来演练一下cmake的残缺构建过程。 此示例基于unbuntu20.04.1的版本 1.筹备工作 首先咱们创立一个文件夹用来寄存cmake的所有示例 mkdir cmake_demos 当前所有的cmake分割都会放在cmake_demos的子目录下,读者能够自行安排目录 而后在cmake_demos新建文件夹d1 mkdir d1 在d1目录,新建main.c和CMakeLists.txt(留神文件名的大小写) touch main.c CMakeLists.txt main.c文件内容 CMakeLists.txt文件内容 2.开始构建 所有文件创建实现,此时d1目录应该存在了main.c和CMakeLists.txt两个文件,接下来咱们开始构建工程 在此目录运行: cmake . 输入大略是这样 让咱们再看一下目录中的内容,会发现零碎主动生成了 CMakeFiles、CMakeCache.txt、cmake_install.cmake等文件 先不必去关注这些文件的作用,最重要的是生成了Makefile 接下来进行工程的理论构建,在这个目录输出make命令,大略会失去以下黑白输入:   如果须要看到make构建的具体过程,能够应用make VERBOSE=1命令来进行构建 输入内容大略是这样 这时候咱们须要的指标文件hello曾经构建实现了位于当前目录,尝试运行一下 ./hello 取得输入  祝贺你,到这里曾经学会了简略应用cmake的构建办法。 接下来的博客将会给大家介绍这些文件内容和指令。 

October 29, 2022 · 1 min · jiezi

关于cmake:记一次在centos7上编译安装mosquitto的过程

首先把mosquitto最新源码包克隆到本地 git clone https://github.com/eclipse/mosquitto.git或者下载压缩包 wget https://mosquitto.org/files/source/mosquitto-2.0.14.tar.gz而后解压tar xzvf mosquitto-2.0.14.tar.gz接着进入解压目录 cd mosquitto-2.0.14mkdir buildcmake ..执行到cmake ..时,提醒如下 CMake Error at CMakeLists.txt:7 (cmake_minimum_required): CMake 3.0 or higher is required. You are running version 2.8.12.2-- Configuring incomplete, errors occurred!提醒cmake版本小于CMakeLists.txt定义的最小版本CMake 3.0 or higher 接下来降级cmake wget https://github.com/Kitware/CMake/releases/download/v3.23.2/cmake-3.23.2-linux-x86_64.tar.gztar xzvf cmake-3.23.2-linux-x86_64.tar.gzmv cmake-3.23.2-linux-x86_64 /opt/cmake-3.23.2sudo yum -y remove cmakesudo ln -s cmake-3.23.2/bin/* /usr/bin/[root@VM-12-4-centos ~]# cmake --versioncmake version 3.23.2CMake suite maintained and supported by Kitware (kitware.com/cmake).而后持续之前的步骤 [root@VM-12-4-centos build]# cmake ..-- The C compiler identification is GNU 4.8.5-- The CXX compiler identification is GNU 4.8.5-- 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-- Found OpenSSL: /usr/lib64/libcrypto.so (found version "1.0.2k") -- WITH_DLT = OFF-- Could NOT find cJSON (missing: CJSON_INCLUDE_DIR CJSON_LIBRARY) -- Optional dependency cJSON not found. Some features will be disabled.-- Looking for getaddrinfo_a in anl-- Looking for getaddrinfo_a in anl - foundCMake Error at man/CMakeLists.txt:29 (message): xsltproc not found: manpages cannot be built-- Configuring incomplete, errors occurred!See also "/root/mosquitto-2.0.14/build/CMakeFiles/CMakeOutput.log".提醒xsltproc not found,那就装置下 ...

July 9, 2022 · 9 min · jiezi

关于cmake:addcustomcommand用法

第一个参数OUTPUT或者TARGET决定了此命令何时被执行。 TARGET意思是当target被编译完时,就执行此COMMAND add_executable(MakeTable MakeTable.cxx)add_custom_command( TARGET MakeTable POST_BUILD(默认值) COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table2.h )OUTPUT意思是OUTPUT所指局部被依赖时,才执行此COMMAND。上面的add_library( ... )如果最初不蕴含${CMAKE_CURRENT_BINARY_DIR}/Table.h 那么这个COMMAND就不会被执行 add_executable(MakeTable MakeTable.cxx) add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h DEPENDS MakeTable ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) add_library(Mylib SHARED mylib.cpp ${CMAKE_CURRENT_BINARY_DIR}/Table.h )源码地址

March 19, 2022 · 1 min · jiezi

关于cmake:CMake实战三自定义编译选项

title: CMake实战三:自定义编译选项 categories:[实战三] tags:[CMake] date: 2021/12/24 作者:hackett 微信公众号:加班猿 CMake 容许为我的项目减少编译选项,从而能够依据用户的环境和需要抉择最合适的编译计划。 很多开源库都会有CMake来进行治理编译,比方亚马逊AWS的WebRTC中的CMake外面有这么一行 option(USE_OPENSSL "Use openssl as crypto library" ON)ON示意应用openssl的库,OFF示意不应用openssl的库 1、批改CMakeLists文件# CMake 最低版本号要求cmake_minimum_required (VERSION 2.8)# 我的项目信息project (demo4)# 退出一个配置头文件,用于解决 CMake 对源码的设置configure_file ( "${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" )# 是否应用本人的 MathFunctions 库option (USE_MYMATH "Use provided math implementation" ON)# 是否退出 MathFunctions 库if (USE_MYMATH) include_directories ("${PROJECT_SOURCE_DIR}/math") add_subdirectory (math) set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)endif (USE_MYMATH)# 查找当前目录下的所有源文件# 并将名称保留到 DIR_SRCS 变量aux_source_directory(. DIR_SRCS)# 指定生成指标add_executable(Demo ${DIR_SRCS})target_link_libraries (demo ${EXTRA_LIBS})其中: configure_file 命令用于退出一个配置头文件 config.h ,这个文件由 CMake 从 config.h.in 生成,通过这样的机制,将能够通过预约义一些参数和变量来控制代码的生成。option 命令增加了一个 USE_MYMATH 选项,并且默认值为 ON 。USE_MYMATH 变量的值来决定是否应用咱们本人编写的 MathFunctions 库。2、批改main.cpp文件让其依据 USE_MYMATH 的预约义值来决定是否调用规范库还是 MathFunctions 库: ...

December 24, 2021 · 3 min · jiezi

关于cmake:CMake实战二多个源文件同一或多个目录

title: CMake实战二:多个源文件,同一或多个目录 categories:[实战二] tags:[CMake] date: 2021/12/23 作者:hackett 微信公众号:加班猿 1、同一目录,多个源文件CMake实战一只有单个源文件,当初把add函数写入myMath.cpp的源文件外面,申明放到myMath.h源文件外面 工程树状图如下: demo2/├── CMakeLists.txt├── main.cpp├── myMath.cpp└── myMath.h这个时候,CMakeLists.txt 能够改成如下的模式: # CMake 最低版本号要求cmake_minimum_required (VERSION 2.8)# 我的项目信息project (Demo2)# 指定生成指标add_executable(Demo main.cpp myMath.cpp)main.cpp #include <stdio.h>#include <stdlib.h>#include "myMath.h"int main(int argc, char *argv[]) { if (argc < 3) { printf("Usage: %s argv[1] argv[2] \n", argv[0]); return 1; } int a = atof(argv[1]); int b = atoi(argv[2]); int result = add(a, b); printf("%d + %d = %d\n", a, b, result); return 0;}myMath.cpp ...

December 24, 2021 · 3 min · jiezi

关于cmake:CMake实战一单个源文件

title: CMake实战一:单个源文件 categories:[实战一] tags:[CMake] date: 2021/12/23 作者:hackett 微信公众号:加班猿 CMake 反对大写、小写和大小写混合命令。 在 linux 平台下应用 CMake 生成 Makefile 并编译的流程如下: 编写 CMake 配置文件 CMakeLists.txt 。执行命令 cmake PATH 或者 ccmake PATH 生成 Makefile(ccmake 和 cmake 的区别在于前者提供了一个交互式的界面)。其中, PATH 是 CMakeLists.txt 所在的目录。应用 make 命令进行编译。编译生成可执行程序运行1、创立目录mkdir cmakecd cmakemkdir demo1cd demo12、筹备好须要编译的文件这里做个演示 所以就来个简略的代码,计算两个数的和,源文件为main.cpp #include <stdio.h>#include <stdlib.h>int add(int a, int b) { return (a + b);}int main(int argc, char *argv[]) { if (argc < 3) { printf("Usage: %s argv[1] argv[2] \n", argv[0]); return 1; } int a = atof(argv[1]); int b = atoi(argv[2]); int result = add(a, b); printf("%d + %d = %d\n", a, b, result); return 0;}3、编写CMakeLists.txt编写 CMakeLists.txt 文件,并保留在与main.cpp 源文件同个目录下: ...

December 24, 2021 · 2 min · jiezi

关于cmake:CMake基础知识

CMake是一个跨平台编译工具,能够用简略的语句来形容所有平台的编译过程。CMake的目标就是输入各种各样可移植的规范的建构档(如Unix的Makefile或Windows Visual C++的projects/workspaces),而后再依个别的建构形式应用。 1. 在 linux 平台下应用CMake生成Makefile并编译的流程 编写CMake配置文件CMakeLists.txt。执行命令cmake PATH或者ccmake PATH生成Makefile。其中,PATH是CMakeLists.txt所在的目录。应用make命令进行编译。2. CMake我的项目的文件目录结 ├── CMakeLists.txt├── include│ └── Hello.h├── src│ ├── Hello.cpp│ └── main.cpp└── build3. CMake根本脚本 # 指明对cmake的最低(高)版本的要求cmake_minimum_required(VERSION 2.6) # 创立我的项目project (ProjectName)# 查找依赖包,如果找到PACK库就把头文件(应该能够这么说吧)门路和库文件门路赋值给上面两个语句中的 ${PACK_INCLUDE_DIRS}、${PACK_LIBRARIES}。find_package(PACK REQUIRED)include_directorise(${PACK_INCLUDE_DIRS})link_directorise(${PACK_LIBARAY_DIRS})add_definition(${PACK_definition})# 创立源文件变量SOURCES,并在可执行程序中增加源文件set(SOURCES src/Hello.cpp src/main.cpp) add_executable(ProjectName ${SOURCES})# 设置要蕴含的头文件的目录、设置要链接的库target_include_directories(ProjectName PRIVATE ${PROJECT_SOURCE_DIR}/include)target_link_libaries(ProjectName ${PACK_LIBARIES})# 指定在装置时运行的规定install(TARGET ProjectName RUNTIME DESTINATION bin)4. 生成可执行文件 cd build #内部编译cmake .. #生成Makefile文件make #生成可执行文件./ProjectName #执行可执行文件

November 16, 2021 · 1 min · jiezi

关于cmake:CMakeListtxt-系列2

1 aux_source_directory(<dir> <variable>)在目录中查找所有源文件。收集指定目录中所有源文件的名称,并将列表存储在提供的变量中。 该命令旨在供应用显式模板实例化的我的项目应用。2 cmake_minimum_required:指定运行此配置文件所需的 CMake 的最低版本;3 反对 gdb 让 CMake 反对 gdb 的设置也很容易,只须要指定 Debug 模式下开启 -g 选项: set(CMAKE_BUILD_TYPE "Debug")set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

October 14, 2021 · 1 min · jiezi

关于cmake:CMakeListstxt系列1

咱们晓得makefile是在Linux编译c或者c++代码的时候的一种脚本文件,然而每一个性能都要写一个makefile文件,这样如果这个工程很大,而且相关性比拟强的话,makefile的书写就会变得绝对繁琐,更要命的是如果当前须要增加新的性能或者是新人须要批改性能的话,看起来就会特地麻烦;因为介于此,cmake的呈现就是为了解决这样的问题,cmake的入门相当容易,而且治理也特地不便简略,那咱们开始吧。 cmake的所有语句都写在一个CMakeLists.txt的文件中,CMakeLists.txt文件确定后,间接应用cmake命令进行运行,然而这个命令要指向CMakeLists.txt所在的目录,cmake之后就会产生咱们想要的makefile文件,而后再间接make就能够编译出咱们须要的后果了。更简略的解释就是cmake是为了生成makefile而存在,这样咱们就不须要再去写makefile了,只须要写简略的CMakeLists.txt即可。cmake的执行流程很简略,咱们的重点是如何编写CMakeLists.txt文件呢,咱们通过例子来学习cmake的语法。 例子从这篇文章中学习http://blog.csdn.net/dbzhang8...,大抵如下:1、一个单文件的简略的例子 文件名字为main.c 内容如下: #include <stdio.h>int main(){ printf("Hello World Test!\n"); return 0;}CMakeLists.txt文件内容如下: project(hello_jelly)set(APP_SRC main.c)add_executable(${PROJECT_NAME} main.c) #print messagemessage(${PROJECT_SOURCE_DIR})解释代码: 第一个行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 文件中,命令名字是不辨别大小写的,而参数和变量是大小写相干的。 而后将以上两个文件放在对立目录上面,留神编译产生时候分为两种,一种是间接在以后源码目录执行cmake命令#cmake ./,然而这样会在当前目录下产生很多临时文件和目录,另一种形式就是在当前目录新建一个build目录,而后我门进入到build目录,执行命令cmake ../,这样产生的所有临时文件都会生成在build目录下,而不影响源码目录的代码,此处咱们采纳第二种办法。咱们进入到build目录,执行命令#cmake ../,而后在当前目录能够看到文件如下 drwxrwxr-x 3 zqq zqq 4096 9月 28 17:12 CMakeFiles-rw-rw-r-- 1 zqq zqq 993 9月 28 17:12 cmake_install.cmake-rw-rw-r-- 1 zqq zqq 5479 9月 28 17:12 Makefile最初再在此目录执行make即可生成相应的可执行程序。2、多个源文件的操作 hello.h头文件内容如下 #ifndef JELLYHELLO#define JELLYHELLOvoid hello(const char* name);#endifhello.c文件内容 ...

October 14, 2021 · 1 min · jiezi

关于cmake:CMake使用入门

在进行C++时,抉择什么样的编译器显得十分的重要。与其它的语言不同,C++的程序最终由头文件(.h)以及库文件(.dll或.so)组件。不同的利用(库)帮助工作时,同样须要对文件及库文件的反对,而不同的平台上的库文件是不统一的,所以在跨平台的开发中,咱们更喜爱应用cmake来进行编译链接。 所以cmake并不是包管理工具,他并不可能解决包的依赖问题,而仅仅解决的跨平台的问题。 编译器将源代码变成可执行的利用须要一个叫做编译器的货色,如果在利用中应用了曾经成型的第三方库,或是本人的利用较大,须要多个模块配合的话。还须要将这些模仿连接起来,最终造成一个能够应用的应用程序。 就这像在一个规范的Spring boot我的项目在构建时,可能构建出一个蕴含本人和其它第三方库,可被间接运行的xxx.jar和一个只蕴含本人的可被用做第三方库的xxx.jar.original文件。 而将源代码变成可执行的字节码的过程叫做编译,将源代码本人生成的库与其它库连在一起,最初造成可执行应用程序的过程则叫做链接。 实现上述性能的工具则称为编译器。 在java开发中,咱们须要针对不同的操作系统下载不同的jdk。这个jdk中有一部分的作用便是java的编译器。在C++开发中,macos中曾经默认装置了一款名为clang的编译器,所以咱们并不需要独自的装置它。 须要叫各个系统中c++的编译器不同,比方macos中默认装置的是clang。除此以外,编译器还有注明的GNU(gcc、g++)。而不同的编译器均领有本人的特点,咱们在开发利用时,也会将这些编译器的特点退出到咱们的源代码中。而后编译器在依据源代码来编译为字节文件。在有些个性只有特定的编译器才反对,这也是为什么有的利用只能应用特定编译器编译能力工作的起因。 依赖治理java中有比拟驰名的maven、gradle包管理器,它可能主动的为咱们下载依赖,接着调用指定的jdk进行编译,可能实现java利用的打包工作。 不太侥幸的是c++利用中并没有这么弱小的包管理工具。但一个多模块有依赖的我的项目,实现的思维依然是雷同的。 如同npm下治理的包在package.json中申明了须要的包及版本号,而后应用npm install的命令来装置。C++的利用则能够在CMakeLists.txt来申明版本号。而后应用其它的形式来装置。 加载依赖后面讲了cmake是一款跨平台的编译器,而它对应的配置文件则是CMakeLists.txt,在该文件中阐明了对其它第三方包的依赖。 find_package()CMakeLists.txt申明依赖的形式大体分为两种,第一种是应用find_package。比方:find_package(JsonCpp REQUIRED)。此时CMake会先查找其外部包,如果没有在外部包中找到,则会在当前目录下查找文件FindJsonCpp.cmake文件。如果找到了FindJsonCpp.cmake文件,则会按该文件的设置加载包;如果没有找到,因为第二个参数设置的值为REQUIRED,则会抛出一个异样。 所以如果某些第三方包提供了FindXxxx.cmake文件的话,能够轻松的应用find_package(name, REQUIRED)函数来加载第三方包。 个别状况下,如胜利的找到第三方包将会定义如下变量: # 找到包时,该值为trueXxxx_FOUND# 该包头文件所在位置Xxxx_INCLUDE_DIRS 或 Xxxx_INCLUDES# 该包库文件所在位置Xxxx_LIBRARY 或 Xxxx_LIBRARIES 或 Xxxx_LIBS# 能够应用message(${Xxxx_LIBRARIES})来打印变量的值pkg_check_modules()第二种形式是借助于PkgConfig: find_package(PkgConfig REQUIRED)当零碎未装置PkgConfig则会提到一个未找到PkgConfig的谬误,此时则须要在零碎中装置PkgConfig。 有了PkgConfig后便能够应用其提供的pkg_check_modules包检测办法来获取第三方包的信息了: pkg_check_modules(JSONCPP jsoncpp)其中JSONCPP为别名能够轻易起,jsoncpp为模块名。 此时当存在jsoncpp时,则零碎变量JSONCPP__FOUND的值为true,否则为false。如果以后我的项目必须依赖于某个第三方包,则能够退出REQUIRED,比方:pkg_check_modules(XXX xxx REQUIRED)此时当不存在xxx时将会产生一个异样。 加载无论是通过find_package()还是通过pkg_check_modules来获取第三方依赖包,其本质上都是在:查看是否存在某个包,如果存在则返回该包的信息,如果不存在,则将零碎变量Xxxx_FOUND设置为false。除此以外,并没有其它作用。 也就是说上述两个办法并没有加载对其第三方的依赖。这所以要应用命令来查找某个包的信息(包的库文件、头文件地位),也是思考了跨平台的起因。在跨平台的状况下,咱们不能应用诸如windows中的c:\xxx\xxx或xunix中的~/xxx/xxx任一模式。所以在加载某个依赖前,须要通过上述办法来动静获取包的信息,如果以后应用的是windows零碎,则能够是c:\xxx\xx的模式,如果应用的是xunix零碎,则可能是/usr/local/xxx的模式。 加载第三方库须要将头文件使在地位应用include_directories蕴含进来,并将库应用target_link_libraries链接进来。 include_directories(project-name ${Xxxxx_INCLUDE_DIRS})target_link_libraries(project-name ${Xxxxx_LIBRARIES})包管理器Microsoft提供了vcpkg来装置c++利用的依赖。应用shell装置形式如下: # clone仓库git clone https://github.com/Microsoft/vcpkg.git --depth=1# 进入仓库cd vcpkg# 运行装置脚本./bootstrap-vcpkg.sh# 设置为全局装置,当前再装置其它包的时候,都是全局的./vcpkg integrate install执行齐全局装置后,将会失去一个提醒: panjie@panjies-iMac vcpkg % ./vcpkg integrate installApplied user-wide integration for this vcpkg root.CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=/Users/panjie/github/Microsoft/vcpkg/scripts/buildsystems/vcpkg.cmake"它在说如果咱们再应用CMake工具的话,则须要在CMake命令后追加上述参数。如果咱们应用了Clion编辑器,则须要将其增加到CMake options中:此时Clion中的Cmake则会在执行时主动退出上述参数。自此以后Clion便能够和cmake及vcpkg包管理器欢快的工作在一起了。 ...

May 22, 2021 · 1 min · jiezi

CMake-系列四用-GoogleTest-测试

今天我们来说说,CMake 测试。 不过,其实我们还是在说 C++ 的测试。 CMake 给我们提供了完善的测试支持,比如它有一个专门的模块 CTest。 CMake 原生测试支持CMake 原生支持的测试很简单,只有两个函数: enable_testing()add_test(NAME <name> COMMAND <command> [<arg>...] [CONFIGURATIONS <config>...] [WORKING_DIRECTORY <dir>] [COMMAND_EXPAND_LISTS])这个用法,简单来说,就是你需要先实现一个可以接受输入参数的可执行程序,用 add_executable 就可以,不用管这个可执行程序的存放目录,CMake 会帮你自动填上。 enable_testing()add_executable(test_example test.cpp)target_link_libraries(test_example example_lib)add_test(NAME test_example1 COMMAND test_example --arg1=a --arg2=b)add_test(NAME test_example2 COMMAND test_example --arg1=c --arg2=d)然后,通过 add_test 注册你的测试用例后,就完成了准备,之后就可以在编译完成后,用以下三种方式来运行来运行测试用例。 make testcmake --build . --target testctest当然了,你也可以用 CTest 来结合 CDash 一起使用,CDash 就是一个可以记录测试日志的地方,你可以去 https://my.cdash.org/index.php 一探究竟,一般来说,项目大了之后就会有这方面的需求。 GoogleTest除了上面的 ctest,我们还有强大的 GoogleTest,这是目前用得比较广泛的 C++ 测试框架。不同于上面需要自己实现测试框架逻辑、解析参数,GoogleTest 提供了测试框架,以及 Mock。 CMake 也提供了 GoogleTest 的支持: gtest_add_tests(TARGET target [SOURCES src1...] [EXTRA_ARGS arg1...] [WORKING_DIRECTORY dir] [TEST_PREFIX prefix] [TEST_SUFFIX suffix] [SKIP_DEPENDENCY] [TEST_LIST outVar])它是用来取代 add_test 的,通过扫描源代码,它就能读出所有的测试用例,省却了两边重复写的问题,但是它有个问题:一旦测试用例改变,它就需要重新跑 cmake,不然无法知道改变后的测试用例。 ...

July 6, 2020 · 1 min · jiezi

CMake基本使用

cmake是个很方便的构建系统。官方的文档写的很明白,就是有点长。于是,根据自己的使用情况,挑选其中最重要的,简要说明于下: CMakeLists.txt的编写CMakeLists.txt的命令不区分大小写。 基本结构# 最低版本声明,如果本机的cmake版本小于这个,会告警cmake_minimum_required(VERSION 3.10)# set the project nameproject(Tutorial)# add the executableadd_executable(Tutorial tutorial.cxx)# 生成库# add_library( MyMath STATIC mymath.cpp)注:add_executable和add_library可以源码列表,源码文件可以在后面通过target_sources添加。因为target_xxx_xxx的命令要求target先定义好,所以这一功能挺重要。 子目录添加子目录前,需要先为子目录编写CMakeLists.txt。 add_subdirectory( MathFunctions )依赖库指定路径link_directories(Tutorial "${PROJECT_SOURCE_DIR}/lib" )注:link_directories只对在它后面声明的target有效。 指定库target_link_libraries支持多种格式,以libopus.a为例 target_link_libraries(Tutorial opus)target_link_libraries(Tutorial -lopus)target_link_libraries(Tutorial libopus.a)# 全路径target_link_libraries(Tutorial ${PROJECT_SOURCE_DIR}/lib/libopus.a)如果不是全路径模式,需要先指定路径。注:target_link_libraries加入的顺序非常重要。比如Tutorial依赖libA.a, libA.a依赖libB.a。那么libA.a需要放在libB.a之前,不然会报错,说libB.a的符号找不到。据说是有一个选项,会尽量去掉没使用的符号。如果先写libB.a,则链接libB.a时发现没有人在使用它,就把它去掉了。不过是啥选项没研究,默认行为,还是注意下顺序吧。 宏定义target_compile_definitions(foo PUBLIC FOO)target_compile_definitions(foo PUBLIC -DFOO) # -D removedtarget_compile_definitions(foo PUBLIC "" FOO) # "" ignoredtarget_compile_definitions(foo PUBLIC -D FOO) # -D becomes "", then ignored#定义带值的target_compile_definitions( Tutorial PRIVATE "LOG_LEVEL=2" )编译选项add_compile_options(-Wall -Wextra -pedantic -Werror)add_compile_options(-std=c++11 -g)设置变量set(LIB_SRC src/mymath.cpp src/myadd.cpp ...)条件生成if(WIN32) xxxelseif(ANDROID) xxxelseif(IOS) xxxendiftarget的生成地址set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}) 增加install#安装target(lib/app)install( TARGETS Tutorial DESTINATION bin)#安装头文件install( FILES ${PROJECT_BINARY_DIR}/config.h DESTINATION include )有了这个以后,就可以用make install安装了 ...

June 28, 2020 · 1 min · jiezi

CMake-系列三ExternalProject-实践

上次 说了第三方依赖管理,提到了我们团队在使用 ExternalProject 来管理依赖,这次来说说具体实践,以及一个基于 CMake 的开源依赖管理工具 vcpkg。 ExternalProject 实践来看看它长什么样: ExternalProject_Add(<name> [<option>...])ExternalProject_Add_Step(<name> <step> [<option>...])ExternalProject_Get_PropertyExternalProject_Add_StepTargets(<name> [NO_DEPENDS] <step1> [<step2>...])是不是很简单,显然不是,文档里写成这样是因为参数太多了,惊不惊喜? 其实大部分参数用不到,我就挑选一些常用的参数来说说,从步骤来说,它主要分以下几步: 目录配置 PREFIX:目录前缀,建议选个自己看得顺眼的;DOWNLOAD_DIR:这个重要了,建议选个编译目录同级的,这样删掉编译目录后,就相当于缓存目录了,下次再编译就可以节约下载时间;下载 URL & URL_HASH:包的下载与校验,建议即使有 Git 项目也使用,这样可以进一步减少下载时间(就国内的网络克隆 GitHub 而言 T_T);GIT_REPOSITORY & GIT_TAG:Git 项目克隆,建议加上 GIT_SHALLOW,减少克隆项目的体积;更新 PATCH_COMMAND 这个可以修改后的源文件,比如你可以作为临时 BUG 的修改方案,毕竟项目的维护者不一定会及时改掉;配置 CONFIGURE_COMMAND:非 CMake 项目的配置参数,可以执行配置命令,如 ./configure --prefix=${CMAKE_INSTALL_PREFIX},另外需要配置 BUILD_IN_SOURCE true;CMAKE_ARGS:CMake 项目的配置参数,如 -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX};编译 多数情况下可略过测试 TEST_COMMAND: 需要测试编译机器执行情况的可以设置,多数情况下可略过,留空即可:TEST_COMMAND "";安装 INSTALL_COMMAND:多数情况下也可以略过,执行的标准 make install 命令,如果不是这个安装命令,可以修改;其它 DEPENDS:有其它依赖的,可以配置这个选项,它会理清这些依赖的关系,然后依次编译;在配置的时候,正如你看到的,我会通过设置 prefix 为 ${CMAKE_INSTALL_PREFIX} 将所有的第三方依赖安装在一个可配置的统一目录,这样就很方便一起打包。另外,这样有另一个好处,如果有依赖关系,大部分情况就能自动解决。 至于 ExternalProject_Add_Step 跟其它两个就略过了,不怎么用到,但是你想要编译文档的话,还是可以用的。而 ExternalProject_Get_Property 对于在你将 ExternalProject 作为主项目编译步骤时使用有些用处,只是考虑到它不是在配置时下载编译,毕竟如 target_link_libraies 这类方法需要求你已经有编译产物了,因此不怎么会用到。 ...

June 7, 2020 · 1 min · jiezi