前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >成为Oceanbase贡献者(2):源码解读build.sh debug --make 的执行过程

成为Oceanbase贡献者(2):源码解读build.sh debug --make 的执行过程

原创
作者头像
程序员小王
发布2025-01-27 17:54:05
发布2025-01-27 17:54:05
4700
代码可运行
举报
文章被收录于专栏:践行笔记
运行总次数:0
代码可运行

本文主要描述:源码如何编译ob build.sh debug --make 的执行过程

代码语言:javascript
代码运行次数:0
复制
# 1. 初始化依赖
./build.sh --init

# 2. 选择编译模式(debug/release等)
./build.sh debug --make -j 10 -DCPP_STANDARD_20=ON
./build.sh release --make

//在在mac执行 ,跳过初始化动作
./build.sh debug --make
  grep: /proc/cpuinfo: No such file or directory
代码语言:javascript
代码运行次数:0
复制
# 设置C++标准
if(CPP_STANDARD_20)
    message(STATUS "Using C++20 standard")
    set(CMAE_CXX_FLAGS "-std=gnu++20")
else()
    message(STATUS "Using C++11 standard")
    set(CMAKE_CXX_FLAGS "-std=gnu++11")
endif()

# 检查编译器
if (OB_CC)
    message(STATUS "Using OB_CC compiler: ${OB_CC}")
endif()
if (OB_CXX)
    message(STATUS "Using OB_CXX compiler: ${OB_CXX}")
endif()

一、最小知识准备:了解 CMake工具

开源软件开发:许多开源项目如 TensorFlow、Boost 等都使用 CMake 进行跨平台构建

CMake 与CMakeLists.txt关系?

CMake 是一个跨平台的开源构建系统,用于管理软件项目的编译过程,

通过读取CMakeLists.txt文件,生成适用于不同的操作系统和编译器环境 构建文件

CMake 与makefile关系?

CMake本身不直接生成可执行文件,而是生成其他构建工具所需的中间文件

例如Make能够输出各种各样的makefile

  • Makefile:适合小型项目或需要手动调整构建流程的场景。由于其直接编写规则,灵活性较高,但难以管理复杂的依赖关系和跨平台兼容性。
  • CMake:适合大型项目和跨平台开发。CMake通过抽象化的配置文件(CMakeLists.txt),可以轻松生成适用于不同平台的构建系统,从而实现“Write once, run anywhere”的理念

CMake 如何管理多个项目的构建?

CMake 提供了多种方式来管理多个项目的构建,具体取决于你的需求和项目结构。以下是几种常见的策略:

  1. 超级构建(Superbuild): 超级构建是一种通过一个顶级的 CMakeLists.txt 文件来管理多个子项目的构建方法。
  • 每个子项目可以有它自己的 CMakeLists.txt 文件。顶级的 CMakeLists.txt 使用 add_subdirectory() 命令将子项目包含进来,从而实现统一管理。这种方法非常适合需要同时构建多个相互依赖的项目。
  1. 使用 add_subdirectory(): 如果你的多个项目是相互关联并且存放在同一个大的源代码仓库中,你可以直接在主项目的 CMakeLists.txt 中使用 add_subdirectory() 来包含其他子项目的目录。这样做的好处是可以保持项目的模块化,同时还能在一个构建树中处理所有项目

特性

Makefile

CMake

定义方式

直接编写规则文件(.make)

编写抽象配置文件(CMakeLists.txt),生成本地化构建系统

适用范围

小型项目、手动控制场景

大型项目、跨平台开发

功能

简单的编译规则管理

高级抽象配置,支持模块化开发

跨平台性

较差,仅适用于特定平台

跨平台,支持多种IDE和编译器

灵活性

高,可直接修改规则

中等,通过配置文件间接修改构建流程

维护性

差,难以管理复杂依赖

好,支持自动化构建和模块化管理

二、最小动手实验:了解CMake编译代码的

官方 资料:https://cmake.org/cmake/help/latest/guide/tutorial/index.html

操作系统:Mac Darwin

Make版本:

brew install cmake

cmake --version

cmake version 3.31.5

/usr/local/bin/cmake -> ../Cellar/cmake/3.31.5/bin/cmake

/usr/local/Cellar/cmake/3.31.5/bin/cmake

ln -s /usr/local/Cellar/cmake/3.31.5/bin/cmake cmake

gcc版本:apple clang version 16.0.0

Clang 16.0.0 是一个相当新的编译器版本,它对C++多个标准提供了支持,包括C++11、C++14、C++17和C++20等

要指定使用哪一个C++标准进行编译,你可以通过在编译命令中添加相应的选项来实现:

  • 使用C++11标准:-std=c++11
  • 使用C++20标准:-std=c++20

为了使用 CMake 构建一个简单的 "Hello World" C++ 程序,你需要准备两个文件:一个是源代码文件(例如 main.cpp),另一个是 CMake 的构建配置文件(即 CMakeLists.txt)。下面是具体的步骤和示例代码:

1. 创建源代码文件

