CMake构建学习笔记28-gmp&mpfr库的构建

1. 引言

gmp 是一个用于任意精度整数、有理数和浮点数运算的高效C语言库;mpfr 构建在 gmp 之上,专注于正确舍入的任意精度浮点运算。这两个库都是非常底层的库,通常一起使用。

2. 构建

使用本系列文章(《CMake构建学习笔记-目录》)实现的自动化工具 BuildCppDependency 来进行构建 gmp 和 mpfr。以 gmp 为例,在 Windows 平台下输入指令:

powershell 复制代码
./BuildCppDependency.ps1 `
  -Generator "Visual Studio 16 2019" `
  -InstallDir "$env:GISBasic" `
  -SymbolDir "$env:GISBasic/symbols" `
  -Install gmp

在 Linux (Ubuntu) 平台下输入指令:

bash 复制代码
./build.sh -install gmp -installdir "$GISBasic"

虽然可以直接使用工具,但是还是说一下构建的细节。在 Windows 平台下,想用 MSVC 来构建 gmp 和 mpfr 还是挺困难的,因为 gmp 和 mpfr 是 GNU 项目,只提供 Linux 下的构建方式。要组织成 CMake 项目需要对项目本身有一定的了解,所以笔者这里也不硬搞了,直接使用了 vcpkg 的预编译包,指令的实现其实就是将这个预编译包解压安装。

不过在 Linux/Ubuntu 下就可以自己编写脚本,使用 Autotools + GCC + Make 工具链来进行构建了。gmp的构建脚本如下:

bash 复制代码
#!/bin/bash

# ===========================================
# gmp.sh - 构建 GMP 库 
# 接收参数:
#   -installdir <dir>    # 安装目录(必须)
#   -force               # 强制重新构建
#   -noclean             # 不清理临时文件
# ===========================================

set -e  # 遇到错误立即退出

# 默认值
InstallDir=""
FORCE=false
NOClean=false

# 解析可选参数
while [[ $# -gt 0 ]]; do
  case $1 in
    -installdir)
      InstallDir="$2"
      shift 2
      ;;
    -force)
      FORCE=true
      shift
      ;;
    -noclean)
      NOClean=true
      shift
      ;;
    --) # 分隔符,后面是项目参数
      shift
      break
      ;;
    -*)
      echo "未知参数: $1"
      exit 1
      ;;
    *)
      break  # 非选项参数开始,停止解析
      ;;
  esac
done

# 检查必要参数
if [[ -z "$InstallDir" ]]; then
  echo "❌ 错误: 必须指定 -installdir <安装目录>"
  exit 1
fi

# 项目配置
InstallDir=$(realpath "$InstallDir")
ScriptDir=$(pwd)
SourceBaseDir=$(realpath "../Source")       # 绝对路径
Name="gmp-6.3.0"
SourceZipFile="${SourceBaseDir}/${Name}.tar.xz"
ExtractedSourceDir="${SourceBaseDir}/${Name}"
BuildDir="${ScriptDir}/build-${Name}"       # 明确区分 build 目录
TargetFile="${InstallDir}/include/gmp.h"

# 检查源码包是否存在
if [[ ! -f "$SourceZipFile" ]]; then
  echo "❌ 源码包未找到: $SourceZipFile"
  exit 1
fi

# 如果没有 -force 且目标文件已存在,跳过构建
if [[ "$FORCE" == false && -f "$TargetFile" ]]; then
    echo "✅ GMP 已安装: $TargetFile,跳过构建(使用 -force 可强制重建)"
    exit 0
fi


if [[ "$FORCE" == true ]]; then
    echo "⚠️  启用 -force 模式,将重新构建 GMP"
    # 清理旧的构建目录(如果存在)
    rm -rf "$BuildDir"
fi


echo "🔍 开始构建 GMP: $Name"
echo "📦 源码包: $SourceZipFile"
echo "📂 解压目录: $ExtractedSourceDir"
echo "⚙️  构建目录: $BuildDir"
echo "📁 安装目录: $InstallDir"

# === 1. 解压源码(如果尚未解压)===
if [[ ! -d "$ExtractedSourceDir" ]]; then
    echo "📦 正在解压源码..."
    tar -xf "$SourceZipFile" -C "../Source/"
else
    echo "📂 源码已存在,跳过解压"
fi

# === 2. 创建并进入构建目录(推荐 out-of-source build)===
mkdir -p "$BuildDir"
cd "$BuildDir"

# === 3. 配置 ===
echo "🔧 正在运行 configure..."
"$ExtractedSourceDir/configure" \
    --prefix="$InstallDir" \
    --enable-cxx \
    --enable-fat  # CPU优化

# === 4. 编译 ===
echo "🔨 正在编译 GMP..."
make -j$(nproc)

# === 5. 安装 ===
echo "📥 正在安装 GMP 到 $InstallDir..."
make install

# === 6. 清理临时文件 ===
if [[ "$NOClean" == false ]]; then
    echo "🧹 正在清理临时目录..."
    rm -rf "$ExtractedSourceDir" && echo "🗑️ 已删除源码目录: $ExtractedSourceDir"
    rm -rf "$BuildDir" && echo "🗑️ 已删除构建目录: $BuildDir"
else
    echo "🚫 已启用 -noclean,保留构建目录: $BuildDir"
fi

echo "🎉 项目 $Name 构建完成"
cd -

其实就是很标准的 Autotools 工具链的构建流程,先 configure,再 make,最后 make install 。其中的一个关键也是看 configure 过程中的构建选项,例如这里的--enable-fat,表示开启CPU优化。

构建 mpfr 的脚本则是:

