基于Python3编写的Golang程序多平台交叉编译自动化脚本

news2024/12/22 3:37:01
import argparse
import os
import shutil
import sys
from shutil import copy2

from loguru import logger


class GoBuild:
    """
    一个用于构建跨平台执行文件的类。

    初始化函数,设置构建的主文件、生成的执行文件名称以及目标平台。
    :param f: 需要构建的主文件(例如: main.go)
    :param n: 生成的执行文件主名称(例如: install)
    """

    def __init__(self, f, n=None):
        self.darwin = darwin
        self.go = "go"
        self.name = n
        self.arch_list = []
        self.os_list = []
        self.amd64 = False
        self.mips64 = False
        self.arm64 = False
        self.arm32 = False
        self.linux = False
        self.windows = False
        self.file = f
        self.basename = ""
        self.archs = "X86_64"
        self.os_type = ""
        self.exe = ""
        self.tmp = ""
        self.logger = logger

    def init(self):
        """
        初始化函数,根据不同的架构和操作系统生成相应的架构和操作系统列表,
        并设置可执行文件的基础名称。
        """
        # 检查并添加架构到架构列表
        if self.arm64:
            self.arch_list.append("arm64")
        if self.mips64:
            self.arch_list.append("mips64le")
        if self.amd64:
            self.arch_list.append("amd64")
        if self.arm32:
            self.arch_list.append("arm")

        # 检查并添加操作系统到操作系统列表
        if self.linux:
            self.os_list.append("linux")
        if self.windows:
            self.os_list.append("windows")
        if self.darwin:
            self.os_list.append("darwin")

        # 设置可执行文件的基础名称
        if self.name is None:
            self.basename = str(os.path.basename(self.file)).replace(".go", "")
        else:
            self.basename = self.name

    def delete(self):
        """
        开始删除生成的临时文件
        :return: None
        """
        # 构造临时文件的完整路径
        tmp = os.path.join(os.getcwd(), self.tmp)
        try:
            # 尝试删除临时文件
            os.remove(path=self.tmp)
            # 删除成功后记录日志
            self.logger.debug(f"删除成功: {tmp}")
        except Exception as e:
            # 删除失败后记录错误日志
            self.logger.error(f"删除出错 - [{tmp} ] : {str(e)}")

    def copy(self):
        """
        复制执行文件到目标目录,并根据当前环境调整文件路径。
        此方法首先构建目标文件路径,然后尝试从临时文件路径复制文件到目标路径,
        如果临时文件存在的话。如果复制成功,它将调用delete方法删除临时文件。
        如果临时文件不存在,它将记录一个警告消息。
        """
        # 构建目标文件路径
        dst = os.path.join("client", self.exe)
        # 将目标路径与当前工作目录结合
        dst = os.path.join(os.getcwd(), dst)
        # 替换路径中的'amd64'为'X86_64'以适配不同架构
        dst = str(dst).replace("amd64", "X86_64")
        # 记录复制操作的开始
        self.logger.debug(f"开始复制: {dst}")
        # 检查临时文件是否存在
        if os.path.isfile(self.tmp):
            try:
                # 尝试复制文件到目标路径
                copy2(src=self.tmp, dst=dst)
                # 复制成功后,删除临时文件
                self.delete()
            except Exception as e:
                # 如果复制过程中发生异常,记录错误信息
                self.logger.error(f"复制失败: {str(e)}")
        else:
            # 如果临时文件不存在,记录警告信息
            self.logger.warning(f"文件不存在: {self.tmp}")

    def build(self):
        """
        构建指定的Go文件,根据操作系统类型和架构进行编译,并处理构建结果。

        1. 根据架构类型转换变量`self.archs`,确保其符合预期的架构命名规范。
        2. 记录构建系统的操作系统类型和架构,用于调试和追踪。
        3. 根据操作系统和架构生成可执行文件名`self.exe`,并调整Windows系统下的文件扩展名。
        4. 构建Go文件,如果构建成功则调用`self.copy()`方法处理构建结果,否则记录错误并退出程序。
        """
        # 根据架构类型转换变量self.archs,确保其符合预期的架构命名规范
        if self.archs == "amd64":
            self.archs = "X86_64"

        # 记录构建系统的操作系统类型和架构,用于调试和追踪
        self.logger.debug(f"构建系统: {self.os_type}", )
        self.logger.debug(f"构建架构: {self.archs}")

        # 根据操作系统和架构生成可执行文件名self.exe,并调整Windows系统下的文件扩展名
        self.exe = self.basename + "_" + self.os_type + "-" + self.archs
        self.tmp = str(os.path.basename(self.file)).replace(".go", "")
        if self.os_type == "windows":
            self.exe = self.exe + ".exe"
            self.tmp = self.tmp + ".exe"

        # 构建Go文件
        c = f"{self.go} build {self.file}"
        if os.system(c) == 0:
            # 如果构建成功则记录信息并调用self.copy()方法处理构建结果
            self.logger.info(f"构建成功,正在生成: {self.exe}")
            self.copy()
        else:
            # 如果构建失败则记录错误并退出程序
            self.logger.error(f"构建失败: {self.exe}")
            print(c)
            sys.exit(2)

    def ost(self, o):
        """
        设置操作系统类型

        该方法主要用于设置GOOS环境变量,以模拟不同的操作系统环境这对于后续的编译过程特别重要,
        因为GOOS环境变量决定了编译输出的目标操作系统。

        参数:
        o (str): 要模拟的操作系统类型,例如"linux"、"windows"等。

        返回:
        无
        """
        # 设置GOOS环境变量以模拟指定的操作系统
        os.environ['GOOS'] = o
        # 更新实例的os_type属性以存储当前设置的操作系统类型
        self.os_type = o

    def arch(self, arch):
        """
        设置架构并触发构建过程

        该方法接收一个架构名称,根据特定规则转换后设置环境变量GOARCH,
        并将该架构名称保存以供后续使用。最后,调用build方法进行构建。

        参数:
        arch (str): 构架名称,可能需要转换以适配特定的命名约定。

        返回:
        无
        """
        # 根据输入的架构名称进行条件判断,以确定是否需要转换架构名称
        if arch == "X86_64":
            arch = "amd64"

        # 设置环境变量GOARCH为转换后的架构名称,以便在后续的构建过程中使用
        os.environ['GOARCH'] = arch

        # 保存当前架构名称到实例变量,以便在类的其他方法中访问
        self.archs = arch

        # 调用实例的build方法,触发针对指定架构的构建过程
        self.build()

    def start(self, save):
        """
        启动初始化和操作系统处理流程

        在这个方法中,首先进行初始化操作,然后根据`save`参数检查目录是否存在,
        如果不存在则创建目录.随后,遍历操作系统列表,对每个操作系统进行处理.
        对于Linux操作系统,进一步遍历其架构列表并进行处理;对于其他操作系统,
        则默认使用X86_64架构进行处理.

        参数:
        save (str): 保存路径字符串,用于检查是否存在以及创建目录
        """
        # 初始化操作
        self.init()
        # 检查save是否为目录,如果不是则创建client目录
        if not os.path.isdir(save):
            os.mkdir("./client")
        # 遍历操作系统列表,对每个操作系统调用ost方法
        for i in self.os_list:
            self.ost(i)
            # 对Linux操作系统,记录架构列表并遍历每个架构
            if i == "linux":
                self.logger.debug(f"架构列表: {self.arch_list}")
                for a in self.arch_list:
                    self.arch(arch=a)
            # 对其他操作系统,默认使用X86_64架构
            else:
                self.arch(arch="X86_64")


