欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

入门CMake跨平台自动化构建系统(一):手动打造深度学习框架的准备

最编程 2024-01-12 20:05:00
...

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

用过 tensorflow 和 pytorch 不过还是想自己实现一个简单的基于 c++ 深度学习框架,帮助自己对这些算法进一步了解。

创建项目并设置可执行文件

最基本的项目是将源代码文件构建成可执行文件。对于简单的项目,创建一个名称为 CMakeLists.txt 文件,然后在文件添加如下 3 行代码即可。这将是学习 CMake 的起点。

cmake_minimum_required(VERSION 3.10)

# 设置项目名称
project(Tutorial)

# 添加可执行文件
add_executable(Tutorial main.cppc)

设置项目名称

注意这个例子在 CMakeLists.txt 文件中使用了小写的命令。CMake 支持大写、小写和混合大小写的命令。main.cpp 的源代码在 demo 目录下提供,也可以放置在 build 目录下,

首选要做的是创建一个项目,然后为项目执行可执行文件。虽然可以完全在源代码中做到这一点,但使用 CMakeLists.txt 提供了更多的灵活性,可以在构建项目来设置项目名和版本号。在 CMakeLists.txt 文件,通过project() 命令来设置项目名称和版本号。

project(Tutorial)

然后,配置一个头文件,将版本号通过头文件传递给源代码。

配置项目版本号

由于配置的文件将被写入二进制树中,需要将该目录添加到搜索包含文件的路径列表中。在 CMakeLists.txt 文件的末尾添加以下几行。在项目目录下创建TutorialConfig.h.in 文件,然后在文件中输入如下

// 配置选项和设置 Tutorial 主版本号和小版本号
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

当 CMake 配置这个头文件时,@Tutorial_VERSION_MAJOR@ @Tutorial_VERSION_MINOR@的值将被替换。可以在 CMakeLists.txt 文件创建并设置一些变量,也就是在 CMakeLists.txt 将替换调用 TutorialConfig.h.in 文件中用 @ 符号包裹的变量

set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)

接下来修改 main.cpp 文件,在头部将 TutorialConfig.h 引入,自动创建好的 TutorialConfig.h 也会出现 build 目录。

#include <iostream>
#include "TutorialConfig.h"

这样一来就可以 main.cpp 来打印输出可执行文件的名称和版本号,代码如下

cout <<  Tutorial_VERSION_MAJOR << endl;
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

project(Tutorial)

set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)

configure_file(TutorialConfig.h.in TutorialConfig.h)

add_executable(Tutorial main.cpp)

target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")
main.cpp
#include <iostream>
#include "TutorialConfig.h"
using namespace std;

int main(int argc, char const *argv[])
{
    // cout << "hello world" << endl;
    cout <<  Tutorial_VERSION_MAJOR << endl;
    // cout << Tutorial_VERSION_MINOR << endl;
    return 0;
}

指定 c++ 标准库

# 执行  C++ 标准库
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

接下来让我们在 main.cpp 中用 std::stod 替换 atof,为我们的项目添加一些 C++11特性。同时移除 #include <cstdlib>

#include <iostream>
#include "TutorialConfig.h"
using namespace std;

int main(int argc, char const *argv[])
{
    // cout << "hello world" << endl;
    cout <<  std::stod(argv[1]) * 10<< endl;
    // cout << Tutorial_VERSION_MINOR << endl;
    return 0;
}

我们将需要在 CMake 代码中明确地说明编译 C++ 标准库的版本。最简单方法是使用 CMAKE_CXX_STANDARD 变量来设置 C++ 标准库。这里将 CMakeLists.txt 文件中的 CMAKE_CXX_STANDARD 变量设为 11,当 CMAKE_CXX_STANDARD_REQUIRED 设为 True,则将CMAKE_CXX_STANDARD 指定版本引用到对 add_executable 的 cpp 文件。

运行 CMake

运行 cmake 可执行文件,然后用你选择的构建工具来构建项目。接下来进入到构建目录build,运行 CMake 来配置项目并生成一个本地构建系统。

cmake ..

使用cmake --build .调用该构建系统来编译和连接(compile/link)该项目。

cmake --build .

如果我们就可以在 build 通过执行./Tutorial来运行应用看效果了。

为项目添加自己实现 lib

现在要做的事为项目添加一个库,这个库提供了用于计算数字的平方根方法,为了解释说明这个库不是由编译器提供的标准平方根函数,而是自己实现的一个库,然后看如何编译过程中将其添加到项目中。

随后创建 MathFunctions 的子目录用于放置我们库文件。这个目录已经包含一个头文件MathFunctions.h 和一个源文件 main.cpp。在源文件中,定义名为 add 的函数,提供了与编译器的 add 函数类似的功能。

在 MathFunctions 目录下创建 MathFunctions.h 文件,这个文件有点类似接口,也就是 cpp 头文件

MathFunctions/MathFunctions.h
double add(double x, double y);

在 MathFunctions 目录下,创建一个 main.cpp 的文件,这个文件会去实现add 方法。

MathFunctions/main.cpp
#include "MathFunctions.h"

double add(double x, double y){
    return x + y;
}

然后在 MathFunctions 这个目录下,同样也创建一个 CMakeLists.txt 文件,内容如下

MathFunctions/CMakeLists.txt
add_library(MathFunctions main.cpp)

可以理解向项目添加一个包,MathFunctions 是包的名称,main.cpp 可以包向外 export 的入口文件。

main.cpp
#include <iostream>
#include "TutorialConfig.h"
#include "MathFunctions.h"

using namespace std;

int main(int argc, char const *argv[])
{
    // cout << "hello world" << endl;
    double inputValue = std::stod(argv[1]);
    // cout <<  std::stod(argv[1])<< endl;
    const double outputValue = add(inputValue,2.0);
    
    cout <<  outputValue << endl;
    // cout << Tutorial_VERSION_MINOR << endl;
    return 0;
}

在 CMakeLists.txt 文件中添加一个 add_subdirectory() 来调用 MathFunctions 目录下 CMakeLists.txt 来构建这个库。同时将也要添加到可执行文件 main.cpp,并将 MathFunctions 添加为包含目录,这样就可以找到 main.cpp 项目主文件引入 MathFunctions.h 头文件。

CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

project(Tutorial)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
set(Tutorial_NAME_VERSION 1)

configure_file(TutorialConfig.h.in TutorialConfig.h)
add_subdirectory(MathFunctions)

add_executable(Tutorial main.cpp)

target_link_libraries(Tutorial PUBLIC MathFunctions)
target_include_directories(Tutorial PUBLIC
                          "${PROJECT_BINARY_DIR}"
                          "${PROJECT_SOURCE_DIR}/MathFunctions"
                          )
add_subdirectory(MathFunctions)
  • target_link_libraries
  • target_include_directories
target_link_libraries(Tutorial PUBLIC MathFunctions)
target_include_directories(Tutorial PUBLIC
                          "${PROJECT_BINARY_DIR}"
                          "${PROJECT_SOURCE_DIR}/MathFunctions"
                          )