标签 build 下的文章

1. cmake 文件中的库具体路径是什么? 比如说 ${CURL_INCLUDE_DIR}。 这个其实是 /usr/share/cmake-3.10/Modules/ 下面的 FindXXX.cmake 去寻找相应的具体目录,可以通过命令查看,当前的cmake 支持哪些库的寻找。

ll -th /usr/share/cmake-3.10/Modules/ | grep Find
cmake --help-module FindCURL

上面这条命令可以看到 cmake 关于 curl 具体能找到哪些东西,可以用于 CMakeLists.txt 的编写。

参考: https://blog.csdn.net/haluoluo211/article/details/80559341

2. ninja 安装

sudo apt install ninja-build

3. cmake 简单示例

CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
​
add_executable(hello-world main.c)

main.c:

#include <stdio.h>
​
int main(char argc, char *argv[])
{
    printf("Hello world\n");
​
    return 0;
}
mkdir build && cd build && cmake .. && make && cd .. && build/hello-world

常用命令:

include_directories(dir):指定包含的头文件目录 dir

add_subdirectory(subdir):包含的子目录 subdir,subdir 中也必须存在 CMakeLists.txt

aux_source_directory(dir var):将 dir 目录下的所有源文件赋值给变量 var

add_library(target src):用变量 src 指定的源文件生成目标文件 target,目标文件为一个库文件

target_link_libraries(target lib):链接 lib 到 target 

${PROJECT_NAME} 指的是最近的 project(name) 里面的 name.

参考: https://zhuanlan.zhihu.com/p/87283287

4. cmake 设置当前项目用的环境变量

# Set Environment Variable
# 这个环境变量只对当前cmake工程有效,对外界是无效的。
set(ENV{<variable>} [<value>])

# 找到所有dir目录下的源文件(不会递归遍历子文件夹),源文件是.c文件(也就是makefile中可以生成.o的文件)
aux_source_directory(<dir> <variable>)

参考: https://zhuanlan.zhihu.com/p/93895403

5. ${PROJECT_NAME}${CMAKE_PROJECT_NAME} 这个需要大写。 小写的话,就认为是自定义的,大写的才能对应到 project() 之类的。

6. target_link_libraries 里面的库,需要先通过 link_directories 指定位置。头文件的包含,需要 include_directories 来指定目录。

7. 简单 CMake 文件,包含对外部库的链接。

#注意:如果工程有依赖库的话,ADD_EXECUTABLE指令要放在LINK_DIRECTORIES指令之后,
#       不然会报错:Linking C executable main
#                   /usr/bin/ld: cannot find -lhello
#                   collect2: ld 返回 1

#1) 设置 cmake 的最低版本
cmake_minimum_required(VERSION 3.10)

#2) 设置 project 名称
project(ffmpeg_test)

#3) 设置代码源文件列表
set(SRC_LIST main.cpp)

#4) 增加头文件搜索路径,解决编译期间找不到头文件的问题
#COMMAND: INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dire1 dire2 ...)
#定义:向工程添加多个特定的头文件搜索路径,路径之间用空格分开,
#       如果路径中包含空格,可以使用双引号括起来
#       默认是追加到当前的头文件搜索路径之后,你可以用2种方式控制搜索路径的添加>方式
#       1)CMAKE_INCLUDE_DIRECTORIES_BEFORE 通过SET设置其为on,使用前置模式
#       2)通过AFTER或BEFORE参数,控制追加还是置前
include_directories("/usr/include/x86_64-linux-gnu")

#5) 增加库文件: 解决链接期间找不到调用外部接口的问题
#main.cpp:(.text+0x5): undefined reference to `HelloFunc()'
#collect2: error: ld returned 1 exit status

#6) 增加库文件搜索路径:解决链接期间找不到库文件的问题
#COMMAND: LINK_DIRECTORIES(dir1 dir2 ...)
#定义:添加非标准的共享库搜索路径
#/usr/bin/ld: cannot find -lhello
#collect2: error: ld returned 1 exit status
#好像相对路径会找不到库文件
link_directories("/usr/lib/x86_64-linux-gnu")

#7) 生成二进制文件
add_executable(ffmpeg_test ${SRC_LIST})

#8) 链接库
#COMMAND: TARGET_LINK_LIBRARIES(target  library1
#                                <debug | optimized> library2
#                                ...)
#定义:用来为target添加需要链接的共享库
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} hello) #链接动态库指令
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} libhello.a)  #链接静态库指令
target_link_libraries(${PROJECT_NAME} PRIVATE avutil avcodec avformat swscale)

参考: https://www.cnblogs.com/jacklikedogs/p/3780064.html https://blog.csdn.net/yangbing1113/article/details/8036707 https://cloud.tencent.com/developer/ask/115652 https://blog.csdn.net/laibowon/article/details/103746594 https://www.cnblogs.com/xianghang123/p/3556425.html https://blog.csdn.net/turbock/article/details/90034787 https://blog.csdn.net/arackethis/article/details/43488177