# 主程序入口
if __name__ == "__main__":
    # 获取当前目录
    cwd = os.getcwd()
    # 解析命令传参
    parser = argparse.ArgumentParser()
    parser.add_argument("-f", "--file", help="源代码文件名", type=str, default="ssl.go")
    parser.add_argument("-n", "--name", help="项目名称", type=str, default="ssl")

    # 是否启用Linux平台, 默认启用
    parser.add_argument("-l", "--linux", help="是否启用Linux平台", action='store_true', default=True)
    parser.add_argument("--no-linux", help="禁用Linux平台", action='store_false', dest='linux')

    # 是否启用Darwin平台, 默认启用
    parser.add_argument("-d", "--darwin", help="是否启用Darwin平台", action='store_true', default=True)
    parser.add_argument("--no-darwin", help="禁用Darwin平台", action='store_false', dest='darwin')

    # 是否启用Windows平台, 默认启用
    parser.add_argument("-w", "--windows", help="是否启用Windows平台", action='store_true', default=True)
    parser.add_argument("--no-windows", help="禁用Windows平台", action='store_false', dest='windows')

    # 是否启用arm64平台, 默认启用
    parser.add_argument("-a", "--arm64", help="是否启用arm64平台", action='store_true', default=True)
    parser.add_argument("--no-arm64", help="禁用arm64平台", action='store_false', dest='arm64')

    # 是否启用arm32平台, 默认启用
    parser.add_argument("-r32", "--arm32", help="是否启用arm32平台", action='store_true', default=True)
    parser.add_argument("--no-arm32", help="禁用arm32平台", action='store_false', dest='arm32')

    # 是否启用mips64平台, 默认启用
    parser.add_argument("-m", "--mips64", help="是否启用mips64平台", action='store_true', default=True)
    parser.add_argument("--no-mips64", help="禁用mips64平台", action='store_false', dest='mips64')

    # 是否启用amd64/x86平台, 默认启用
    parser.add_argument("-x", "--x86", help="是否启用amd64/x86平台", action='store_true', default=True)
    parser.add_argument("--no-x86", help="禁用amd64/x86平台", action='store_false', dest='x86')
    # 设置保存目录,默认: ./client
    client_ = os.path.join(cwd, 'client')
    parser.add_argument("-o", "--output", help=f"保存目录->默认: {client_}", type=str, default=client_)
    # 显示版本号
    parser.add_argument("-v", "--version", action='version', version='%(prog)s 1.0')
    # 解析命令行参数
    args = parser.parse_args()
    # 提取命令行参数中的文件名
    file = args.file
    # 提取命令行参数中的项目名称
    name = args.name
    # 提取命令行参数中的MIPS64平台编译选项
    mips64 = args.mips64
    # 提取命令行参数中的Linux平台编译选项
    linux = args.linux
    # 提取命令行参数中的Darwin平台编译选项
    darwin = args.darwin
    # 提取命令行参数中的ARM64平台编译选项
    arm64 = args.arm64
    # 提取命令行参数中的X86平台编译选项
    x86 = args.x86
    # 提取命令行参数中的ARM32平台编译选项
    arm32 = args.arm32
    # 提取命令行参数中的Windows平台编译选项
    windows = args.windows
    # 打印所有命令行参数
    print(args)
    # 打印提取的文件名
    print(f"文件名: {file}")
    # 打印提取的项目名称

    # 打印启用的平台
    print(f"Linux: {args.linux}")
    print(f"Darwin: {args.darwin}")
    print(f"Windows: {args.windows}")
    print(f"ARM64: {args.arm64}")
    print(f"ARM32: {args.arm32}")
    print(f"MIPS64: {args.mips64}")
    print(f"X86: {args.x86}")

    # 创建GoBuild实例,传入文件名、项目名称及各平台编译选项
    up = GoBuild(f=file, n=name)
    # 设置ARM32架构的编译选项
    up.arm32 = arm32
    # 设置Windows系统的编译选项
    up.windows = windows
    # 设置ARM64架构的编译选项
    up.arm64 = arm64
    # 设置MIPS64架构的编译选项
    up.mips64 = mips64
    # 设置X86架构的编译选项
    up.x86 = x86
    # 设置Linux系统的编译选项
    up.linux = linux
    # 设置Darwin系统的编译选项
    up.darwin = darwin
    # 启动编译过程
    up.start(save=args.output)

