Files
spark/tools/py/publish_api_server.py
T

207 lines
5.5 KiB
Python

import argparse
import os
import subprocess
import sys
from typing import Optional
from build_spark import SparkPaths
from core.iter_utils import at_bounded
def _dotnet_verbosity(level):
names = ['quiet', 'minimal', 'normal', 'detailed', 'diagnostic']
return at_bounded(names, level)
def _cmake_verbosity(level):
# Skip 'WARNING' and 'NOTICE' levels, since the default CMake verbosity,
# 'STATUS', doesn't produce that much output. This also better normalizes
# numeric representation of verbosity w/ dotnet, which only has 5 levels.
names = [
'ERROR',
# 'WARNING',
# 'NOTICE',
'STATUS',
'VERBOSE',
'DEBUG',
'TRACE',
]
return at_bounded(names, level)
def _cmake_preset():
match sys.platform:
case 'win32':
return 'spark-api-server-windows'
case 'linux':
return 'spark-api-server-linux'
case _:
raise ValueError(f'Unsupported platform {sys.platform}')
def _cmake_build_preset(configuration):
match sys.platform:
case 'win32':
return f'spark-api-server-windows-{configuration}'
case 'linux':
return f'spark-api-server-linux-{configuration}'
case _:
raise ValueError(f'Unsupported platform {sys.platform}')
def _dotnet_runtime():
match sys.platform:
case 'win32':
return 'win-x64'
case 'linux':
return 'linux-x64'
case _:
raise ValueError(f'Unsupported platform {sys.platform}')
class PublishArgs:
def __init__(
self,
configuration: str = 'release',
clean: bool = False,
verbosity: int = 1,
dry_run: bool = False,
output: Optional[str] = None,
framework='net7.0',
runtime=_dotnet_runtime(),
):
self.configuration = configuration
self.clean = clean
self.verbosity = verbosity
self.dry_run = dry_run
self.dotnet_verbosity = at_bounded(
['quiet', 'minimal', 'normal', 'detailed', 'diagnostic'],
verbosity)
# Leave out WARNING and NOTICE to normalize cmake log level and dotnet verbosity
# (so both can be expressed as an int 1-5)
self.cmake_log_level = at_bounded(
[
'ERROR',
# 'WARNING',
# 'NOTICE',
'STATUS',
'VERBOSE',
'DEBUG',
'TRACE',
],
verbosity)
self.output = output
self.framework = framework
self.runtime = runtime
def _get_arg_parser():
parser = argparse.ArgumentParser(
description='Publish a self-contined spark client application')
parser.add_argument(
'--configuration',
metavar='debug|release',
help='The build configuration',
)
parser.add_argument(
'--clean',
action='store_true',
help='Perform a clean build (remove artifacts from previous build)',
)
parser.add_argument(
'-o',
'--output',
type=str,
help='The output directory for published artifacts.')
parser.add_argument(
'--verbosity',
metavar='{0-5}',
choices=range(0, 6),
type=int,
help='The output verbosity level',
)
parser.add_argument(
'--dry-run',
action='store_true',
help='Preview the build commands without running them',
)
defaults = PublishArgs()
parser.set_defaults(
configuration=defaults.configuration,
clean=defaults.clean,
output=defaults.output,
verbosity=defaults.verbosity,
dry_run=defaults.dry_run,
)
return parser
def publish(args: PublishArgs):
def run(cmd):
print(cmd)
if args.dry_run:
return
subprocess.run(cmd, shell=True).check_returncode()
def dotnet_cmd(action='build'):
sln = SparkPaths.root().joinpath('Spark.Api.Server.sln')
return ' '.join([
f'dotnet {action} {sln}',
f'--configuration {args.configuration.title()}',
f'--verbosity {_dotnet_verbosity(args.verbosity)}',
])
os.chdir(SparkPaths.root())
publish_dir = SparkPaths.default_build().joinpath(
args.configuration.title(),
'bin',
args.framework,
args.runtime,
'publish',
)
cmake_configure_cmd = ' '.join([
f'cmake',
f'--preset',
_cmake_preset(),
f'-DCMAKE_MESSAGE_LOG_LEVEL={_cmake_verbosity(args.verbosity)}',
f'-DDOTNET_BINARY_DIR={publish_dir}',
])
cmake_build_cmd = ' '.join([
f'cmake',
f'--build',
f'--preset {_cmake_build_preset(args.configuration.lower())}',
])
if args.clean:
run(f'{cmake_build_cmd} --target clean')
run(dotnet_cmd('clean'))
run(cmake_configure_cmd)
run(cmake_build_cmd)
publish_cmd = f'{dotnet_cmd("publish")} -f {args.framework} -r {args.runtime} --sc'
run(publish_cmd)
if args.output:
run(f'mv {publish_dir} {args.output}')
def _main():
parser = _get_arg_parser()
args = parser.parse_args()
publish(
PublishArgs(
configuration=args.configuration,
clean=args.clean,
verbosity=args.verbosity,
dry_run=args.dry_run,
output=args.output,
))
if __name__ == '__main__':
try:
_main()
except Exception as e:
print(f"publish_api_server.py failed: {e}")
exit(1)