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)
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()`方法处理构建结果,否则记录错误并退出程序。
"""
if self. archs == "amd64" :
self. archs = "X86_64"
self. logger. debug( f"构建系统: { self. os_type} " , )
self. logger. debug( f"构建架构: { self. archs} " )
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"
c = f" { self. go} build { self. file } "
if os. system( c) == 0 :
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"等。
返回:
无
"""
os. environ[ 'GOOS' ] = o
self. os_type = o
def arch ( self, arch) :
"""
设置架构并触发构建过程
该方法接收一个架构名称,根据特定规则转换后设置环境变量GOARCH,
并将该架构名称保存以供后续使用。最后,调用build方法进行构建。
参数:
arch (str): 构架名称,可能需要转换以适配特定的命名约定。
返回:
无
"""
if arch == "X86_64" :
arch = "amd64"
os. environ[ 'GOARCH' ] = arch
self. archs = arch
self. build( )
def start ( self, save) :
"""
启动初始化和操作系统处理流程
在这个方法中,首先进行初始化操作,然后根据`save`参数检查目录是否存在,
如果不存在则创建目录.随后,遍历操作系统列表,对每个操作系统进行处理.
对于Linux操作系统,进一步遍历其架构列表并进行处理;对于其他操作系统,
则默认使用X86_64架构进行处理.
参数:
save (str): 保存路径字符串,用于检查是否存在以及创建目录
"""
self. init( )
if not os. path. isdir( save) :
os. mkdir( "./client" )
for i in self. os_list:
self. ost( i)
if i == "linux" :
self. logger. debug( f"架构列表: { self. arch_list} " )
for a in self. arch_list:
self. arch( arch= a)
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" )
parser. add_argument( "-l" , "--linux" , help = "是否启用Linux平台" , action= 'store_true' , default= True )
parser. add_argument( "--no-linux" , help = "禁用Linux平台" , action= 'store_false' , dest= 'linux' )
parser. add_argument( "-d" , "--darwin" , help = "是否启用Darwin平台" , action= 'store_true' , default= True )
parser. add_argument( "--no-darwin" , help = "禁用Darwin平台" , action= 'store_false' , dest= 'darwin' )
parser. add_argument( "-w" , "--windows" , help = "是否启用Windows平台" , action= 'store_true' , default= True )
parser. add_argument( "--no-windows" , help = "禁用Windows平台" , action= 'store_false' , dest= 'windows' )
parser. add_argument( "-a" , "--arm64" , help = "是否启用arm64平台" , action= 'store_true' , default= True )
parser. add_argument( "--no-arm64" , help = "禁用arm64平台" , action= 'store_false' , dest= 'arm64' )
parser. add_argument( "-r32" , "--arm32" , help = "是否启用arm32平台" , action= 'store_true' , default= True )
parser. add_argument( "--no-arm32" , help = "禁用arm32平台" , action= 'store_false' , dest= 'arm32' )
parser. add_argument( "-m" , "--mips64" , help = "是否启用mips64平台" , action= 'store_true' , default= True )
parser. add_argument( "--no-mips64" , help = "禁用mips64平台" , action= 'store_false' , dest= 'mips64' )
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_ = 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 = args. mips64
linux = args. linux
darwin = args. darwin
arm64 = args. arm64
x86 = args. x86
arm32 = args. arm32
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} " )
up = GoBuild( f= file , n= name)
up. arm32 = arm32
up. windows = windows
up. arm64 = arm64
up. mips64 = mips64
up. x86 = x86
up. linux = linux
up. darwin = darwin
up. start( save= args. output)
效果