C Tomar notas de estudio y práctica

No he escrito un blog en algunos días, y hoy estoy a punto de comenzar de nuevo con la "creación". Escribiré una nota de estudio sobre CMake, una herramienta de construcción de ingeniería multiplataforma, para poder revisarla y revisarla más tarde.

Introducción

  • Antecedentes
    CMake es un derivado de la compañía de kitware y algunos desarrolladores de código abierto en el proceso de desarrollar varios kits de herramientas (VTK), y finalmente formó un sistema y se convirtió en un proyecto de código abierto independiente. El proyecto nació en 2001 y su sitio web oficial es https: // La documentación de cmake. org / help es https://cmake.org/documentation/
  • Caracteristicas
  1. Código abierto, publicado bajo licencia BSD
  2. Multiplataforma, puede generar archivos de configuración de compilación nativos, en plataformas Linux / Unix, generar archivos Makefile; en plataformas macOS, generar proyectos Xcode; en plataformas Windows, generar archivos de proyectos MSVC
  3. Capaz de gestionar grandes proyectos, por ejemplo: KDE4
  4. Simplifique el proceso de compilación y el proceso de compilación, solo necesita cmake + make
  5. eficiente
  6. Extensible, puede escribir módulos con funciones específicas para CMake y expandir las funciones de CMake

Construye CMake "hola mundo"

1. Construcción interna
  • Cree archivos de origen y cree archivos de definición
#!/bin/bash
mkdir cmake_test1
cd cmake_test1
touch main.cpp 
touch CMakeLists.txt #创建CMake的构建定义文件,文件名大小写敏感
  • Editar código fuente
//main.cpp
#include <iostream>

int main() {
    
    
    std::cout << "hello world" << std::endl;
    return 0;
}
  • Edite el archivo de definición de compilación (los comandos son independientes del caso, los parámetros están relacionados)
#CMakeLists.txt
#指明对 CMake 最低版本的要求(对版本没有特殊要求可以省略)
cmake_minimum_required(VERSION 3.10.0)
#定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,默认情况表示支持所有语言
project(HELLO)
#显式定义变量,如果有多个源文件,可以在 main.cpp 后面追加,可以用空格 " " 或分号隔开 ";"
set(SRC_LISTS main.cpp)
#定义了这个工程会生成一个文件名为 hello 的可执行文件,相关的源文件是 SRC_LISTS 中定义的源文件列表,在这里可以直接写成 add_executable(hello main.cpp)
#另外需要注意的是作为工程名的 HELLO 和生成的可执行文件 hello 是没有任何关系的
add_executable(hello ${SRC_LISTS})
  • Empiece a construir
#在当前目录构建对应平台的编译配置文件
cmake . 
#输出下面的信息    
-- The C compiler identification is AppleClang 12.0.0.12000032
-- The CXX compiler identification is AppleClang 12.0.0.12000032
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/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: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/liuwenlong/Downloads/code/cmake_proj/cmake_test1

Genere archivos intermedios como CMakeCache.txt y un Makefile

  • Compilar
#编译
make
#输出下面的信息   
Scanning dependencies of target hello
[ 50%] Building CXX object CMakeFiles/hello.dir/main.cpp.o
[100%] Linking CXX executable hello
[100%] Built target hello

Se genera el archivo ejecutable hola

  • Nota
  1. projectname_BINARY_DIR (se refiere a la ruta de compilación) y projectname_SOURCE_DIR (se refiere a la ruta del proyecto)
cmake_minimum_required(VERSION 3.10.0)
#project 指令不仅定义工程名称,
#还隐式定义了两个 cmake 变量: <projectname>_BINARY_DIR(在这里就是HELLO_BINARY_DIR)和 <projectname>_SOURCE_DIR(在这里就是HELLO_SOURCE_DIR)
#CMake 系统也帮助我们预定义了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR 变量,他们的值分别跟 <projectname>_BINARY_DIR 与 <projectname>_SOURCE_DIR 一致
project(HELLO)
#message([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)指令用于向终端输出用户定义的信息,包含了三种类型:
#1.SEND_ERROR 产生错误,生成过程被跳过
#2.SATUS 输出前缀为“--”的信息
#3.FATAL_ERROR 立即终止所有 cmake 过程
message(STATUS "HELLO_BINARY_DIR: " ${HELLO_BINARY_DIR})
message(STATUS "HELLO_SOURCE_DIR: " ${HELLO_SOURCE_DIR})
message(STATUS "PROJECT_BINARY_DIR: " ${PROJECT_BINARY_DIR})
message(STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR})
  1. Variable de referencia