效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2263561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java全栈day20--Web后端实战(Mybatis基础2)

一、Mybatis基础 1.1辅助配置 配置 SQL 提示。 默认在 mybatis 中编写 SQL 语句是不识别的。可以做如下配置: 现在就有sql提示了 新的问题 产生原因: Idea 和数据库没有建立连接,不识别表信息 解决方式:在 Idea 中配置 MySQL 数…

MacOS下PostIn安装配置指南

PostIn是一款开源免费的接口管理工具, 下面介绍私有部署版本的MacOS下安装与配置。私有部署版本更适合有严格数据安全要求的企业,实现对数据和系统的完全控制。   1、MacOS服务端安装 Mac安装包下载地址:下载Mac安…

【Apache Doris】周FAQ集锦:第 26 期

SQL问题 Q1 doris 3.0存算分离模式下,建表的时是否需要指定表的副本数 不需要,指定了也会忽略;存算分离模式下,数据副本由远端存储去管控。 Q2 doris 通过dbeaver查询时报错:[SXXXX]… doris的错误码通常都是EXXXX&…

【Mongo工具】Mongo迁移工具之Mongo-shake

Mongo-Shake 简介 Mongo-Shake 是一个基于 MongoDB 操作日志(oplog)的通用服务平台。它从源 MongoDB 数据库中获取操作日志,并在目标 MongoDB 数据库中重放,或者通过不同的隧道发送到其他终端。如果目标端是 MongoDB 数据库&…

【Unity基础】AudioSource 常用方法总结

在 Unity 中,AudioSource 组件用于控制音频的播放和管理。以下是常用的 AudioSource 控制方法及其说明。 1. 播放和暂停音频 Play():开始播放音频,如果是从暂停的地方继续播放,可以直接调用。Pause():暂停当前播放的…

flink SQL实现mysql source sink

接上文:一文说清flink从编码到部署上线 环境说明:MySQL:5.7;flink:1.14.0;hadoop:3.0.0;操作系统:CentOS 7.6;JDK:1.8.0_401。 1.代码实现 1.1 E…