8. so 的库文件,后缀名必须是 .so,才能被 cmake 添加进去,如果是 .so.57 这样的,就添加不进去。

9. cmake 变量 参考: https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html

cmake 命令 参考: https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html cmake 教程 参考: https://cmake.org/cmake/help/v3.16/guide/tutorial/index.html

10. cmake 多层目录如下:

.
├── CMakeLists.txt
├── CMakeLists.txt.bak
├── common.c
├── common.h
├── compile.sh
├── json
│   ├── cJSON.c
│   ├── cJSON.h
│   ├── CJsonObject.cpp
│   ├── CJsonObject.hpp
│   └── CMakeLists.txt
├── main.cpp
├── main.h
├── run.sh
├── sa_in.txt
├── token.c
└── token.h

顶层 CMakeLists.txt :

cmake_minimum_required(VERSION 3.10)
project(sentiment_analysis)

find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR})

add_subdirectory(json)

add_executable(${PROJECT_NAME} main.cpp common.c token.c)
target_link_libraries(${PROJECT_NAME} ${CURL_LIBRARY} json_binary)

下层 CMakeLists.txt :

project(json_binary)

add_library(${PROJECT_NAME} cJSON.c CJsonObject.cpp)

target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})

参考: https://www.cnblogs.com/svenzhang9527/p/10704777.html

11. 设置 C++ 标准为 C++11

set(CMAKE_CXX_STANDARD 11)

参考: https://www.cnblogs.com/svenzhang9527/p/10704718.html https://blog.csdn.net/justidle/article/details/105240822

12.

PROJECT(projectname [CXX] [C] [JAVA])

用于指定工程名字,[]为可选内容,默认表示支持所有语言。注意这条指令还隐式定义了另外两个变量<projectName>_BINARY_DIR<projectName>_SOURCE_DIR。我们这里的project定义为了hello,所以这两个变量就是${hello_BINARY_DIR}${hello_SOURCE_DIR}。什么意思呢,可以用message命令打印出来看看他的值。

${hello_BINARY_DIR} :就是cmake要(构建)编译我们的项目(main.c)的具体路径。这里当然就是build。

${hello_SOURCE_DIR} :就是我们项目的源码的具体路径,这里当然是项目的根目录。

如果采用的是内部构建的方式,即直接在项目根目录下运行cmake,那这两个变量的值是一样的。不过一般很少使用这两个变量。大家都比较喜欢用 ${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR}.

参考: https://blog.csdn.net/Tommy_wxie/article/details/77675895

13. 编译报错:

interpreter_builder.cc:(.text+0x394): undefined reference to `dlopen'
interpreter_builder.cc:(.text+0x3a4): undefined reference to `dlsym'

在链接库里面添加 ${CMAKE_DL_LIBS} 即可

 target_link_libraries(${PROJECT_NAME} PRIVATE tensorflow-lite ${CMAKE_DL_LIBS})

参考: https://bl.ocks.org/kwk/3595733

14. 编译报错:

thread_pool.cc:(.text+0x228): undefined reference to `pthread_create'
thread_pool.cc:(.text+0x238): undefined reference to `pthread_create'

在链接库里面添加 pthread 即可

target_link_libraries(${PROJECT_NAME} PRIVATE tensorflow-lite pthread ${CMAKE_DL_LIBS})

参考: https://stackoverflow.com/questions/956640/linux-c-error-undefined-reference-to-dlopen

15. opencv

#opencv 4.+需要c++11以上版本的编译器
set(CMAKE_CXX_FLAGS "-std=c++11")
# 引入Opencv包
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# 注意use_opencv.cpp是我源代码文件名,你需要改成你源代码名
add_executable(use_opencv use_opencv.cpp)
# 链接OpenCV库
target_link_libraries(use_opencv ${OpenCV_LIBS})

参考: https://blog.csdn.net/varyshare/article/details/94162064

16. 当子文件夹需要使用第三方的 静态库 的时候,有三种方法:

1. 直接把静态库编译到子文件夹里面,这样 顶层 cmake 不需要关心这个第三方库。

#link_directories("./lib")
add_library(${PROJECT_NAME} ${ALL_SOURCE_LIST} ./lib/libtensorflow-lite.a)
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})

上面这种方法,不需要 link_directories 来链接第三方库,只需要生成子文件库的时候,指明需要添加进去的库即可,这样第三方库变为子文件库二进制文件的一部分,所以对于上层来说,只要不直接调用第三方库的 API,那么就不需要添加第三方库的库文件夹路径和头文件夹路径。

2. 不把静态库编译到子文件夹里面,顶层 cmake 需要关系这个第三方库。

add_library(${PROJECT_NAME} ${ALL_SOURCE_LIST})
target_link_libraries(${PROJECT_NAME} PRIVATE tensorflow-lite ${CMAKE_DL_LIBS})
link_directories("./sub/lib")

子文件夹下不用把 第三方库编译进去,只需要指明链接的库就行,在顶层 cmake 里面需要指定库所在的路径,否则最后链接库的时候,会找不到这个第三方库。

3. 类似于第一种方法