首先,创建一个名为 main.cpp 的源代码文件,并添加如下内容:

代码语言:javascript
代码运行次数:0
复制
#include <iostream>

int main() {
    std::cout << "Hello, LLVM!" << std::endl;
    return 0;
}

2. 创建 CMakeLists.txt 文件

接下来,在同一目录下创建一个名为 CMakeLists.txt 的文件,并添加以下内容:

代码语言:javascript
代码运行次数:0
复制
# 设置最低版本的CMake(可选)
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和版本号(可选)
project(HelloWorld VERSION 1.0)

# 查找所需的C++标准版本。这里我们使用C++11作为示例。
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 
#开启后,其生成的文件compile_commands.json,包含所有编译单元所执行的指令

# 添加可执行文件
add_executable(HelloWorld main.cpp)

3. 使用 CMake 构建项目

完成上述两步后,你就可以使用 CMake 来构建你的项目了。以下是构建步骤:

  • 打开命令行界面,导航到包含 CMakeLists.txtmain.cpp 文件的目录。
  • 创建一个用于存放构建结果的子目录(这是一个好习惯,它能保持源代码目录的清洁),并进入该目录:
代码语言:javascript
代码运行次数:0
复制
mkdir  build_debug
cd build_debug
  • 运行 CMake 配置步骤,指定源代码所在的目录(上一级目录):
代码语言:javascript
代码运行次数:0
复制
cmake -DCMAKE_BUILD_TYPE=Debug ..
//Now we need to setup debug and release builds. 
//We can use CMAKE_BUILD_TYPE to set the configuration type:
  • 最后,编译项目:
代码语言:javascript
代码运行次数:0
复制
构建、编译和运行

cmake --build .
//cmake --build . 是一种简化构建流程的方法,让你不必关心底层使用的具体构建工具是什么,
//同时提供了足够的灵活性来满足不同的构建需求。
[ 50%] Building CXX object CMakeFiles/HelloWorld.dir/main.cpp.o
[100%] Linking CXX executable HelloWorld
[100%] Built target HelloWorld

 --build <dir>                = Build a CMake-generated project binary tree.
                                 Run "cmake --build" to see compatible

如果一切顺利,这将在 build 目录中生成一个名为 HelloWorld 的可执行文件(在 Windows 上可能是 HelloWorld.exe)。你可以直接运行这个文件来查看输出:

代码语言:javascript
代码运行次数:0
复制
./HelloWorld

tool -L HelloWorld 

HelloWorld:
	/usr/local/opt/llvm/lib/unwind/libunwind.1.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/local/opt/llvm/lib/c++/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)

你应该会在终端看到输出 "Hello, World!"。

这就是使用 CMake 和 C++ 编写一个简单的 "Hello World" 应用程序的完整过程。

三。 build.sh debug --make 源码阅读

代码如下:

./build.sh debug --make -j 10 -DCPP_STANDARD_20=ON

代码语言:javascript
代码运行次数:0
复制
*)  
parse_args //参数解析阶段
try_init
build 编译配置阶段
try_make CMake处理阶段
;;

./build.sh debug --make -j 10 -DCPP_STANDARD_20=ON

1. 参数解析阶段 获取命令参数 保持到全局变量中

# parse_args函数处理参数

BUILD_ARGS=(debug) # 编译类型 debug

MAKE_ARGS=(-j $CPU_CORES) # 并行构建的任务数 32

NEED_MAKE=true # 需要执行make --make

说明:try_init 过程前面执行完成,这里跳过

2.编译配置阶段【这里跳过初始化】
代码语言:javascript
代码运行次数:0
复制
function do_build {
    # -f 检查 ${TOOLS_DIR}/bin/cmake 文件是否存在,如果不存在则提示初始化依赖并退出
    if [ ! -f ${TOOLS_DIR}/bin/cmake ]; then
      echo_log "[NOTICE] Your workspace has not initialized dependencies, please append '--init' args to initialize dependencies"
      exit 1
    fi
    // mac :ln -s  /usr/local/bin/cmake cmake 

    # 获取第一个参数作为构建类型debug,并将其赋值给 TYPE 变量,然后移除该参数
    //./build_mac.sh debug --make
    TYPE=$1; shift
    // TYPE: debug  第一个参数
    # 调用 prepare_build_dir 函数准备构建目录,如果失败则返回
    # create build directory and cd it.
    # /Users/wcy/code/github/oceanbase/build_debug
    # 2. 准备构建目录
    prepare_build_dir $TYPE || return
    
    # 使用 CMAKE_COMMAND 运行 cmake 命令生成 Makefile,传递 TOPDIR 和剩余参数,并设置 CPP_STANDARD_20 选项
    ${CMAKE_COMMAND} ${TOPDIR} "$@" -DCPP_STANDARD_20=$CPP_STANDARD_20_OPTION
    //cmake 
    // -DCMAKE_BUILD_TYPE=Debug 
    // -DCPP_STANDARD_20
    //-DCMAKE_EXPORT_COMPILE_COMMANDS=1 
    GCC版本要求
    //默认支持C++11标准 (代码中 CPP_STANDARD_OPTION=11)
    //如果使用-DCPP_STANDARD_20=ON,则需要支持C++20标准的GCC版本
    # 检查上一条命令的退出状态,如果不为 0 则打印错误信息并退出
    if [ $? -ne 0 ]; then
      echo_err "Failed to generate Makefile"
      exit 1
    fi
}
3. CMake处理阶段

