Giter VIP home page Giter VIP logo

ue4cli's Introduction

Command-line interface for Unreal Engine 4

The ue4cli Python package implements a command-line tool called ue4 that provides a simplified interface to various functionality of the build system for Epic Games' Unreal Engine 4. The primary goals of this tool are as follows:

  • Abstract away the platform-specific details of the various batch files and shell scripts scattered throughout the Engine's source tree.
  • Provide the ability to easily generate IDE project files under Linux, where no shell integration currently exists to perform this task from outside the Editor.
  • Determine the compiler flags required to build third-party libraries for use within Engine modules. This is particularly important under macOS and Linux where symbol interposition can cause clashes between external libraries and those bundled in the ThirdParty directory of the Engine source tree, and under Linux where libraries need to build against the Engine's bundled version of libc++.

This package requires Unreal Engine 4.19 or newer (since 4.19 is the first release to include the necessary patches to UnrealBuildTool.) The package also requires Python 3.5 or newer.

Check out the comprehensive documentation to view installation instructions and the full command reference.

Resources:

Legal

Copyright © 2017-2018, Adam Rehn. Licensed under the MIT License, see the file LICENSE for details.

ue4cli's People

Contributors

adamrehn avatar canishelix avatar gcandal avatar jaiber avatar jonpas avatar rayza avatar sleeptightansic avatar uhlenbrock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ue4cli's Issues

Wrong exit code for unknown reasons

Hello,

I am having a weird problem that I cannot really understand if it's a ue4cli problem, a UE problem or more specifically a UE5 problem
I have 2 computers on which I package a plugin.

UE4 -> everything always works on both

UE5 -> on one computer everything works fine, on another, I get the wrong exit code for packaging.

