merge upstream

This commit is contained in:
2025-04-10 17:16:12 +00:00
15 changed files with 263 additions and 42 deletions

View File

@ -427,6 +427,19 @@ def build(target, is_play=False, is_publish=False, is_export=False):
global profile_time
profile_time = time.time()
wrd = bpy.data.worlds['Lnx']
if is_play and wrd.lnx_runtime == 'Hashlink':
current_os = lnx.utils.get_os()
if current_os == 'win':
target = 'windows-hl'
elif current_os == 'linux':
target = 'linux-hl'
elif current_os == 'macos':
target = 'macos-hl'
else:
log.error(f"Unsupported OS '{current_os}' for Hashlink runtime.")
state.target = target
state.is_play = is_play
state.is_publish = is_publish
@ -680,6 +693,148 @@ def build_success():
cmd.append(str(pid))
if wrd.lnx_audio == 'Disabled':
cmd.append('--nosound')
elif state.target.startswith(('windows-hl', 'linux-hl', 'macos-hl')):
log.info(f"Runtime Hashlink/C target: {state.target}")
hl_build_dir, _, _ = lnx.utils.hashlink_paths(state.target)
if not hl_build_dir:
log.error(f"Could not find build directory for target {state.target}. Playback aborted.")
return
if state.target == 'windows-hl':
vs_version_major = wrd.lnx_project_win_list_vs
build_mode = wrd.lnx_project_win_build_mode # Debug or Release
build_arch = wrd.lnx_project_win_build_arch # x64 or x86 (maps to Win32 for MSBuild)
platform = 'x64' if build_arch == 'x64' else 'Win32' # MSBuild uses Win32 for x86
installation = lnx.utils_vs.get_installed_version(vs_version_major, re_fetch=True)
if installation is None:
vs_info = lnx.utils_vs.get_supported_version(vs_version_major)
log.error(f'Visual Studio {vs_info["name"]} not found. Cannot compile {state.target}.')
return
msbuild_path = os.path.join(installation['path'], 'MSBuild', 'Current', 'Bin', 'MSBuild.exe')
if not os.path.isfile(msbuild_path):
msbuild_path = os.path.join(installation['path'], 'MSBuild', '15.0', 'Bin', 'MSBuild.exe') # VS 2017 fallback
if not os.path.isfile(msbuild_path):
log.error(f'MSBuild.exe not found for {installation["name"]}. Cannot compile {state.target}.')
return
proj_name = lnx.utils.blend_name()
vcxproj_path = os.path.join(hl_build_dir, proj_name + '.vcxproj')
if not os.path.isfile(vcxproj_path):
found_vcxproj = None
for file in os.listdir(hl_build_dir):
if file.endswith(".vcxproj"):
found_vcxproj = os.path.join(hl_build_dir, file)
log.warn(f"Could not find '{proj_name}.vcxproj', using found '{file}' instead.")
break
if not found_vcxproj:
log.error(f'.vcxproj file not found in {hl_build_dir}. Cannot compile.')
return
vcxproj_path = found_vcxproj
proj_name = os.path.splitext(os.path.basename(vcxproj_path))[0]
msbuild_cmd = [
msbuild_path,
vcxproj_path,
f'/p:Configuration={build_mode}',
f'/p:Platform={platform}',
'/m'
]
log.info(f"Compiling {state.target} project with MSBuild...")
log.info(f"Command: {' '.join(msbuild_cmd)}")
compile_success = False
try:
compile_result = subprocess.run(msbuild_cmd, cwd=hl_build_dir, check=False, capture_output=True, text=True)
if compile_result.returncode == 0:
log.info(f"MSBuild compilation successful.")
compile_success = True
else:
log.error(f"MSBuild compilation failed (Exit Code: {compile_result.returncode}).")
log.error(f"MSBuild Output:\n{compile_result.stdout}")
log.error(f"MSBuild Errors:\n{compile_result.stderr}")
except Exception as e:
log.error(f"Error running MSBuild: {e}")
traceback.print_exc()
if not compile_success:
return
exe_path = os.path.join(hl_build_dir, platform, build_mode, proj_name + '.exe')
if not os.path.isfile(exe_path):
exe_path = os.path.join(hl_build_dir, build_mode, proj_name + '.exe')
if not os.path.isfile(exe_path):
log.error(f'Compiled executable not found at expected location: {exe_path} (or variants). Cannot run.')
return
log.info(f"Found compiled executable: {exe_path}")
dest_exe_name = proj_name + '.exe'
base_build_dir = lnx.utils.get_fp_build()
dest_dir = os.path.join(base_build_dir, state.target)
dest_path = os.path.join(dest_dir, dest_exe_name)
try:
shutil.move(exe_path, dest_path)
cmd = [dest_path]
except Exception as e:
cmd = [exe_path]
os.chdir(dest_dir)
elif state.target in ('linux-hl', 'macos-hl'):
wrd = bpy.data.worlds['Lnx']
paths = lnx.utils.hashlink_paths(state.target)
hl_build_dir = paths[0]
# TO DO switch from default Release
build_mode = 'Release'
proj_name = lnx.utils.blend_name()
exe_path = str(hl_build_dir + "/" + build_mode)
if not exe_path:
log.error(f"Build finished, but could not find the executable for {state.target}.")
return
makefile_path = os.path.join(exe_path, 'makefile')
if not os.path.isfile(makefile_path):
log.error(f"Makefile not found at '{makefile_path}'. Cannot compile C code.")
return
make_cmd = ['make']
log.info(f"Compiling C code using 'make' in directory '{exe_path}'...")
log.info(f"Make command: {' '.join(make_cmd)}")
try:
result = subprocess.run(make_cmd, cwd=exe_path, check=True, capture_output=True, text=True, encoding='utf-8')
log.info("'make' compilation successful.")
except subprocess.CalledProcessError as e:
log.error(f"'make' compilation failed with return code {e.returncode}.")
log.error(f"Make Error Output:\n{e.stderr}")
return
except FileNotFoundError:
log.error("'make' command not found. Ensure 'make' is installed and in your system's PATH.")
return
except Exception as e:
log.error(f"An unexpected error occurred running make: {e}")
return
log.info(f"Found compiled executable: {exe_path}")
dest_exe_name = lnx.utils.safesrc(wrd.lnx_project_name + '-' + wrd.lnx_project_version)
base_build_dir = lnx.utils.get_fp_build()
dest_dir = os.path.join(base_build_dir, state.target)
og_path = os.path.join(exe_path, dest_exe_name)
dest_path = os.path.join(dest_dir, dest_exe_name)
os.makedirs(dest_dir, exist_ok=True)
try:
log.info(f"Moving '{og_path}' to '{dest_dir}'...")
shutil.move(og_path, dest_dir)
cmd = [dest_path]
except Exception as e:
log.error(f"Failed to move executable: {e}. Attempting to run from original location.")
cmd = [exe_path]
os.chdir(dest_dir)
log.info(f"Hashlink final command: {' '.join(cmd)}")
try:
state.proc_play = run_proc(cmd, play_done)
except Exception:

