diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a38177714..bd02eeb7ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,8 +28,8 @@ include(cmake/FileUtil.cmake) include(cmake/PAL.cmake) include(cmake/PALTools.cmake) include(cmake/RuntimeDependencies.cmake) -include(cmake/Install.cmake) include(cmake/Configurations.cmake) # Requires to be after PAL so we get platform variable definitions +include(cmake/Install.cmake) include(cmake/Dependencies.cmake) include(cmake/Deployment.cmake) include(cmake/3rdParty.cmake) diff --git a/Code/Editor/Platform/Mac/editor_mac.cmake b/Code/Editor/Platform/Mac/editor_mac.cmake index 2afbee4251..fdccfafb46 100644 --- a/Code/Editor/Platform/Mac/editor_mac.cmake +++ b/Code/Editor/Platform/Mac/editor_mac.cmake @@ -13,3 +13,27 @@ set_target_properties(Editor PROPERTIES RESOURCE ${CMAKE_CURRENT_LIST_DIR}/Images.xcassets XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME EditorAppIcon ) + +# We cannot use ly_add_target here because we're already including this file from inside ly_add_target +# So we need to setup target, dependencies and install logic manually. +add_executable(EditorDummy Platform/Mac/main_dummy.cpp) +add_executable(AZ::EditorDummy ALIAS EditorDummy) + +ly_target_link_libraries(EditorDummy + PRIVATE + AZ::AzCore + AZ::AzFramework) + +ly_add_dependencies(Editor EditorDummy) + +# Store the aliased target into a DIRECTORY property +set_property(DIRECTORY APPEND PROPERTY LY_DIRECTORY_TARGETS AZ::EditorDummy) + +# Store the directory path in a GLOBAL property so that it can be accessed +# in the layout install logic. Skip if the directory has already been added +get_property(ly_all_target_directories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) +if(NOT CMAKE_CURRENT_SOURCE_DIR IN_LIST ly_all_target_directories) + set_property(GLOBAL APPEND PROPERTY LY_ALL_TARGET_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +ly_install_add_install_path_setreg(Editor) \ No newline at end of file diff --git a/Code/Editor/Platform/Mac/gui_info.plist b/Code/Editor/Platform/Mac/gui_info.plist index 5b5f94e977..cc87cbbb47 100644 --- a/Code/Editor/Platform/Mac/gui_info.plist +++ b/Code/Editor/Platform/Mac/gui_info.plist @@ -3,7 +3,7 @@ CFBundleExecutable - Editor + EditorDummy CFBundleIdentifier org.O3DE.Editor CFBundlePackageType diff --git a/Code/Editor/Platform/Mac/main_dummy.cpp b/Code/Editor/Platform/Mac/main_dummy.cpp new file mode 100644 index 0000000000..fb4a431295 --- /dev/null +++ b/Code/Editor/Platform/Mac/main_dummy.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include + +#include + +int main(int argc, char* argv[]) +{ + // Create a ComponentApplication to initialize the AZ::SystemAllocator and initialize the SettingsRegistry + AZ::ComponentApplication::Descriptor desc; + AZ::ComponentApplication application; + application.Create(desc); + + AZStd::vector envVars; + + const char* homePath = std::getenv("HOME"); + envVars.push_back(AZStd::string::format("HOME=%s", homePath)); + + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + const char* dyldLibPathOrig = std::getenv("DYLD_LIBRARY_PATH"); + AZStd::string dyldSearchPath = AZStd::string::format("DYLD_LIBRARY_PATH=%s", dyldLibPathOrig); + if (AZ::IO::FixedMaxPath projectModulePath; + settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath)) + { + dyldSearchPath.append(":"); + dyldSearchPath.append(projectModulePath.c_str()); + } + + if (AZ::IO::FixedMaxPath installedBinariesFolder; + settingsRegistry->Get(installedBinariesFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder)) + { + if (AZ::IO::FixedMaxPath engineRootFolder; + settingsRegistry->Get(engineRootFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder)) + { + installedBinariesFolder = engineRootFolder / installedBinariesFolder; + dyldSearchPath.append(":"); + dyldSearchPath.append(installedBinariesFolder.c_str()); + } + } + envVars.push_back(dyldSearchPath); + } + + AZStd::string commandArgs; + for (int i = 1; i < argc; i++) + { + commandArgs.append(argv[i]); + commandArgs.append(" "); + } + + AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; + AZ::IO::Path processPath{ AZ::IO::PathView(AZ::Utils::GetExecutableDirectory()) }; + processPath /= "Editor"; + processLaunchInfo.m_processExecutableString = AZStd::move(processPath.Native()); + processLaunchInfo.m_commandlineParameters = commandArgs; + processLaunchInfo.m_environmentVariables = &envVars; + processLaunchInfo.m_showWindow = true; + + AzFramework::ProcessWatcher* processWatcher = AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE); + + application.Destroy(); + + return 0; +} + diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index 2926a40252..02346c2ba1 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -28,6 +28,7 @@ namespace AZ::SettingsRegistryMergeUtils inline static constexpr char FilePathsRootKey[] = "/Amazon/AzCore/Runtime/FilePaths"; inline static constexpr char FilePathKey_BinaryFolder[] = "/Amazon/AzCore/Runtime/FilePaths/BinaryFolder"; inline static constexpr char FilePathKey_EngineRootFolder[] = "/Amazon/AzCore/Runtime/FilePaths/EngineRootFolder"; + inline static constexpr char FilePathKey_InstalledBinaryFolder[] = "/Amazon/AzCore/Runtime/FilePaths/InstalledBinariesFolder"; //! Stores the absolute path to root of a project's cache. No asset platform in this path, this is where the asset database file lives. //! i.e. /Cache diff --git a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp index 4c67c5cfc5..a8a6ffea21 100644 --- a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp +++ b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp @@ -25,29 +25,7 @@ namespace AZStd AZStd::sys_time_t GetTimeNowTicks() { AZStd::sys_time_t timeNow; - struct timespec ts; - clock_serv_t cclock; - mach_timespec_t mts; - kern_return_t ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - if (ret == KERN_SUCCESS) - { - ret = clock_get_time(cclock, &mts); - if (ret == KERN_SUCCESS) - { - ts.tv_sec = mts.tv_sec; - ts.tv_nsec = mts.tv_nsec; - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - mach_port_deallocate(mach_task_self(), cclock); - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - timeNow = ts.tv_sec * GetTimeTicksPerSecond() + ts.tv_nsec; + timeNow = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); return timeNow; } @@ -62,29 +40,7 @@ namespace AZStd AZStd::sys_time_t GetTimeNowSecond() { AZStd::sys_time_t timeNowSecond; - struct timespec ts; - clock_serv_t cclock; - mach_timespec_t mts; - kern_return_t ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - if (ret == KERN_SUCCESS) - { - ret = clock_get_time(cclock, &mts); - if (ret == KERN_SUCCESS) - { - ts.tv_sec = mts.tv_sec; - ts.tv_nsec = mts.tv_nsec; - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - mach_port_deallocate(mach_task_self(), cclock); - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - timeNowSecond = ts.tv_sec; + timeNowSecond = GetTimeNowTicks()/GetTimeTicksPerSecond(); return timeNowSecond; } diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp index 68e7c4e483..148b1cbdfe 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp @@ -24,7 +24,9 @@ #include #include // for iopolicy #include +#include +extern char **environ; namespace AzFramework { @@ -45,7 +47,7 @@ namespace AzFramework // result == 0 means child PID is still running, nothing to check if (result == -1) { - AZ_TracePrintf("ProcessWatcher", "IsChildProcessDone could not determine child process status (waitpid errno %d). assuming process either failed to launch or terminated unexpectedly\n", errno); + AZ_TracePrintf("ProcessWatcher", "IsChildProcessDone could not determine child process status (waitpid errno %d(%s)). assuming process either failed to launch or terminated unexpectedly\n", errno, strerror(errno)); exitCode = 0; } else if (result == childProcessId) @@ -274,28 +276,27 @@ namespace AzFramework azstrcat(commandAndArgs[i], token.size(), token.c_str()); } commandAndArgs[commandTokens.size()] = nullptr; - - char** environmentVariables = nullptr; - int numEnvironmentVars = 0; + + constexpr int MaxEnvVariables = 128; + using EnvironmentVariableContainer = AZStd::fixed_vector; + EnvironmentVariableContainer environmentVariables; + for (char **env = ::environ; *env; env++) + { + environmentVariables.push_back(*env); + } if (processLaunchInfo.m_environmentVariables) { - const int numEnvironmentVars = processLaunchInfo.m_environmentVariables->size(); - // Adding one more as exec expects the array to have a nullptr as the last element - environmentVariables = new char*[numEnvironmentVars + 1]; - for (int i = 0; i < numEnvironmentVars; i++) + for (AZStd::string& processLaunchEnv : *processLaunchInfo.m_environmentVariables) { - const AZStd::string& envVarString = processLaunchInfo.m_environmentVariables->at(i); - environmentVariables[i] = new char[envVarString.size() + 1]; - environmentVariables[i][0] = '\0'; - azstrcat(environmentVariables[i], envVarString.size(), envVarString.c_str()); + environmentVariables.push_back(processLaunchEnv.data()); } - environmentVariables[numEnvironmentVars] = NULL; } + environmentVariables.push_back(nullptr); pid_t child_pid = fork(); if (IsIdChildProcess(child_pid)) { - ExecuteCommandAsChild(commandAndArgs, environmentVariables, processLaunchInfo, processData.m_startupInfo); + ExecuteCommandAsChild(commandAndArgs, environmentVariables.data(), processLaunchInfo, processData.m_startupInfo); } processData.m_childProcessId = child_pid; @@ -303,15 +304,6 @@ namespace AzFramework // Close these handles as they are only to be used by the child process processData.m_startupInfo.CloseAllHandles(); - if (processLaunchInfo.m_environmentVariables) - { - for (int i = 0; i < numEnvironmentVars; i++) - { - delete [] environmentVariables[i]; - } - delete [] environmentVariables; - } - for (int i = 0; i < commandTokens.size(); i++) { delete [] commandAndArgs[i]; diff --git a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake index 54ed70c496..e34ce9d341 100644 --- a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake +++ b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake @@ -13,3 +13,27 @@ set_target_properties(AssetProcessor PROPERTIES RESOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Platform/Mac/Images.xcassets XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME AssetProcessorAppIcon ) + +# We cannot use ly_add_target here because we're already including this file from inside ly_add_target +# So we need to setup target, dependencies and install logic manually. +add_executable(AssetProcessorDummy Platform/Mac/main_dummy.cpp) +add_executable(AZ::AssetProcessorDummy ALIAS AssetProcessorDummy) + +ly_target_link_libraries(AssetProcessorDummy + PRIVATE + AZ::AzCore + AZ::AzFramework) + +ly_add_dependencies(AssetProcessor AssetProcessorDummy) + +# Store the aliased target into a DIRECTORY property +set_property(DIRECTORY APPEND PROPERTY LY_DIRECTORY_TARGETS AZ::AssetProcessorDummy) + +# Store the directory path in a GLOBAL property so that it can be accessed +# in the layout install logic. Skip if the directory has already been added +get_property(ly_all_target_directories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) +if(NOT CMAKE_CURRENT_SOURCE_DIR IN_LIST ly_all_target_directories) + set_property(GLOBAL APPEND PROPERTY LY_ALL_TARGET_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +ly_install_add_install_path_setreg(AssetProcessor) \ No newline at end of file diff --git a/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist b/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist index 665abea1d3..301f0c5cee 100644 --- a/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist +++ b/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist @@ -11,7 +11,7 @@ CFBundleSignature ASPR CFBundleExecutable - AssetProcessor + AssetProcessorDummy CFBundleIdentifier com.Amazon.AssetProcessor diff --git a/Code/Tools/AssetProcessor/Platform/Mac/main_dummy.cpp b/Code/Tools/AssetProcessor/Platform/Mac/main_dummy.cpp new file mode 100644 index 0000000000..12832cc488 --- /dev/null +++ b/Code/Tools/AssetProcessor/Platform/Mac/main_dummy.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include + +#include + +int main(int argc, char* argv[]) +{ + // Create a ComponentApplication to initialize the AZ::SystemAllocator and initialize the SettingsRegistry + AZ::ComponentApplication::Descriptor desc; + AZ::ComponentApplication application; + application.Create(desc); + + AZStd::vector envVars; + + const char* homePath = std::getenv("HOME"); + envVars.push_back(AZStd::string::format("HOME=%s", homePath)); + + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + const char* dyldLibPathOrig = std::getenv("DYLD_LIBRARY_PATH"); + AZStd::string dyldSearchPath = AZStd::string::format("DYLD_LIBRARY_PATH=%s", dyldLibPathOrig); + if (AZ::IO::FixedMaxPath projectModulePath; + settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath)) + { + dyldSearchPath.append(":"); + dyldSearchPath.append(projectModulePath.c_str()); + } + + if (AZ::IO::FixedMaxPath installedBinariesFolder; + settingsRegistry->Get(installedBinariesFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder)) + { + if (AZ::IO::FixedMaxPath engineRootFolder; + settingsRegistry->Get(engineRootFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder)) + { + installedBinariesFolder = engineRootFolder / installedBinariesFolder; + dyldSearchPath.append(":"); + dyldSearchPath.append(installedBinariesFolder.c_str()); + } + } + envVars.push_back(dyldSearchPath); + } + + AZStd::string commandArgs; + for (int i = 1; i < argc; i++) + { + commandArgs.append(argv[i]); + commandArgs.append(" "); + } + + AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; + AZ::IO::Path processPath{ AZ::IO::PathView(AZ::Utils::GetExecutableDirectory()) }; + processPath /= "AssetProcessor"; + processLaunchInfo.m_processExecutableString = AZStd::move(processPath.Native()); + processLaunchInfo.m_commandlineParameters = commandArgs; + processLaunchInfo.m_environmentVariables = &envVars; + processLaunchInfo.m_showWindow = true; + + AzFramework::ProcessWatcher* processWatcher = AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE); + + application.Destroy(); + + return 0; +} + diff --git a/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp b/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp index 5ef2ebd2f4..751afc1a5d 100644 --- a/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp @@ -28,7 +28,7 @@ namespace AssetProcessor //! Amount of time in seconds to wait for a builder to start up and connect // sometimes, builders take a long time to start because of things like virus scanners scanning each // builder DLL, so we give them a large margin. - static const int s_StartupConnectionWaitTimeS = 120; + static const int s_StartupConnectionWaitTimeS = 300; static const int s_MillisecondsInASecond = 1000; diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp index 5cc69bc9a1..8c64f1611f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp @@ -304,7 +304,7 @@ namespace AZ uint32_t exitCode = 0; bool timedOut = false; - const AZStd::sys_time_t maxWaitTimeSeconds = 120; + const AZStd::sys_time_t maxWaitTimeSeconds = 300; const AZStd::sys_time_t startTimeSeconds = AZStd::GetTimeNowSecond(); const AZStd::sys_time_t startTime = AZStd::GetTimeNowTicks(); diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 353c015fd3..2b56a1f0b4 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -448,11 +448,15 @@ endfunction() function(ly_setup_runtime_dependencies) # Common functions used by the bellow code - install(CODE + if(COMMAND ly_install_code_function_override) + ly_install_code_function_override() + else() + install(CODE "function(ly_copy source_file target_directory) file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) endfunction()" - ) + ) + endif() unset(runtime_commands) get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS) diff --git a/cmake/Platform/Mac/Install_mac.cmake b/cmake/Platform/Mac/Install_mac.cmake index 808299e09d..c7f22e9149 100644 --- a/cmake/Platform/Mac/Install_mac.cmake +++ b/cmake/Platform/Mac/Install_mac.cmake @@ -6,6 +6,34 @@ # # +# This is used to generate a setreg file which will be placed inside the bundle +# for targets that request it(eg. AssetProcessor/Editor). This is the relative path +# to the bundle from the installed engine's root. This will be used to compute the +# absolute path to bundle which may contain dependent dylibs(eg. Gems) used by a project. +set(installed_binaries_path_template [[ +{ + "Amazon": { + "AzCore": { + "Runtime": { + "FilePaths": { + "InstalledBinariesFolder": "bin/Mac/$" + } + } + } + } +}]] +) + +unset(target_conf_dir) +foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${conf} UCONF) + string(APPEND target_conf_dir $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${UCONF}}>) +endforeach() + +set(installed_binaries_setreg_path ${target_conf_dir}/Registry/installed_binaries_path.setreg) + +file(GENERATE OUTPUT ${installed_binaries_setreg_path} CONTENT ${installed_binaries_path_template}) + #! ly_install_target_override: Mac specific target installation function(ly_install_target_override) @@ -49,4 +77,26 @@ function(ly_install_target_override) endif() endfunction() +#! ly_install_add_install_path_setreg: Adds the install path setreg file as a dependency +function(ly_install_add_install_path_setreg NAME) + set_property(TARGET ${NAME} APPEND PROPERTY INTERFACE_LY_TARGET_FILES "${installed_binaries_setreg_path}\nRegistry") +endfunction() + +#! ly_install_code_function_override: Mac specific copy function to handle frameworks +function(ly_install_code_function_override) + + install(CODE +"function(ly_copy source_file target_directory) + if(\"\${source_file}\" MATCHES \"\\\\.[Ff]ramework[^\\\\.]\") + + # fixup origin to copy the whole Framework folder + string(REGEX REPLACE \"(.*\\\\.[Ff]ramework).*\" \"\\\\1\" source_file \"\${source_file}\") + get_filename_component(target_filename \"\${source_file}\" NAME) + + endif() + file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) +endfunction()") + +endfunction() + include(cmake/Platform/Common/Install_common.cmake) diff --git a/cmake/Platform/Mac/LYWrappers_mac.cmake b/cmake/Platform/Mac/LYWrappers_mac.cmake index 2254d422b0..578f6fe041 100644 --- a/cmake/Platform/Mac/LYWrappers_mac.cmake +++ b/cmake/Platform/Mac/LYWrappers_mac.cmake @@ -11,6 +11,7 @@ function(ly_apply_platform_properties target) set_target_properties(${target} PROPERTIES BUILD_RPATH "@executable_path/;@executable_path/../Frameworks" + INSTALL_RPATH "@executable_path/;@executable_path/../Frameworks" ) endfunction()