All checks were successful
Deploy Tools / build-package (push) Successful in 34s
454 lines
20 KiB
Python
454 lines
20 KiB
Python
import pl_build.core as pl
|
||
|
||
class plWin32Helper:
|
||
|
||
def __init__(self):
|
||
self.buffer = '\n'
|
||
self.indent = 0
|
||
|
||
def set_indent(self, indent):
|
||
self.indent = indent
|
||
|
||
def write_file(self, file_path):
|
||
with open(file_path, "w") as file:
|
||
file.write(self.buffer)
|
||
|
||
def add_line(self, line):
|
||
self.buffer += ' ' * self.indent + line + '\n'
|
||
|
||
def add_raw(self, text):
|
||
self.buffer += text
|
||
|
||
def add_label(self, label):
|
||
self.buffer += ':' + label + '\n'
|
||
|
||
def add_spacing(self, count = 1):
|
||
self.buffer += '\n' * count
|
||
|
||
def add_title(self, title):
|
||
line_length = 80
|
||
padding = (line_length - 2 - len(title)) / 2
|
||
self.buffer += ":: " + "#" * line_length + "\n"
|
||
self.buffer += ":: #" + " " * int(padding) + title + " " * int(padding + 0.5) + "#" + "\n"
|
||
self.buffer += (":: " + "#" * line_length) + "\n"
|
||
|
||
def add_sub_title(self, title):
|
||
line_length = 80
|
||
padding = (line_length - 2 - len(title)) / 2
|
||
self.buffer += "::" + "~" * int(padding) + " " + title + " " + "~" * int(padding + 0.5) + "\n"
|
||
|
||
def add_comment(self, comment):
|
||
self.buffer += ' ' * self.indent + ':: ' + comment + '\n'
|
||
|
||
def print_line(self, text):
|
||
self.buffer += ' ' * self.indent + '@echo ' + text + '\n'
|
||
|
||
def print_space(self):
|
||
self.buffer += '@echo.\n'
|
||
|
||
def create_directory(self, directory):
|
||
self.buffer += ' ' * self.indent + '@if not exist "' + directory + '" @mkdir "' + directory + '"\n\n'
|
||
|
||
def delete_file(self, file):
|
||
self.buffer += ' ' * self.indent + '@if exist "' + file + '"'
|
||
self.buffer += ' del "' + file + '"\n'
|
||
|
||
def generate_build(name, user_options = None):
|
||
|
||
platform = "Windows"
|
||
compiler = "msvc"
|
||
|
||
data = pl.get_script_data()
|
||
|
||
# retrieve settings supported by this platform/compiler & add
|
||
# default extensions if the user did not
|
||
platform_settings = []
|
||
for settings in data.current_settings:
|
||
if settings.platform_name == platform and settings.name == compiler:
|
||
if settings.output_binary_extension is None:
|
||
if settings.target_type == pl.TargetType.EXECUTABLE:
|
||
settings.output_binary_extension = ".exe"
|
||
elif settings.target_type == pl.TargetType.DYNAMIC_LIBRARY:
|
||
settings.output_binary_extension = ".dll"
|
||
elif settings.target_type == pl.TargetType.STATIC_LIBRARY:
|
||
settings.output_binary_extension = ".lib"
|
||
platform_settings.append(settings)
|
||
|
||
|
||
helper = plWin32Helper()
|
||
|
||
hot_reload = False
|
||
|
||
###############################################################################
|
||
# Intro #
|
||
###############################################################################
|
||
|
||
helper.add_comment("Project: " + data.project_name)
|
||
helper.add_comment("Auto Generated by:")
|
||
helper.add_comment('"pl_build.py" version: ' + data.version)
|
||
helper.add_spacing()
|
||
helper.add_comment("Project: " + data.project_name)
|
||
helper.add_spacing()
|
||
|
||
helper.add_title("Development Setup")
|
||
helper.add_spacing()
|
||
|
||
helper.add_comment('keep environment variables modifications local')
|
||
helper.add_line("@setlocal")
|
||
helper.add_spacing()
|
||
|
||
helper.add_comment("make script directory CWD")
|
||
helper.add_line('@pushd %~dp0')
|
||
helper.add_line('@set dir=%~dp0')
|
||
helper.add_spacing()
|
||
|
||
# try to setup dev environment
|
||
if isinstance(user_options, dict):
|
||
if "dev env setup" in user_options:
|
||
if user_options["dev env setup"] == True:
|
||
helper.add_comment("modify PATH to find vcvarsall.bat")
|
||
helper.add_line('@set PATH=C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build;%PATH%')
|
||
helper.add_line('@set PATH=C:\\Program Files\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build;%PATH%')
|
||
helper.add_line('@set PATH=C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build;%PATH%')
|
||
helper.add_line('@set PATH=C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build;%PATH%')
|
||
helper.add_line('@set PATH=C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise/VC\\Auxiliary\\Build;%PATH%')
|
||
helper.add_spacing()
|
||
|
||
helper.add_comment("setup environment for MSVC dev tools")
|
||
helper.add_line('@call vcvarsall.bat amd64 > nul')
|
||
helper.add_spacing()
|
||
|
||
helper.add_comment("default compilation result")
|
||
helper.add_line('@set PL_RESULT=[1m[92mSuccessful.[0m')
|
||
helper.add_spacing()
|
||
|
||
# set default config
|
||
if data.registered_configurations:
|
||
helper.add_comment("default configuration")
|
||
helper.add_line("@set PL_CONFIG=" + data.registered_configurations[0])
|
||
helper.add_spacing()
|
||
|
||
# check command line args for config
|
||
helper.add_comment("check command line args for configuration")
|
||
helper.add_label("CheckConfiguration")
|
||
helper.add_line('@if "%~1"=="-c" (@set PL_CONFIG=%2) & @shift & @shift & @goto CheckConfiguration')
|
||
for register_config in data.registered_configurations:
|
||
helper.add_line('@if "%PL_CONFIG%" equ "' + register_config + '" ( goto ' + register_config + ' )')
|
||
helper.add_spacing()
|
||
|
||
# if _context.pre_build_step is not None:
|
||
# helper.add_line(_context.pre_build_step)
|
||
# helper.add_spacing()
|
||
|
||
|
||
|
||
for register_config in data.registered_configurations:
|
||
|
||
# filter this config only settings
|
||
config_only_settings = []
|
||
for settings in platform_settings:
|
||
if settings.config_name == register_config:
|
||
config_only_settings.append(settings)
|
||
|
||
if len(config_only_settings) == 0:
|
||
continue
|
||
|
||
# find hot reload target
|
||
if data.reload_target_name is not None:
|
||
hot_reload = True
|
||
|
||
helper.add_title("configuration | " + register_config)
|
||
helper.add_spacing()
|
||
helper.add_label(register_config)
|
||
helper.add_spacing()
|
||
|
||
output_dirs = set()
|
||
for settings in config_only_settings:
|
||
output_dirs.add(settings.output_directory)
|
||
|
||
# create output directories
|
||
helper.add_comment("create output directories")
|
||
for dir in output_dirs:
|
||
helper.create_directory(dir)
|
||
|
||
lock_files = set()
|
||
for settings in config_only_settings:
|
||
lock_files.add(settings.lock_file)
|
||
helper.add_comment("create lock file(s)")
|
||
for lock_file in lock_files:
|
||
helper.add_line('@echo LOCKING > "' + settings.output_directory + '/' + lock_file + '"')
|
||
|
||
helper.add_spacing()
|
||
|
||
if hot_reload:
|
||
|
||
helper.add_comment("check if this is a hot reload")
|
||
helper.add_line("@set PL_HOT_RELOAD_STATUS=0")
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("hack to see if " + data.reload_target_name + " exe is running")
|
||
helper.add_line("@echo off")
|
||
helper.add_line('2>nul (>>"' + data.reload_target_name + '.exe" echo off) && (@set PL_HOT_RELOAD_STATUS=0) || (@set PL_HOT_RELOAD_STATUS=1)')
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("let user know if hot reloading")
|
||
helper.add_line("@if %PL_HOT_RELOAD_STATUS% equ 1 (")
|
||
helper.set_indent(4)
|
||
helper.print_line("[1m[97m[41m--------[42m HOT RELOADING [41m--------[0m")
|
||
helper.set_indent(0)
|
||
helper.add_line(")")
|
||
helper.set_indent(0)
|
||
helper.add_spacing()
|
||
helper.add_comment("cleanup binaries if not hot reloading")
|
||
helper.add_line("@if %PL_HOT_RELOAD_STATUS% equ 0 (\n")
|
||
helper.set_indent(4)
|
||
|
||
# delete old binaries & files
|
||
for settings in config_only_settings:
|
||
if settings.source_files:
|
||
helper.delete_file(settings.output_directory + '/' + settings.output_binary + settings.output_binary_extension)
|
||
if settings.target_type == pl.TargetType.DYNAMIC_LIBRARY:
|
||
helper.delete_file(settings.output_directory + '/' + settings.output_binary + '_*' + settings.output_binary_extension)
|
||
helper.delete_file(settings.output_directory + '/' + settings.output_binary + '_*.pdb')
|
||
elif settings.target_type == pl.TargetType.EXECUTABLE:
|
||
helper.delete_file(settings.output_directory + '/' + settings.output_binary + '_*.pdb')
|
||
|
||
helper.set_indent(0)
|
||
if hot_reload:
|
||
helper.add_spacing()
|
||
helper.add_line(")")
|
||
helper.add_spacing()
|
||
|
||
# other targets
|
||
for settings in config_only_settings:
|
||
helper.add_sub_title(settings.target_name + " | " + register_config)
|
||
helper.add_spacing()
|
||
|
||
if not settings.reloadable and hot_reload:
|
||
helper.add_comment("skip during hot reload")
|
||
helper.add_line('@if %PL_HOT_RELOAD_STATUS% equ 1 goto ' + "Exit_" + settings.target_name)
|
||
helper.add_spacing()
|
||
|
||
if settings.pre_build_step is not None:
|
||
helper.add_line(settings.pre_build_step)
|
||
helper.add_spacing()
|
||
|
||
if settings.definitions:
|
||
helper.add_raw('@set PL_DEFINES=')
|
||
for define in settings.definitions:
|
||
helper.add_raw("-D" + define + " ")
|
||
helper.add_spacing()
|
||
|
||
if settings.include_directories:
|
||
helper.add_raw('@set PL_INCLUDE_DIRECTORIES=')
|
||
for include in settings.include_directories:
|
||
helper.add_raw('-I"' + include + '" ')
|
||
helper.add_spacing()
|
||
|
||
if settings.link_directories:
|
||
helper.add_raw('@set PL_LINK_DIRECTORIES=')
|
||
for link in settings.link_directories:
|
||
helper.add_raw('-LIBPATH:"' + link + '" ')
|
||
helper.add_spacing()
|
||
|
||
if settings.compiler_flags:
|
||
helper.add_raw('@set PL_COMPILER_FLAGS=')
|
||
for flag in settings.compiler_flags:
|
||
helper.add_raw(flag + " ")
|
||
helper.add_spacing()
|
||
|
||
settings.linker_flags.extend(["-incremental:no"])
|
||
if settings.target_type == pl.TargetType.DYNAMIC_LIBRARY:
|
||
settings.linker_flags.extend(["-noimplib", "-noexp"])
|
||
|
||
if settings.linker_flags:
|
||
helper.add_raw('@set PL_LINKER_FLAGS=')
|
||
for flag in settings.linker_flags:
|
||
helper.add_raw(flag + " ")
|
||
helper.add_spacing()
|
||
|
||
if settings.static_link_libraries:
|
||
helper.add_raw('@set PL_STATIC_LINK_LIBRARIES=')
|
||
for link in settings.static_link_libraries:
|
||
helper.add_raw(link + ".lib ")
|
||
helper.add_spacing()
|
||
|
||
if settings.dynamic_link_libraries:
|
||
helper.add_raw('@set PL_DYNAMIC_LINK_LIBRARIES=')
|
||
for link in settings.dynamic_link_libraries:
|
||
helper.add_raw(link + ".lib ")
|
||
helper.add_spacing()
|
||
|
||
if settings.target_type == pl.TargetType.STATIC_LIBRARY:
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("run compiler only")
|
||
helper.print_space()
|
||
helper.print_line("[1m[93mStep: " + settings.target_name +"[0m")
|
||
helper.print_line("[1m[93m~~~~~~~~~~~~~~~~~~~~~~[0m")
|
||
helper.print_line("[1m[36mCompiling...[0m")
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment('each file must be compiled separately')
|
||
for source in settings.source_files:
|
||
sub_buffer = ""
|
||
if settings.include_directories:
|
||
sub_buffer += " %PL_INCLUDE_DIRECTORIES%"
|
||
if settings.definitions:
|
||
sub_buffer += " %PL_DEFINES%"
|
||
if settings.compiler_flags:
|
||
sub_buffer += " %PL_COMPILER_FLAGS%"
|
||
helper.add_line('cl -c' + sub_buffer + " " + source + ' -Fo"' + settings.output_directory + '/"')
|
||
helper.add_spacing()
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("check build status")
|
||
helper.add_line("@set PL_BUILD_STATUS=%ERRORLEVEL%")
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("if failed, skip linking")
|
||
helper.add_raw("@if %PL_BUILD_STATUS% NEQ 0 (\n")
|
||
helper.add_raw(" @echo [1m[91mCompilation Failed with error code[0m: %PL_BUILD_STATUS%\n")
|
||
helper.add_raw(" @set PL_RESULT=[1m[91mFailed.[0m\n")
|
||
helper.add_raw(" goto " + 'Cleanup' + register_config)
|
||
helper.add_raw("\n)\n")
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment('link object files into a shared lib')
|
||
helper.add_raw("@echo [1m[36mLinking...[0m\n")
|
||
helper.add_raw('lib -nologo -OUT:"' + settings.output_directory + '/' + settings.output_binary + settings.output_binary_extension + '" "' + settings.output_directory + '/*.obj"\n')
|
||
|
||
elif settings.target_type == pl.TargetType.DYNAMIC_LIBRARY:
|
||
|
||
helper.add_raw('@set PL_SOURCES=')
|
||
for source in settings.source_files:
|
||
helper.add_raw('"' + source + '" ')
|
||
helper.add_spacing()
|
||
|
||
sub_buffer0 = ""
|
||
sub_buffer1 = ""
|
||
sub_buffer2 = ""
|
||
if settings.include_directories:
|
||
sub_buffer0 += " %PL_INCLUDE_DIRECTORIES%"
|
||
if settings.definitions:
|
||
sub_buffer0 += " %PL_DEFINES%"
|
||
if settings.compiler_flags:
|
||
sub_buffer0 += " %PL_COMPILER_FLAGS%"
|
||
if settings.linker_flags:
|
||
sub_buffer1 = " %PL_LINKER_FLAGS%"
|
||
if settings.link_directories:
|
||
sub_buffer2 += " %PL_LINK_DIRECTORIES%"
|
||
if settings.static_link_libraries:
|
||
sub_buffer2 += " %PL_STATIC_LINK_LIBRARIES%"
|
||
if settings.dynamic_link_libraries:
|
||
sub_buffer2 += " %PL_DYNAMIC_LINK_LIBRARIES%"
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("run compiler (and linker)")
|
||
helper.print_space()
|
||
helper.add_raw('@echo [1m[93mStep: ' + settings.target_name +'[0m\n')
|
||
helper.add_raw('@echo [1m[93m~~~~~~~~~~~~~~~~~~~~~~[0m\n')
|
||
helper.add_raw('@echo [1m[36mCompiling and Linking...[0m\n')
|
||
helper.add_raw('cl' + sub_buffer0 + ' %PL_SOURCES% -Fe"' + settings.output_directory + '/' + settings.output_binary + settings.output_binary_extension + '" -Fo"' + settings.output_directory + '/" -LD -link' + sub_buffer1 + ' -PDB:"' + settings.output_directory + '/' + settings.output_binary + '_%random%.pdb"' + sub_buffer2 + "\n\n")
|
||
|
||
helper.add_comment("check build status")
|
||
helper.add_raw("@set PL_BUILD_STATUS=%ERRORLEVEL%\n")
|
||
|
||
helper.add_raw("\n:: failed\n")
|
||
helper.add_raw("@if %PL_BUILD_STATUS% NEQ 0 (\n")
|
||
helper.add_raw(" @echo [1m[91mCompilation Failed with error code[0m: %PL_BUILD_STATUS%\n")
|
||
helper.add_raw(" @set PL_RESULT=[1m[91mFailed.[0m\n")
|
||
helper.add_raw(" goto " + 'Cleanup' + register_config)
|
||
helper.add_raw("\n)\n")
|
||
|
||
elif settings.target_type == pl.TargetType.EXECUTABLE:
|
||
|
||
helper.add_raw('@set PL_SOURCES=')
|
||
for source in settings.source_files:
|
||
helper.add_raw('"' + source + '" ')
|
||
helper.add_spacing(2)
|
||
|
||
sub_buffer0 = ""
|
||
sub_buffer1 = ""
|
||
sub_buffer2 = ""
|
||
if settings.include_directories:
|
||
sub_buffer0 += " %PL_INCLUDE_DIRECTORIES%"
|
||
if settings.definitions:
|
||
sub_buffer0 += " %PL_DEFINES%"
|
||
if settings.compiler_flags:
|
||
sub_buffer0 += " %PL_COMPILER_FLAGS%"
|
||
if settings.linker_flags:
|
||
sub_buffer1 = " %PL_LINKER_FLAGS%"
|
||
if settings.link_directories:
|
||
sub_buffer2 += " %PL_LINK_DIRECTORIES%"
|
||
if settings.static_link_libraries:
|
||
sub_buffer2 += " %PL_STATIC_LINK_LIBRARIES%"
|
||
if settings.dynamic_link_libraries:
|
||
sub_buffer2 += " %PL_DYNAMIC_LINK_LIBRARIES%"
|
||
|
||
helper.add_comment("run compiler (and linker)")
|
||
helper.print_space()
|
||
helper.print_line('[1m[93mStep: ' + settings.target_name +'[0m')
|
||
helper.print_line('[1m[93m~~~~~~~~~~~~~~~~~~~~~~[0m')
|
||
helper.print_line('[1m[36mCompiling and Linking...[0m')
|
||
|
||
|
||
if hot_reload:
|
||
helper.add_raw('\n:: skip actual compilation if hot reloading\n')
|
||
helper.add_raw('@if %PL_HOT_RELOAD_STATUS% equ 1 ( goto ' + 'Cleanup' + settings.target_name + ' )\n')
|
||
|
||
helper.add_raw('\n:: call compiler\n')
|
||
helper.add_raw('cl' + sub_buffer0 + ' %PL_SOURCES% -Fe"' + settings.output_directory + '/' + settings.output_binary + settings.output_binary_extension + '" -Fo"' + settings.output_directory + '/" -link' + sub_buffer1 + ' -PDB:"' + settings.output_directory + '/' + settings.output_binary + '_%random%.pdb"' + sub_buffer2 + "\n\n")
|
||
|
||
helper.add_comment("check build status")
|
||
helper.add_raw("@set PL_BUILD_STATUS=%ERRORLEVEL%\n")
|
||
helper.add_raw("\n:: failed\n")
|
||
helper.add_raw("@if %PL_BUILD_STATUS% NEQ 0 (\n")
|
||
helper.add_raw(" @echo [1m[91mCompilation Failed with error code[0m: %PL_BUILD_STATUS%\n")
|
||
helper.add_raw(" @set PL_RESULT=[1m[91mFailed.[0m\n")
|
||
helper.add_raw(" goto " + 'Cleanup' + register_config)
|
||
helper.add_raw("\n)\n")
|
||
|
||
helper.add_spacing()
|
||
|
||
helper.add_comment("print results")
|
||
helper.print_line("[36mResult: [0m %PL_RESULT%")
|
||
helper.add_raw("@echo [36m~~~~~~~~~~~~~~~~~~~~~~[0m\n")
|
||
helper.add_spacing()
|
||
|
||
if settings.post_build_step is not None:
|
||
helper.add_line(settings.post_build_step)
|
||
helper.add_spacing()
|
||
|
||
if not settings.reloadable:
|
||
helper.add_label("Exit_" + settings.target_name)
|
||
helper.add_spacing()
|
||
|
||
helper.add_line(':Cleanup' + register_config)
|
||
helper.add_spacing()
|
||
helper.print_line('[1m[36mCleaning...[0m')
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("delete obj files(s)")
|
||
for dir in output_dirs:
|
||
helper.add_line('@del "' + dir + '/*.obj" > nul 2> nul')
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment("delete lock file(s)")
|
||
for lock_file in lock_files:
|
||
helper.delete_file(settings.output_directory + '/' + lock_file)
|
||
|
||
helper.add_spacing()
|
||
helper.add_comment('~' * 40)
|
||
helper.add_comment('end of ' + settings.config_name + ' configuration')
|
||
helper.add_line("goto ExitLabel")
|
||
helper.add_spacing()
|
||
|
||
helper.add_label("ExitLabel")
|
||
helper.add_spacing()
|
||
# if _context.post_build_step is not None:
|
||
# helper.add_line(_context.post_build_step)
|
||
# helper.add_spacing()
|
||
helper.add_comment("return CWD to previous CWD")
|
||
helper.add_line('@popd')
|
||
helper.write_file(name) |