View File

@ -308,7 +308,8 @@ def init_properties():
bpy.types.World.lnx_verbose_output = BoolProperty(name="Verbose Output", description="Print additional information to the console during compilation", default=False)
bpy.types.World.lnx_runtime = EnumProperty(
items=[('Krom', 'Krom', 'Krom'),
('Browser', 'Browser', 'Browser')],
('Browser', 'Browser', 'Browser'),
('Hashlink', 'Hashlink', 'Hashlink')],
name="Runtime", description="Runtime to use when launching the game", default='Krom', update=assets.invalidate_shader_cache)
bpy.types.World.lnx_loadscreen = BoolProperty(name="Loading Screen", description="Show asset loading progress on published builds", default=True)
bpy.types.World.lnx_vsync = BoolProperty(name="VSync", description="Vertical Synchronization", default=True, update=assets.invalidate_compiler_cache)

View File

@ -363,6 +363,25 @@ def krom_paths():
krom_path = krom_location + '/Krom'
return krom_location, krom_path
def hashlink_paths(target):
"""Returns path for Hashlink runtime target."""
sdk_path = get_sdk_path()
proj_name = blend_name()
build_base_dir = get_fp_build()
if target in ('windows-hl', 'linux-hl', 'macos-hl'):
hl_build_dir = os.path.join(build_base_dir, target + '-build')
log.info(f"Identified Hashlink/C build directory: {hl_build_dir}")
return hl_build_dir, None, None # Return build_dir, no file, no interpreter
else:
return '', None, None
def fetch_bundled_script_names():
wrd = bpy.data.worlds['Lnx']
wrd.lnx_bundled_scripts_list.clear()