bash 复制代码
#!/bin/bash

# ===========================================
# mpfr.sh - 构建 MPFR 库 
# 接收参数:
#   -installdir <dir>    # 安装目录(必须)
#   -force               # 强制重新构建
#   -noclean             # 不清理临时文件
# ===========================================

set -e  # 遇到错误立即退出

# 默认值
InstallDir=""
FORCE=false
NOClean=false

# 解析可选参数
while [[ $# -gt 0 ]]; do
  case $1 in
    -installdir)
      InstallDir="$2"
      shift 2
      ;;
    -force)
      FORCE=true
      shift
      ;;
    -noclean)
      NOClean=true
      shift
      ;;
    --) # 分隔符,后面是项目参数
      shift
      break
      ;;
    -*)
      echo "未知参数: $1"
      exit 1
      ;;
    *)
      break  # 非选项参数开始,停止解析
      ;;
  esac
done

# 检查必要参数
if [[ -z "$InstallDir" ]]; then
  echo "❌ 错误: 必须指定 -installdir <安装目录>"
  exit 1
fi

# 项目配置
InstallDir=$(realpath "$InstallDir")
ScriptDir=$(pwd)
SourceBaseDir=$(realpath "../Source")       # 绝对路径
Name="mpfr-4.2.2"
SourceZipFile="${SourceBaseDir}/${Name}.tar.xz"
ExtractedSourceDir="${SourceBaseDir}/${Name}"
BuildDir="${ScriptDir}/build-${Name}"       # 明确区分 build 目录
TargetFile="${InstallDir}/include/mpfr.h"

# 检查源码包是否存在
if [[ ! -f "$SourceZipFile" ]]; then
  echo "❌ 源码包未找到: $SourceZipFile"
  exit 1
fi

# 如果没有 -force 且目标文件已存在,跳过构建
if [[ "$FORCE" == false && -f "$TargetFile" ]]; then
    echo "✅ MPFR 已安装: $TargetFile,跳过构建(使用 -force 可强制重建)"
    exit 0
fi

if [[ "$FORCE" == true ]]; then
    echo "⚠️  启用 -force 模式,将重新构建 MPFR"
    # 清理旧的构建目录(如果存在)
    rm -rf "$BuildDir"
fi

echo "🔍 开始构建 MPFR: $Name"
echo "📦 源码包: $SourceZipFile"
echo "📂 解压目录: $ExtractedSourceDir"
echo "⚙️  构建目录: $BuildDir"
echo "📁 安装目录: $InstallDir"

# === 1. 解压源码(如果尚未解压)===
if [[ ! -d "$ExtractedSourceDir" ]]; then
    echo "📦 正在解压源码..."
    tar -xf "$SourceZipFile" -C "../Source/"
else
    echo "📂 源码已存在,跳过解压"
fi

# === 2. 创建并进入构建目录(推荐 out-of-source build)===
mkdir -p "$BuildDir"
cd "$BuildDir" > /dev/null

# === 3. 配置 ===
# 注意:MPFR 依赖 GMP,需确保能正确找到 GMP(头文件 + 库)
echo "🔧 正在运行 configure..."
"$ExtractedSourceDir/configure" \
    --prefix="$InstallDir" \
    --with-gmp="$InstallDir" \
    --enable-thread-safe

# === 4. 编译 ===
echo "🔨 正在编译 MPFR..."
make -j$(nproc)

# === 5. 安装 ===
echo "📥 正在安装 MPFR 到 $InstallDir..."
make install

# === 6. 清理临时文件 ===
if [[ "$NOClean" == false ]]; then
    echo "🧹 正在清理临时目录..."
    rm -rf "$ExtractedSourceDir" && echo "🗑️ 已删除源码目录: $ExtractedSourceDir"
    rm -rf "$BuildDir" && echo "🗑️ 已删除构建目录: $BuildDir"
else
    echo "🚫 已启用 -noclean,保留构建目录: $BuildDir"
fi

echo "🎉 项目 $Name 构建完成"
cd - > /dev/null

可以看到,脚本内容基本都差不多。两者其实可以抽象出一个通用的构建脚本,用来针对于 Autotools 工具链构建的情况。不过这个工作就放到后续来做了。

3. 其他

系列文章:《CMake构建学习笔记-目录》 构建工具: Github地址GitCode地址 二进制构建结果:Github地址GitCode地址

相关推荐
charlee444 小时前
CMake构建学习笔记27-初步完成C&C++自动化构建工具
跨平台·cmake·构建·依赖管理
羑悻的小杀马特3 天前
现代 CMake 项目构建完全指南:从基础配置到高级技巧的目标属性管理与智能依赖传递机制解析
cmake·项目构建·属性传递机制
Theliars9 天前
Ubuntu 上使用 VSCode 调试 C++ (CMake 项目) 指南
c++·vscode·ubuntu·cmake
Molesidy21 天前
【Embedded System】【CMake】Windows下CMake+VSCode的开发环境搭建以及初步认识
ide·vscode·编辑器·cmake
fedorayang1 个月前
precompilation-headers 以及在cmake中的实现
cmake
AAA小肥杨1 个月前
cmake使用教程
c语言·c++·cmake
辰尘_星启1 个月前
『CMake』关于使用CMake构建项目时的现代/传统指令
c++·架构·系统·cmake·项目·构建
安全二次方security²1 个月前
TF-A CMake构建系统
编译·cmake·atf·tf-a·arm安全架构·构建系统
玩转C语言和数据结构1 个月前
CMake下载和安装图解(附安装包,适合新手)
cmake·cmake下载·cmake安装·cmake 下载·cmake 安装·安装cmake·cmake下载安装