本文主要描述:源码如何编译ob build.sh debug --make 的执行过程
# 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
# 设置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()
开源软件开发:许多开源项目如 TensorFlow、Boost 等都使用 CMake 进行跨平台构建
CMake 是一个跨平台的开源构建系统,用于管理软件项目的编译过程,
通过读取CMakeLists.txt
文件,生成适用于不同的操作系统和编译器环境 构建文件
CMake本身不直接生成可执行文件,而是生成其他构建工具所需的中间文件
例如Make能够输出各种各样的makefile
CMakeLists.txt
),可以轻松生成适用于不同平台的构建系统,从而实现“Write once, run anywhere”的理念CMake 提供了多种方式来管理多个项目的构建,具体取决于你的需求和项目结构。以下是几种常见的策略:
CMakeLists.txt
文件来管理多个子项目的构建方法。CMakeLists.txt
文件。顶级的 CMakeLists.txt
使用 add_subdirectory()
命令将子项目包含进来,从而实现统一管理。这种方法非常适合需要同时构建多个相互依赖的项目。add_subdirectory()
: 如果你的多个项目是相互关联并且存放在同一个大的源代码仓库中,你可以直接在主项目的 CMakeLists.txt
中使用 add_subdirectory()
来包含其他子项目的目录。这样做的好处是可以保持项目的模块化,同时还能在一个构建树中处理所有项目特性 | Makefile | CMake |
---|---|---|
定义方式 | 直接编写规则文件(.make) | 编写抽象配置文件(CMakeLists.txt),生成本地化构建系统 |
适用范围 | 小型项目、手动控制场景 | 大型项目、跨平台开发 |
功能 | 简单的编译规则管理 | 高级抽象配置,支持模块化开发 |
跨平台性 | 较差,仅适用于特定平台 | 跨平台,支持多种IDE和编译器 |
灵活性 | 高,可直接修改规则 | 中等,通过配置文件间接修改构建流程 |
维护性 | 差,难以管理复杂依赖 | 好,支持自动化构建和模块化管理 |
官方 资料: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++标准进行编译,你可以通过在编译命令中添加相应的选项来实现:
-std=c++11
-std=c++20
为了使用 CMake 构建一个简单的 "Hello World" C++ 程序,你需要准备两个文件:一个是源代码文件(例如 main.cpp
),另一个是 CMake 的构建配置文件(即 CMakeLists.txt
)。下面是具体的步骤和示例代码:
首先,创建一个名为 main.cpp
的源代码文件,并添加如下内容:
#include <iostream>
int main() {
std::cout << "Hello, LLVM!" << std::endl;
return 0;
}
接下来,在同一目录下创建一个名为 CMakeLists.txt
的文件,并添加以下内容:
# 设置最低版本的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)
完成上述两步后,你就可以使用 CMake 来构建你的项目了。以下是构建步骤:
CMakeLists.txt
和 main.cpp
文件的目录。mkdir build_debug
cd build_debug
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:
构建、编译和运行
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
)。你可以直接运行这个文件来查看输出:
./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 -j 10 -DCPP_STANDARD_20=ON
*)
parse_args //参数解析阶段
try_init
build 编译配置阶段
try_make CMake处理阶段
;;
./build.sh debug --make -j 10 -DCPP_STANDARD_20=ON
# parse_args函数处理参数
BUILD_ARGS=(debug) # 编译类型 debug
MAKE_ARGS=(-j $CPU_CORES) # 并行构建的任务数 32
NEED_MAKE=true # 需要执行make --make
说明:try_init 过程前面执行完成,这里跳过
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
}
顶层CMakeLists.txt
代码路径:oceanbase/CMakeLists.txt
cmake_minimum_required(VERSION 3.20.0)
project(oceanbase)
# 包含环境配置
include(cmake/Env.cmake)
# 添加子目录
add_subdirectory(src)
add_subdirectory(deps/oblib/src/lib)
Env.cmake配置
# 设置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
-std=gnu++11
编译器区别:
在 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 -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 删除。