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:
committed by
GitHub
parent
711db7e0f7
commit
8b8a582f02
@@ -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
|
||||
|
||||
+4
-4
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-12
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+47
-30
@@ -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)
|
||||
|
||||
+25
-3
@@ -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([®istry, &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([®istry](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, ""))
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"project-path",
|
||||
"engine-path",
|
||||
"project-cache-path",
|
||||
"project-build-path",
|
||||
"regset",
|
||||
"regremove",
|
||||
"regdump",
|
||||
|
||||
+47
-1
@@ -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})
|
||||
|
||||
Reference in New Issue
Block a user