如何用脚本实现自动化编译

wen 实用脚本 2

本文目录导读:

如何用脚本实现自动化编译

  1. Bash/Shell 脚本(最常用)
  2. Makefile(项目管理)
  3. CMake + CTest(跨平台)
  4. Python 自动化脚本
  5. 高级:Git Hook 集成
  6. 使用示例

Bash/Shell 脚本(最常用)

#!/bin/bash
# 编译脚本 build.sh
set -e  # 出错即停止
echo "===== 开始编译 ====="
# 定义变量
BUILD_DIR="build"
SOURCE_DIR="src"
COMPILER="gcc"
FLAGS="-Wall -O2"
# 清理旧文件
clean() {
    echo "清理旧文件..."
    rm -rf $BUILD_DIR
    mkdir -p $BUILD_DIR
}
# 编译函数
compile() {
    echo "开始编译..."
    cd $BUILD_DIR
    cmake .. -DCMAKE_BUILD_TYPE=Release
    make -j$(nproc)  # 多核编译
    cd ..
}
# 测试函数
test() {
    echo "运行测试..."
    ./$BUILD_DIR/test_program
}
# 安装函数
install() {
    echo "安装..."
    sudo make install -C $BUILD_DIR
}
# 主函数
main() {
    clean
    compile
    test
    # install  # 可选
    echo "===== 编译完成 ====="
}
# 执行
main "$@"

Makefile(项目管理)

# Makefile
CC = gcc
CXX = g++
CFLAGS = -Wall -O2 -g
LDFLAGS = -lm
# 源文件
SRCS = main.c utils.c file_handler.c
OBJS = $(SRCS:.c=.o)
HEADERS = *.h
# 可执行文件
TARGET = myapp
# 默认目标
all: $(TARGET)
# 链接
$(TARGET): $(OBJS)
    $(CC) $(OBJS) -o $(TARGET) $(LDFLAGS)
# 编译规则
%.o: %.c $(HEADERS)
    $(CC) $(CFLAGS) -c $< -o $@
# 清理
clean:
    rm -f $(OBJS) $(TARGET)
# 重新编译
rebuild: clean all
# 安装
install: $(TARGET)
    install -m 755 $(TARGET) /usr/local/bin/
# 测试
test: $(TARGET)
    ./$(TARGET) --test
.PHONY: all clean rebuild install test

CMake + CTest(跨平台)

# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# 编译类型
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()
# 源文件
set(SOURCES
    src/main.cpp
    src/utils.cpp
    src/api.cpp
)
# 生成可执行文件
add_executable(${PROJECT_NAME} ${SOURCES})
# 链接库
target_link_libraries(${PROJECT_NAME}
    pthread
    m
)
# 安装规则
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
# 启用测试
enable_testing()
add_test(NAME basic_test COMMAND ${PROJECT_NAME} --test)

Python 自动化脚本

#!/usr/bin/env python3
# build.py
import os
import subprocess
import sys
import shutil
import argparse
from datetime import datetime
class BuildSystem:
    def __init__(self):
        self.project_dir = os.path.dirname(os.path.abspath(__file__))
        self.build_dir = os.path.join(self.project_dir, "build")
        self.src_dir = os.path.join(self.project_dir, "src")
        self.log_file = os.path.join(self.project_dir, "build.log")
    def log(self, message):
        """记录日志"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_message = f"[{timestamp}] {message}"
        print(log_message)
        with open(self.log_file, "a") as f:
            f.write(log_message + "\n")
    def run_command(self, cmd, cwd=None):
        """执行命令"""
        self.log(f"执行命令: {cmd}")
        try:
            result = subprocess.run(
                cmd, 
                shell=True, 
                cwd=cwd or self.project_dir,
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            self.log(result.stdout.decode())
            return True
        except subprocess.CalledProcessError as e:
            self.log(f"命令失败: {e}")
            self.log(e.stderr.decode())
            return False
    def clean(self):
        """清理构建目录"""
        self.log("清理构建目录...")
        if os.path.exists(self.build_dir):
            shutil.rmtree(self.build_dir)
        os.makedirs(self.build_dir, exist_ok=True)
    def configure(self, build_type="Release"):
        """配置项目"""
        self.log(f"配置项目 (构建类型: {build_type})...")
        cmd = f"cmake .. -DCMAKE_BUILD_TYPE={build_type}"
        return self.run_command(cmd, self.build_dir)
    def build(self, jobs=None):
        """编译项目"""
        self.log(f"编译项目 (作业数: {jobs or 'auto'})...")
        if not jobs:
            import multiprocessing
            jobs = multiprocessing.cpu_count()
        cmd = f"make -j{jobs}"
        return self.run_command(cmd, self.build_dir)
    def test(self):
        """运行测试"""
        self.log("运行测试...")
        return self.run_command("ctest --output-on-failure", self.build_dir)
    def install(self):
        """安装"""
        self.log("安装项目...")
        return self.run_command("make install", self.build_dir)
    def build_all(self, build_type="Release", run_tests=True, install=False):
        """完整构建流程"""
        self.log("开始完整构建流程")
        # 执行构建
        if not self.clean():
            return False
        if not self.configure(build_type):
            return False
        if not self.build():
            return False
        # 运行测试
        if run_tests:
            if not self.test():
                self.log("测试失败")
                return False
        # 安装
        if install:
            if not self.install():
                return False
        self.log("构建完成!")
        return True
def main():
    parser = argparse.ArgumentParser(description="自动化构建脚本")
    parser.add_argument("--clean", action="store_true", help="清理构建")
    parser.add_argument("--configure", action="store_true", help="配置项目")
    parser.add_argument("--build", action="store_true", help="编译项目")
    parser.add_argument("--test", action="store_true", help="运行测试")
    parser.add_argument("--install", action="store_true", help="安装项目")
    parser.add_argument("--type", default="Release", help="构建类型")
    parser.add_argument("--all", action="store_true", help="执行完整流程")
    args = parser.parse_args()
    build = BuildSystem()
    if args.all:
        success = build.build_all(args.type, args.test, args.install)
    else:
        # 根据参数执行特定操作
        success = True
        if args.clean or not os.path.exists(build.build_dir):
            build.clean()
        if args.configure or not os.path.exists(os.path.join(build.build_dir, "Makefile")):
            build.configure(args.type)
        if args.build or args.all:
            build.build()
        if args.test:
            build.test()
        if args.install:
            build.install()
    sys.exit(0 if success else 1)
if __name__ == "__main__":
    main()

高级:Git Hook 集成

#!/bin/bash
# .git/hooks/pre-commit
echo "运行预提交检查..."
# 运行代码格式检查
python -m black --check . || exit 1
# 运行单元测试
python -m pytest tests/ || exit 1
# 运行编译检查
make build || exit 1
echo "预提交检查通过!"

使用示例

# Bash脚本使用
chmod +x build.sh
./build.sh
# Makefile使用
make              # 编译
make clean        # 清理
make rebuild      # 重新编译
make install      # 安装
# Python脚本使用
python build.py --all
python build.py --test --type Debug
python build.py --clean

选择哪种脚本取决于你的项目需求:

  • 小型项目:用 Makefile 或简单 Bash 脚本
  • 跨平台项目:用 CMake + Python
  • 复杂依赖项目:用 CMake + CI/CD(如 Jenkins)
  • 需要频繁集成:加入 Git Hook 或 CI 流水线

抱歉,评论功能暂时关闭!