知乎 PB 级别 TiDB 数据库集群管控实践

以下文章来源于知乎技术专栏 ,作者代晓磊 导读 在现代企业中,数据库的运维管理至关重要,特别是面对分布式数据库的复杂性和大规模集群的挑战。作为一款兼容 MySQL 协议的分布式关系型数据库,TiDB 在高可用、高扩展性和强一致性方…

SpringBoot+Vue3实现阿里云视频点播 实现教育网站 在上面上传对应的视频,用户开会员以后才能查看视频

要使用阿里云视频点播(VOD)实现一个教育网站,其中用户需要成为会员后才能查看视频,这个过程包括上传视频、设置权限控制、构建前端播放页面以及确保只有付费会员可以访问视频内容。 1. 视频上传与管理 创建阿里云账号&#xff…

【前端】 async 和 await 以及 generator生成器函数

一、背景 这一篇随机主要是想记录一下自己学习js中有关异步内容的东西。然后发现有人拿异步跟生成器函数进行比较了一下,因此一起学习了一下。 二、知识点相关内容及实验test 2.1 generator 生成器函数 generator函数的作用:每次访问返回函数中yield…

智能座舱进阶-应用框架层-Handler分析

首先明确, handler是为了解决单进程内的线程之间的通信问题的。我也需要理解Android系统中进程和线程的概念, APP启动后,会有三四个线程启动起来,其中,有一条mainUITread的线程,专门用来处理UI事件&#xf…

windows openssl编译x64版libssl.lib,编译x64版本libcurl.lib,支持https,vs2015编译器

不要纠结,直接选择用perl编译! 告诫想要用弄成vs编译版的,暂时先别给自己增加麻烦 告诫,以下执行的每一步,都不要纠结 先安装环境 nasm 64位版本 https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-…

汽车供应链 “剧变”开始,“智能感知潜在龙头”诞生

智能汽车产业链“剧变”已经开启,智能感知软硬件能力的权重正在不断被放大。 比如满足高阶泊车的第二代AK2超声波传感器、满足人机共驾场景需求的电子外后视镜(CMS)、iTOF 3D成像视觉感知(用于舱内监控)等新产品&…

Python+OpenCV系列:AI看图识人、识车、识万物

在人工智能风靡全球的今天,用 Python 和 OpenCV 结合机器学习实现物体识别,不仅是酷炫技能,更是掌握未来的敲门砖。本篇博文手把手教你如何通过摄像头或图片输入,识别人、动物、车辆及其他物品,让你的程序瞬间具备 AI …

JVM 详解

一. JVM 内存区域的划分 1. 程序计数器 程序计数器是JVM中一块比较小的空间, 它保存下一条要执行的指令的地址. [注]: 与CPU的程序计数器不同, 这里的下一条指令不是二进制的机器语言, 而是Java字节码. 2. 栈 保存方法中的局部变量, 方法的形参, 方法之间的调用关系. 栈又…

C# opencvsharp 流程化-脚本化-(2)ROI

ROI ROI也是经常需要使用的方法。特别是在图像编辑中。ROI又称感兴趣的区域,但是图像是矩阵是矩形的,感兴趣的是乱八七糟的,所以还有一个Mask需要了解一下的。 public class RoiStep : IImageProcessingStep{public ImageProcessingStepType…

wazuh-modules-sca-scan

sca模块主函数wm_sca_main -> wm_sca_start 检查policy文件中的每一个项目wm_sca_check_policy static int wm_sca_check_policy(const cJSON * const policy, const cJSON * const checks, OSHash *global_check_list) {if(!policy) {return 1;}const cJSON * const id c…

uniapp 自定义图标03

插入工程,修改名称文件内容 编译运行

在Windows本地用网页查看编辑服务器上的 jupyter notebook

​ Motivation: jupyter notebook 可以存中间变量,方便我调整代码,但是怎么用服务器的GPU并在网页上查看编辑呢? 参考 https://zhuanlan.zhihu.com/p/440080687 服务端(Ubuntu): 激活环境 source activate my_env安装notebook …

【YOLO 项目实战】(11)YOLO8 数据集与模型训练

欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【YOLO 项目实战】(1)YOLO5 环境配置与检测 【YOLO 项目实战】(10)YOLO8 环境配置与推理检测 【YOLO 项目实战】(11)YOLO8 数据…

Ubuntu22.04上安装esp-idf

一、安装准备# 建议使用Ubuntu 20.04 或 Ubuntu 22.04 操作系统 为了在 Ubuntu 22.04 中使用 esp-idf,需要安装一些依赖包 sudo apt-get install git wget flex bison gperf python3\python3-pip python3-venv cmake ninja-build ccache\libffi-dev libssl-dev dfu…