顶层CMakeLists.txt

代码路径:oceanbase/CMakeLists.txt

代码语言:javascript
代码运行次数:0
复制
cmake_minimum_required(VERSION 3.20.0)
project(oceanbase)

# 包含环境配置
include(cmake/Env.cmake)

# 添加子目录
add_subdirectory(src)
add_subdirectory(deps/oblib/src/lib)

Env.cmake配置

代码语言:javascript
代码运行次数:0
复制
# 设置C++标准
if(CPP_STANDARD_20)
    message(STATUS "Using C++20 standard")
    set(CMAKE_CXX_FLAGS "-std=gnu++20")
else()
    message(STATUS "Using C++11 standard")
    set(CMAKE_CXX_FLAGS "-std=gnu++11")
endif()

# get compiler from build.sh
ob_define(OB_CC "")
ob_define(OB_CXX "")
# 检查编译器
 if (OB_CC)
    message(STATUS "Using OB_CC compiler: ${OB_CC}")
  else()
    find_program(OB_CC clang
    "${DEVTOOLS_DIR}/bin"
      NO_DEFAULT_PATH)
  endif()

if (OB_CXX)
    message(STATUS "Using OB_CXX compiler: ${OB_CXX}")
  else()
    find_program(OB_CXX clang++
    "${DEVTOOLS_DIR}/bin"
      NO_DEFAULT_PATH)
  endif()
CMake中编译器如何选择?
if (OB_CC AND OB_CXX)
  set(CMAKE_C_COMPILER ${OB_CC})
  set(CMAKE_CXX_COMPILER ${OB_CXX})
else()
  message(FATAL_ERROR "can't find suitable compiler")
endif()

标准库区别:

在使用 C++ 编译器(如 GCC 和 Clang)时,-std=gnu++11-std=c++11 是两个不同的标准选项,它们有一些关键的区别。以下是这两个选项的详细解释:

-std=c++11

  • 纯 C++ 标准:这个选项严格遵循 C++11 标准。
  • 不包含 GNU 扩展:编译器不会启用任何 GNU 特定的扩展。
  • 可移植性更好:由于不包含 GNU 扩展,代码更容易在不同编译器之间移植。

-std=gnu++11

  • C++ 标准 + GNU 扩展:这个选项不仅遵循 C++11 标准,还启用了 GNU 编译器的一系列扩展。
  • 包含 GNU 扩展:编译器会启用一些非标准的功能和特性,这些功能可能在其他编译器上不可用。

编译器区别:

在 macOS 上,默认的 C 和 C++ 编译器通常是基于 LLVM 的 Clang 编译器,而非 GCC(GNU Compiler Collection)

gcc:/usr/bin/gcc gcc - GNU project C and C++ compiler

g++ /usr/bin/g++. GNU project C and C++ compiler

clang:clang - the Clang C, C++, and Objective-C compiler

/usr/local/opt/llvm/bin/clang

四、build.sh debug --make具体执行过程

代码语言:javascript
代码运行次数:0
复制
./build.sh debug --make -j 10 -DCPP_STANDARD_20=ON

目录准备:
//prepare_build_dir
mkdir  /Users/watchpoints/code/github/oceanbase/build_debug
cd /Users/watchpoints/code/github/oceanbase/build_debug

//CMake配置:
//转变成cmake命令
/Users/watchpoints/oceanbase/deps/3rd/usr/local/oceanbase/devtools/bin/cmake
-DCMAKE_EXPORT_COMPILE_COMMANDS=1 
/Users/watchpoints/code/github/oceanbase 
-DCMAKE_BUILD_TYPE=Debug 
-DOB_USE_LLD=ON 
-DCPP_STANDARD_20=OFF


https://discourse.cmake.org/t/could-not-find-cmake-root/216



 输出信息解释
-- Using C++11 standard  # 来自Env.cmake
-- build with pie        # 编译选项设置
-- Using OB_CC compiler  # 显示使用的编译器
-- check deps for libeasy  # 依赖检查

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、最小知识准备:了解 CMake工具
    • CMake 与CMakeLists.txt关系?
    • CMake 与makefile关系?
    • CMake 如何管理多个项目的构建?
  • 二、最小动手实验:了解CMake编译代码的
    • 1. 创建源代码文件
    • 2. 创建 CMakeLists.txt 文件
    • 3. 使用 CMake 构建项目
  • 三。 build.sh debug --make 源码阅读
    • -std=c++11
    • -std=gnu++11
  • 四、build.sh debug --make具体执行过程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档