cmake 使用 “${
    
    }” 引用(应用)变量,但是在 “IF” 控制语句,变量是直接使用变量名引用,而不需要 “${
    
    }” ;如果使用了 “${
    
    }” 引用变量,“IF” 会去判断名为 “${
    
    }” 所代表的变量的值,那是不存在的
  • Proyecto de limpieza
#可以对构建结果进行清理,但是无法对产生的中间文件进行清理,因为 CMakeLists.txt 可以执行脚本并通过脚本生成一些临时文件,但是却没有办法来跟踪这些临时文件到底是哪些,所以推荐使用外部构建
make clean 
2. Construcción externa
  • Debido a que la compilación interna producirá archivos intermedios que no se pueden limpiar automáticamente, el directorio original parece desordenado, por lo que el método de compilación externo generalmente se usa para compilar el proyecto
cd cmake_test1
#在之前的工程目录下创建用于放置中间文件和最终生成的文件目录(build)
mkdir build
#".."利用上一层目录的CMakeLists.txt文件构建构成
cmake ..
#构建过程中的中间文件和最终生成的文件都在一个子目录中了,不会对原始目录产生任何影响了
make

Más CMake estándar "hola mundo"

A continuación, cree un proyecto "hola mundo" de CMake más estandarizado

  • Agregue un subdirectorio src al directorio del proyecto para almacenar archivos fuente
  • Los archivos intermedios y los archivos de salida binarios generados por el proceso de compilación se colocan en el archivo bin en el directorio de compilación
  • Cree un archivo ejecutable binario generado por run.sh en el directorio del proyecto
#!/bin/bash
mkdir cmake_test2
cd cmake_test2
mkdir src
mkdir build
touch run.sh
touch CMakeLists.txt
cd src
touch main.cpp
touch CMakeLists.txt
cd ../build
  • Edite el archivo de definición de compilación en el directorio del proyecto
#cmake_test2/CMakeLists.txt
cmake_minimum_required(VERSION 3.10.0)
project(HELLO)
#add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL]),该指令用于添加存放源文件的子目录( source_dir ),并可以指定中间二进制和目标二进制存放的位置( [binary_dir] 可选),EXCLUDE_FROM_ALL 参数的含义是将这个目录从编译过程中排除,如工程有 example,可能就需要工程构建完成后,再进入 example 目录单独进行构建
#下面的命令将src子目录加入工程,并指定编译输出(包含编译中间结果)路径为 bin 目录;如果不进行 bin 目录的指定,那么编译结果(包括中间结果)都将存放在 build/src 目录(这个目录跟原有的 src 目录对应),指定 bin 目录后,相当于在编译时将 src 重命名为 bin,所有的中间结果和目标二进制都将存放在 bin 目录
add_subdirectory(src bin)
  • Edite el archivo de definición de compilación en el subdirectorio src (si hay varios directorios en el proyecto, debe asegurarse de que haya un CMakeLists.txt en cada directorio a administrar)
set(SRC_LISTS main.cpp)
add_executable(hello ${SRC_LISTS})
  • EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH
#不论 add_subdirectory 是否指定编译输出目录,我们都可以通过 set 指令重新定义 EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH 变量来指定最终的目标二进制的位置(指最终生成的 hello 或者最终的共享库,不包含编译生成的中间文件)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
#添加上面命令的原则是:在哪里 add_executable 或 add_library,如果需要改变目标存放路径,就在哪里加入上述的定义
#将上面的命令加在 cmake_test2/src/CMakeLists.txt 文件中
set(SRC_LISTS main.cpp)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello ${SRC_LISTS})
  • Editar secuencia de comandos de ejecución
#!/bin/bash
cd build/bin/
./hello

Cree bibliotecas estáticas y dinámicas

  • Cree archivos de origen y cree archivos de definición
#!/bin/bash
mkdir cmake_test3
cd cmake_test3
touch CMakeLists.txt
mkdir lib
cd lib
touch hello.h
touch hello.cpp
touch CMakeLists.txt
mkdir -p ../build
  • Editar archivo fuente
//hello.h
#ifndef __HELLO__
#define __HELLO__
#include <iostream>
void printFunc();
#endif //__HELLO__
//hello.cpp
#include "hello.h"
void printFunc() {
    
    
    std::cout << "hello world" << std::endl;
}
  • Edite el archivo de definición de compilación
#/cmake_test3/CMakeLists.txt
cmake_minimum_required(VERSION 3.10.0)
project(HELLOLIB)
add_subdirectory(lib)
#/cmake_test3/lib/CMakeLists.txt