This is a deliberate failed packaging because the problem only happens when the packaging fails (for any reason, let's say syntax error in the code)

The steps to reproduce, with the specific difference between computers:

ue4 setroot to ue5
cd PluginName
ue4 package

Computer 1 Result

Took 157,81171410000002s to run UnrealBuildTool.exe, ExitCode=6
AutomationTool executed for 0h 2m 39s
AutomationTool exiting with ExitCode=6 (6)
BUILD FAILED
Traceback (most recent call last):
  File "C:\Python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Python38\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Python38\Scripts\ue4.exe\__main__.py", line 7, in <module>
  File "C:\Python38\lib\site-packages\ue4cli\cli.py", line 222, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "C:\Python38\lib\site-packages\ue4cli\cli.py", line 94, in <lambda>
    'action': lambda m, args: m.packageDescriptor(os.getcwd(), args),
  File "C:\Python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 476, in packageDescriptor
    self.packagePlugin(dir, args)
  File "C:\Python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 457, in packagePlugin
    self.runUAT([
  File "C:\Python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 383, in runUAT
    Utility.run([self.getRunUATScript()] + args, cwd=self.getEngineRoot(), raiseOnError=True)
  File "C:\Python38\lib\site-packages\ue4cli\Utility.py", line 145, in run
    raise Exception('child process ' + str(command) + ' failed with exit code ' + str(returncode))
Exception: child process ['D:\\UE\\UE_5.0\\Engine\\Build\\BatchFiles\\RunUAT.bat', 'BuildPlugin', '-Plugin=D:\\UEprojects\\Project\\Plugins\\PluginName\\plugin.uplugin', '-Package=D:\\UEprojects\\Project\\Plugins\\PluginName\\dist'] failed with exit code 6

(Everything is fine, the packaging failed and we go on with our lives)


ue4 setroot to ue5
cd PluginName
ue4 package

Computer 2 Result

Took 224,4925119s to run UnrealBuildTool.exe, ExitCode=6
UnrealBuildTool failed. See log for more details. (C:\Users\user\AppData\Roaming\Unreal Engine\AutomationTool\Logs\C+Program+Files+Epic+Games+UE_5.0\UBT-UnrealEditor-Win64-Development.txt)
AutomationTool executed for 0h 3m 54s
AutomationTool exiting with ExitCode=6 (6)
Updating environment variables set by a Turnkey sub-process
The system cannot find the path specified.
The system cannot find the path specified.

(packaging failed, yet we get a exit code 0)


The main problem being the second computer process actually exits with exit code 0
I'm presuming because of the Turnkey sub process. Which in turn really messes up our CI process, since it basically breaks, and continues with the broken build since the CI isn't halted.
I cannot seem to reproduce this in computer 1, google doesn't really help and I have not found any project or engine based setting regarding "turnkey"
Both are windows 10, ue5 5.0.1 installed from the launcher, ue4cli-0.0.54

Do you have any idea or clue on what would make this different on 2 computers?

Infinite recursion bug

Using master branch I am getting these issues, my Unreal Engine lives in ~/UnrealEngine and is 4.27.

  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerLinux.py", line 15, in _detectEngineRoot
    if self._getEngineVersionDetails()['MajorVersion'] >= 5:
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 632, in _getEngineVersionDetails
    versionFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'Build.version')
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/home/russ/work/ue4cli/ue4cli/UnrealManagerBase.py", line 615, in _getEngineRoot
    override = ConfigurationManager.getConfigKey('rootDirOverride')
  File "/home/russ/work/ue4cli/ue4cli/ConfigurationManager.py", line 30, in getConfigKey
    configFile = ConfigurationManager._configFile()
  File "/home/russ/work/ue4cli/ue4cli/ConfigurationManager.py", line 45, in _configFile
    return os.path.join(ConfigurationManager.getConfigDirectory(), 'config.json')
  File "/home/russ/work/ue4cli/ue4cli/ConfigurationManager.py", line 16, in getConfigDirectory
    if 'UE4CLI_CONFIG_DIR' in os.environ:
  File "/usr/lib/python3.10/_collections_abc.py", line 825, in __contains__
    self[key]
  File "/usr/lib/python3.10/os.py", line 676, in __getitem__
    value = self._data[self.encodekey(key)]
RecursionError: maximum recursion depth exceeded

UnrealBuildTool isn't built by `ue4 build`

Switching UE4 branches, I cleaned my source checkout hard, using git clean -f -x d.

I then ran the Setup.bat which installed Git dependencies and pre-reqs without issue.

However, ue4 build was not able to build my project in this state.

I ran ue4 gen -vscode, and after that ue4 build worked.

This is because ue4 gen calls GenerateProjectFiles.bat on Windows which explicitly compiles UBT.

However, this was a surprising dependency to me, and there's nothing logged by the batch file that it's building UBT, so I had to check the code to make sure that this was why it worked as a fix.

I'm not sure if there's a nicer way to bootstrap UBT than used in GenerateProjectFiles.bat, and I'm not sure if this is Windows-specific, as I only tested Windows.

This isn't a problem for installed builds, and now that I know the trick, I'm not blocked on this, nor is the workaround particularly onerous.

Logs

(venv) PS D:\project\repos\unreal> ue4 build
Using user-specified engine root: D:\Unreal\UnrealEngine
Ensuring ShaderCompileWorker is built before building project Editor modules...
UnrealBuildTool.exe not found in ..\..\Engine\Binaries\DotNET\UnrealBuildTool.exe
Traceback (most recent call last):
  File "C:\Program Files\Python37\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Program Files\Python37\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "D:\Unreal\venv\Scripts\ue4.exe\__main__.py", line 7, in <module>
  File "d:\unreal\venv\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "d:\unreal\venv\lib\site-packages\ue4cli\cli.py", line 70, in <lambda>
    'action': lambda m, args: m.buildDescriptor(os.getcwd(), args.pop(0) if (len(args) > 0 and args[0].startswith('-') == False) else 'Development', args.pop(0) if (len(args) > 0 and args[0].startswith('-') == False) else 'Editor',
 args),
  File "d:\unreal\venv\lib\site-packages\ue4cli\UnrealManagerBase.py", line 342, in buildDescriptor
    self._runUnrealBuildTool('ShaderCompileWorker', self.getPlatformIdentifier(), 'Development', [], capture=suppressOutput)
  File "d:\unreal\venv\lib\site-packages\ue4cli\UnrealManagerBase.py", line 657, in _runUnrealBuildTool
    Utility.run(arguments, cwd=self.getEngineRoot(), raiseOnError=True)
  File "d:\unreal\venv\lib\site-packages\ue4cli\Utility.py", line 145, in run
    raise Exception('child process ' + str(command) + ' failed with exit code ' + str(returncode))
Exception: child process ['D:\\Unreal\\UnrealEngine\\Engine\\Build\\BatchFiles\\Build.bat', 'ShaderCompileWorker', 'Win64', 'Development'] failed with exit code 999
(venv) PS D:\project\repos\unreal> ue4 gen -vscode
Using user-specified engine root: D:\Unreal\UnrealEngine
D:\project\repos\unreal\Demo.uproject
Setting up Unreal Engine 4 project files...
Discovering modules, targets and source code for project...
Binding IntelliSense data... 100%
Writing project files... 100%
(venv) PS D:\project\repos\unreal> ue4 build
Using user-specified engine root: D:\Unreal\UnrealEngine
Ensuring ShaderCompileWorker is built before building project Editor modules...
Using 'git status' to determine working set for adaptive non-unity build (D:\Unreal\UnrealEngine).
Creating makefile for ShaderCompileWorker (no existing makefile)
Creating makefile for UnrealHeaderTool (no existing makefile)
Building UnrealHeaderTool...

`ue4 test` doesn't exit with non-zero with failed tests

We recently noticed that we had passing builds with failing tests.

It turns out we were relying on ue4 test as the last command in our pipeline, and it fails to detect the test failures.

We do see this:

[2020.03.10-03.56.20:514][204]LogAutomationCommandLine: Display: Setting GIsCriticalError due to test failures (will cause non-zero exit code).

so UE4 is exiting with error code 1.

None of the strings checked in automationTests appear in our logs though.

The most-likely candidate for a string-based check looks like:

[2020.03.10-03.56.00:819][ 32]LogAutomationController: Error: Test Completed. Result={Failed} Name={MatchmakingTest} Path={Project.Functional Tests./PluginSystem/Tests/TestLevel.OneTest}

This is with the ue4-full Docker image for 4.24.2, so it's possible the output format has changed in recent UE4 versions. I don't know off-hand if this was also failing in 4.22.2, which we moved from a couple of weeks ago.

It would probably be nicer if this (and in fact all command wrappers) propagated a failure error code back to the caller, and then we could just use that.

Bug: setroot breaks with trailing backslash

I don't have UE4 installed on my C drive, so I needed to manually pass the root directory. I ran into a bug with the text parsing when it comes to passing in the root.

Replication

Given an installed path at F:\Program Files\Epic Games\UE_4.26,
When a user runs ue4 setroot F:\Program Files\Epic Games\UE_4.26\,
Then the tool throws this error: Warning: the specified directory does not appear to contain a valid version of the Unreal Engine.

Fix

The fix is super easy, just don't pass a backslash for the value of setroot. I dug into the code a bit, but I didn't see a 5m, platform-specific fix that I could contribute.

`ue4 test` always exits with non-zero in UE 4.27

Seems like 4.27 changed the test exit code behaviour. In 4.26 it always exited with RequestExit(1), but in 4.27 it's doing RequestExitWithStatus(1, 0).

ue4 test in 4.26 returns the correct exit code, while 4.27 always fails, which is a problem for CI use.

UE 4.26

[2021.09.13-10.30.15:828][420]LogAutomationController: Display: Test Completed. Result={Passed} Name={FunctionalTest1} Path={Project.Functional Tests./Game/FirstPersonCPP/Maps/FTestMap.FunctionalTest1}
[2021.09.13-10.30.15:835][420]LogAutomationController: BeginEvents: Project.Functional Tests./Game/FirstPersonCPP/Maps/FTestMap.FunctionalTest1
[2021.09.13-10.30.15:846][420]LogAutomationController: FunctionalTest_1: Assertion passed (Version is not empty)
[2021.09.13-10.30.15:858][420]LogAutomationController: FunctionalTest_1: Assertion passed (Version component is numeric)
[2021.09.13-10.30.15:869][420]LogAutomationController: FunctionalTest_1: Assertion passed (Version component is numeric)
[2021.09.13-10.30.15:880][420]LogAutomationController: FunctionalTest_1: Assertion passed (Version component is numeric)
[2021.09.13-10.30.15:892][420]LogAutomationController: EndEvents: Project.Functional Tests./Game/FirstPersonCPP/Maps/FTestMap.FunctionalTest1
[2021.09.13-10.30.15:904][420]LogAutomationController: Display: Report can be opened in the editor at 'D:/Work/IDI/internal/basic/Saved/Automation/Reports/'
[2021.09.13-10.30.15:915][422]LogAutomationCommandLine: Forcing shutdown.
[2021.09.13-10.30.15:926][422]LogAutomationCommandLine: Display: **** TEST COMPLETE. EXIT CODE: 0 ****
[2021.09.13-10.30.15:938][422]LogWindows: FPlatformMisc::RequestExit(1)
[2021.09.13-10.30.15:950][422]LogCore: Engine exit requested (reason: Win RequestExit)

UE 4.27

[2021.09.13-10.26.17:703][436]LogAutomationController: Display: Test Completed. Result={Passed} Name={FunctionalTest1} Path={Project.Functional Tests./Game/FirstPersonCPP/Maps/FTestMap.FunctionalTest1}
[2021.09.13-10.26.17:712][436]LogAutomationController: BeginEvents: Project.Functional Tests./Game/FirstPersonCPP/Maps/FTestMap.FunctionalTest1
[2021.09.13-10.26.17:726][436]LogAutomationController: FunctionalTest_1: Assertion passed (Version is not empty)
[2021.09.13-10.26.17:741][436]LogAutomationController: FunctionalTest_1: Assertion passed (Version component is numeric)
[2021.09.13-10.26.17:756][436]LogAutomationController: FunctionalTest_1: Assertion passed (Version component is numeric)
[2021.09.13-10.26.17:767][436]LogAutomationController: FunctionalTest_1: Assertion passed (Version component is numeric)
[2021.09.13-10.26.17:779][436]LogAutomationController: FunctionalTest_1: 0.1.0
[2021.09.13-10.26.17:790][436]LogAutomationController: EndEvents: Project.Functional Tests./Game/FirstPersonCPP/Maps/FTestMap.FunctionalTest1
[2021.09.13-10.26.17:803][436]LogAutomationController: Display: Report can be opened in the editor at 'D:/Work/IDI/internal/basic/Saved/Automation/Reports/'
[2021.09.13-10.26.17:814][438]LogAutomationCommandLine: Shutting down. GIsCriticalError=0
[2021.09.13-10.26.17:825][438]LogAutomationCommandLine: Display: **** TEST COMPLETE. EXIT CODE: 0 ****
[2021.09.13-10.26.17:836][438]LogWindows: FPlatformMisc::RequestExitWithStatus(1, 0)
[2021.09.13-10.26.17:848][438]LogCore: Engine exit requested (reason: Win RequestExit)

'ue4 setroot' saves the root even when specified directory is NOT valid

$ ue4 setroot jndksfjnaskldjfnksda
Set engine root path override: /home/kornel/Projects/ue4cli/jndksfjnaskldjfnksda
Using user-specified engine root: /home/kornel/Projects/ue4cli/jndksfjnaskldjfnksda
Warning: the specified directory does not appear to contain a valid version of the Unreal Engine.
# return code 0

$ ue4 root
Using user-specified engine root: /home/kornel/Projects/ue4cli/jndksfjnaskldjfnksda
/home/kornel/Projects/ue4cli/jndksfjnaskldjfnksda
# return code 0

This should not happen. Setting root override to a non-valid Engine directory should fail.
Currently it always saves the override no matter what, and only prints warning.

In #65 I already changed warning to error by throwing UnrealManagerException.
Now I need to also prevent the override from being saved.

This is a bit tricky to fix as currently we save the override first and then validate it afterwards:

def setEngineRootOverride(self, rootDir):
"""
Sets a user-specified directory as the root engine directory, overriding any auto-detection
"""
# Set the new root directory
rootDir = os.path.abspath(rootDir)
ConfigurationManager.setConfigKey('rootDirOverride', rootDir)
print('Set engine root path override: {}'.format(rootDir))
# Check that the specified directory is valid and warn the user if it is not
try:
self.getEngineVersion()
except:
print('Warning: the specified directory does not appear to contain a valid version of the Unreal Engine.')

non-portable path to file when build Linux Server on Windows

I have tried to package Linux build on Windows

ue4 setroot E:\UnrealEngine
ue4 package Development -noclient -server -serverplatform=Linux -platform=Linux

And got this error:

 [9/468] PCH.Engine.h
    E:/BuildAgentAccord/work/rnd_shooter_game/Intermediate/Build/Linux/B4D820EA/ShooterGameServer/Development/Engine/PCH.Engine.h(163,10):  error: non-portable path to file '"e\\UnrealEngine\Engine\Source\Runtime\Engine\Private\EnginePrivatePCH.h"'; specified path differs in case from file name on disk [-Werror,-Wnonportable-include-path]
    #include "e:\UnrealEngine\Engine\Source\Runtime\Engine\Private\EnginePrivatePCH.h"
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             "e\\UnrealEngine\Engine\Source\Runtime\Engine\Private\EnginePrivatePCH.h"
 raise Exception('child process ' + str(command) + ' failed with exit code ' + str(returncode))
Exception: child process ['e:\\UnrealEngine\\Engine\\Build\\BatchFiles\\RunUAT.bat', 'BuildCookRun', '-utf8output', '-clientconfig=Development', '-serverconfig=Development', '-project=E:\\BuildAgentAccord\\work\\rnd_shooter_game\\ShooterGame.uproject', '-noP4', '-cook', '-build', '-stage', '-prereqs', '-pak', '-archive', '-archivedirectory=E:\\BuildAgentAccord\\work\\rnd_shooter_game\\dist', '-server', '-serverplatform=Linux', '-platform=Win64', '-allmaps'] failed with exit code 5

Any thoughts?

Couldn't find target rules file for target 'UE4Editor' in rules assembly 'UE5Rules, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in windows server 2019

Step 6/8 : RUN .\Engine\Build\BatchFiles\Build.bat UE4Editor Win64 Development -WaitMutex && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo.
---> Running in 4ec92b61447e
Using bundled DotNet SDK
Log file: C:\UnrealEngine\Engine\Programs\UnrealBuildTool\Log.txt
Using 'git status' to determine working set for adaptive non-unity build (C:\UnrealEngine).
Creating makefile for UE4Editor (no existing makefile)
ERROR: Couldn't find target rules file for target 'UE4Editor' in rules assembly 'UE5Rules, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
Location: C:\UnrealEngine\Engine\Intermediate\Build\BuildRules\UE5Rules.dll
Target rules found:
The command 'cmd /S /C .\Engine\Build\BatchFiles\Build.bat UE4Editor Win64 Development -WaitMutex && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo.' returned a non-zero code: 6
[ue4-docker build] Error: failed to build image "adamrehn/ue4-engine:5.0.0-ltsc2019-vs2019".

Packaging with UE 4.22.0 full fails

First of all, thanks for doing all this great work!

My project builds perfectly fine when using ue4 build, however when executing ue4 package, I get the following error. I'm not really sure what I'm doing wrong, but I'm pretty sure the mistake is on my side. My project is able to build using the UE4Editor GUI, am I missing a setting somewhere, or am I using the ue4 package command incorrectly perhaps? I'm using adamrehn/ue4-full:4.22.0

ue4@e3c157e0c282:~/Github$ ue4 package
Using user-specified engine root: /home/ue4/UnrealEngine

Running AutomationTool...

Fixing inconsistent case in filenames.
Setting up Mono
AutomationTool exists: Deleting
Compiling AutomationTool with xbuild
xbuild Source/Programs/AutomationTool/AutomationTool.csproj /p:Configuration=Development /p:Platform=AnyCPU /verbosity:quiet /nologo /p:TargetFrameworkProfile=
/home/ue4/UnrealEngine/Engine/Binaries/ThirdParty/Mono/Linux/lib/mono/xbuild/14.0/bin/Microsoft.Common.targets:  warning : Referenced Project ../IOS/MobileDeviceInterface/MobileDeviceInterface.csproj not found, ignoring.
Compilation Succeeded
Start UAT: mono AutomationTool.exe BuildCookRun -utf8output -clientconfig=Shipping -serverconfig=Shipping -project=/home/ue4/Github/swarm_cpp.uproject -noP4 -cook -allmaps -build -stage -prereqs -pak -archive -archivedirectory=/home/ue4/Github/dist -platform=Linux -nodebuginfo
Parsing command line: BuildCookRun -utf8output -clientconfig=Shipping -serverconfig=Shipping -project=/home/ue4/Github/swarm_cpp.uproject -noP4 -cook -allmaps -build -stage -prereqs -pak -archive -archivedirectory=/home/ue4/Github/dist -platform=Linux -nodebuginfo -compile
WARNING: Ignoring -Compile argument because engine is installed.
ERROR: Scripts folder /home/ue4/UnrealEngine/Engine/Binaries/DotNET/AutomationScripts does not exist!
ERROR: AutomationScripts.Automation.dll was not found or could not be loaded, can't run scripts.
       (see /home/ue4/Library/Logs/Unreal Engine/LocalBuildLogs/Log.txt for full exception trace)
AutomationTool exiting with ExitCode=1 (Error_Unknown)
RunUAT ERROR: AutomationTool was unable to run successfully.
Traceback (most recent call last):
  File "/usr/local/bin/ue4", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.6/dist-packages/ue4cli/cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "/usr/local/lib/python3.6/dist-packages/ue4cli/cli.py", line 88, in <lambda>
    'action': lambda m, args: m.packageDescriptor(os.getcwd(), args),
  File "/usr/local/lib/python3.6/dist-packages/ue4cli/UnrealManagerBase.py", line 423, in packageDescriptor
    self.packageProject(dir, args[0] if len(args) > 0 else 'Shipping', args[1:])
  File "/usr/local/lib/python3.6/dist-packages/ue4cli/UnrealManagerBase.py", line 398, in packageProject
    ] + extraArgs)
  File "/usr/local/lib/python3.6/dist-packages/ue4cli/UnrealManagerBase.py", line 353, in runUAT
    Utility.run([self.getRunUATScript()] + args, cwd=self.getEngineRoot(), raiseOnError=True)
  File "/usr/local/lib/python3.6/dist-packages/ue4cli/Utility.py", line 138, in run
    raise Exception('child process ' + str(command) + ' failed with exit code ' + str(returncode))
