[Mac] Building and running game projects from an SDK (#2943)

* 1. Initial support for loading dylibs outside the bundle.
2. Child processes inherit parent's environment if no environment is explicitly specified(should change to append the parent's environment even if environment variables are explicitly specified).
3. Update some time functions to use system uptime instead of wall clock time when computing elapsed time. This fixes false timeouts when the OS goes to sleep.
4. Increase wait times for AssetBuilders and some Atom tools to connect to the AssetProcessor. This is needed because GateKeeper slows down first time bootup which results in asset processing failures.
With this change we'll be able to run Editor and AssetProcessor from an install on Mac and we will also be able to build and run projects using the installed engine as an SDK.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Remove debug messages.
2. Fix license
3. Pass parent's environment variables to child processes by default(on Mac).

Signed-off-by: amzn-sj <srikkant@amazon.com>

* 1. Add more detailed comments.2. Use a custom ly_copy for Mac and leave the default as is.

Signed-off-by: amzn-sj <srikkant@amazon.com>

* Address some feedback from review

Signed-off-by: amzn-sj <srikkant@amazon.com>
This commit is contained in:
SJ
2021-08-10 08:10:37 -07:00
committed by GitHub
parent e1ce9b21d5
commit 44b053df58
15 changed files with 278 additions and 76 deletions
@@ -24,7 +24,9 @@
#include <sys/ioctl.h>
#include <sys/resource.h> // for iopolicy
#include <time.h>
#include <unistd.h>
extern char **environ;
namespace AzFramework
{
@@ -45,7 +47,7 @@ namespace AzFramework
// result == 0 means child PID is still running, nothing to check
if (result == -1)
{
AZ_TracePrintf("ProcessWatcher", "IsChildProcessDone could not determine child process status (waitpid errno %d). assuming process either failed to launch or terminated unexpectedly\n", errno);
AZ_TracePrintf("ProcessWatcher", "IsChildProcessDone could not determine child process status (waitpid errno %d(%s)). assuming process either failed to launch or terminated unexpectedly\n", errno, strerror(errno));
exitCode = 0;
}
else if (result == childProcessId)
@@ -274,28 +276,27 @@ namespace AzFramework
azstrcat(commandAndArgs[i], token.size(), token.c_str());
}
commandAndArgs[commandTokens.size()] = nullptr;
char** environmentVariables = nullptr;
int numEnvironmentVars = 0;
constexpr int MaxEnvVariables = 128;
using EnvironmentVariableContainer = AZStd::fixed_vector<char*, MaxEnvVariables>;
EnvironmentVariableContainer environmentVariables;
for (char **env = ::environ; *env; env++)
{
environmentVariables.push_back(*env);
}
if (processLaunchInfo.m_environmentVariables)
{
const int numEnvironmentVars = processLaunchInfo.m_environmentVariables->size();
// Adding one more as exec expects the array to have a nullptr as the last element
environmentVariables = new char*[numEnvironmentVars + 1];
for (int i = 0; i < numEnvironmentVars; i++)
for (AZStd::string& processLaunchEnv : *processLaunchInfo.m_environmentVariables)
{
const AZStd::string& envVarString = processLaunchInfo.m_environmentVariables->at(i);
environmentVariables[i] = new char[envVarString.size() + 1];
environmentVariables[i][0] = '\0';
azstrcat(environmentVariables[i], envVarString.size(), envVarString.c_str());
environmentVariables.push_back(processLaunchEnv.data());
}
environmentVariables[numEnvironmentVars] = NULL;
}
environmentVariables.push_back(nullptr);
pid_t child_pid = fork();
if (IsIdChildProcess(child_pid))
{
ExecuteCommandAsChild(commandAndArgs, environmentVariables, processLaunchInfo, processData.m_startupInfo);
ExecuteCommandAsChild(commandAndArgs, environmentVariables.data(), processLaunchInfo, processData.m_startupInfo);
}
processData.m_childProcessId = child_pid;
@@ -303,15 +304,6 @@ namespace AzFramework
// Close these handles as they are only to be used by the child process
processData.m_startupInfo.CloseAllHandles();
if (processLaunchInfo.m_environmentVariables)
{
for (int i = 0; i < numEnvironmentVars; i++)
{
delete [] environmentVariables[i];
}
delete [] environmentVariables;
}
for (int i = 0; i < commandTokens.size(); i++)
{
delete [] commandAndArgs[i];