2022-10-07 05:41:04 +03:00
import path from 'node:path'
import fs from 'node:fs'
import { command } from 'execa'
import archiver from 'archiver'
import prettyBytes from 'pretty-bytes'
2022-10-07 06:53:43 +03:00
import {
PYTHON _BRIDGE _SRC _PATH ,
TCP _SERVER _SRC _PATH ,
BINARIES _FOLDER _NAME ,
PYTHON _BRIDGE _DIST _PATH ,
TCP _SERVER _DIST _PATH ,
PYTHON _BRIDGE _BIN _NAME ,
TCP _SERVER _BIN _NAME
} from '@/constants'
2022-11-20 18:21:06 +03:00
import { OSTypes } from '@/types'
2022-10-07 05:41:04 +03:00
import { LogHelper } from '@/helpers/log-helper'
import { LoaderHelper } from '@/helpers/loader-helper'
2022-11-20 18:21:06 +03:00
import { SystemHelper } from '@/helpers/system-helper'
2022-10-07 05:41:04 +03:00
/ * *
* Build binaries for the given OS according to the given build target
* 1. Get the correct OS platform and CPU architecture
* 2. If Linux , install the required dependencies
* 3. Build the given build target
* 4. Pack the distribution entities into a ZIP file
* /
const BUILD _TARGETS = new Map ( )
BUILD _TARGETS . set ( 'python-bridge' , {
name : 'Python bridge' ,
pipfilePath : path . join ( PYTHON _BRIDGE _SRC _PATH , 'Pipfile' ) ,
setupFilePath : path . join ( PYTHON _BRIDGE _SRC _PATH , 'setup.py' ) ,
2022-10-07 06:53:43 +03:00
distPath : PYTHON _BRIDGE _DIST _PATH ,
2022-10-07 07:07:48 +03:00
archiveName : ` ${ PYTHON _BRIDGE _BIN _NAME } - ${ BINARIES _FOLDER _NAME } .zip ` ,
dotVenvPath : path . join ( PYTHON _BRIDGE _SRC _PATH , '.venv' )
2022-10-07 05:41:04 +03:00
} )
BUILD _TARGETS . set ( 'tcp-server' , {
name : 'TCP server' ,
pipfilePath : path . join ( TCP _SERVER _SRC _PATH , 'Pipfile' ) ,
setupFilePath : path . join ( TCP _SERVER _SRC _PATH , 'setup.py' ) ,
2022-10-07 06:53:43 +03:00
distPath : TCP _SERVER _DIST _PATH ,
2022-10-07 07:07:48 +03:00
archiveName : ` ${ TCP _SERVER _BIN _NAME } - ${ BINARIES _FOLDER _NAME } .zip ` ,
dotVenvPath : path . join ( TCP _SERVER _SRC _PATH , '.venv' )
2022-10-07 05:41:04 +03:00
} )
; ( async ( ) => {
LoaderHelper . start ( )
const { argv } = process
const givenBuildTarget = argv [ 2 ] . toLowerCase ( )
if ( ! BUILD _TARGETS . has ( givenBuildTarget ) ) {
LogHelper . error (
` Invalid build target: ${ givenBuildTarget } . Valid targets are: ${ Array . from (
BUILD _TARGETS . keys ( )
) . join ( ', ' ) } `
)
process . exit ( 1 )
}
const {
name : buildTarget ,
pipfilePath ,
setupFilePath ,
distPath ,
2022-10-07 07:07:48 +03:00
archiveName ,
dotVenvPath
2022-10-07 05:41:04 +03:00
} = BUILD _TARGETS . get ( givenBuildTarget )
const buildPath = path . join ( distPath , BINARIES _FOLDER _NAME )
2022-11-20 18:21:06 +03:00
const { type : osType } = SystemHelper . getInformation ( )
2022-10-07 05:41:04 +03:00
/ * *
* Install requirements
* /
try {
if ( osType === OSTypes . Linux ) {
LogHelper . info ( 'Checking whether the "patchelf" utility can be found...' )
await command ( 'patchelf --version' , { shell : true } )
LogHelper . success ( 'The "patchelf" utility has been found' )
}
} catch ( e ) {
const installPatchelfCommand = 'sudo apt install patchelf'
LogHelper . error (
` The "patchelf" utility is not installed. Please run the following command: " ${ installPatchelfCommand } " or install it via a packages manager supported by your Linux distribution such as DNF, YUM, etc. Then try again `
)
process . exit ( 1 )
}
/ * *
* Build
* /
try {
LogHelper . info ( ` Building the ${ buildTarget } ... ` )
// Required environment variables to set up
process . env . PIPENV _PIPFILE = pipfilePath
process . env . PIPENV _VENV _IN _PROJECT = true
await command (
` pipenv run python ${ setupFilePath } build --build-exe ${ buildPath } ` ,
{
shell : true ,
stdio : 'inherit'
}
)
LogHelper . success ( ` The ${ buildTarget } has been built ` )
} catch ( e ) {
2022-10-07 07:07:48 +03:00
LogHelper . error (
` An error occurred while building the ${ buildTarget } . Try to delete the ${ dotVenvPath } folder, run the setup command then build again: ${ e } `
)
2022-10-07 05:41:04 +03:00
process . exit ( 1 )
}
/ * *
* Pack distribution entities into a ZIP archive
* /
const archivePath = path . join ( distPath , archiveName )
LogHelper . info ( ` Packing to ${ archivePath } ... ` )
const output = fs . createWriteStream ( archivePath )
const archive = archiver ( 'zip' )
output . on ( 'close' , ( ) => {
const size = prettyBytes ( archive . pointer ( ) )
LogHelper . info ( ` Total archive size: ${ size } ` )
LogHelper . success ( ` ${ buildTarget } has been packed to ${ archivePath } ` )
process . exit ( 0 )
} )
archive . on ( 'error' , ( err ) => {
LogHelper . error (
` An error occurred while packing the ${ buildTarget } : ${ err } `
)
} )
archive . pipe ( output )
archive . directory ( buildPath , BINARIES _FOLDER _NAME )
await archive . finalize ( )
} ) ( )