#构建动态库
set(SRC_LISTS hello.cpp)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/shared)
#add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN) 
#libname 不需要写全 libhello.so,只需要填写 hello 即可,cmake 系统会自动为你生成 libhello.X
#类型有三种:
#SHARED,动态库
#STATIC,静态库
#MODULE,在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。
#EXCLUDE_FROM_ALL 参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手工构建
add_library(hello SHARED ${SRC_LISTS})

#构建静态库
set(SRC_LISTS hello.cpp)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/static)
add_library(hello STATIC ${SRC_LISTS})

#动态库和静态库同时构建
set(SRC_LISTS hello.cpp)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/library)
#因为如果库的名字相同会创建失败,这里先创建两个不同名字的库
add_library(hello_static STATIC ${SRC_LISTS})
add_library(hello_shared SHARED ${SRC_LISTS})
#set_target_properties(target1 target2 ... PROPERTIES prop1 value1 prop2 value2 ...) 指令设置 target 属性
#可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API 版本
set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")
set_target_properties(hello_shared PROPERTIES OUTPUT_NAME "hello")
  • Construir y compilar
cmake ..
make

Hacer referencia a bibliotecas compartidas externas y archivos de encabezado

  • Cree archivos de origen y cree archivos de definición
#!/bin/bash
mkdir cmake_test4
cd cmake_test4
touch CMakeLists.txt
mkdir build
mkdir lib
mkdir src
cd src
touch main.cpp
touch CMakeLists.txt
  • Copie las bibliotecas dinámicas y estáticas y los archivos de encabezado correspondientes generados en cmake_test3 en el directorio lib
  • Editar archivo fuente
//main.cpp
#include "hello.h"
int main() {
    
    
    printFunc();
    return 0;
}
  • Edite el archivo de definición de compilación
#cmake_test4/CMakeLists.txt
cmake_minimum_required(VERSION 3.10.0)
project(LINKLIB)
add_subdirectory(src)
#cmake_test4/src/CMakeLists.txt

#默认链接动态库
set(SRC_LISTS main.cpp)
#include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...) 用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,如果路径中包含了空格,可以使用双引号将它括起来,默认的行为是追加到当前的头文件搜索路径的后面
#可以通过两种方式来进行控制搜索路径添加的方式:
#1.CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过 set 使这个 cmake 变量为 on,可以将添加的头文件搜索路径放在已有路径的前面
#2.通过 AFTER 或者 BEFORE 参数,也可以控制是追加还是置前
include_directories(../lib)
#link_directories(directory1 directory2 ...) 添加非标准的共享库搜索路径
link_directories(../lib)
add_executable(main ${SRC_LISTS})
#target_link_libraries(target library1 <debug | optimized> library2 ...) 可以用来为 target 添加需要链接的共享库
#直接写共享库的名字默认链接的使动态库
target_link_libraries(main hello)

#查看编译依赖情况
ldd main
	linux-vdso.so.1 (0x00007ffe09558000)
	libhello.so => /home/vim/longlong/cmake_test4/src/../lib/libhello.so (0x00007fa94f17a000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa94edf1000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa94ea00000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa94e662000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa94f57e000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa94e44a000)

#指定要链接的动态库
set(SRC_LISTS main.cpp)
include_directories(../lib)
link_directories(../lib)
add_executable(main ${SRC_LISTS})
#指定要链接的动态库
target_link_libraries(main libhello.so)

#Linux下查看编译依赖情况(macOS下:otool -L main)
ldd main
	linux-vdso.so.1 (0x00007ffd644fc000)
	libhello.so => /home/vim/longlong/cmake_test4/src/../lib/libhello.so (0x00007f7735891000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7735508000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7735117000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7734d79000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f7735c95000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7734b61000)

#指定要链接的静态库
set(SRC_LISTS main.cpp)
include_directories(../lib)
link_directories(../lib)
add_executable(main ${SRC_LISTS})
#指定要链接的静态库
target_link_libraries(main libhello.a)

#查看编译依赖情况
ldd main
	linux-vdso.so.1 (0x00007ffd5d197000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6fbb7e0000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6fbb3ef000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f6fbb051000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f6fbbd6b000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f6fbae39000)
  • Compilar compilar
cmake ..
make

Artículo de referencia:
[1]. "Cmake Practice"

Si hay alguna infracción, comuníquese para eliminarla. Si hay un error, corríjame, gracias

Supongo que te gusta

Origin blog.csdn.net/xiao_ma_nong_last/article/details/109687728
Recomendado
Clasificación