You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
396 lines
13 KiB
396 lines
13 KiB
#!/usr/bin/env python3 |
|
|
|
import glob, os, platform, re, shutil, sys, tempfile |
|
|
|
assert sys.version_info >= ( 3, 8 ) |
|
|
|
from Detail.Config import config |
|
import Detail.Utility as utility |
|
|
|
class Build: |
|
|
|
platformString = "" |
|
productVersion = "x.y.z" |
|
productStage = "stage" |
|
productBaseName = "Synergy" |
|
productPackageName = "" |
|
|
|
def __init__( self ): |
|
|
|
self.configure() |
|
|
|
def __configureSubmodules( self ): |
|
|
|
utility.printHeading( "Updating Git submodules..." ) |
|
|
|
os.chdir( config.toplevelPath() ) |
|
|
|
utility.runCommand( "git submodule update --init --remote --recursive" ) |
|
|
|
def __configureCMake( self ): |
|
|
|
utility.printHeading( "Configuring CMake..." ) |
|
|
|
command = ( "cmake" |
|
' -S "' + config.synergyCorePath() + '" ' |
|
' -B "' + config.synergyBuildPath() + '" ' |
|
" -D CMAKE_BUILD_TYPE=Release " |
|
" -D CMAKE_CONFIGURATION_TYPES=Release " |
|
" -D SYNERGY_ENTERPRISE=ON " |
|
) |
|
|
|
if platform.system() == "Darwin": |
|
command += " -D CMAKE_OSX_DEPLOYMENT_TARGET=10.12 " |
|
command += " -D CMAKE_OSX_ARCHITECTURES=x86_64 " |
|
|
|
if config.libQtPath() != "": |
|
command += ' -D CMAKE_PREFIX_PATH="' + config.libQtPath() +'" ' |
|
|
|
if config.cmakeGenerator() != "": |
|
command += ' -G "' + config.cmakeGenerator() + '" ' |
|
|
|
if config.vcvarsallPath() != "": |
|
command = 'call "' + config.vcvarsallPath() + '" x64 && ' + command |
|
|
|
utility.runCommand( command ) |
|
|
|
def __configureVersion( self ): |
|
|
|
utility.printHeading( "Configuring version information..." ) |
|
|
|
def makePlatformString(): |
|
|
|
if platform.system() == "Windows": |
|
return "-".join( [ platform.system(), platform.release(), platform.machine() ] ) |
|
|
|
import distro # TODO: Move this to global scope when distro supports Windows |
|
|
|
platformInfo = list( distro.linux_distribution( full_distribution_name = False ) ); |
|
|
|
while "" in platformInfo: |
|
platformInfo.remove( "" ) |
|
|
|
platformInfo.append( platform.machine() ) |
|
|
|
return "-".join( platformInfo ) |
|
|
|
def makeProductVersion(): |
|
|
|
versionFile = open( config.synergyVersionPath(), "r" ) |
|
versionData = versionFile.read(); |
|
versionFile.close() |
|
|
|
versionParts = re.findall( r" *(?:SET|export) +SYNERGY_VERSION_\w+ *= *\"?(\w+)\"?", versionData ) |
|
|
|
if len( versionParts ) != 4: |
|
printError( "Failed to extract version information." ) |
|
raise SystemExit( 1 ) |
|
|
|
return versionParts |
|
|
|
self.platformString = makePlatformString() |
|
|
|
versionParts = makeProductVersion() |
|
|
|
self.productVersion = ".".join( versionParts[ 0:3 ] ) |
|
self.productStage = versionParts[ 3 ] |
|
|
|
self.productPackageName = "-".join( [ self.productBaseName, self.productVersion, self.productStage, self.platformString ] ).lower() |
|
|
|
utility.printItem( "platformString: ", self.platformString ) |
|
utility.printItem( "productVersion: ", self.productVersion ) |
|
utility.printItem( "productStage: ", self.productStage ) |
|
utility.printItem( "productPackageName: ", self.productPackageName ) |
|
|
|
def configure( self ): |
|
|
|
self.__configureSubmodules() |
|
self.__configureCMake() |
|
self.__configureVersion() |
|
|
|
# Windows builds |
|
def __windowsMakeBinaries( self ): |
|
|
|
utility.printHeading( "Building binaries..." ) |
|
|
|
os.chdir( config.synergyBuildPath() ) |
|
|
|
utility.runCommand( |
|
'call "' + config.vcvarsallPath() + '" x64 && ' |
|
'msbuild synergy-core.sln /p:Platform="x64" /p:Configuration=Release /m ') |
|
|
|
def __windowsMakeMSI( self ): |
|
|
|
utility.printHeading( "Building MSI package..." ) |
|
|
|
installerPath = utility.joinPath( config.synergyBuildPath(), "installer" ) |
|
|
|
os.chdir( installerPath ) |
|
|
|
utility.runCommand( |
|
'call "' + config.vcvarsallPath() + '" x64 && ' |
|
"msbuild Synergy.sln /p:Configuration=Release " ) |
|
|
|
sourcePath = utility.joinPath( installerPath, "bin/Release/Synergy.msi" ) |
|
targetPath = utility.joinPath( config.binariesPath(), self.productPackageName + ".msi" ) |
|
|
|
shutil.move( sourcePath, targetPath ) |
|
|
|
def __windowsMakeZIP( self ): |
|
|
|
utility.printHeading( "Building standalone ZIP package..." ) |
|
|
|
def copySynergyBinaries( sourcePath, productPath ): |
|
|
|
fileList = [ |
|
"libEGL.dll", |
|
"libGLESv2.dll", |
|
"Qt5Core.dll", |
|
"Qt5Gui.dll", |
|
"Qt5Network.dll", |
|
"Qt5Svg.dll", |
|
"Qt5Widgets.dll", |
|
"synergy.exe", |
|
"synergyc.exe", |
|
"synergyd.exe", |
|
"synergys.exe", |
|
"syntool.exe" |
|
] |
|
|
|
if not os.path.exists( productPath ): |
|
os.mkdir( productPath ) |
|
|
|
for fileName in fileList: |
|
filePath = utility.joinPath( sourcePath, fileName ) |
|
shutil.copy2( filePath, productPath ) |
|
|
|
shutil.copytree( utility.joinPath( sourcePath, "Platforms" ), utility.joinPath( productPath, "Platforms" ), dirs_exist_ok = True ) |
|
shutil.copytree( utility.joinPath( sourcePath, "Styles" ), utility.joinPath( productPath, "Styles" ), dirs_exist_ok = True ) |
|
|
|
def copyOpenSSLBinaries( sourceOpenSSLPath, productPath ): |
|
|
|
productOpenSSLPath = utility.joinPath( productPath, "OpenSSL" ) |
|
|
|
if not os.path.exists( productOpenSSLPath ): |
|
os.mkdir( productOpenSSLPath ) |
|
|
|
for filePath in glob.glob( sourceOpenSSLPath + "/*" ): |
|
shutil.copy2( filePath, productOpenSSLPath ) |
|
|
|
for filePath in glob.glob( sourceOpenSSLPath + "/*.dll" ): |
|
shutil.copy2( filePath, productPath ) |
|
|
|
def makeZipArchive( productPath, zipPath ): |
|
|
|
rootPath = utility.joinPath( productPath, ".." ) |
|
basePath = os.path.relpath( productPath, rootPath ) |
|
|
|
shutil.make_archive( zipPath, 'zip', rootPath, basePath ) |
|
|
|
sourcePath = utility.joinPath( config.synergyBuildPath(), "bin/Release" ) |
|
productPath = utility.joinPath( config.synergyBuildPath(), "bin", self.productPackageName ) |
|
|
|
copySynergyBinaries( sourcePath, productPath ) |
|
|
|
sourceOpenSSLPath = utility.joinPath( config.synergyCorePath(), "ext/openssl/windows/x64/bin" ) |
|
|
|
copyOpenSSLBinaries( sourceOpenSSLPath, productPath ) |
|
|
|
zipPath = utility.joinPath( config.binariesPath(), self.productPackageName ) |
|
|
|
makeZipArchive( productPath, zipPath ) |
|
|
|
# Darwin builds |
|
def __darwinMakeApplication( self ): |
|
|
|
utility.printHeading( "Building application bundle..." ) |
|
|
|
os.chdir( config.synergyBuildPath() ) |
|
|
|
# utility.runCommand( "make -j && make install/strip" ) |
|
|
|
appBundlePath = utility.joinPath( config.synergyBuildPath(), "bundle/Synergy.app" ) |
|
|
|
# utility.runCommand( 'macdeployqt "' + appBundlePath + '"' ) |
|
|
|
shutil.copytree( appBundlePath, utility.joinPath( config.binariesPath(), self.productBaseName + ".app" ), dirs_exist_ok = True ) |
|
|
|
def __darwinMakeDMG( self ): |
|
|
|
utility.printHeading( "Building DMG disk image file..." ) |
|
|
|
targetSymlinkPath = utility.joinPath( config.synergyBuildPath(), "bundle/Applications" ) |
|
|
|
if not os.path.exists( targetSymlinkPath ): |
|
os.symlink( "/Applications", targetSymlinkPath, target_is_directory = True ) |
|
|
|
volumeLabel = self.productBaseName + ' ' + self.productVersion; |
|
bundlePath = utility.joinPath( config.synergyBuildPath(), "bundle" ) |
|
packagePath = utility.joinPath( config.binariesPath(), self.productPackageName + ".dmg" ) |
|
|
|
utility.runCommand( "hdiutil create " |
|
'-volname "' + volumeLabel + '" ' |
|
'-srcfolder "' + bundlePath + '" ' |
|
'-ov -format UDZO ' + packagePath ) |
|
|
|
# Linux builds |
|
def __linuxMakeBinaries( self ): |
|
|
|
utility.printHeading( "Building binaries..." ) |
|
|
|
utility.runCommand( 'cmake --build "' + config.synergyBuildPath() + '" --parallel' ) |
|
|
|
def __linuxMakeAppImage( self ): |
|
|
|
utility.printHeading( "Building AppImage package..." ) |
|
|
|
os.chdir( config.toolsPath() ) |
|
|
|
utility.runCommand( "wget -O linuxdeploy -c " + config.linuxdeployURL() + " && chmod a+x linuxdeploy" ) |
|
|
|
appImagePath = utility.joinPath( config.synergyBuildPath(), self.productPackageName + ".AppDir" ) |
|
|
|
# Needed by linuxdeploy |
|
os.environ[ "VERSION" ] = "-".join( [ self.productVersion, self.productStage ] ).lower() |
|
|
|
utility.runCommand( "./linuxdeploy " |
|
'--appdir "' + appImagePath + '" ' |
|
'--executable "' + utility.joinPath( config.synergyBuildPath(), "bin/synergy" ) + '" ' |
|
'--executable "' + utility.joinPath( config.synergyBuildPath(), "bin/synergyc" ) + '" ' |
|
'--executable "' + utility.joinPath( config.synergyBuildPath(), "bin/synergyd" ) + '" ' |
|
'--executable "' + utility.joinPath( config.synergyBuildPath(), "bin/synergys" ) + '" ' |
|
'--executable "' + utility.joinPath( config.synergyBuildPath(), "bin/syntool" ) + '" ' |
|
'--create-desktop-file ' |
|
'--icon-file "' + utility.joinPath( config.synergyCorePath(), "res/synergy.svg" ) + '" ' |
|
'--output appimage' ) |
|
|
|
os.unsetenv( "VERSION" ) |
|
|
|
for fileName in glob.glob( "*.AppImage" ): |
|
shutil.move( |
|
utility.joinPath( config.toolsPath(), fileName ), |
|
utility.joinPath( config.binariesPath(), self.productPackageName + ".AppImage" ) ) |
|
|
|
def __linuxMakeDebian( self ): |
|
|
|
utility.printHeading( "Building Debian package..." ) |
|
|
|
def makeChangeLog(): |
|
|
|
if not os.path.exists( "./debian/changelog" ): |
|
|
|
os.environ[ "SYNERGY_ENTERPRISE" ] = "1" |
|
|
|
utility.runCommand( 'dch ' |
|
'--create ' |
|
'--package "' + self.productBaseName.lower() + '" ' |
|
'--controlmaint ' |
|
'--distribution unstable ' |
|
'--newversion ' + self.productVersion.lower() + ' ' |
|
'"Snapshot release."' ) |
|
|
|
def buildDebianPackage(): |
|
|
|
os.environ[ "DEB_BUILD_OPTIONS" ] = "parallel=8" |
|
|
|
utility.runCommand( "debuild --preserve-envvar SYNERGY_* -us -uc" ) |
|
|
|
def moveDebianPackage(): |
|
|
|
for fileName in glob.glob( "../" + self.productBaseName.lower() + "*.deb" ): |
|
shutil.move( |
|
utility.joinPath( config.synergyCorePath(), fileName ), |
|
utility.joinPath( config.binariesPath(), self.productPackageName + ".deb" ) ) |
|
|
|
for fileName in glob.glob( "../" + self.productBaseName.lower() + "*" ): |
|
shutil.move( |
|
utility.joinPath( config.synergyCorePath(), fileName ), |
|
config.synergyBuildPath() ) |
|
|
|
os.chdir( config.synergyCorePath() ) |
|
|
|
makeChangeLog() |
|
buildDebianPackage() |
|
moveDebianPackage() |
|
|
|
os.unsetenv( "SYNERGY_ENTERPRISE" ) |
|
os.unsetenv( "DEB_BUILD_OPTIONS" ) |
|
|
|
def __linuxMakeRPM( self ): |
|
|
|
utility.printHeading( "Building RPM package..." ) |
|
|
|
def makeSymlinkPath( temporaryPath ): |
|
|
|
sourceSymlinkPath = utility.joinPath( config.synergyBuildPath(), "rpm" ) |
|
targetSymlinkPath = utility.joinPath( temporaryPath, "rpm" ) |
|
|
|
os.symlink( sourceSymlinkPath, targetSymlinkPath, target_is_directory = True ) |
|
|
|
return targetSymlinkPath |
|
|
|
def installBinaries( installPath ): |
|
|
|
utility.runCommand( "cmake" |
|
' -S "' + config.synergyCorePath() + '" ' |
|
' -B "' + config.synergyBuildPath() + '" ' |
|
" -D CMAKE_BUILD_TYPE=Release " |
|
" -D SYNERGY_ENTERPRISE=ON " |
|
' -D CMAKE_INSTALL_PREFIX:PATH="' + installPath + '" ' ) |
|
|
|
os.chdir( config.synergyBuildPath() ) |
|
|
|
utility.runCommand( "make -j && make install/strip" ) |
|
|
|
def makeRpmPackage( rpmToplevelPath, rpmBuildrootPath ): |
|
|
|
if " " in rpmToplevelPath: |
|
printError( "RPM top-level path contained spaces:\n\t", rpmToplevelPath ) |
|
raise SystemExit( 1 ) |
|
|
|
os.chdir( rpmToplevelPath ) |
|
|
|
utility.runCommand( 'rpmbuild -bb ' |
|
'--define "_topdir ' + rpmToplevelPath + '" ' |
|
'--buildroot ' + rpmBuildrootPath + ' ' |
|
"synergy.spec" ) |
|
|
|
def moveRpmPackage( rpmToplevelPath ): |
|
|
|
os.chdir( rpmToplevelPath ) |
|
|
|
for fileName in glob.glob( "RPMS/x86_64/*.rpm" ): |
|
shutil.move( fileName, utility.joinPath( config.binariesPath(), self.productPackageName + ".rpm" ) ) |
|
|
|
# rpmbuild can't handle spaces in paths so we operate inside a temporary path |
|
with tempfile.TemporaryDirectory() as temporaryPath: |
|
|
|
utility.printInfo( "Created: ", temporaryPath ) |
|
|
|
rpmToplevelPath = makeSymlinkPath( temporaryPath ) |
|
rpmBuildrootPath = utility.joinPath( rpmToplevelPath, "BUILDROOT" ) |
|
installPath = utility.joinPath( rpmBuildrootPath, "usr" ) |
|
|
|
installBinaries( installPath ) |
|
makeRpmPackage( rpmToplevelPath, rpmBuildrootPath ) |
|
moveRpmPackage( rpmToplevelPath ) |
|
|
|
def make( self ): |
|
|
|
if platform.system() == "Windows": |
|
self.__windowsMakeBinaries() |
|
self.__windowsMakeMSI() |
|
self.__windowsMakeZIP() |
|
elif platform.system() == "Darwin": |
|
self.__darwinMakeApplication() |
|
self.__darwinMakeDMG() |
|
elif platform.system() == "Linux": |
|
self.__linuxMakeBinaries() |
|
self.__linuxMakeAppImage() |
|
self.__linuxMakeDebian() |
|
self.__linuxMakeRPM() |
|
|
|
|
|
build = Build() |
|
|
|
build.make()
|
|
|