C++:(1) 动态库配置、GDB配置、CMake与编译脚本模板、docker 安装与 git 基础
·
1. 系统查找动态库路径的配置:
- 1. 临时环境变量设置: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,但是切换终端即失效
- 2. 单独用户级设置: 写入用户配置文件 ~/.bashrc, 然后 source ~/.bashrc
echo 'export PATH=$PATH:/opt/zeek/bin' >> ~/.bashrc
source ~/.bashrc
- 3. 所有用户级设置: 写入 /etc/profile
echo 'export PATH=$PATH:/opt/zeek/bin' | sudo tee -a /etc/profile
source /etc/profile
- 4. 系统级设置: 写入 /etc/ld.so.conf 加入库的绝对路径, 然后更新: sudo ldconfig -v
- 5. 创建符号链接到系统库目录 /lib 或 /usr/lib: sudo ln -s /自己的/库/路径/libxxx.so /lib/libxxx.so
2. GDB 配置与使用流程
2.1 检查核心转储设置,启用核心转储:
ulimit -c # 检查核心转储设置
ulimit -c unlimited # 允许无限大小的 core 文件
2.2 配置核心转储文件生成路径:
ulimit -c unlimited #步骤1:允许无限大小的 core 文件
sudo mkdir -p /coredumps #步骤2:创建专门存放 core 文件的目录
sudo chmod 777 /coredumps #步骤3:设置目录权限(程序崩溃时应显示: Segmentation fault(core dumped), 若没有core dumped, 可能是文件夹权限问题)
echo "/coredumps/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern #步骤4:设置 core_pattern 到新目录
cat /proc/sys/kernel/core_pattern #步骤5:确认 core_pattern 已设置成功,查看核心文件生成的位置
./home/yy/SecKey/scripts/run.sh #步骤6:运行测试程序触发段错误
cd /coredumps/ #步骤7:检查 core 文件是否生成
2.3 加载核心转储文件到 GDB:
gdb //home/yy/SecKey/server /coredumps/core.server.11939
2.4 GDB命令:
bt # 查看堆栈跟踪,输出崩溃时的函数调用栈
frame <frame_number> # 切换到指定的堆栈帧,查看崩溃点的代码
list # 查看代码上下文,显示崩溃点附近的代码
print <variable_name> # 打印变量的值,查看崩溃时的变量状态
quit # 退出GDB
3. CMakeLists.txt 模板
# ===========================
# 1.基本配置
# ===========================
cmake_minimum_required(VERSION 3.5.1) # 设置最低 CMake 版本要求
project(FAULT_DIAG VERSION 1.0 LANGUAGES CXX) # 定义项目名称和版本
# ===========================
# 2.用户可选参数: 架构
# 参数:
# ARCH:变量名
# ${ARCH}:初始值为用户传递参数
# CACHE:表示这是一个缓存变量(即可以在命令行通过 -DARCH=x86_64 传入)
# STRING:变量类型为字符串
# "Target architecture ...": 帮助信息,显示在 GUI 工具(如 ccmake 或 cmake-gui)中
# FORCE:覆盖之前的设置
# ===========================
set(ARCH ${ARCH} CACHE STRING "Target architecture (required: x86_64 or aarch64)" FORCE)
set_property(CACHE ARCH PROPERTY STRINGS "x86_64" "aarch64") # 限制 ARCH 只能为 x86_64 或 aarch64
if(NOT ARCH) # 检查 ARCH 是否为空
message(FATAL_ERROR "You must specify -DARCH=x86_64 or -DARCH=aarch64")
endif()
if(NOT ARCH STREQUAL "x86_64" AND NOT ARCH STREQUAL "aarch64") # 检查 ARCH 是否为 x86_64 或 aarch64
message(FATAL_ERROR "Invalid ARCH specified. Must be 'x86_64' or 'aarch64'.")
endif()
# ===========================
# 根据架构添加宏定义,用于在代码中区分不同的架构,目前未使用可省略
# 示例调用:
# #ifdef TARGET_AARCH64
# // aarch64 特定的代码
# #else
# // 其他架构的代码
# #endif
# ===========================
# if(ARCH STREQUAL "aarch64")
# add_definitions(-DTARGET_AARCH64)
# elseif(ARCH STREQUAL "x86_64")
# add_definitions(-DTARGET_X86_64)
# endif()
# ===========================
# 3.全局编译选项
# ===========================
set(CMAKE_CXX_STANDARD 20) # 使用 C++20 标准
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制使用指定的标准
set(CMAKE_CXX_EXTENSIONS OFF) # 关闭编译器特定扩展
# ===========================
# 4.根据构建类型设置编译选项
# ===========================
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -O0 -fPIC -rdynamic -Wno-unused-variable -Wno-deprecated-declarations -DWITH_INCLUDE_XLOCALE_H)
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -O2 -fPIC -rdynamic -Wno-unused-variable -Wno-deprecated-declarations -DWITH_INCLUDE_XLOCALE_H -g)
else()
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -O2 -fPIC -rdynamic -Wno-unused-variable -Wno-deprecated-declarations -DWITH_INCLUDE_XLOCALE_H)
endif()
# ===========================
# 5.收集源文件
# ===========================
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src MAIN_SRC) # 主函数源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/common COMMON_SRC) # 通用源文件
# ......
# ===========================
# 6.定义可执行文件
# ===========================
add_executable(
${PROJECT_NAME}
${MAIN_SRC}
# ......
)
# ===========================
# 7.添加头文件搜索路径
# ===========================
target_include_directories(
${PROJECT_NAME} PRIVATE # 私有头文件路径,只在本模块中可见并使用, 这里不必要, 因为只有一个构建目标
${CMAKE_CURRENT_SOURCE_DIR}/src/common # common 的头文件路径
# ......
)
# =================================================================================
# 8.指定库文件路径替代 link_directories, 通过指定的是动态库或静态库进行动态或静态链接
# =================================================================================
set(SQLITE_SO "${CMAKE_CURRENT_SOURCE_DIR}/lib/sqlite/${ARCH}/lib/libsqlite3.so")
# ===========================
# 9.链接库
# ===========================
target_link_libraries(${PROJECT_NAME}
pthread
${SQLITE_SO}
)
4. build.sh 编译脚本模板
#!/bin/bash
# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# 项目根目录(scripts 的上级目录)
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# 默认值
BUILD_TYPE="Debug"
ARCH="x86_64"
COMPILER="/usr/bin/g++"
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-t|--type)
BUILD_TYPE="$2"
shift 2
;;
-a|--arch)
ARCH="$2"
shift 2
;;
-c|--compiler)
COMPILER="$2"
shift 2
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [-t build_type] [-a arch] [-c compiler]"
echo " build_type: Debug, Release, RelWithDebInfo (default: Debug)"
echo " arch: x86_64, aarch64 (default: x86_64)"
echo " compiler: path to compiler (default: /usr/bin/g++)"
exit 1
;;
esac
done
# 验证参数
if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "aarch64" ]; then
echo "Error: ARCH must be 'x86_64' or 'aarch64'"
exit 1
fi
BUILD_DIR="$PROJECT_DIR/build/"
# 清理旧的构建目录
if [ -d "$BUILD_DIR" ]; then
echo "Cleaning old build directory..."
rm -rf "$BUILD_DIR"
fi
# 创建新的构建目录并进入
echo "Creating new build directory..."
mkdir "$BUILD_DIR"
cd "$BUILD_DIR" || { echo "Failed to enter build directory"; exit 1; }
# 配置 CMake 项目
echo "Configuring CMake project with:"
echo " Build type: $BUILD_TYPE"
echo " Target architecture: $ARCH"
echo " Compiler: $COMPILER"
cmake \
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
-DARCH="$ARCH" \
-DCMAKE_CXX_COMPILER="$COMPILER"
"$PROJECT_DIR"
# 构建项目,.表示当前目录
echo "Building the FAULT_DIAG project..."
cmake --build .
# 检查构建是否成功
if [ $? -eq 0 ]; then
echo "FAULT_DIAG build completed successfully!"
else
echo "FAULT_DIAG build failed!"
exit 1
fi
5. docker 安装与配置
5.1 安装 docker
# 1. 更新系统并安装依赖
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
# 2. 添加 Docker 官方 GPG 密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 3. 添加仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 4. 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 5. 添加当前用户到 docker 组
sudo usermod -aG docker yy
# 6. 配置镜像
sudo vim /etc/docker/daemon.json
# 输入:
# {
# "registry-mirrors": [
# "https://docker.1ms.run",
# "https://docker.m.daocloud.io"
# ]
# }
# 7. 查看镜像源
docker info | grep "Registry Mirrors" -A 3
# 8. 测试
docker version
sudo systemctl daemon-reload
sudo systemctl restart docker
docker run hello-world
5.2 拉取镜像
# 1. 从 dockerhub 拉取镜像
docker pull ubuntu:latest
# 2. 查看当前所有的镜像
docker images
# 3. 运行容器
# -it: 交互式终端, -d: 后台运行, --rm: 退出容器后自动删除容器, -p 8080:80: 宿主机的 8080 端口映射到容器的 80 端口
# -v /home/user:/app/data: 把宿主机的 /home/user 目录挂载到容器的 /app/data 目录
docker run -it --rm ubuntu /bin/bash
# 4. 退出容器
exit # 交互式
docker stop <container_id> # 守护进程
# 5. 查看容器
docker ps -a
# 6. 启动容器
docker start <container_id>
# 7. 停止容器
docker stop <container_id>
# 8. 删除容器
docker rm <container_id>
# 9. 删除所有容器
docker rm 'docker ps -a -q'
# 10. 删除镜像
docker rmi <image_id>
5.3 推送镜像
# 1. 登陆,按照提示输入github的用户名密码
docker login
# 2. 将本地镜像重命名成规范名称才可推送
docker tag ubuntu yy/ubuntu:v1.0
# 3. 推送自己的镜像
docker push yy/ubuntu:v1.0
5.4 手动构建镜像
# 1. 进入容器
docker run -it ubuntu /bin/bash
# 2. 配置环境
# 3. 退出容器
exit
# 4. 查看容器
docker ps -a
# 5. 提交容器为新的镜像
docker commit <container_id> yy/newUbuntu:v1.1
# 6. 查看新的镜像
docker images
5.5 Dockerfile 构建镜像
- 编写Dockerfile:
# 确定基础镜像
# 安装所需环境
# 定义执行点(即 docker run 的默认命令)
FROM ubuntu
RUN apt-get update
RUN apt-get install -y gcc
ENTRYPOINT ["./project"]
-
构建镜像:
# 1. 编写 Dockerfile
# 2. 构建镜像(-t: 镜像名称)
docker build -t yy/ubuntu:v1.2
# 3. 查看镜像
docker images
5.6 离线分发
# 1. 导出镜像
docker save -o ubuntu.tar yy/ubuntu:v1.2
# 2. 导入镜像
docker load -i ubuntu.tar
# 3. 查看镜像
docker images
# 只包含容器中的文件系统, 无执行点, 暴露端口, 构建历史等
5.7 构建适配于程序的容器
# 1. 查看程序运行时依赖的动态库
ldd ./project
# 2. 在容器中编译库易失败, 故静态编译
# 2.1. 完全静态编译
gcc -static -o project project.c # Makefile
set(CMAKE_EXE_LINKER_FLAGS "-static") # cmake
# 2.2. 静态编译第三方库
6. git 基础命令
- 远程仓库设置:
- 查看已有的远程仓库: git remote -v
- 删除远程仓库origin: git remote rm origin
- 新建远程仓库gitee01: git remote add gitee01 https://gitee.com/xxxx.git
- 更新gitee01指向的项目地址: git remote set-url gitee01 https://gitee.com/xxxx.git
- 获取gitee01仓库的所有分支和提交记录, 用于被本地分支跟踪: git fetch gitee01
- 查看、删除远程分支:
- git branch -r
- git push gitee01 --delete main
- 本地分支操作:
- 查看当前分支: git branch, * 号表示当前分支
- 查看跟踪的远程分支: git branch -vv
- 设置跟踪分支: git branch -u gitee01/master
- 切换分支: git checkout master
- 删除分支: git branch -d main
- 新建master分支并跟踪到gitee01的master分支: git checkout -b master gitee01/master
- 设置本地分支与远程分支的关联关系,远程仓库的内容会被拉取到你现有的文件夹中,而不会创建额外的子文件夹:
- git branch --set-upstream-to=gitee01/master
- 拉取远程分支的最新代码:
- git pull gitee01 master --allow-unrelated-histories
- 提交本地修改:
- git status
- git add .
- git commit -m "01"
- 推送到远程仓库gitee01的master分支:
- git push gitee01 master
- git push gitee01 master --force(强制推送,会覆盖当前分支远程仓库的修改和内容)
- 从跟踪移除文件:
- 检查该目录下的文件是否被跟踪:git ls-files | grep 'lib/sqlite/x86_64/'
- 从跟踪移除文件:git rm --cached -r lib/
更多推荐

所有评论(0)