link_directories("./lib")
add_library(${PROJECT_NAME} ${ALL_SOURCE_LIST})
link_libraries(${PROJECT_NAME} PRIVATE tensorflow-lite ${CMAKE_DL_LIBS})

这样,在编译子文件夹后,立刻链接第三方库,然后生成子文件夹的二进制文件,这样顶层 cmake 也不需要关心第三方库了。

参考: https://segmentfault.com/a/1190000022075547 https://zhuanlan.zhihu.com/p/149191302 https://cmake.org/cmake/help/v3.5/command/link_libraries.html

17. add_definitions

add_definitions 作用是代码中的 #define 的功能。类似于 add_definitions(-DTEST_IT_CMAKE) 这样的写法。

option(TEST_IT_CMAKE "test" ON)
message(${TEST_IT_CMAKE})
if(TEST_IT_CMAKE)
    message("itis" ${TEST_IT_CMAKE})
    add_definitions(-DTEST_IT_CMAKE)
endif()

参考: https://blog.csdn.net/qq_35699473/article/details/115837708
https://cmake.org/cmake/help/latest/command/add_definitions.html

18. cmake 代码分支编译

代码写法类似

option (USE_MYMATH "Use provided math implementation" ON)
if (USE_MYMATH)
    message(STATUS "USE_MYMATH")
elseif (USE_XXX)
    message(STATUS "USE_XXX")
endif()

if(${address} STREQUAL "ON") 这种字符串比较经过实际测试,发现不起效果,可能是版本问题,或者其他情况。 具体参考: https://www.cnblogs.com/lidabo/p/13846640.html
https://www.jianshu.com/p/f0f71d36411a
https://blog.csdn.net/maizousidemao/article/details/104103279
https://www.cnblogs.com/rickyk/p/3872568.html
https://blog.csdn.net/Calvin_zhou/article/details/104025714
https://blog.csdn.net/hp_cpp/article/details/110373926
https://blog.csdn.net/lyq308152569/article/details/109388437

19. cmake 调试, 线程,报警信息

add_definitions("-Wall -lpthread -g -rdynamic")  

参考: https://www.cnblogs.com/lidabo/p/7359422.html
https://blog.csdn.net/liu0808/article/details/79046022/

20. gcc 报警信息综合

https://blog.csdn.net/XiaoH0_0/article/details/107513936

21. sanitize

target_link_libraries(${PROJECT_NAME} PRIVATE libtengine-lite.so libface.so ${OpenCV_LIBS} -fsanitize=address -fsanitize=leak )

cmake 资料参考:

https://www.cnblogs.com/binbinjx/p/5626916.html https://www.cnblogs.com/is-smiling/p/3269059.html https://www.cnblogs.com/coderfenghc/archive/2012/06/23/2559603.html https://blog.csdn.net/bigdog_1027/article/details/79113342

ninja 资料参考:

https://ninja-build.org/manual.html#_the_literal_phony_literal_rule https://blog.csdn.net/qiuguolu1108/article/details/103842556 https://www.jianshu.com/p/c4d3ba6c6470 https://ninja-build.org/manual.html https://github.com/ninja-build/ninja https://blog.csdn.net/u010164190/article/details/104932437 https://www.cnblogs.com/fuland/p/3641311.html https://www.cnblogs.com/fuland/p/3641314.html https://www.cnblogs.com/fuland/p/3641317.html https://www.cnblogs.com/sandeepin/p/ninja.html

学习 《QT快速入门》命令行这一小节,发现有点问题。 编译的时候会提示没有 QApplication。 解决办法是在 *.pro 中添加

QT += widgets

在win7的命令行中要进行编译,首先环境变量当中要加入 \Tools\mingw482_32\bin 和 \5.3\mingw482_32\bin

  1. qmake -project
  2. qmake
  3. mingw32-make.exe

今天使用GCC编译的时候发现了一个错误,invalid application of 'sizeof' to incomplete type 。 这个错误的原因是sizeof是在编译阶段进行计算的,而extern是在链接阶段工作的,所以在多文件的时候会出现这个错误。 解决办法也很简单,就是在头文件里面extern的地方显式的表现出数组的大小。

在archlinux中,使用kmod 替换了 module-init-tools,所以造成了安装 目标板对应的 nfs中的模块提示出错,解决方法是:先安装module-init-tools, 再修改linux 源代码目录下面的Makefile。

安装 module-init-tools: 先安装docbook2x: sudo pacman -S docbook2x 然后下载module-init-tools-3.2.2,我这边3.12版本的make check 都不能通过,所以只好用3.2.2的 如果有补丁 patch -Np1 -i ../../src/module-init-tools-3.2.2-modprobe-1.patch

编译 ./configure make check make distclean ./configure --prefix=/ --enable-zlib make

安装 make INSTALL=install DESTDIR=/usr/local/module-init-tools install

下面是修改linux源代码目录的makefile 找到 DEPMOD 定义的那一行,把/sbin/depmod, 修改为/usr/local/module-init-tools/depmod 就可以安装目标系统模块了