Integrating latest from github/staging

Integrating up through commit 5e1bdae
This commit is contained in:
alexpete
2021-03-26 14:31:50 -07:00
parent 9c54341af8
commit 36c4e827bd
764 changed files with 11453 additions and 20251 deletions
@@ -20,8 +20,8 @@ namespace AzFramework::AssetSystem::Platform
{
void AllowAssetProcessorToForeground()
{}
bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view appRoot,
AZStd::string_view gameProjectName)
bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot,
AZStd::string_view projectPath)
{
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
// In Mac the Editor and game is within a bundle, so the path to the sibling app
@@ -30,19 +30,19 @@ namespace AzFramework::AssetSystem::Platform
assetProcessorPath = assetProcessorPath.LexicallyNormal();
auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"(open -g "%s" --args --start-hidden)", assetProcessorPath.c_str());
// Add the app-root to the launch command if not empty
if (!appRoot.empty())
// Add the engine path to the launch command if not empty
if (!engineRoot.empty())
{
fullLaunchCommand += R"( --app-root=")";
fullLaunchCommand += appRoot;
fullLaunchCommand += R"( --engine-path=")";
fullLaunchCommand += engineRoot;
fullLaunchCommand += '"';
}
// Add the active game project to the launch command if not empty
if (!gameProjectName.empty())
// Add the active project path to the launch command if not empty
if (!projectPath.empty())
{
fullLaunchCommand += R"( --gameFolder=")";
fullLaunchCommand += gameProjectName;
fullLaunchCommand += R"( --project-path=")";
fullLaunchCommand += projectPath;
fullLaunchCommand += '"';
}
@@ -16,3 +16,6 @@
#define AZ_TRAIT_AZFRAMEWORK_USE_C11_LOCALTIME_S 0
#define AZ_TRAIT_AZFRAMEWORK_USE_ERRNO_T_TYPEDEF 0
#define AZ_TRAIT_AZFRAMEWORK_USE_POSIX_LOCALTIME_R 1
#define AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL "python.sh"
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 0
#define AZ_TRAIT_AZFRAMEWORK_PROCESSLAUNCH_DEFAULT 0
@@ -0,0 +1,55 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace AzFramework
{
class CommunicatorHandleImpl
{
public:
~CommunicatorHandleImpl() = default;
bool IsValid() const;
bool IsBroken() const;
int GetHandle() const;
void Break();
void Close();
void SetHandle(int handle);
protected:
int m_handle = -1;
bool m_broken = false;
};
struct StartupInfo
{
~StartupInfo();
void SetupHandlesForChildProcess();
void CloseAllHandles();
int m_inputHandleForChild = -1;
int m_outputHandleForChild = -1;
int m_errorHandleForChild = -1;
};
struct ProcessData
{
StartupInfo m_startupInfo;
int m_childProcessId = 0;
bool m_childProcessIsDone = false;
};
} // namespace AzFramework
@@ -0,0 +1,245 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#if AZ_TRAIT_OS_PLATFORM_APPLE
#include <errno.h>
#include <sys/ioctl.h>
#include <AzFramework/Process/ProcessCommunicator.h>
namespace AzFramework
{
bool CommunicatorHandleImpl::IsValid() const
{
return fcntl(m_handle, F_GETFD) != -1;
}
bool CommunicatorHandleImpl::IsBroken() const
{
return m_broken;
}
int CommunicatorHandleImpl::GetHandle() const
{
return m_handle;
}
void CommunicatorHandleImpl::Break()
{
m_broken = true;
}
void CommunicatorHandleImpl::Close()
{
close(m_handle);
m_handle = -1;
}
void CommunicatorHandleImpl::SetHandle(int handle)
{
m_handle = handle;
}
AZ::u32 StdInOutCommunication::PeekHandle(StdProcessCommunicatorHandle& handle)
{
if (handle->IsBroken() || (!handle->IsValid() && (errno == EBADF)))
{
return 0;
}
size_t bytesAvailable = 0;
const int result = ioctl(handle->GetHandle(), FIONREAD, &bytesAvailable);
if ((result == -1) && (errno == EBADF))
{
// Child process released pipe
handle->Break();
}
return bytesAvailable;
}
AZ::u32 StdInOutCommunication::ReadDataFromHandle(StdProcessCommunicatorHandle& handle, void* readBuffer, AZ::u32 bufferSize)
{
if (handle->IsBroken() || (!handle->IsValid() && (errno == EBADF)))
{
return 0;
}
//Block if buffersize == 0
if (bufferSize == 0)
{
fd_set set;
FD_ZERO(&set);
FD_SET(handle->GetHandle(), &set);
int numReady = select(handle->GetHandle() + 1, &set, NULL, NULL, NULL);
// if numReady == -1 and errno == EINTR then the child process died unexpectedly and
// the handle was closed. Not something to assert about in regards to trying to read
// data from the child as there is not anything useful we can say or do in that case.
// Normal code/data flow will work and we as the parent will know that the child is
// dead and return any error codes the child may have written to the error stream.
AZ_Assert(numReady != -1 || errno == EINTR, "Could not determine if any data is available for reading due to an error. Errno: %d", errno);
const bool wasSet = FD_ISSET(handle->GetHandle(), &set);
AZ_Assert(wasSet, "handle was not set when we selected it for read");
return 0;
}
ssize_t bytesRead = 0;
bytesRead = read(handle->GetHandle(), readBuffer, bufferSize);
if (bytesRead < 0)
{
AZ_Assert(errno != EIO, "ReadFile performed unexpected async io");
if (errno == EBADF || errno == EINVAL)
{
// Child process exited, we may have read something, so return amount
handle->Break();
return bytesRead;
}
AZ_Assert(false, "Unexpected error from ReadFile %d", errno);
return bytesRead;
}
//EOF
if (bytesRead == 0)
{
handle->Break();
}
return bytesRead;
}
AZ::u32 StdInOutCommunication::WriteDataToHandle(StdProcessCommunicatorHandle& handle, const void* writeBuffer, AZ::u32 bytesToWrite)
{
AZ_Assert(writeBuffer, "Write buffer is null");
if (!writeBuffer || handle->IsBroken() || (!handle->IsValid() && (errno == EBADF)))
{
return 0;
}
const ssize_t bytesWritten = write(handle->GetHandle(), writeBuffer, bytesToWrite);
if (bytesWritten < 0)
{
AZ_Assert(errno != EIO, "Parent performed unexpected async io when trying to write to child process.");
if (errno == EPIPE)
{
// Child process exited, may have written something, so return amount
handle->Break();
return bytesWritten;
}
AZ_Assert(false, "Unexpected error trying to write to child process. errno = %d", errno);
return 0;
}
return bytesWritten;
}
bool StdInOutProcessCommunicator::CreatePipesForProcess(ProcessData* processData)
{
int pipeFileDescriptors[2] = { 0 };
// Create a pipe to monitor process std in (output from us)
int result = pipe(pipeFileDescriptors);
AZ_Assert(result != -1, "Failed to create pipe for std in pipe: errno = %d", errno);
if (result == -1)
{
return false;
}
processData->m_startupInfo.m_inputHandleForChild = pipeFileDescriptors[0];
m_stdInWrite->SetHandle(pipeFileDescriptors[1]);
// Create a pipe to monitor process std out (input to us)
result = pipe(pipeFileDescriptors);
AZ_Assert(result != -1, "Failed to create pipe for std out pipe: errno = %d", errno);
if (result == -1)
{
processData->m_startupInfo.CloseAllHandles();
CloseAllHandles();
return false;
}
m_stdOutRead->SetHandle(pipeFileDescriptors[0]);
processData->m_startupInfo.m_outputHandleForChild = pipeFileDescriptors[1];
// Create a pipe to monitor process std error (input to us)
result = pipe(pipeFileDescriptors);
AZ_Assert(result != -1, "Failed to create pipe for std err pipe: errno = %d", errno);
if (result == -1)
{
processData->m_startupInfo.CloseAllHandles();
CloseAllHandles();
return false;
}
m_stdErrRead->SetHandle(pipeFileDescriptors[0]);
processData->m_startupInfo.m_errorHandleForChild = pipeFileDescriptors[1];
m_initialized = true;
return true;
}
void StdInOutProcessCommunicator::WaitForReadyOutputs(OutputStatus& status) const
{
status.outputDeviceReady = m_stdOutRead->IsValid() && !m_stdOutRead->IsBroken();
status.errorsDeviceReady = m_stdErrRead->IsValid() && !m_stdErrRead->IsBroken();
status.shouldReadOutput = status.shouldReadErrors = false;
if (status.outputDeviceReady || status.errorsDeviceReady)
{
fd_set readSet;
int maxHandle = 0;
FD_ZERO(&readSet);
if (status.outputDeviceReady)
{
int currentHandle = m_stdOutRead->GetHandle();
FD_SET(currentHandle, &readSet);
maxHandle = currentHandle > maxHandle ? currentHandle : maxHandle;
}
if (status.errorsDeviceReady)
{
int currentHandle = m_stdErrRead->GetHandle();
FD_SET(currentHandle, &readSet);
maxHandle = currentHandle > maxHandle ? currentHandle : maxHandle;
}
if (select(maxHandle + 1, &readSet, nullptr, nullptr, nullptr) != -1)
{
status.shouldReadOutput = (status.outputDeviceReady && FD_ISSET(m_stdOutRead->GetHandle(), &readSet));
status.shouldReadErrors = (status.errorsDeviceReady && FD_ISSET(m_stdErrRead->GetHandle(), &readSet));
}
}
}
bool StdInOutProcessCommunicatorForChildProcess::AttachToExistingPipes()
{
m_stdInRead->SetHandle(STDIN_FILENO);
AZ_Assert(m_stdInRead->IsValid(), "In read handle is invalid");
m_stdOutWrite->SetHandle(STDOUT_FILENO);
AZ_Assert(m_stdOutWrite->IsValid(), "Output write handle is invalid");
m_stdErrWrite->SetHandle(STDERR_FILENO);
AZ_Assert(m_stdErrWrite->IsValid(), "Error write handle is invalid");
m_initialized = m_stdInRead->IsValid() && m_stdOutWrite->IsValid() && m_stdErrWrite->IsValid();
return m_initialized;
}
} // namespace AzFramework
#endif // AZ_TRAIT_OS_PLATFORM_APPLE
@@ -0,0 +1,436 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#if AZ_TRAIT_OS_PLATFORM_APPLE
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/Process/ProcessCommunicator.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzCore/base.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/parallel/thread.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <iostream>
#include <errno.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/resource.h> // for iopolicy
#include <time.h>
namespace AzFramework
{
namespace
{
/*! Checks to see if the child process specified by the id is done or not
*
* \param childProcessId - Id of the child process to check
* \param outExitCode - any exit code the child process returned if it is not running
* \return True if the process is still running, otherwise false
*/
bool IsChildProcessDone(int childProcessId, AZ::u32* outExitCode = nullptr)
{
// Check exit code
int exitCode = 0;
int result = waitpid(childProcessId, &exitCode, WNOHANG);
// 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);
exitCode = 0;
}
else if (result == childProcessId)
{
// result == child PID indicates done
int realExitCode = 0;
if (WIFEXITED(exitCode))
{
realExitCode = WEXITSTATUS(exitCode);
}
else if (WIFSIGNALED(exitCode))
{
int termSig = WTERMSIG(exitCode);
if (termSig != 0)
{
realExitCode = termSig;
}
int coreDump = WCOREDUMP(exitCode);
if (coreDump != 0)
{
realExitCode = coreDump;
}
}
else if (WIFSTOPPED(exitCode))
{
int stopSig = WSTOPSIG(exitCode);
realExitCode = stopSig;
}
exitCode = realExitCode;
}
if (outExitCode)
{
*outExitCode = exitCode;
}
return (result != 0);
}
inline bool IsIdChildProcess(pid_t processId)
{
return processId == 0;
}
/*! Executes a command in the child process after the fork operation has been executed.
* This function will never return. If the execvp command fails this will call _exit with
* the errno value as the return value since continuing execution after a execvp command
* is invalid (it will be running the parent's code and in its address space and will
* cause many issues).
*
* \param commandAndArgs - Array of strings that has the command to execute in index 0 with any args for the command following. Last element must be a null pointer.
* \param envionrmentVariables - Array of strings that contains environment variables that command should use. Last element must be a null pointer.
* \param processLaunchInfo - struct containing information about luanching the command
* \param startupInfo - struct containing information needed to startup the command
*/
void ExecuteCommandAsChild(char** commandAndArgs, char** environmentVariables, const ProcessLauncher::ProcessLaunchInfo& processLaunchInfo, StartupInfo& startupInfo)
{
if (!processLaunchInfo.m_workingDirectory.empty())
{
int res = chdir(processLaunchInfo.m_workingDirectory.c_str());
if (res != 0)
{
std::cerr << strerror(errno) << std::endl;
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: Unable to change the launched process' directory to '%s'.", processLaunchInfo.m_workingDirectory.c_str());
// We *have* to _exit as we are the child process and simply
// returning at this point would mean we would start running
// the code from our parent process and that will just wreck
// havoc.
_exit(errno);
}
}
switch (processLaunchInfo.m_processPriority)
{
case PROCESSPRIORITY_BELOWNORMAL:
nice(1);
// also reduce disk impact:
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_UTILITY);
break;
case PROCESSPRIORITY_IDLE:
nice(20);
// also reduce disk impact:
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE);
break;
}
startupInfo.SetupHandlesForChildProcess();
execve(commandAndArgs[0], commandAndArgs, environmentVariables);
// If we get here then execve failed to run the requested program and
// we have an error. In this case we need to exit the child process
// to stop it from continuing to run as a clone of the parent
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: Unable to launch process %s : errno = %s ", commandAndArgs[0], strerror(errno));
std::cerr << strerror(errno) << std::endl;
_exit(errno);
}
}
StartupInfo::~StartupInfo()
{
CloseAllHandles();
}
void StartupInfo::SetupHandlesForChildProcess()
{
if (m_inputHandleForChild != STDIN_FILENO)
{
dup2(m_inputHandleForChild, STDIN_FILENO);
close(m_inputHandleForChild);
}
if (m_outputHandleForChild != STDOUT_FILENO)
{
dup2(m_outputHandleForChild, STDOUT_FILENO);
close(m_outputHandleForChild);
}
if (m_errorHandleForChild != STDERR_FILENO)
{
dup2(m_errorHandleForChild, STDERR_FILENO);
close(m_errorHandleForChild);
}
}
void StartupInfo::CloseAllHandles()
{
if (m_inputHandleForChild != -1)
{
close(m_inputHandleForChild);
m_inputHandleForChild = -1;
}
if (m_outputHandleForChild != -1)
{
close(m_outputHandleForChild);
m_outputHandleForChild = -1;
}
if (m_errorHandleForChild != -1)
{
close(m_errorHandleForChild);
m_errorHandleForChild = -1;
}
}
bool ProcessLauncher::LaunchUnwatchedProcess(const ProcessLaunchInfo& processLaunchInfo)
{
ProcessData processData = ProcessData();
return LaunchProcess(processLaunchInfo, processData);
}
bool ProcessLauncher::LaunchProcess(const ProcessLaunchInfo& processLaunchInfo, ProcessData& processData)
{
bool result = false;
// note that the convention here is that it uses windows-shell style escaping of combined args with spaces in it
// (so surrounding with quotes like param="hello world")
// this is so that the callers (which could be numerous) do not have to worry about this and sprinkle ifdefs
// all over their code.
// We'll convert this to UNIX style command line parameters by counting and eliminating quotes:
AZStd::vector<AZStd::string> commandTokens;
AZStd::string outputString;
bool inQuotes = false;
for (size_t pos = 0; pos < processLaunchInfo.m_commandlineParameters.size(); ++pos)
{
char currentChar = processLaunchInfo.m_commandlineParameters[pos];
if (currentChar == '"')
{
// Allow quote literals to go through as quotes which do NOT alter our "in quotes" bool below
// This is to conform with our PC parameter strings which will sometimes include path parameters which
// Can have spaces and commas and need to be output as paramname="\"Some pa,ram\"" in order to capture both correctly
if (outputString.length() && outputString.back() == '\\')
{
outputString.back() = currentChar;
}
else
{
inQuotes = !inQuotes;
}
}
else if ((currentChar == ' ') && (!inQuotes))
{
// its a space outside of quotes, so it ends the current parameter
commandTokens.push_back(outputString);
outputString.clear();
}
else
{
// Its a normal character, or its a space inside quotes
outputString.push_back(currentChar);
}
}
if (!outputString.empty())
{
commandTokens.push_back(outputString);
outputString.clear();
}
if (!processLaunchInfo.m_processExecutableString.empty())
{
commandTokens.insert(commandTokens.begin(), processLaunchInfo.m_processExecutableString);
}
AZStd::string commandNameWithPath = processLaunchInfo.m_workingDirectory + " " + commandTokens[0];
if (AZ::IO::SystemFile::Exists(commandNameWithPath.c_str()))
{
return false;
}
// Because of the way execve is defined we need to copy the strings from
// AZ::string (using c_str() returns a const char*) into a non-const char*
// Need to add one more as exec requires the array's last element to be a null pointer
char** commandAndArgs = new char*[commandTokens.size() + 1];
for (int i = 0; i < commandTokens.size(); ++i)
{
const AZStd::string& token = commandTokens[i];
commandAndArgs[i] = new char[token.size() + 1];
commandAndArgs[i][0] = '\0';
azstrcat(commandAndArgs[i], token.size(), token.c_str());
}
commandAndArgs[commandTokens.size()] = nullptr;
char** environmentVariables = nullptr;
int numEnvironmentVars = 0;
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++)
{
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[numEnvironmentVars] = NULL;
}
pid_t child_pid = fork();
if (IsIdChildProcess(child_pid))
{
ExecuteCommandAsChild(commandAndArgs, environmentVariables, processLaunchInfo, processData.m_startupInfo);
}
processData.m_childProcessId = child_pid;
// 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];
}
delete [] commandAndArgs;
// If an error occurs, exit the application.
return child_pid >= 0;
}
StdProcessCommunicator* ProcessWatcher::CreateStdCommunicator()
{
return new StdInOutProcessCommunicator();
}
StdProcessCommunicatorForChildProcess* ProcessWatcher::CreateStdCommunicatorForChildProcess()
{
return new StdInOutProcessCommunicatorForChildProcess();
}
ProcessWatcher* ProcessWatcher::LaunchProcess(const ProcessLauncher::ProcessLaunchInfo& processLaunchInfo, ProcessCommunicationType communicationType)
{
ProcessWatcher* pWatcher = new ProcessWatcher {};
if (!pWatcher->SpawnProcess(processLaunchInfo, communicationType))
{
delete pWatcher;
return nullptr;
}
return pWatcher;
}
void ProcessWatcher::InitProcessData(bool stdProcessData)
{
/** Nothing to do for this on macOS */
}
ProcessWatcher::ProcessWatcher()
: m_pCommunicator(nullptr)
{
m_pWatcherData = AZStd::make_unique<ProcessData>();
}
ProcessWatcher::~ProcessWatcher()
{
if (IsProcessRunning())
{
TerminateProcess(0);
}
delete m_pCommunicator;
}
bool ProcessWatcher::IsProcessRunning(AZ::u32* outExitCode)
{
AZ_Assert(m_pWatcherData, "No watcher data");
if (!m_pWatcherData || m_pWatcherData->m_childProcessIsDone)
{
return false;
}
m_pWatcherData->m_childProcessIsDone = IsChildProcessDone(m_pWatcherData->m_childProcessId, outExitCode);
return !m_pWatcherData->m_childProcessIsDone;
}
bool ProcessWatcher::WaitForProcessToExit(AZ::u32 waitTimeInSeconds, AZ::u32* outExitCode /*= nullptr*/)
{
AZ_UNUSED(outExitCode);
if (IsChildProcessDone(m_pWatcherData->m_childProcessId))
{
// Already exited
return true;
}
bool isProcessDone = false;
time_t startTime = time(0);
time_t currentTime = startTime;
AZ_Assert(currentTime != -1, "time(0) returned an invalid time");
while (((currentTime - startTime) < waitTimeInSeconds) && !isProcessDone)
{
usleep(100);
int wait_status = 0;
int result = waitpid(m_pWatcherData->m_childProcessId, &wait_status, WNOHANG);
if (result == m_pWatcherData->m_childProcessId)
{
isProcessDone = true;
m_pWatcherData->m_childProcessIsDone = true;
if (outExitCode)
{
*outExitCode = static_cast<AZ::u32>(WEXITSTATUS(wait_status));
}
}
currentTime = time(0);
}
//returns false if process is still running after time
return isProcessDone;
}
void ProcessWatcher::TerminateProcess(AZ::u32 exitCode)
{
AZ_Assert(m_pWatcherData, "No watcher data");
if (!m_pWatcherData)
{
return;
}
if (!IsProcessRunning())
{
return;
}
kill(m_pWatcherData->m_childProcessId, SIGKILL);
waitpid(m_pWatcherData->m_childProcessId, NULL, 0);
}
} //namespace AzFramework
#endif // AZ_TRAIT_OS_PLATFORM_APPLE
@@ -1,27 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/ProjectManager/ProjectManager.h>
#include <AzCore/PlatformIncl.h>
namespace AzFramework
{
namespace ProjectManager
{
bool LaunchProjectManager()
{
return false;
}
} // ProjectManager
} // AzFramework
@@ -16,7 +16,9 @@ set(FILES
AzFramework/API/ApplicationAPI_Mac.h
AzFramework/Application/Application_Mac.mm
AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp
AzFramework/ProjectManager/ProjectManager_Mac.cpp
AzFramework/Process/ProcessWatcher_Mac.cpp
AzFramework/Process/ProcessCommon.h
AzFramework/Process/ProcessCommunicator_Mac.cpp
../Common/UnixLike/AzFramework/IO/LocalFileIO_UnixLike.cpp
../Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp