From 6651ae3d784d9e2eb7a7f30f36f9729c3cba9852 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Tue, 16 Nov 2021 15:32:24 -0600 Subject: [PATCH] Fix for python load errors on Linux (#5627) * Explicitly load libpython on Linux Downstream loads of python modules that weren't linked to libpython would fail to load because libraries were loaded using the RTLD_LOCAL flag. This adds a function that will explicitly load libpython on Linux using the RTLD_GLOBAL flag. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Fix misspelled function name Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Addressing PR feedback - Updates naming and location of things. - Adds load code to a Gem template. - Updates error checking. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Address further feedback Removes the api function in favor of just having modules inherit off a PythonLoader class, that way we get RAAI behavior and lifetime management for free. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../AzToolsFramework/API/PythonLoader.h | 25 ++++++++++++++ .../aztoolsframework_files.cmake | 1 + .../API/PythonLoader_Default.cpp | 20 +++++++++++ .../API/PythonLoader_Linux.cpp | 34 +++++++++++++++++++ .../Platform/Linux/platform_linux_files.cmake | 1 + .../Platform/Mac/platform_mac_files.cmake | 1 + .../Windows/platform_windows_files.cmake | 1 + .../Code/Source/AtomToolsFrameworkModule.h | 2 ++ .../Source/EditorPythonBindingsModule.cpp | 3 ++ .../Code/Source/PythonAssetBuilderModule.cpp | 3 ++ .../Code/Source/${Name}EditorModule.cpp | 2 ++ 11 files changed, 93 insertions(+) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/API/PythonLoader.h create mode 100644 Code/Framework/AzToolsFramework/Platform/Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp create mode 100644 Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/API/PythonLoader_Linux.cpp diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/PythonLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/PythonLoader.h new file mode 100644 index 0000000000..29125667d6 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/PythonLoader.h @@ -0,0 +1,25 @@ +/* + * 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 + * + */ + +#pragma once + +namespace AzToolsFramework::EmbeddedPython +{ + // When using embedded Python, some platforms need to explicitly load the python library. + // For any modules that depend on 3rdParty::Python package, the AZ::Module should inherit this class. + class PythonLoader + { + public: + PythonLoader(); + ~PythonLoader(); + + private: + void* m_embeddedLibPythonHandle{ nullptr }; + }; + +} // namespace AzToolsFramework::EmbeddedPython diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index b57eedcd81..d61d6486a9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -47,6 +47,7 @@ set(FILES API/EntityCompositionRequestBus.h API/EntityCompositionNotificationBus.h API/EditorViewportIconDisplayInterface.h + API/PythonLoader.h API/ViewPaneOptions.h API/ViewportEditorModeTrackerInterface.h Application/Ticker.h diff --git a/Code/Framework/AzToolsFramework/Platform/Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp b/Code/Framework/AzToolsFramework/Platform/Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp new file mode 100644 index 0000000000..42fef21db6 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Platform/Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp @@ -0,0 +1,20 @@ +/* +* 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 + +namespace AzToolsFramework::EmbeddedPython +{ + PythonLoader::PythonLoader() + { + } + + PythonLoader::~PythonLoader() + { + } +} diff --git a/Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/API/PythonLoader_Linux.cpp b/Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/API/PythonLoader_Linux.cpp new file mode 100644 index 0000000000..76fa36a048 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/API/PythonLoader_Linux.cpp @@ -0,0 +1,34 @@ +/* + * 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 + +namespace AzToolsFramework::EmbeddedPython +{ + PythonLoader::PythonLoader() + { + constexpr char libPythonName[] = "libpython3.7m.so.1.0"; + if (m_embeddedLibPythonHandle = dlopen(libPythonName, RTLD_NOW | RTLD_GLOBAL); + m_embeddedLibPythonHandle == nullptr) + { + char* err = dlerror(); + AZ_Error("PythonLoader", false, "Failed to load %s with error: %s\n", libPythonName, err ? err : "Unknown Error"); + } + } + + PythonLoader::~PythonLoader() + { + if (m_embeddedLibPythonHandle) + { + dlclose(m_embeddedLibPythonHandle); + } + } + +} // namespace AzToolsFramework::EmbeddedPython diff --git a/Code/Framework/AzToolsFramework/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzToolsFramework/Platform/Linux/platform_linux_files.cmake index c2c5a11c4c..3b04a903a4 100644 --- a/Code/Framework/AzToolsFramework/Platform/Linux/platform_linux_files.cmake +++ b/Code/Framework/AzToolsFramework/Platform/Linux/platform_linux_files.cmake @@ -7,4 +7,5 @@ # set(FILES + AzToolsFramework/API/PythonLoader_Linux.cpp ) diff --git a/Code/Framework/AzToolsFramework/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzToolsFramework/Platform/Mac/platform_mac_files.cmake index c2c5a11c4c..6342747a38 100644 --- a/Code/Framework/AzToolsFramework/Platform/Mac/platform_mac_files.cmake +++ b/Code/Framework/AzToolsFramework/Platform/Mac/platform_mac_files.cmake @@ -7,4 +7,5 @@ # set(FILES + ../Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp ) diff --git a/Code/Framework/AzToolsFramework/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzToolsFramework/Platform/Windows/platform_windows_files.cmake index c2c5a11c4c..6342747a38 100644 --- a/Code/Framework/AzToolsFramework/Platform/Windows/platform_windows_files.cmake +++ b/Code/Framework/AzToolsFramework/Platform/Windows/platform_windows_files.cmake @@ -7,4 +7,5 @@ # set(FILES + ../Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp ) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.h index 759b2558bf..ae60220314 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.h @@ -9,11 +9,13 @@ #pragma once #include +#include namespace AtomToolsFramework { class AtomToolsFrameworkModule : public AZ::Module + , public AzToolsFramework::EmbeddedPython::PythonLoader { public: AZ_RTTI(AtomToolsFrameworkModule, "{B58B7CA8-98C9-4DC8-8607-E094989BBBE2}", AZ::Module); diff --git a/Gems/EditorPythonBindings/Code/Source/EditorPythonBindingsModule.cpp b/Gems/EditorPythonBindings/Code/Source/EditorPythonBindingsModule.cpp index cef8931722..f168cc5ab2 100644 --- a/Gems/EditorPythonBindings/Code/Source/EditorPythonBindingsModule.cpp +++ b/Gems/EditorPythonBindings/Code/Source/EditorPythonBindingsModule.cpp @@ -9,6 +9,8 @@ #include #include +#include + #include #include #include @@ -18,6 +20,7 @@ namespace EditorPythonBindings { class EditorPythonBindingsModule : public AZ::Module + , public AzToolsFramework::EmbeddedPython::PythonLoader { public: AZ_RTTI(EditorPythonBindingsModule, "{851B9E35-4FD5-49B1-8207-E40D4BBA36CC}", AZ::Module); diff --git a/Gems/PythonAssetBuilder/Code/Source/PythonAssetBuilderModule.cpp b/Gems/PythonAssetBuilder/Code/Source/PythonAssetBuilderModule.cpp index d7143a159a..1d330c90df 100644 --- a/Gems/PythonAssetBuilder/Code/Source/PythonAssetBuilderModule.cpp +++ b/Gems/PythonAssetBuilder/Code/Source/PythonAssetBuilderModule.cpp @@ -9,12 +9,15 @@ #include #include +#include + #include namespace PythonAssetBuilder { class PythonAssetBuilderModule : public AZ::Module + , public AzToolsFramework::EmbeddedPython::PythonLoader { public: AZ_RTTI(PythonAssetBuilderModule, "{35C9457E-54C2-474C-AEBE-5A70CC1D435D}", AZ::Module); diff --git a/Templates/PythonToolGem/Template/Code/Source/${Name}EditorModule.cpp b/Templates/PythonToolGem/Template/Code/Source/${Name}EditorModule.cpp index 0027af011a..fdd971440e 100644 --- a/Templates/PythonToolGem/Template/Code/Source/${Name}EditorModule.cpp +++ b/Templates/PythonToolGem/Template/Code/Source/${Name}EditorModule.cpp @@ -10,6 +10,7 @@ #include <${Name}ModuleInterface.h> #include <${Name}EditorSystemComponent.h> +#include void Init${SanitizedCppName}Resources() { @@ -21,6 +22,7 @@ namespace ${SanitizedCppName} { class ${SanitizedCppName}EditorModule : public ${SanitizedCppName}ModuleInterface + , public AzToolsFramework::EmbeddedPython::PythonLoader { public: AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);