@ -32,17 +32,12 @@
namespace AZ : : Internal
{
AZ : : SettingsRegistryInterface : : FixedValueString GetEngineMonikerForProject (
SettingsRegistryInterface & settingsRegistry , const AZ : : IO : : FixedMaxPath & project Path)
SettingsRegistryInterface & settingsRegistry , const AZ : : IO : : FixedMaxPath & project Json Path)
{
// projectPath needs to be an absolute path here.
using namespace AZ : : SettingsRegistryMergeUtils ;
bool projectJsonMerged = false ;
auto projectJsonPath = projectPath / " project.json " ;
if ( AZ : : IO : : SystemFile : : Exists ( projectJsonPath . c_str ( ) ) )
{
projectJsonMerged = settingsRegistry . MergeSettingsFile (
projectJsonPath . Native ( ) , AZ : : SettingsRegistryInterface : : Format : : JsonMergePatch , ProjectSettingsRootKey ) ;
}
bool projectJsonMerged = settingsRegistry . MergeSettingsFile (
projectJsonPath . Native ( ) , AZ : : SettingsRegistryInterface : : Format : : JsonMergePatch , ProjectSettingsRootKey ) ;
AZ : : SettingsRegistryInterface : : FixedValueString engineMoniker ;
if ( projectJsonMerged )
@ -105,12 +100,12 @@ namespace AZ::Internal
const auto engineMonikerKey = AZ : : SettingsRegistryInterface : : FixedValueString : : format ( " %s/engine_name " , EngineSettingsRootKey ) ;
AZStd : : set < AZ : : IO : : FixedMaxPath > projectPathsNotFound ;
for ( EngineInfo & engineInfo : pathVisitor . m_enginePaths )
{
AZ : : IO : : FixedMaxPath engineSettingsPath { engineInfo . m_path } ;
engineSettingsPath / = " engine.json " ;
if ( AZ : : IO : : SystemFile : : Exists ( engineSettingsPath . c_str ( ) ) )
if ( auto engineSettingsPath = AZ : : IO : : FixedMaxPath { engineInfo . m_path } / " engine.json " ;
AZ : : IO : : SystemFile : : Exists ( engineSettingsPath . c_str ( ) ) )
{
if ( settingsRegistry . MergeSettingsFile (
engineSettingsPath . Native ( ) , AZ : : SettingsRegistryInterface : : Format : : JsonMergePatch , EngineSettingsRootKey ) )
@ -119,12 +114,61 @@ namespace AZ::Internal
}
}
auto engineMoniker = Internal : : GetEngineMonikerForProject ( settingsRegistry , engineInfo . m_path / projectPath ) ;
if ( ! engineMoniker . empty ( ) & & engineMoniker = = engineInfo . m_moniker )
if ( auto projectJsonPath = ( engineInfo . m_path / projectPath / " project.json " ) . LexicallyNormal ( ) ;
AZ : : IO : : SystemFile : : Exists ( projectJsonPath . c_str ( ) ) )
{
engineRoot = engineInfo . m_path ;
break ;
if ( auto engineMoniker = Internal : : GetEngineMonikerForProject ( settingsRegistry , projectJsonPath ) ;
! engineMoniker . empty ( ) & & engineMoniker = = engineInfo . m_moniker )
{
engineRoot = engineInfo . m_path ;
break ;
}
}
else
{
projectPathsNotFound . insert ( projectJsonPath ) ;
}
// Continue looking for candidates, remove the previous engine and project settings that were merged above.
settingsRegistry . Remove ( ProjectSettingsRootKey ) ;
settingsRegistry . Remove ( EngineSettingsRootKey ) ;
}
if ( engineRoot . empty ( ) )
{
AZStd : : string errorStr ;
if ( ! projectPathsNotFound . empty ( ) )
{
// This case is usually encountered when a project path is given as a relative path,
// which is assumed to be relative to an engine root.
// When no project.json files are found this way, dump this error message about
// which project paths were checked.
AZStd : : string projectPathsTested ;
for ( const auto & path : projectPathsNotFound )
{
projectPathsTested . append ( AZStd : : string : : format ( " %s \n " , path . c_str ( ) ) ) ;
}
errorStr = AZStd : : string : : format ( " No valid project was found at these locations: \n %s "
" Please supply a valid --project-path to the application. " ,
projectPathsTested . c_str ( ) ) ;
}
else
{
// The other case is that a project.json was found, but after checking all the registered engines
// none of them matched the engine moniker.
AZStd : : string enginePathsChecked ;
for ( const auto & engineInfo : pathVisitor . m_enginePaths )
{
enginePathsChecked . append ( AZStd : : string : : format ( " %s (%s) \n " , engineInfo . m_path . c_str ( ) , engineInfo . m_moniker . c_str ( ) ) ) ;
}
errorStr = AZStd : : string : : format (
" No engine was found in o3de_manifest.json with a name that matches the one set in the project.json. \n "
" Engines that were checked: \n %s "
" Please check that your engine and project have both been registered with scripts/o3de.py. " , enginePathsChecked . c_str ( )
) ;
}
settingsRegistry . Set ( FilePathKey_ErrorText , errorStr . c_str ( ) ) ;
}
}
@ -158,7 +202,7 @@ namespace AZ::Internal
return { } ;
}
void InjectSettingToCommandLine Front ( AZ : : SettingsRegistryInterface & settingsRegistry ,
void InjectSettingToCommandLine Back ( AZ : : SettingsRegistryInterface & settingsRegistry ,
AZStd : : string_view path , AZStd : : string_view value )
{
AZ : : CommandLine commandLine ;
@ -168,7 +212,7 @@ namespace AZ::Internal
auto projectPathOverride = AZStd : : string : : format ( R " (--regset= " % . * s = % . * s " ) " ,
aznumeric_cast < int > ( path . size ( ) ) , path . data ( ) , aznumeric_cast < int > ( value . size ( ) ) , value . data ( ) ) ;
paramContainer . emplace ( paramContainer . b egi n( ) , AZStd : : move ( projectPathOverride ) ) ;
paramContainer . emplace ( paramContainer . end ( ) , AZStd : : move ( projectPathOverride ) ) ;
commandLine . Parse ( paramContainer ) ;
AZ : : SettingsRegistryMergeUtils : : StoreCommandLineToRegistry ( settingsRegistry , commandLine ) ;
}
@ -197,8 +241,8 @@ namespace AZ::SettingsRegistryMergeUtils
if ( ! engineRoot . empty ( ) )
{
settingsRegistry . Set ( engineRootKey , engineRoot . Native ( ) ) ;
// Inject the engine root into the front of the command line settings
Internal : : InjectSettingToCommandLine Front ( settingsRegistry , engineRootKey , engineRoot . Native ( ) ) ;
// Inject the engine root at the end of the command line settings
Internal : : InjectSettingToCommandLine Back ( settingsRegistry , engineRootKey , engineRoot . Native ( ) ) ;
return engineRoot ;
}
}
@ -244,8 +288,8 @@ namespace AZ::SettingsRegistryMergeUtils
if ( ! projectRoot . empty ( ) )
{
settingsRegistry . Set ( projectRootKey , projectRoot . c_str ( ) ) ;
// Inject the project root into the front of the command line settings
Internal : : InjectSettingToCommandLine Front ( settingsRegistry , projectRootKey , projectRoot . Native ( ) ) ;
// Inject the project root at the end of the command line settings
Internal : : InjectSettingToCommandLine Back ( settingsRegistry , projectRootKey , projectRoot . Native ( ) ) ;
return projectRoot ;
}
}
@ -874,6 +918,49 @@ namespace AZ::SettingsRegistryMergeUtils
return true ;
}
void ParseCommandLine ( AZ : : CommandLine & commandLine )
{
struct OptionKeyToRegsetKey
{
AZStd : : string_view m_optionKey ;
AZStd : : string m_regsetKey ;
} ;
// Provide overrides for the engine root, the project root and the project cache root
AZStd : : array commandOptions = {
OptionKeyToRegsetKey {
" engine-path " , AZStd : : string : : format ( " %s/engine_path " , AZ : : SettingsRegistryMergeUtils : : BootstrapSettingsRootKey ) } ,
OptionKeyToRegsetKey {
" 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 : : fixed_vector < AZStd : : string , commandOptions . size ( ) > overrideArgs ;
for ( auto & & [ optionKey , regsetKey ] : commandOptions )
{
if ( size_t optionCount = commandLine . GetNumSwitchValues ( optionKey ) ; optionCount > 0 )
{
// Use the last supplied command option value to override previous values
auto overrideArg = AZStd : : string : : format (
R " (--regset= " % s = % s " ) " , regsetKey . c_str ( ) , commandLine . GetSwitchValue ( optionKey , optionCount - 1 ) . c_str ( ) ) ;
overrideArgs . emplace_back ( AZStd : : move ( overrideArg ) ) ;
}
}
if ( ! overrideArgs . empty ( ) )
{
// Dump the input command line, add the additional option overrides
// and Parse the new command line args (write back) into the input command line.
AZ : : CommandLine : : ParamContainer commandLineArgs ;
commandLine . Dump ( commandLineArgs ) ;
commandLineArgs . insert (
commandLineArgs . end ( ) , AZStd : : make_move_iterator ( overrideArgs . begin ( ) ) , AZStd : : make_move_iterator ( overrideArgs . end ( ) ) ) ;
commandLine . Parse ( commandLineArgs ) ;
}
}
bool DumpSettingsRegistryToStream ( SettingsRegistryInterface & registry , AZStd : : string_view key ,
AZ : : IO : : GenericStream & stream , const DumperSettings & dumperSettings )
{