Exception: child process ['/home/ue4/UnrealEngine/Engine/Build/BatchFiles/RunUAT.sh', 'BuildCookRun', '-utf8output', '-clientconfig=Shipping', '-serverconfig=Shipping', '-project=/home/ue4/Github/swarm_cpp.uproject', '-noP4', '-cook', '-allmaps', '-build', '-stage', '-prereqs', '-pak', '-archive', '-archivedirectory=/home/ue4/Github/dist', '-platform=Linux', '-nodebuginfo'] failed with exit code 1

Minor annoyance: Control-C on `ue4 run` raises an exception

I've been "just living with" this for ages, and thought I should bug-report it.

> ue4 run "Highrise" -server -nosteam
# <stuff happens, then I hit Control-C>
[2021.02.05-09.52.09:829][630]LogCore: Engine exit requested (reason: ConsoleCtrl RequestExit)
[2021.02.05-09.52.09:831][630]LogCore: Warning: *** INTERRUPTED *** : SHUTTING DOWN
[2021.02.05-09.52.09:831][630]LogCore: Warning: *** INTERRUPTED *** : CTRL-C TO FORCE QUIT
[2021.02.05-09.52.09:831][630]LogCore: Engine exit requested (reason: EngineExit() was called; note: exit was already requested)
[2021.02.05-09.52.09:834][630]LogInit: Display: PreExit Game.
[2021.02.05-09.52.09:847][630]LogWorld: BeginTearingDown for /Game/Maps/Highrise
# <nice clean shutdown from UE4>
[2021.02.05-09.52.11:635][630]LogModuleManager: Shutting down and abandoning module RSA (3)
[2021.02.05-09.52.11:647][630]LogExit: Exiting.
Traceback (most recent call last):
  File "c:\program files\python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\program files\python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\paulh\.local\bin\ue4.exe\__main__.py", line 7, in <module>
  File "c:\users\paulh\.local\pipx\venvs\ue4cli\lib\site-packages\ue4cli\cli.py", line 222, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\paulh\.local\pipx\venvs\ue4cli\lib\site-packages\ue4cli\cli.py", line 60, in <lambda>
    'action': lambda m, args: m.runEditor(
  File "c:\users\paulh\.local\pipx\venvs\ue4cli\lib\site-packages\ue4cli\UnrealManagerBase.py", line 365, in runEditor
    Utility.run([self.getEditorBinary(True), projectFile, '-stdout', '-FullStdOutLogOutput'] + extraFlags, raiseOnError=True)
  File "c:\users\paulh\.local\pipx\venvs\ue4cli\lib\site-packages\ue4cli\Utility.py", line 143, in run
    returncode = subprocess.call(command, cwd=cwd, shell=shell)
  File "c:\program files\python39\lib\subprocess.py", line 351, in call
    return p.wait(timeout=timeout)
  File "c:\program files\python39\lib\subprocess.py", line 1185, in wait
    return self._wait(timeout=timeout)
  File "c:\program files\python39\lib\subprocess.py", line 1466, in _wait
    result = _winapi.WaitForSingleObject(self._handle,
KeyboardInterrupt

I think it'd be nice if that if a KeyboardInterrupt is raised from subprocess.call, the called subprocess was assumed to have handled it, and it was treated as a clean exit.

It'd be nicer if the return code from the subprocess.call was returned like any other exit.

And poking around, python/cpython#5026 and the relevant wait function, it looks like since Python 3.7 there's a _sigint_wait_secs value which defaults to 250ms for the first control-c, and that's probably too short for us here, which is why we don't get the "nicer" version already.

So a possible improvement would be to use the Popen object directly (replace the call to subprocess.call with its implementation, like Utility.capture) and then either change _sigint_wait_secs before waiting to a higher first-time value, or wrap the call to wait with another KeyboardInterrupt catch that perhaps doesn't put a timeout on the first control-C (assuming UE4's handling it) and has a second control-c catch that gives a timeout for the UE4 "force-quit", and a third control-C would immediately kill, if that second timeout is too long for the user in the heat of the moment.

If I have some spare time, I could take a shot at implementing it (probably the latter approach, doing more wait calls in Utility.py, not changing _sigint_wait_secs) unless you have any concerns, or want to offer particular advice on this?

Should this only apply to runEditor? I haven't checked if UAT has a similar "one to exit cleanly, two to hard-kill" behaviour, or if that's Editor-only.

No .ipa file built in Binaries/

I am using a mac machine, trying to package for IOS. Using UE v4.27.2

When I package via the UE4 GUI there is a file created in myproject/Binaries/IOS/ name Distro_myproject-Shipping.ipa

If I run the ue4cli with the following command ue4 package Shipping -platform=IOS -archivedirectory=<my-archive-dir> -distribution the command will fail if the myproject/Binaries/IOS/Distro_myproject-Shipping.ipa file has not already been created. If I remove that file, the ue4cli package command will fail at the final "ARCHIVE COMMAND STARTED" step with an error message saying that the file is missing.

I tried to use the ue4 build command, hoping that would generate the required .ipa file, but I get a message saying "Pure Blueprint project. Nothing to build"

I'm trying to automate the packaging and distribution of our IOS app created with UE, but I can't do that because this file is not created. How can I create this file with ue4cli?

'__main__.py' isn't used anywhere

__main__.py does not seem to be used anywhere.
The entry point for ue4cli is actually in a different place:

ue4cli/setup.py

Lines 35 to 37 in fed71c1

entry_points = {
'console_scripts': ['ue4=ue4cli.cli:main']
}

I'm also not able to use this file directly like a script, as it does not bootstrap the module:

# cwd is repo root directory
$ python ./ue4cli                
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/kornel/Projects/ue4cli/./ue4cli/__main__.py", line 1, in <module>
    from .cli import main
ImportError: attempted relative import with no known parent package

Maybe I'm not using it right?
Shall we fix this?

Problems with the Library Commands on 4.24.3

Hi!

Thanks for your great work, it should come in very handy if I can get it running.

I`m following the "Introduction to ue4cli", and almost none of the library commands in ue4cli work:

D:\>ue4 setroot D:\Tools\UE4\
Using user-specified engine root: D:\Tools\UE4

D:\>ue4 version
Using user-specified engine root: D:\Tools\UE4
4.24.3

D:\>ue4 libs
Using user-specified engine root: D:\Tools\UE4
Traceback (most recent call last):
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\kalujny\AppData\Local\Programs\Python\Python38\Scripts\ue4.exe\__main__.py", line 9, in <module>
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 94, in <lambda>
    'action': lambda m, args: print('\n'.join(m.listThirdPartyLibs())),
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 178, in listThirdPartyLibs
    return interrogator.list(self.getPlatformIdentifier(), configuration, self._getLibraryOverrides())
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UE4BuildInterrogator.py", line 20, in list
    modules = self._getThirdPartyLibs(platformIdentifier, configuration)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UE4BuildInterrogator.py", line 156, in _getThirdPartyLibs
    self.runUBTFunc('UE4Editor', platformIdentifier, configuration, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 663, in <lambda>
    ubtLambda = lambda target, platform, config, args: self._runUnrealBuildTool(target, platform, config, args, True)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 655, in _runUnrealBuildTool
    return Utility.capture(arguments, cwd=self.getEngineRoot(), raiseOnError=True)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\Utility.py", line 125, in capture
    raise Exception(
Exception: child process ['D:\\Tools\\UE4\\Engine\\Build\\BatchFiles\\Build.bat', 'UE4Editor', 'Win64', 'Development', '-Mode=JsonExport', '-OutputFile=C:\\Users\\kalujny\\AppData\\Local\\Temp\\tmp1th1azlh\\ubt_output.json'] failed with exit code 5
stdout: "WARNING: Ignoring child plugin: CableComponent_XXX.uplugin - Unknown suffix "XXX". Expected valid platform or group
Writing C:\Users\kalujny\AppData\Local\Temp\tmp1th1azlh\ubt_output.json...
ERROR: Environment variable 'BinaryOutputDir' is not defined (referenced by D:\Tools\UE4\Engine\Plugins\Experimental\AlembicImporter\Source\ThirdParty\Alembic\AlembicLib.Build.cs)
"
stderr: ""

D:\>set BinaryOutputDir=D:\Temp

D:\>ue4 libs
Using user-specified engine root: D:\Tools\UE4
ADO
AMD_AGS
APEX
CEF3
Crunch
DX11
DX11Audio
DX12
DX9
DirectShow
DirectSound
Eigen
Expat
FBX
Facebook
ForsythTriOptimizer
FreeImage
FreeType2
GlsLang
GoogleARCoreSDK
GoogleInstantPreview
GoogleTest
GoogleVR
HLSLCC
HarfBuzz
ICU
IntelISPC
IntelISPCTexComp
IntelMetricsDiscovery
IntelTBB
IntelVTune
Kiss_FFT
LibOVRAudio
LibOVRAvatar
LibOVRPlatform
MCPP
MikkTSpace
NVAPI
NVAftermath
NvCloth
OVRPlugin
OpenGL
OpenSSL
OpenSubdiv
OpenVR
OpenXR
Perforce
PhysX
PhysXCookingLib
Python
QualcommTextureConverter
RenderDoc
SPIRVReflect
ShaderConductor
SpeedTree
Steamworks
UELibSampleRate
UEOgg
UEOpenExr
UElibJPG
UElibPNG
VHACD
VisualStudioDTE
VivoxClientAPI
VivoxCoreSDK
Vorbis
VorbisFile
Vulkan
WebRTC
WinHttp
WindowsMixedRealityInterop
XInput
coremod
gltfToolkit
libOpus
libPhonon
libWebSockets
libcurl
libstrophe
nvTessLib
nvTextureTools
nvTriStrip
portmidi
zlib

D:\>ue4 cxxflags
Traceback (most recent call last):
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\kalujny\AppData\Local\Programs\Python\Python38\Scripts\ue4.exe\__main__.py", line 9, in <module>
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 100, in <lambda>
    'action': lambda m, args: print(m.getThirdPartyLibCompilerFlags(args)),
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 194, in getThirdPartyLibCompilerFlags
    if libs[0] == '--multiline':
IndexError: list index out of range

D:\>ue4 ldflags
Traceback (most recent call last):
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\kalujny\AppData\Local\Programs\Python\Python38\Scripts\ue4.exe\__main__.py", line 9, in <module>
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 106, in <lambda>
    'action': lambda m, args: print(m.getThirdPartyLibLinkerFlags(args)),
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 211, in getThirdPartyLibLinkerFlags
    if libs[0] == '--multiline':
IndexError: list index out of range

D:\>ue4 includedirs
Traceback (most recent call last):
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\kalujny\AppData\Local\Programs\Python\Python38\Scripts\ue4.exe\__main__.py", line 9, in <module>
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 118, in <lambda>
    'action': lambda m, args: print(m.getThirdPartyLibIncludeDirs(args)),
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 251, in getThirdPartyLibIncludeDirs
    if libs[0] == '--nodefaults':
IndexError: list index out of range

D:\>ue4 libfiles
Traceback (most recent call last):
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\kalujny\AppData\Local\Programs\Python\Python38\Scripts\ue4.exe\__main__.py", line 9, in <module>
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 124, in <lambda>
    'action': lambda m, args: print(m.getThirdPartyLibFiles(args)),
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 263, in getThirdPartyLibFiles
    if libs[0] == '--nodefaults':
IndexError: list index out of range

D:\>ue4 cmakeflags
Traceback (most recent call last):
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\kalujny\AppData\Local\Programs\Python\Python38\Scripts\ue4.exe\__main__.py", line 9, in <module>
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 112, in <lambda>
    'action': lambda m, args: print(m.getThirdPartyLibCmakeFlags(args)),
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 233, in getThirdPartyLibCmakeFlags
    if libs[0] == '--multiline':
IndexError: list index out of range

D:\>ue4 defines
Traceback (most recent call last):
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\kalujny\AppData\Local\Programs\Python\Python38\Scripts\ue4.exe\__main__.py", line 9, in <module>
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\cli.py", line 130, in <lambda>
    'action': lambda m, args: print(m.getThirdPartyLibDefinitions(args)),
  File "c:\users\kalujny\appdata\local\programs\python\python38\lib\site-packages\ue4cli\UnrealManagerBase.py", line 275, in getThirdPartyLibDefinitions
    if libs[0] == '--nodefaults':
IndexError: list index out of range

`ue4 build-target` crashes when not specifying any target

Running ue4 build-target without giving any argument causes a crash:

╰─$ ue4 build-target
Traceback (most recent call last):
  File "/usr/bin/ue4", line 33, in <module>
    sys.exit(load_entry_point('ue4cli==0.0.54', 'console_scripts', 'ue4')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/ue4cli/cli.py", line 222, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "/usr/lib/python3.11/site-packages/ue4cli/cli.py", line 54, in <lambda>
    'action': lambda m, args: m.buildTarget(args.pop(0), args.pop(0) if (len(args) > 0) else 'Development', args),
                                            ^^^^^^^^^^^
IndexError: pop from empty list

This is happening because some commands detect arguments with following condition: len(args) > 0 Said condition will always evaluate to True because Python always takes script directory as the first argument. We can easily change len(args) > 0 to len(args) > 1 and this should be resolved for most cases. However, when I was testing it, seems like not every function related to this issue would fail as I was expecting it, e.g. ue4 version works just fine, so it's worth investigating what's going on under the hood before fixing it.

EDIT: No, I was wrong about it. The problem is super simple. We do args.pop(0) without checking if args contains anything which is clearly mentioned in callstack :D

Leaving this one for myself, should be quick to fix.

Reference:

ue4cli/ue4cli/cli.py

Lines 52 to 56 in fed71c1

'build-target': {
'description': 'Build the specified target using UBT',
'action': lambda m, args: m.buildTarget(args.pop(0), args.pop(0) if (len(args) > 0) else 'Development', args),
'args': '<TARGET> [CONFIGURATION]'
},

No platforms specified for target

Got this problem running directly on MacOS., in the adamrehn/ue4-* images it works fine.

Running ue4 build results in:

Running installed mono, version:  Mono JIT compiler version 5.20.1.19 (tarball Fri May 31 11:54:57 WEST 2019)
Running command : Engine/Binaries/DotNET/UnrealBuildTool.exe SomeProjEditor macosx Development -project=/Users/gcc/Documents/Unreal Projects/SomeProj/SomeProj/SomeProj.uproject
ERROR: No platforms specified for target
Traceback (most recent call last):
  File "/Users/gcc/homebrew/bin/ue4", line 11, in <module>
    load_entry_point('ue4cli==0.0.31', 'console_scripts', 'ue4')()
  File "/Users/gcc/homebrew/lib/python3.7/site-packages/ue4cli/cli.py", line 216, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "/Users/gcc/homebrew/lib/python3.7/site-packages/ue4cli/cli.py", line 70, in <lambda>
    'action': lambda m, args: m.buildDescriptor(os.getcwd(), args[0] if len(args) > 0 else 'Development'),
  File "/Users/gcc/homebrew/lib/python3.7/site-packages/ue4cli/UnrealManagerBase.py", line 339, in buildDescriptor
    self._runUnrealBuildTool(target, self.getPlatformIdentifier(), configuration, baseArgs + args, capture=suppressOutput)
  File "/Users/gcc/homebrew/lib/python3.7/site-packages/ue4cli/UnrealManagerBase.py", line 616, in _runUnrealBuildTool
    Utility.run(arguments, cwd=self.getEngineRoot(), raiseOnError=True)
  File "/Users/gcc/homebrew/lib/python3.7/site-packages/ue4cli/Utility.py", line 138, in run
    raise Exception('child process ' + str(command) + ' failed with exit code ' + str(returncode))
Exception: child process ['/Users/Shared/Epic Games/UE_4.22/Engine/Build/BatchFiles/Mac/Build.sh', 'SomeProjEditor', 'macosx', 'Development', '-project=/Users/gcc/Documents/Unreal Projects/SomeProj/SomeProj/SomeProj.uproject'] failed with exit code 5

Most notably: ERROR: No platforms specified for target.

ue4 clean deletes third party binaries

ue4 clean deletes third party libraries that are not built from source. Not sure how this could be filtered.

Workaround for us is to use ue4 build -clean instead.

Package linux dedicated server

How to build and package a linux dedicated server with ue4?
Is there some argument to ue4 package command or I need to construct all with ue4 uat?

I have prepared a docker container with ue4-docker with Linux engine compiled inside. And run command ue4 inside it.

[Feature Request] Configurable target directory for packaged artifacts

Hey,

for my Jenkins pipeline its crucuial that I can configure the outpuut directory of

#ue4 package

My Jenkins slaves are ephemeral and running in docker, therefore I'm sharing the workspace between all of these slave-containers.
Since one of my pipelinesteps consists of parallel stages and each stage executes the package-command for a different platform I would like to configure thhe output-directory.

e.g.

pipeline {
agent none

stages {	
	//...

	stage("Package") {
		parallel {				
			stage("Package: Win64-Client") {
				agent {
					label 'ue4-windows' 
				}

				steps {
					sh 'ue4 package Shipping -platform=Win64'
					sh 'zip -r win64_client.zip dist'
					archiveArtifacts (
						artifacts: 'win64_client.zip',
						onlyIfSuccessful: true
					)
				}
			}

			stage("Package: Linux-Client") {
				agent {
					label 'ue4-linux' 
				}

				steps {
					sh 'ue4 package Shipping -platform=Linux'
					sh 'zip -r linux_client.zip dist'
					archiveArtifacts (
						artifacts: 'linux_client.zip',
						onlyIfSuccessful: true
					)
				}
			}
			
			//...
		}
	}
	
	//...
}

//...

}

As you can see its packaging for windows and linux and then creates a .zip for each. Since these steps are in parallel and the workspace is shared it zips me different files depending on speed of the package-process.
However this could be dodged by making the output-directory configurable.

I would like to be able to execute

ue4 package Shipping -platform=Linux -archivedirectory=linux_client
ue4 package Shipping -platform=Win64 -archivedirectory=win64_client

without it 'just' appending the string to the actually executed command but rather replacing:

Start UAT: mono AutomationTool.exe BuildCookRun -utf8output -clientconfig=Shipping -serverconfig=Shipping -project=/home/ue4/workspace/Game/Game.uproject -noP4 -cook -build -stage -prereqs -pak -archive -archivedirectory=/home/ue4/workspace/Game/dist -archivedirectory=./linux_client -platform=Linux -nodebuginfo -allmaps

Parsing command line: BuildCookRun -utf8output -clientconfig=Shipping -serverconfig=Shipping -project=/home/ue4/workspace/Game/Game.uproject -noP4 -cook -build -stage -prereqs -pak -archive -archivedirectory=/home/ue4/workspace/Game/dist -archivedirectory=./linux_client -platform=Linux -nodebuginfo -allmaps

In the code I've found the position where you're hardcoding the directory-name 'dist':

grafik

I could also imagine this could be useful when it comes to multibranch pipelines.

Unable to pass platform in command line

Hello @adamrehn. When trying to add platform to the cli command i get:

ue4 package -platform=android  
Error: invalid build configuration "-platform=android"

Not sure if i am currently doing something wrong. I also triend with -platform=Linux and -platform=Mac with same result. Thank in advance for any help you can provide.

`ue4 setroot` fails if path has a trailing slash

(venv) PS> ue4 setroot 'C:\Games\Epic Games\UE_4.21\'
Using user-specified engine root: C:\Games\Epic Games\UE_4.21"
Warning: the specified directory does not appear to contain a valid version of the Unreal Engine.

but

(venv) PS> ue4 setroot 'C:\Games\Epic Games\UE_4.21'
Using user-specified engine root: C:\Games\Epic Games\UE_4.21

It picked up a trailing " due to the trailing backslash, which suggests a string-escaping error somewhere.

Feature Request: detecting the engine root honours the .uproject's EngineAssociation

I've just accidentally failed to cause a rebuild when I would have expected to need one, because I switched my .uproject's EngineAssociation from my local git checkout (UUID) to a installer packaged-build ("4.24"), and then did a ue4 build without thinking about it.

This is because setroot, as documented, is the authority on what UE4 installation to use for ue4cli.

I suspect this would have caused issues later if I hadn't noticed it, because compilation triggered in the editor or a generated project would have honoured the .uproject file's EngineAssociation.

I'd much prefer to not set the engineroot, and have my .u4project file parsed to get the correct root, rather than the current _detectEngineRoot behaviour of "latest installed version in the default install directory".

I know on Windows this should all be feasible via the registry, as UnrealVersionSelector must be doing that, but I don't know how it works on other platforms.

It would also be nice if in-tree Engine (i.e. next to the project) projects would work correctly out-of-the-box.

I understand that the logic in UBT will ignore an EngineAssociation value in a .uproject if the Engine directory is sitting next to the project, but haven't tested it myself, I just saw it mentioned on the Unreal forums once when talking about getting the Server binaries into the Installer Packaged Builds.

Build ShaderCompilerWorker when building Editor target in `ue4 build`

On Windows, I was trying to work out why my Editor was hanging at 39% when launching a project using a clean git checkout and a successful ue4 build Development Editor.

I noticed the following in the logs right before it hung:

'XGEControlWorker.exe' is not recognized as an internal or external command, operable program or batch file.

This was UE4 trying to use Incredibuild to compiler Shaders during startup.

It turns out XGEControlWorker.exe is a post-build copy of ShaderCompileWorker.exe. Poking around, I discovered that on OS X and Linux, the setup instructions/scripts build ShaderCompileWorker explicitly before building UE4Editor.

On Linux, it also suggests building CrashReportClient, UnrealLightmass, and UnrealPak.

On OS X, Build.sh and XcodeBuild.sh take a parameter -buildscw in ($4 or $5) to build ShaderCompilerWorker before passing the command line over to UnrealBuildTool.exe.

On Windows, the VC Project Files generate Build.bat calls and add ShaderCompilerWorker as an extra target when building the Editor, based on a default-true config option bEditorDependsOnShaderCompileWorker.

You can see where it adds ShaderCompilerWorker it also adds LiveCodingConsole if enabled (defaults to true in Win64 non-Shipping non-Programs).

To fix the editor, I had to manually compile ShaderCompilerWorker.exe:

D:\Unreal\UnrealEngine\Engine\Build\BatchFiles\Build.bat ShaderCompileWorker Win64 Development

and everything worked fine after that.

In the end, what I'm hoping for is some piece of magic in ue4 build when it's given or defaults to an Editor target which will also build the appropriate extra targets for the platform.

ue4cli depends on 'pkg_resources' which prevents it from running on vanilla python

Looks like I missed this one during #59

ue4cli still depends on package outside of vanilla python and cannot be run directly from source without it:

$ python ~/ue4cli
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/korn/ue4cli/__main__.py", line 1, in <module>
    from ue4cli.cli import main
  File "/home/korn/ue4cli/ue4cli/cli.py", line 2, in <module>
    from .PluginManager import PluginManager
  File "/home/korn/ue4cli/ue4cli/PluginManager.py", line 2, in <module>
    import pkg_resources
ModuleNotFoundError: No module named 'pkg_resources'

For now, I only spotted pkg_resources (provided by setuptools) which is used in two places:

  1. pkg_resources.iter_entry_points
    # Retrieve the list of detected entry points in the ue4cli.plugins group
    plugins = {
    entry_point.name: entry_point.load()
    for entry_point
    in pkg_resources.iter_entry_points('ue4cli.plugins')
    }
  2. pkg_resources.parse_version
    def _editorPathSuffix(self, cmdVersion):
    version = parse_version(self.getEngineVersion())
    if version < parse_version('5.0.0'):
    return '.app/Contents/MacOS/UE4Editor'
    else:
    return '.app/Contents/MacOS/UnrealEditor'
    def _transformBuildToolPlatform(self, platform):
    # Prior to 4.22.2, Build.sh under Mac requires "macosx" as the platform name for macOS
    version = parse_version(self.getEngineVersion())
    return 'macosx' if platform == 'Mac' and version < parse_version('4.22.2') else platform

First one is tricky, we have to use it for loading ue4cli-plugins which is invoked in ue4cli/cli.py.
Second one should be fairly easy to replace (I hope).

TODO:
I gotta make sure there is no more dependencies like this one and find good workaround for this.
Perhaps we can try; import pkg_resources: and load ue4cli-plugins only if said dependency is resolved.

Either way, I'll probably take this one :)

Output not streamed to stdout

It seems all output is captured and then returned to stdout only once the underlying Unreal process is complete. This means it's hard to determine the progress of the command, especially for long-running test suites (using ue4 test).

_editorPathSuffix behaves inconsistently across all Platforms

Hi Adam,

Is there a reason for _editorPathSuffix taking cmdVersion parameter into consideration only on Windows?
I can see those executable variations on Linux (screenshot below).
I'm not sure how these executables work and if they're also supported on MacOS and on Installed builds.
Anyway, should be pretty easy to fix. I can quickly change it. Let me know what do you think.

image

def _editorPathSuffix(self, cmdVersion):
return '-Cmd.exe' if cmdVersion == True else '.exe'

def _editorPathSuffix(self, cmdVersion):
version = parse_version(self.getEngineVersion())
if version < parse_version('5.0.0'):
return '.app/Contents/MacOS/UE4Editor'
else:
return '.app/Contents/MacOS/UnrealEditor'

def _editorPathSuffix(self, cmdVersion):
return ''

doesnt work on 5.2

% ls /Users/Shared/Epic\ Games/UE_5.2/Engine/Binaries/Mac/BuildPatchTool --version
ls (GNU coreutils) 9.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Richard M. Stallman and David MacKenzie.

﷽      ~/unreal-rust/example/RustExampleمَّنْ عَمِلَ صَٰلِحا ࣰ فَلِنَفْسِهِۦۖ وَمَنَ اَسَآءَ فَعَلَيْهَاۖ وَمَا رَبُّكَ بِظَلَّٰم ࣲ لِّلْعَبِيدِۖ 
% ue4 build Development Editor                      239234c [239234c] untracked 6213 12:53:12

Traceback (most recent call last):
  File "/opt/homebrew/bin/ue4", line 8, in <module>
    sys.exit(main())
  File "/opt/homebrew/lib/python3.10/site-packages/ue4cli/cli.py", line 222, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "/opt/homebrew/lib/python3.10/site-packages/ue4cli/cli.py", line 76, in <lambda>
    'action': lambda m, args: m.buildDescriptor(os.getcwd(), args.pop(0) if (len(args) > 0 and args[0].startswith('-') == False) else 'Development', args.pop(0) if (len(args) > 0 and args[0].startswith('-') == False) else 'Editor', args),
  File "/opt/homebrew/lib/python3.10/site-packages/ue4cli/UnrealManagerBase.py", line 351, in buildDescriptor
    if noTools == False and self.isInstalledBuild() == False and self.isProject(descriptor) and target == 'Editor':
  File "/opt/homebrew/lib/python3.10/site-packages/ue4cli/UnrealManagerBase.py", line 98, in isInstalledBuild
    sentinelFile = os.path.join(self.getEngineRoot(), 'Engine', 'Build', 'InstalledBuild.txt')
  File "/opt/homebrew/lib/python3.10/site-packages/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
  File "/opt/homebrew/lib/python3.10/site-packages/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
  File "/opt/homebrew/lib/python3.10/site-packages/ue4cli/UnrealManagerDarwin.py", line 25, in _detectEngineRoot
    if version < parse_version('5.0.0'):
NameError: name 'version' is not defined

API doesn't support launching non-Editor targets

I'm working on #56 and already have a solution but it only supports Editor target. According to documentation ue4 run was never meant to support non-Editor targets, so my fix for the linked issue would do a job for now. However, I also wish to support non-Editor targets. Currently ue4cli API does not have any logic for that, but it is possible to implement. If I fail to do so, this ticket will remind about the problem.

ThirdParty library enumeration fails if engine path includes a symlink

Hi there,

for me, the third party library enumeration and therefore ue4 libs result was empty, probably because my engine installation path contains a symlink.
The intermediate ubt_output.json contains canonicalized paths whereas the engine root used in the UE4BuildInterrogator was different because it included a symlink.
Therefore, the check for a third party plugin using the full engine path fails for every module.
Thus, I propose to only check if the path includes Engine/Source/ThirdParty which should be sufficient.

See PR #9.

Cheers,
Stefan

Add a `Game` target to `ue4 build Shipping`

Following the docs on this page: https://docs.adamrehn.com/ue4cli/descriptor-commands/build#top, I am trying to execute
ue4 build Shipping, to build this build of TargetType.Game (notice that it has no target appended, e.g. ActionRPGGame.Target.cs)

However, ue4 build Shipping, as per the docs, also tries to build the Editor modules, but the Editor does not support Shipping configuration.

Basically, ue4 build Shipping always fails...

To workaround this, we could add the Game target, to be used as ue4 build Shipping Game, which will not build Editor modules.

Or, a cli option -noEditor, such as ue4 build Shipping -noEditor.

Note: the BuildRunCook already supports -SkipCookingEditorContent and -noCompileEditor, but passing them to ue4 build Shipping -SkipCookingEditorContent -noCompileEditor doesn't seem to fix it.

Feature Request: ReportOutputPath for `ue4 test`

The UE4 Automation Tests can write out a JSON results file when the command-line -ReportOutputPath is provided.

However, the command-line processing for ue4 test puts all arguments inside the "RunTests Now " argument, so we can't trivially append -ReportOutputPath to the ue4 test call as we do with ue4 package for example.

Since we already provide flags that aren't what the internal command-line uses (i.e. --all and --filter, then simply supporting something like --reportOutputPath would be reasonable.

If it's helpful, I noticed an example of the index.json output file at https://www.emidee.net/ue4/2018/11/13/UE4-Unit-Tests-in-Jenkins.html.

Packaging multiple plugins at the same time

Hello!
I have been using u4cli for packaging my plugin and it has been working great!
I am facing a problem now that I don't see a direct solution for from the docs

I have 2 plugins, that can depend on each other, let call them A and B
I can build A, i can build B, independently everything works fine.
But if I want to package plugin A that has a dependency on B (which is the case in real life) the problem is in the build procedure folder B is of course not moved to the dist folder, so the build fails as it cannot find its B dependency.

Is there a solution for such a scenario?
Can I somehow move B maybe to the dist folder first? Will the creation overwrite it?
B can be prebuilt in my case, it is not strictly necessary to build them both at the same time for me

There is a hardcoded logic that builds Development ShaderCompilerWorker

Hey @adamrehn ,

When invoking Editor build process, the following logic will always run inside of buildDescriptor() call:

# If we're using a source build of the Engine then make sure ShaderCompileWorker is built before building project Editor modules
if noTools == False and self.isInstalledBuild() == False and self.isProject(descriptor) and target == 'Editor':
Utility.printStderr('Ensuring ShaderCompileWorker is built before building project Editor modules...')
self.buildTarget('ShaderCompileWorker', 'Development', [], suppressOutput)

As I understand, this was requested by #14 and added with 259d03c However, I have a feeling the change should be reverted. Said logic wastes few seconds for invoking additional build. ue4 build isn't meant to bootstap the Engine and building the ShaderCompilerWorker wouldn't solve said issue anyway as Unreal needs more modules to function properly such as CrashReportClient, UnrealFrontend, UnrealLightmass, etc

User is expected to bootstrap Unreal before using ue4 build. If we want to suport bootstraping from ue4cli we should probably make a custom command.

Also, looking through #14 it seems that this case was a problem with OP's environment setup as he was using a custom Engine source. This wasn't a bug with ue4cli and I doubt anyone else would encounter it. Though I might be mistaken.

Cheers!

"ue4 run DebugGame" runs default Development executable instead of DebugGame

Hello,

First of all, thanks for the tool, I'm really enjoying it!

Description

I've noticed that when invoking "ue4 run DebugGame", it tries to run:
/Engine/Binaries/Linux/UnrealEditor (with "DebugGame" parameter)
instead of:
/Engine/Binaries/Linux/UnrealEditor-Linux-DebugGame

so it actually fires default Editor Development executable instead of Editor DebugGame executable.
I'm not sure if this is how it supposed to work, since documentation doesn't tell anything about DebugGame target support for "run" command but, for comparison, when invoking "ue4 build DebugGame", it builds the Editor DebugGame as I would expect it.

If this is "by design", then it makes the API inconsistent, and there is no way to run other executables than Development one.

Looking through the code... UnrealManagerBase._editorPathSuffix is probably where this case should be supported, but right now said function just returns empty string for Linux, and other platforms also doesn't seem to support it at all.

Additional Info

OS: Arch Linux x86_64 (Kernel: 6.6.3-arch1-1)
Unreal version: UE 5.3.2 (built from source with clang and makefile)
Python interpreter: Python 3.11.6 (main, Nov 14 2023, 09:36:21) [GCC 13.2.1 20230801] on linux
API version: ue4cli 0.0.54, Released: Apr 6, 2022, installed via pip
Unreal root directory: I've set it manually via "ue4 setroot ~/Unreal/UnrealEngine"

Run tests in Editor type modules

I'ed like to run ue4 test MyEditorTypeModule but no dice. Seems the Unreal -game flag the test command uses means my "Type": "Editor" module does not get loaded.

Perhaps a --with-editor flag that leaves out the -game? Or am I missing something else...

Thanks for this tool.

"ue4 root" throws "NameError" on Mac OS X

Hello,

using "ue4 root" on Mac OS X will always throw the following error:

Traceback (most recent call last):
  File "/usr/local/bin/ue4", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/local/lib/python3.11/site-packages/ue4cli/cli.py", line 222, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "/usr/local/lib/python3.11/site-packages/ue4cli/cli.py", line 36, in <lambda>
    'action': lambda m, args: print(m.getEngineRoot()),
                                    ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/ue4cli/UnrealManagerBase.py", line 60, in getEngineRoot
    self._engineRoot = self._getEngineRoot()
                       ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/ue4cli/UnrealManagerBase.py", line 620, in _getEngineRoot
    return self._detectEngineRoot()
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/ue4cli/UnrealManagerDarwin.py", line 25, in _detectEngineRoot
    if version < parse_version('5.0.0'):
       ^^^^^^^
NameError: name 'version' is not defined

This is happening because "version" is actually not assigned anywhere in UnrealManagerDarwin._detectEngineRoot, even simple LSP catches this:

Screenshot 2024-01-23 at 14 56 55

On my side, adding version = parse_version(self.getEngineVersion()) on line before simply fixes this.

`ue4cli` does not recover if the `config.json` file is not a valid JSON

Hello,

Thanks for the project. Very useful and we are using it on a daily basis for our CI pipeline to build our project or even rebuild UE using our custom sources.

Today we got a weird crash using the ue4 setroot {path_to_engine} command on Windows:

Traceback (most recent call last):
  File "<Python Path>\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "<Python Path>\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "<redacted>\.env\Scripts\ue4.exe\__main__.py", line 7, in <module>
  File "<redacted>\.env\lib\site-packages\ue4cli\cli.py", line 222, in main
    SUPPORTED_COMMANDS[command]['action'](manager, args)
  File "<redacted>\.env\lib\site-packages\ue4cli\cli.py", line 18, in <lambda>
    'action': lambda m, args: m.setEngineRootOverride(args[0]),
  File "<redacted>\.env\lib\site-packages\ue4cli\UnrealManagerBase.py", line 40, in setEngineRootOverride
    ConfigurationManager.setConfigKey('rootDirOverride', rootDir)
  File "<redacted>\.env\lib\site-packages\ue4cli\ConfigurationManager.py", line 39, in setConfigKey
    return JsonDataManager(configFile).setKey(key, value)
  File "<redacted>\.env\lib\site-packages\ue4cli\JsonDataManager.py", line 38, in setKey
    data = self.getDictionary()
  File "<redacted>\.env\lib\site-packages\ue4cli\JsonDataManager.py", line 30, in getDictionary
    return json.loads(Utility.readFile(self.jsonFile))
  File "<Python Path>\lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "<Python Path>\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "<Python Path>\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

This was due because of the config.json that was only containing spaces (ie. not a valid JSON), probably because the host was not shutdown cleanly. I fixed it by manually editing the config.json file to make it a valid JSON.

I think it would be great if that kind of (weird, I concur, but possible) case would be handled gracefully by ue4cli, maybe by catching the exception and "resetting" the config file (or simply giving a clear error message). But that is only my thinking, I let you decide if that would make sens or not and please feel free to close this issue if you don't see it as such.

PermissionError: [WinError 5] Access is denied

When I run ue4 test --all on my build server (Jenkins & Windows) I ran into this issue. It is the same on my local machine when I do it.
My SCM has control over the folder aka the folder is 'Read Only' (Perforce). Running ps as admin does not help either.

Duplicate log from `ue4 run` command

Hi, I'm using a custom 4.27.2 installed build on Linux. When I execute the ue4 run command to run a commandlet most logs are duplicated, see this example:

[2023.05.13-00.10.37:589][  0]LogHAL: Linux SourceCodeAccessSettings: NullSourceCodeAccessor
[2023.05.13-00.10.37:589][  0]LogHAL: Linux SourceCodeAccessSettings: NullSourceCodeAccessor
[2023.05.13-00.11.10:468][  0]LogUObjectArray: 18576 objects as part of root set at end of initial load.
[2023.05.13-00.11.10:468][  0]LogUObjectArray: 18576 objects as part of root set at end of initial load.
[2023.05.13-00.11.10:468][  0]LogUObjectAllocator: 5195368 out of 0 bytes used by permanent object pool.
[2023.05.13-00.11.10:468][  0]LogUObjectAllocator: 5195368 out of 0 bytes used by permanent object pool.
[2023.05.13-00.11.10:468][  0]LogUObjectArray: CloseDisregardForGC: 0/0 objects in disregard for GC pool
[2023.05.13-00.11.10:468][  0]LogUObjectArray: CloseDisregardForGC: 0/0 objects in disregard for GC pool
[2023.05.13-00.11.10:469][  0]LogEngine: Initializing Engine...
[2023.05.13-00.11.10:470][  0]LogStats: UGameplayTagsManager::InitializeManager -  0.000 s
[2023.05.13-00.11.13:102][  0]LogAIModule: Creating AISystem for world Untitled

I think this is caused by either of the additional parameters -stdout or -FullStdOutLogOutput.

Release new version

Hello,

Currently it seems the cmakeflags command is broken with the version on pypi but isn't with trunk. Maybe it's time to push a new release?

Kind regards,

Russ

`ue4 run` command-line cannot pass a level URL due to parameter ordering

Trying to work out why

ue4 run Highrise?Bots=8 -server -nosteam

doesn't pass Bots through to the started server, I realised that the command being generated was

D:\Unreal\UnrealEngine\Engine\Binaries\Win64\UE4Editor-Cmd.exe D:\Unreal\ShooterGame\ShooterGame.uproject -stdout -FullStdOutLogOutput Highrise?Bots=8 -server -nosteam

but UE4 (4.24 here) isn't parsing the URL that late in the CLI, so it needs to be

D:\Unreal\UnrealEngine\Engine\Binaries\Win64\UE4Editor-Cmd.exe D:\Unreal\ShooterGame\ShooterGame.uproject Highrise?Bots=8 -server -nosteam -stdout -FullStdOutLogOutput

i.e. in UnrealManagerBase.runEditor, extraFlags needs to be interpolated immediately after projectFile, not at the end. The below seems to work in my testing:

Utility.run([self.getEditorBinary(True), projectFile, *extraFlags, '-stdout', '-FullStdOutLogOutput'], raiseOnError=True)

`ue4 version` - print only the version

The version command prints additional info. Ideally, it should only print the version to be (more easily) usable in other command line tools.

Current behavior:

$ ue4 version full 
Using user-specified engine root: C:\Program Files\Epic Games\UE_5.0
5.0.3

Expected behavior:

$ ue4 version full
5.0.3

-VS2019 Optional Argument needs to be earlier

Passing in the optional argument -VS2019 as per ue4 package Development -VS2019 results in errors that VS2017 doesn't exist. Running RunUAT also produces this error unless -VS2019 is just after BuildPlugin arg but before the Plugin/Package paraments.

Feature Request: Build non-project-specific tools with ue4 build

Right now, ue4 build prepends the project name to the provided target.

We have special-case code to build ShaderCompilerWorker (from #14) but no way to do such compilation in general.

In my immediate use-case, I was trying to compile UnrealFrontend.

PS > ue4 build Development UnrealFrontend
Using user-specified engine root: D:\Project
Creating makefile for ProjectUnrealFrontend (no existing makefile)
ERROR: Couldn't find target rules file for target 'ProjectUnrealFrontend' in rules assembly 'UE4Rules, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
       Location: D:\Project\Engine\Intermediate\Build\BuildRules\UE4Rules.dll
       Target rules found:
Traceback (most recent call last):
...
Exception: child process ['D:\\Project\\Engine\\Build\\BatchFiles\\Build.bat', 'ProjectUnrealFrontend', 'Win64', 'Development', '-project=D:\\Project\\project\\Project.uproject'] failed with exit code 5

Taking the command-line that was generated and removing the project name from the target name was sufficient to make this work, e.g.,

D:\\Project\\Engine\\Build\\BatchFiles\\Build.bat UnrealFrontend Win64 Development -project=D:\\Project\\project\\Project.uproject

That would have worked without -project too, I was just looking for the minimal patch. I'm honestly not sure if every Target in a project needs to start with (or equal) the project name, or if that's just convention for the game-variant and editor builds.

Possible UX:

ue4 build Development -istool UnrealFrontend

I'm not sure what the right command-line option would be in this case.

Another option is -noproject (which would also exclude -project from UBT like we do for ShaderCompileWorker now) but that would block targets in the project that do not include the name of the project as a prefix, I think.

It might also be possible to get UE4BuildTool to list the possible targets, and then automatically recognise when a target needs the Project prefix added, in which case -noproject is a better option.

Edit: I was looking at TargetDescriptor.cs, and the way this tool currently takes 'Game', 'Editor', 'Client', 'Server' is actually something we could pass verbatim to -TargetType=, and then the flag for this feature request would be -explicittarget to indicate to pass the given name to -Target, i.e.

# These two build the same thing, from ProjectEditor.Target.cs, which specifies `Type = TargetType.Editor`.
# -TargetType requires a -project
PS> D:\Project\Engine\Build\BatchFiles\Build.bat -TargetType=Editor Win64 Development -project=D:\\Project\\project\\Project.uproject
PS> D:\Project\Engine\Build\BatchFiles\Build.bat -Target=ProjectEditor Win64 Development -project=D:\\Project\\project\\Project.uproject
# This builds shadercompileworker. -project is unnecessary for this particular instance, but you can't tell that without parsing the rules assembly for NativeTargets.
PS> D:\Project\Engine\Build\BatchFiles\Build.bat -Target=ShaderCompileWorker Win64 Development -project=D:\\Project\\project\\Project.uproject

-Target and -TargetType were introduced in UE4.20 though, replacing the existing code which generally concatenated the project name and the target name. So they might not be feasible for ue4cli, depending on how far back it needs to support UE4.

API uses "bare" exceptions in multiple places

Hi @adamrehn

Per our conversation with @TBBle under #65, looks like there are several bare exceptions in current API.
This is considered a bad practice and non-Pythonic way of catching exceptions - reference1, reference2
It can potentially suppress unwanted exceptions and hide bugs. Something that we don't really want.

Fixing it right now is a bit risky, especially at this stage of the project. It would require some retesting and probably adding more code for edge cases. However, it would be a good change after all. I can try fixing it.

Let me know what do you think!

Example:

def getDescriptor(self, dir):
"""
Detects the descriptor file for either an Unreal project or an Unreal plugin in the specified directory
"""
try:
return self.getProjectDescriptor(dir)
except:
try:
return self.getPluginDescriptor(dir)
except:
raise UnrealManagerException('could not detect an Unreal project or plugin in the directory "{}"'.format(dir))

For reference, grep shows at least 7 usages of bare exception:

╰─$ grep -Rno "except:" . 
./ue4cli/UE4BuildInterrogator.py:192:except:
./ue4cli/UnrealManagerBase.py:52:except:
./ue4cli/UnrealManagerBase.py:173:except:
./ue4cli/UnrealManagerBase.py:176:except:
./ue4cli/UnrealManagerWindows.py:9:except:
./ue4cli/UnrealManagerWindows.py:42:except:
./ue4cli/UnrealManagerWindows.py:95:except:

No way for cooking content

To launch a Client/Server/Game instance, you need to cook content first. Otherwise it will fail to boot (which is expected).

Currently ue4cli does not support a way to explicitly cook content. The alternatives are:

  • cooking from Editor: Platforms > [PlatformName] > Cook Content (proper Target/Configuration must be specified)
  • cooking from command line by launching UnrealEditor with -run=cook and few more flags
  • cooking from command line by launching RunUAT with BuildCookRun -CookAll (not sure it this gonna work)
  • packing the whole project with ue4 package as it also cooks the content during the process

Would be nice to support it since cooking is pretty important and can fail so user might want to test it few times.

References:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.