External Project Build Path Support using SDK Binaries (#690)

* Updated the DynamicModuleHandle code to search within the
SettingsRegistry for the FilePathKey_ProjectBuildPath setting in order
to determine the binary directory for the Project.

This is used to locate shared libraries and executables built by the
project when running and Engine SDK binary from within the Engine SDK

* Added a generation step within the Projects.cmake file to generate a
.setreg file containing the CMake build directory root.
The file is output to the <project-root>/user/Registry/build_path.setreg
file.
This occurs only on non-host platforms when configuring for
non-Monolithic builds, since the Build Directory is used to located the
project binary directory in order to located the project's generated
${CMAKE_BINARY_DIR}/bin/$<CONFIG>/Registry directory containing the
cmake_dependencies.<project-name>.<application-name>.setreg file
containing the list of gem modules to load for a given application

Updated the SettingsRegistryMergeUtils AddRuntimeFilePaths function to
be read in the new "/Amazon/Project/Settings/Build/project_build_path"
and use that to form an absolute path to the project build directory by
appending it to the FilePathKey_ProjectPath key.
That key is set in the 'FilePathKey_ProjectBuildPath' constant
Next updated the SettingsRegistryMergeUtils
MergeSettingsToRegistry_TargetBuildDependencyRegistry function to look
within the project build directory to locate the
cmake_dependencies.*.setreg file to load

Tweaked the Settings Registry merge order of the ComponentApplication,
GameApplication and Settings Registry builder to merge the command line
after merging the global user registry and after merging the project
user registry.
Moved the call to MergeSettingsToRegistry_TargetBuildDependencyRegistry
to occur after the above calls to make sure the properly overriden
projects' user registry was merged in order for the correct project
build path to be stored in the SettingsRegistry

* Added a ProjectConfigurationBinPath key which contains the path to the <build-dir>/bin/$<CONFIG> directory for a project which is used to load gem dlls and the Registry/cmake_dependencies.*.setreg files when using an pre-built Editor/AssetProcessor on an external project

* Fixed variable reference to fileNamePath variable

* Removing the default Project Build Path from the Settings Registry
Runtime Filepaths.

Any paths would have to be set explicitly via .setreg/.setregpatch file
or the --project-build-path parameter

Updated the setting of the project build path and project binary
directory to perform existance checks on the paths before setting the
keys of /Amazon/AzCore/Runtime/FilePaths/ProjectBuildPath and
/Amazon/AzCore/Runtime/FilePaths/ProjectConfigurationBinPath

Added a backup project binary path of
<project-build-path>/bin/$<PLATFORM>/$<CONFIG> which is used if the path
of <project-build-path>/bin/$<CONFIG> has not been found

Fixed compile error in DynamicModuleHandle_Apple.cpp

* UnixLike Platform Build fix for the DynamicModuleHandle code
This commit is contained in:
lumberyard-employee-dm
2021-05-14 13:01:11 -05:00
committed by GitHub
parent 711db7e0f7
commit 8b8a582f02
13 changed files with 236 additions and 89 deletions
@@ -916,27 +916,49 @@ namespace AZ
SetSettingsRegistrySpecializations(specializations);
AZStd::vector<char> scratchBuffer;
// Retrieves the list gem module build targets that the active project depends on
SettingsRegistryMergeUtils::MergeSettingsToRegistry_TargetBuildDependencyRegistry(registry,
AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
#if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
// In development builds apply the o3de registry and the command line to allow early overrides. This will
// allow developers to override things like default paths or Asset Processor connection settings. Any additional
// values will be replaced by later loads, so this step will happen again at the end of loading.
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
// Project User Registry is merged after the command line here to allow make sure the any command line override of the project path
// is used for merging the project's user registry
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
#endif
//! Retrieves the list gem targets that the project has load dependencies on
//! This populates the /Amazon/Gems/<GemName>/SourcePaths array entries which is required
//! by the MergeSettingsToRegistry_GemRegistry() function below to locate the gem's root folder
//! and merge in the gem's registry files.
//! But when running from a pre-built app from the O3DE SDK(Editor/AssetProcessor), the projects binary
//! directory is needed in order to located the load dependency registry files
//! That project binary folder is generated with the <ProjectRoot>/user/Registry when CMake is configured
//! for the project
//! Therefore the order of merging must be as follows
//! 1. MergeSettingsToRegistry_ProjectUserRegistry - Populates the /Amazon/Project/Settings/Build/project_build_path
//! which contains the path to the project binary directory
//! 2. MergeSettingsToRegistry_TargetBuildDependencyRegistry - Loads the cmake_dependencies.<project_name>.<application_name>.setreg
//! file from the locations in order of
//! 1. <executable_directory>/Registry
//! 2. <cache_root>/Registry
//! 3. <project_build_path>/bin/$<CONFIG>/Registry
//! 3. MergeSettingsToRegistry_GemRegistries - Merges the settings registry files from each gem's <GemRoot>/Registry directory
SettingsRegistryMergeUtils::MergeSettingsToRegistry_TargetBuildDependencyRegistry(registry,
AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
#if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
#endif
// Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
}
void ComponentApplication::SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations)
@@ -599,6 +599,34 @@ namespace AZ::SettingsRegistryMergeUtils
? devWriteStorage.value()
: projectUserPath.Native());
// Set the project in-memory build path if the ProjectBuildPath key has been supplied
if (AZ::IO::FixedMaxPath projectBuildPath; registry.Get(projectBuildPath.Native(), ProjectBuildPath))
{
registry.Remove(FilePathKey_ProjectBuildPath);
registry.Remove(FilePathKey_ProjectConfigurationBinPath);
AZ::IO::FixedMaxPath buildConfigurationPath = normalizedProjectPath / projectBuildPath;
if (IO::SystemFile::Exists(buildConfigurationPath.c_str()))
{
registry.Set(FilePathKey_ProjectBuildPath, buildConfigurationPath.LexicallyNormal().Native());
}
// Add the specific build configuration paths to the Settings Registry
// First try <project-build-path>/bin/$<CONFIG> and if that path doesn't exist
// try <project-build-path>/bin/$<PLATFORM>/$<CONFIG>
buildConfigurationPath /= "bin";
if (IO::SystemFile::Exists((buildConfigurationPath / AZ_BUILD_CONFIGURATION_TYPE).c_str()))
{
registry.Set(FilePathKey_ProjectConfigurationBinPath,
(buildConfigurationPath / AZ_BUILD_CONFIGURATION_TYPE).LexicallyNormal().Native());
}
else if (IO::SystemFile::Exists((buildConfigurationPath / AZ_TRAIT_OS_PLATFORM_CODENAME / AZ_BUILD_CONFIGURATION_TYPE).c_str()))
{
registry.Set(FilePathKey_ProjectConfigurationBinPath,
(buildConfigurationPath / AZ_TRAIT_OS_PLATFORM_CODENAME / AZ_BUILD_CONFIGURATION_TYPE).LexicallyNormal().Native());
}
}
// Project name - if it was set via merging project.json use that value, otherwise use the project path's folder name.
auto projectNameKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
@@ -689,6 +717,14 @@ namespace AZ::SettingsRegistryMergeUtils
mergePath /= SettingsRegistryInterface::RegistryFolder;
registry.MergeSettingsFolder(mergePath.Native(), specializations, platform, "", scratchBuffer);
}
AZ::IO::FixedMaxPath projectBinPath;
if (registry.Get(projectBinPath.Native(), FilePathKey_ProjectConfigurationBinPath))
{
// Append the project build path path to the project root
projectBinPath /= SettingsRegistryInterface::RegistryFolder;
registry.MergeSettingsFolder(projectBinPath.Native(), specializations, platform, "", scratchBuffer);
}
}
void MergeSettingsToRegistry_EngineRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
@@ -934,7 +970,8 @@ namespace AZ::SettingsRegistryMergeUtils
"project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)},
OptionKeyToRegsetKey{
"project-cache-path",
AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)}};
AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)},
OptionKeyToRegsetKey{"project-build-path", ProjectBuildPath} };
AZStd::fixed_vector<AZStd::string, commandOptions.size()> overrideArgs;
@@ -52,6 +52,14 @@ namespace AZ::SettingsRegistryMergeUtils
//! project settings can be stored
inline static constexpr char FilePathKey_ProjectUserPath[] = "/Amazon/AzCore/Runtime/FilePaths/SourceProjectUserPath";
//! User facing key which represents the root of a project cmake build tree. i.e the ${CMAKE_BINARY_DIR}
//! A relative path is taking relative to the *project* root, NOT *engine* root.
inline constexpr AZStd::string_view ProjectBuildPath = "/Amazon/Project/Settings/Build/project_build_path";
//! In-Memory only key which stores an absolute path to the project build directory
inline constexpr AZStd::string_view FilePathKey_ProjectBuildPath = "/Amazon/AzCore/Runtime/FilePaths/ProjectBuildPath";
//! In-Memory only key which stores the configuration directory containing the built binaries
inline constexpr AZStd::string_view FilePathKey_ProjectConfigurationBinPath = "/Amazon/AzCore/Runtime/FilePaths/ProjectConfigurationBinPath";
//! Development write storage path may be considered temporary or cache storage on some platforms
inline static constexpr char FilePathKey_DevWriteStorage[] = "/Amazon/AzCore/Runtime/FilePaths/DevWriteStorage";
@@ -128,7 +136,7 @@ namespace AZ::SettingsRegistryMergeUtils
//! Callback function that is after a has been filtered through the CommentPrefixFunc
//! to determine if the text matches a section header
//! returns a view of the section name if the line contains a section
//! Otherwise an empty view is returend
//! Otherwise an empty view is returned
using SectionHeaderFunc = AZStd::function<AZStd::string_view(AZStd::string_view line)>;
//! Root JSON pointer path to place all key=values pairs of configuration data within
@@ -17,8 +17,9 @@ namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path)
AZ::IO::FixedMaxPath GetModulePath()
{
return {};
}
void* OpenModule(const AZ::OSString& fileName, bool&)
@@ -26,10 +27,9 @@ namespace AZ
// Android 19 does not have RTLD_NOLOAD but it should be OK since only the Editor expects to reopen modules
return dlopen(fileName.c_str(), RTLD_NOW);
}
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath)
void ConstructModuleFullFileName(AZ::IO::FixedMaxPath&)
{
fullPath = path + fileName;
}
}
}
@@ -10,7 +10,6 @@
*
*/
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
#include <AzCore/std/string/osstring.h>
#include <AzCore/Utils/Utils.h>
#include <dlfcn.h>
@@ -19,15 +18,9 @@ namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path)
AZ::IO::FixedMaxPath GetModulePath()
{
char exePath[AZ_MAX_PATH_LEN];
if (AZ::Utils::GetExecutableDirectory(exePath, AZ_ARRAY_SIZE(exePath)) ==
AZ::Utils::ExecutablePathResult::Success)
{
path = exePath;
path.push_back('/');
}
return AZ::Utils::GetExecutableDirectory();
}
void* OpenModule(const AZ::OSString& fileName, bool& alreadyOpen)
@@ -40,10 +33,9 @@ namespace AZ
}
return handle;
}
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath)
void ConstructModuleFullFileName(AZ::IO::FixedMaxPath&)
{
fullPath = path + fileName;
}
}
}
@@ -11,9 +11,11 @@
*/
#include <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <dlfcn.h>
#include <libgen.h>
@@ -21,9 +23,9 @@ namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path);
AZ::IO::FixedMaxPath GetModulePath();
void* OpenModule(const AZ::OSString& fileName, bool& alreadyOpen);
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath);
void ConstructModuleFullFileName(AZ::IO::FixedMaxPath& fullPath);
}
class DynamicModuleHandleUnixLike
@@ -36,40 +38,55 @@ namespace AZ
: DynamicModuleHandle(fullFileName)
, m_handle(nullptr)
{
AZ::OSString path;
AZ::OSString fileName;
AZ::OSString fullPath = "";
AZ::OSString::size_type finalSlash = m_fileName.find_last_of("/");
if (finalSlash != AZ::OSString::npos)
AZ::IO::FixedMaxPath fullFilePath(AZStd::string_view{m_fileName});
if (fullFilePath.HasFilename())
{
// Path up to and including final slash
path = m_fileName.substr(0, finalSlash + 1);
// Everything after the final slash
// If m_fileName ends in /, the end result is path/lib.dylib, which just fails to load.
fileName = m_fileName.substr(finalSlash + 1);
}
else
{
// If no slash found, assume empty path, only file name
path = "";
Platform::GetModulePath(path);
fileName = m_fileName;
AZ::IO::FixedMaxPathString fileNamePath{fullFilePath.Filename().Native()};
if (!fileNamePath.starts_with(AZ_TRAIT_OS_DYNAMIC_LIBRARY_PREFIX))
{
fileNamePath = AZ_TRAIT_OS_DYNAMIC_LIBRARY_PREFIX + fileNamePath;
}
if (!fileNamePath.ends_with(AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION))
{
fileNamePath += AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION;
}
fullFilePath.ReplaceFilename(AZStd::string_view(fileNamePath));
}
if (fileName.substr(0, 3) != AZ_TRAIT_OS_DYNAMIC_LIBRARY_PREFIX)
Platform::ConstructModuleFullFileName(fullFilePath);
// Check if the module exist at the given path within the current working directory
// If it doesn't attempt to append the path to the executable path
if (!AZ::IO::SystemFile::Exists(fullFilePath.c_str()))
{
fileName = AZ_TRAIT_OS_DYNAMIC_LIBRARY_PREFIX + fileName;
auto candidatePath = Platform::GetModulePath() / fullFilePath;
if (AZ::IO::SystemFile::Exists(candidatePath.c_str()))
{
fullFilePath = candidatePath;
}
}
size_t extensionLen = strlen(AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION);
if (fileName.substr(fileName.length() - extensionLen, extensionLen) != AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION)
// If the path still doesn't exist at this point, check the SettingsRegistryMergeUtils
// FilePathKey_ProjectBuildPath key to see if a project-build-path argument has been supplied
if (!AZ::IO::SystemFile::Exists(fullFilePath.c_str()))
{
fileName = fileName + AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
if(AZ::IO::FixedMaxPath projectModulePath;
settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath))
{
projectModulePath /= fullFilePath;
if (AZ::IO::SystemFile::Exists(projectModulePath.c_str()))
{
fullFilePath = projectModulePath;
}
}
}
}
Platform::ConstructModuleFullFileName(path, fileName, fullPath);
m_fileName = fullPath;
m_fileName = AZStd::string_view{fullFilePath.Native()};
}
~DynamicModuleHandleUnixLike() override
@@ -81,9 +98,9 @@ namespace AZ
{
AZ::Debug::Trace::Printf("Module", "Attempting to load module:%s\n", m_fileName.c_str());
bool alreadyOpen = false;
m_handle = Platform::OpenModule(m_fileName, alreadyOpen);
if(m_handle)
{
if (alreadyOpen)
@@ -15,6 +15,7 @@
#include <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
namespace AZ
@@ -31,13 +32,13 @@ namespace AZ
{
// Ensure filename ends in ".dll"
// Otherwise filenames like "gem.1.0.0" fail to load (.0 is assumed to be the extension).
if (m_fileName.substr(m_fileName.length() - 4) != AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION)
if (!m_fileName.ends_with(AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION))
{
m_fileName = m_fileName + AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION;
m_fileName += AZ_TRAIT_OS_DYNAMIC_LIBRARY_EXTENSION;
}
AZ::IO::PathView modulePathView{ m_fileName };
// If the module path doesn't have a directory within it, prepend it to the path
// If the module path doesn't have a directory within it, prepend the executable directory to the path
// and check if the new path exist
if (modulePathView.HasFilename() && !modulePathView.HasParentPath())
{
@@ -54,6 +55,27 @@ namespace AZ
}
}
}
// If the module file path does not exist, attempt to search for the module within
// the project's build directory
if (!AZ::IO::SystemFile::Exists(m_fileName.c_str()))
{
// The Settings Registry may not exist in early startup if modules are loaded
// before the ComponentApplication is crated(such as in the Editor main.cpp)
// Therefore an existence check is needed
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
if(AZ::IO::FixedMaxPath projectModulePath;
settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath))
{
projectModulePath /= AZStd::string_view(m_fileName);
if (AZ::IO::SystemFile::Exists(projectModulePath.c_str()))
{
m_fileName.assign(projectModulePath.c_str(), projectModulePath.Native().size());
}
}
}
}
}
~DynamicModuleHandleWindows() override
@@ -10,7 +10,6 @@
*
*/
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
#include <AzCore/std/string/osstring.h>
#include <AzCore/Utils/Utils.h>
#include <dlfcn.h>
@@ -19,15 +18,9 @@ namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path)
AZ::IO::FixedMaxPath GetModulePath()
{
char exePath[AZ_MAX_PATH_LEN];
if (AZ::Utils::GetExecutableDirectory(exePath, AZ_ARRAY_SIZE(exePath)) ==
AZ::Utils::ExecutablePathResult::Success)
{
path = exePath;
path.push_back('/');
}
return AZ::Utils::GetExecutableDirectory();
}
void* OpenModule(const AZ::OSString& fileName, bool& alreadyOpen)
@@ -40,10 +33,9 @@ namespace AZ
}
return handle;
}
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath)
void ConstructModuleFullFileName(AZ::IO::FixedMaxPath&)
{
fullPath = path + fileName;
}
}
}
@@ -10,7 +10,6 @@
*
*/
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
#include <AzCore/std/string/osstring.h>
#include <AzCore/Utils/Utils.h>
#include <dlfcn.h>
@@ -19,15 +18,9 @@ namespace AZ
{
namespace Platform
{
void GetModulePath(AZ::OSString& path)
AZ::IO::FixedMaxPath GetModulePath()
{
char exePath[AZ_MAX_PATH_LEN];
if (AZ::Utils::GetExecutableDirectory(exePath, AZ_ARRAY_SIZE(exePath)) ==
AZ::Utils::ExecutablePathResult::Success)
{
AZ::OSString frameworks = "/Frameworks/";
path = exePath + frameworks;
}
return AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) / "Frameworks";
}
void* OpenModule(const AZ::OSString& fileName, bool& alreadyOpen)
@@ -40,10 +33,15 @@ namespace AZ
}
return handle;
}
void ConstructModuleFullFileName(const AZ::OSString& path, const AZ::OSString& fileName, AZ::OSString& fullPath)
void ConstructModuleFullFileName(AZ::IO::FixedMaxPath& fullPath)
{
fullPath = path + fileName + ".framework/" + fileName;
// Append .framework to the name of full path
// Afterwards use the AZ::IO::Path Append function append the filename as a child
// of the framework directory
AZ::IO::FixedMaxPathString fileName = fullPath.Filename().Native();
fullPath.ReplaceFilename(fileName + ".framework");
fullPath /= fileName;
}
}
}
@@ -57,13 +57,16 @@ namespace AzGameFramework
AZStd::vector<char> scratchBuffer;
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_TargetBuildDependencyRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
#if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
#endif
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_TargetBuildDependencyRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
// Used the lowercase the platform name since the bootstrap.game.<config>.<platform>.setreg is being loaded
// from the asset cache root where all the files are in lowercased from regardless of the filesystem case-sensitivity
static constexpr char filename[] = "bootstrap.game." AZ_BUILD_CONFIGURATION_TYPE "." AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER ".setreg";
@@ -77,6 +80,7 @@ namespace AzGameFramework
#if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
#endif
@@ -297,20 +297,28 @@ namespace AssetProcessor
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, platform, specialization, &scratchBuffer);
// Merge the Project User and User home settings registry only in non-release builds
constexpr bool executeRegDumpCommands = false;
AZ::CommandLine* commandLine{};
AZ::ComponentApplicationBus::Broadcast([&registry, &commandLine](AZ::ComponentApplicationRequests* appRequests)
{
commandLine = appRequests->GetAzCommandLine();
});
if (!specialization.Contains("release"))
{
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, platform, specialization, &scratchBuffer);
if (commandLine)
{
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, *commandLine, executeRegDumpCommands);
}
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, platform, specialization, &scratchBuffer);
}
AZ::ComponentApplicationBus::Broadcast([&registry](AZ::ComponentApplicationRequests* appRequests)
if (commandLine)
{
if (AZ::CommandLine* commandLine = appRequests->GetAzCommandLine(); commandLine != nullptr)
{
constexpr bool executeRegDumpCommands = false;
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, *commandLine, executeRegDumpCommands);
}
});
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, *commandLine, executeRegDumpCommands);
}
if (registry.Visit(exporter, ""))
{
+1
View File
@@ -6,6 +6,7 @@
"project-path",
"engine-path",
"project-cache-path",
"project-build-path",
"regset",
"regremove",
"regdump",
+47 -1
View File
@@ -105,9 +105,54 @@ function(ly_add_project_dependencies)
)
endfunction()
#template for generating the project build_path setreg
set(project_build_path_template [[
{
"Amazon": {
"Project": {
"Settings": {
"Build": {
"project_build_path": "@project_bin_path@"
}
}
}
}
}]]
)
#! ly_generate_project_build_path_setreg: Generates a .setreg file that contains an absolute path to the ${CMAKE_BINARY_DIR}
# This allows locate the directory where the project it's binaries are built to be located within the engine.
# Which are the shared libraries and launcher executables
# When an a pre-built engine application runs from a directory other than the project build directory, it needs
# to be able to locate the project build directory to determine the list of gems that the project depends on to load
# as well the location of those gems.
# For example if the project uses an external gem not associated with the engine, that gem's dlls/so/dylib files
# would be located within the project build directory and the engine SDK binary directory would need that info
# NOTE: This only needed for non-monolithic host platforms.
# This is because there are no dynamic gems to load on monolithic builds
# Furthermore the pre-built SDK engine applications such as the Editor and AssetProcessor
# can only run on the host platform
# \arg:project_real_path Full path to the o3de project directory
function(ly_generate_project_build_path_setreg project_real_path)
# The build path isn't needed on non-monolithic platforms
# Nor on any non-host platforms
if (LY_MONOLITHIC_GAME OR NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
# Set the project_bin_path to the ${CMAKE_BINARY_DIR} to provide the configure template
# with the project build directory
set(project_bin_path ${CMAKE_BINARY_DIR})
string(CONFIGURE ${project_build_path_template} project_build_path_setreg_content @ONLY)
set(project_user_build_path_setreg_file ${project_real_path}/user/Registry/Platform/${PAL_PLATFORM_NAME}/build_path.setreg)
file(GENERATE OUTPUT ${project_user_build_path_setreg_file} CONTENT ${project_build_path_setreg_content})
endfunction()
# Add the projects here so the above function is found
foreach(project ${LY_PROJECTS})
get_filename_component(full_directory_path ${project} REALPATH ${CMAKE_SOURCE_DIR})
file(REAL_PATH ${project} full_directory_path BASE_DIRECTORY ${CMAKE_SOURCE_DIR})
string(SHA256 full_directory_hash ${full_directory_path})
# Truncate the full_directory_hash down to 8 characters to avoid hitting the Windows 260 character path limit
@@ -117,5 +162,6 @@ foreach(project ${LY_PROJECTS})
get_filename_component(project_folder_name ${project} NAME)
list(APPEND LY_PROJECTS_FOLDER_NAME ${project_folder_name})
add_subdirectory(${project} "${project_folder_name}-${full_directory_hash}")
ly_generate_project_build_path_setreg(${full_directory_path})
endforeach()
ly_set(LY_PROJECTS_FOLDER_NAME ${LY_PROJECTS_FOLDER_NAME})