From 6ba25c1b0d2c1cbe16426c35e0d9541e24ebe705 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Thu, 6 Jun 2024 21:11:12 +0100 Subject: [PATCH] Native Linux compile working and works on steam deck --- .../Private/HarmonyLinkLibrary.cpp | 70 +++++++++++++++---- .../Private/Objects/HarmonyLinkGraphics.cpp | 30 ++++++-- .../HarmonyLink/Public/HarmonyLinkLibrary.h | 28 ++++++-- .../Public/Objects/HarmonyLinkGraphics.h | 8 +-- .../HarmonyLinkLib/HarmonyLinkLib.Build.cs | 42 ++++++----- .../bin/Linux/libHarmonyLinkLibShared.so | 4 +- .../Linux/libHarmonyLinkLibStatic_clang++.a | 3 + .../lib/Win64/HarmonyLinkLibStatic.lib | 4 +- 8 files changed, 137 insertions(+), 52 deletions(-) create mode 100644 Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic_clang++.a diff --git a/Source/HarmonyLink/Private/HarmonyLinkLibrary.cpp b/Source/HarmonyLink/Private/HarmonyLinkLibrary.cpp index 5197354..a9a0f25 100644 --- a/Source/HarmonyLink/Private/HarmonyLinkLibrary.cpp +++ b/Source/HarmonyLink/Private/HarmonyLinkLibrary.cpp @@ -5,6 +5,21 @@ #include "HarmonyLinkLib.h" +bool UHarmonyLinkLibrary::bIsWineCached = false; +bool UHarmonyLinkLibrary::bIsLinuxCached = false; +bool UHarmonyLinkLibrary::bIsSteamDeckCached = false; +bool UHarmonyLinkLibrary::bCPUInfoCached = false; +bool UHarmonyLinkLibrary::bDeviceInfoCached = false; +bool UHarmonyLinkLibrary::bOSInfoCached = false; + +bool UHarmonyLinkLibrary::bIsWine = false; +bool UHarmonyLinkLibrary::bIsLinux = false; +bool UHarmonyLinkLibrary::bIsSteamDeck = false; + +FCPUInfo UHarmonyLinkLibrary::CachedCPUInfo = FCPUInfo(); +FDevice UHarmonyLinkLibrary::CachedDeviceInfo = FDevice(); +FOSVerInfo UHarmonyLinkLibrary::CachedOSInfo = FOSVerInfo(); + UHarmonyLinkLibrary::UHarmonyLinkLibrary() { if (!HarmonyLinkLib::HL_Init()) @@ -16,34 +31,65 @@ UHarmonyLinkLibrary::UHarmonyLinkLibrary() UE_LOG(LogHarmonyLink, Log, TEXT("HarmonyLinkLib Initialised!")); } -bool UHarmonyLinkLibrary::IsWine() +bool UHarmonyLinkLibrary::IsWine(bool bForce) { - return HarmonyLinkLib::get_is_wine(); + if (!bIsWineCached || bForce) + { + bIsWine = HarmonyLinkLib::get_is_wine(); + bIsWineCached = true; + } + return bIsWine; } -bool UHarmonyLinkLibrary::IsLinux() +bool UHarmonyLinkLibrary::IsLinux(bool bForce) { - return HarmonyLinkLib::get_is_linux(); + if (!bIsLinuxCached || bForce) + { + bIsLinux = HarmonyLinkLib::get_is_linux(); + bIsLinuxCached = true; + } + return bIsLinux; } -bool UHarmonyLinkLibrary::IsSteamDeck() +bool UHarmonyLinkLibrary::IsSteamDeck(bool bForce) { - return GetDeviceInfo().Device == EDevice::STEAM_DECK; + if (!bIsSteamDeckCached || bForce) + { + bIsSteamDeck = GetDeviceInfo().Device == EDevice::STEAM_DECK; + bIsSteamDeckCached = true; + } + return bIsSteamDeck; } -FCPUInfo UHarmonyLinkLibrary::GetCPUInfo() +FCPUInfo UHarmonyLinkLibrary::GetCPUInfo(bool bForce) { - return FCPUInfo(HarmonyLinkLib::get_cpu_info()); + if (!bCPUInfoCached || bForce) + { + CachedCPUInfo = FCPUInfo(HarmonyLinkLib::get_cpu_info()); + bCPUInfoCached = true; + } + + return CachedCPUInfo; } -FDevice UHarmonyLinkLibrary::GetDeviceInfo() +FDevice UHarmonyLinkLibrary::GetDeviceInfo(bool bForce) { - return FDevice(HarmonyLinkLib::get_device_info()); + if (!bDeviceInfoCached || bForce) + { + CachedDeviceInfo = FDevice(HarmonyLinkLib::get_device_info()); + bDeviceInfoCached = true; + } + return CachedDeviceInfo; } -FOSVerInfo UHarmonyLinkLibrary::GetOSInfo() +FOSVerInfo UHarmonyLinkLibrary::GetOSInfo(bool bForce) { - return FOSVerInfo(HarmonyLinkLib::get_os_version()); + if (!bOSInfoCached || bForce) + { + CachedOSInfo = FOSVerInfo(HarmonyLinkLib::get_os_version()); + bOSInfoCached = true; + } + return CachedOSInfo; } FBattery UHarmonyLinkLibrary::GetBatteryStatus() diff --git a/Source/HarmonyLink/Private/Objects/HarmonyLinkGraphics.cpp b/Source/HarmonyLink/Private/Objects/HarmonyLinkGraphics.cpp index f1e17d6..d22efd4 100644 --- a/Source/HarmonyLink/Private/Objects/HarmonyLinkGraphics.cpp +++ b/Source/HarmonyLink/Private/Objects/HarmonyLinkGraphics.cpp @@ -7,6 +7,7 @@ #include "HarmonyLinkLibrary.h" #include "GameFramework/GameUserSettings.h" #include "Kismet/GameplayStatics.h" +#include "HarmonyLinkLib.h" UHarmonyLinkGraphics* UHarmonyLinkGraphics::_INSTANCE = nullptr; int32 UHarmonyLinkGraphics::_TickRate = 1; @@ -72,8 +73,8 @@ UHarmonyLinkGraphics::UHarmonyLinkGraphics() AddToRoot(); - FWorldDelegates::OnPostWorldInitialization.AddUObject(this, &UHarmonyLinkGraphics::OnPostWorldInitialization); - FWorldDelegates::OnPreWorldFinishDestroy.AddUObject(this, &UHarmonyLinkGraphics::OnWorldEnd); + FWorldDelegates::OnPostWorldInitialization.AddStatic(&UHarmonyLinkGraphics::OnPostWorldInitialization); + FWorldDelegates::OnPreWorldFinishDestroy.AddStatic(&UHarmonyLinkGraphics::OnWorldEnd); Init(); } @@ -82,6 +83,7 @@ UHarmonyLinkGraphics::~UHarmonyLinkGraphics() { UE_LOG(LogHarmonyLink, Verbose, TEXT("~UHarmonyLinkGraphics called.")); FWorldDelegates::OnPostWorldInitialization.RemoveAll(this); + FWorldDelegates::OnPreWorldFinishDestroy.RemoveAll(this); } void UHarmonyLinkGraphics::LoadConfig(const bool bForceReload) @@ -352,13 +354,27 @@ void UHarmonyLinkGraphics::DestroySettings() void UHarmonyLinkGraphics::Init() { UE_LOG(LogHarmonyLink, Log, TEXT("Init called.")); + + if (!HarmonyLinkLib::HL_Init()) + { + UE_LOG(LogHarmonyLink, Fatal, TEXT("Failed to initialise HarmonyLinkLib!")); + return; + } + LoadConfig(); const FBattery BatteryStatus = UHarmonyLinkLibrary::GetBatteryStatus(); - + if (BatteryStatus.HasBattery) { - ApplyProfileInternal(EProfile::BATTERY); + if (BatteryStatus.IsACConnected) + { + ApplyProfileInternal(EProfile::BATTERY); + } + else + { + ApplyProfileInternal(EProfile::CHARGING); + } } } @@ -584,7 +600,7 @@ void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::Init if (World->IsGameWorld()) { - if (IsValid(_INSTANCE)) + if (IsValid(GetSettings())) { FTimerManager* TimerManager = &World->GetTimerManager(); if (!TimerManager) @@ -598,7 +614,7 @@ void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::Init World->GetTimerManager().SetTimer(_TickTimerHandle, [TimerManager] { - if (!_INSTANCE) + if (!GetSettings()) { UE_LOG(LogHarmonyLink, Error, TEXT("'This' is destroyed, Clearing timer.")) if (TimerManager) @@ -607,7 +623,7 @@ void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::Init } return; } - _INSTANCE->Tick(); + GetSettings()->Tick(); }, _TickRate, true); } else diff --git a/Source/HarmonyLink/Public/HarmonyLinkLibrary.h b/Source/HarmonyLink/Public/HarmonyLinkLibrary.h index 19dc5ff..926b6c8 100644 --- a/Source/HarmonyLink/Public/HarmonyLinkLibrary.h +++ b/Source/HarmonyLink/Public/HarmonyLinkLibrary.h @@ -25,29 +25,45 @@ public: // Checks if the game is running under Wine. UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink") - static bool IsWine(); + static bool IsWine(bool bForce = false); // Checks if the operating system is Linux. UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink") - static bool IsLinux(); + static bool IsLinux(bool bForce = false); // Checks if the game is running on a Steam Deck. UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink") - static bool IsSteamDeck(); + static bool IsSteamDeck(bool bForce = false); // Retrieves information about the CPU of the current device. UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink") - static FCPUInfo GetCPUInfo(); + static FCPUInfo GetCPUInfo(bool bForce = false); // Retrieves information about the current device. UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink") - static FDevice GetDeviceInfo(); + static FDevice GetDeviceInfo(bool bForce = false); // Retrieves information about the operating system of the current device. UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink") - static FOSVerInfo GetOSInfo(); + static FOSVerInfo GetOSInfo(bool bForce = false); // Retrieves the current battery status of the device. UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink") static FBattery GetBatteryStatus(); + +private: + static bool bIsWineCached; + static bool bIsWine; + static bool bIsLinuxCached; + static bool bIsLinux; + static bool bIsSteamDeckCached; + static bool bIsSteamDeck; + + static bool bCPUInfoCached; + static bool bDeviceInfoCached; + static bool bOSInfoCached; + + static FCPUInfo CachedCPUInfo; + static FDevice CachedDeviceInfo; + static FOSVerInfo CachedOSInfo; }; diff --git a/Source/HarmonyLink/Public/Objects/HarmonyLinkGraphics.h b/Source/HarmonyLink/Public/Objects/HarmonyLinkGraphics.h index 80d2475..0147020 100644 --- a/Source/HarmonyLink/Public/Objects/HarmonyLinkGraphics.h +++ b/Source/HarmonyLink/Public/Objects/HarmonyLinkGraphics.h @@ -6,7 +6,7 @@ #include "Enums/Profile.h" #include "Structs/SettingsProfile.h" -#include "UObject/Object.h" +#include "Kismet/BlueprintFunctionLibrary.h" #include "HarmonyLinkGraphics.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnProfileChanged, EProfile, Profile); @@ -17,7 +17,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnBatteryLevelChanged, int32, Batte * */ UCLASS(Blueprintable, config="HarmonyLink") -class HARMONYLINK_API UHarmonyLinkGraphics : public UObject +class HARMONYLINK_API UHarmonyLinkGraphics : public UBlueprintFunctionLibrary { GENERATED_BODY() @@ -390,7 +390,7 @@ private: * * @note Uses UE_LOG for logging errors and informational messages. */ - void OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS); + static void OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS); /** * @brief Handles actions to be performed when the world ends. @@ -406,7 +406,7 @@ private: * * @note Uses UE_LOG for logging errors and informational messages. */ - void OnWorldEnd(UWorld* World); + static void OnWorldEnd(UWorld* World); /** * @brief Resets the singleton instance of the UHarmonyLinkGraphics settings. diff --git a/Source/ThirdParty/HarmonyLinkLib/HarmonyLinkLib.Build.cs b/Source/ThirdParty/HarmonyLinkLib/HarmonyLinkLib.Build.cs index 0dc8bbd..2ce9175 100644 --- a/Source/ThirdParty/HarmonyLinkLib/HarmonyLinkLib.Build.cs +++ b/Source/ThirdParty/HarmonyLinkLib/HarmonyLinkLib.Build.cs @@ -43,26 +43,30 @@ public class HarmonyLinkLib : ModuleRules } else if (Target.Platform == UnrealTargetPlatform.Linux) { - PublicDefinitions.Add("HARMONYLINKLIB_SHARED=1"); + PublicDefinitions.Add("HARMONYLINKLIB_STATIC=1"); //Console.WriteLine("Building Linux"); PublicDefinitions.Add("BUILD_LINUX=1"); - string libPath = Path.Combine(ModuleDirectory, "bin", platformString, "libHarmonyLinkLibShared.so"); - //Console.WriteLine("Library Path: " + libPath); - PublicAdditionalLibraries.Add(libPath); - - // Add the C++ standard library explicitly - //string toolchainLibPath = "E:/UnrealToolChains/v22_clang-16.0.6-centos7/x86_64-unknown-linux-gnu/lib"; - //PublicSystemLibraryPaths.Add(toolchainLibPath); - RuntimeDependencies.Add(libPath); - } - // I shall include this if anyone wishes to provide Mac binaries of HarmonyLink but these are not included by default as I don't own one. - else if (Target.Platform == UnrealTargetPlatform.Mac) - { - PublicDefinitions.Add("HARMONYLINKLIB_SHARED=1"); - PublicDefinitions.Add("BUILD_MACOS=1"); - string dynlibPath = Path.Combine(ModuleDirectory, "lib", platformString, "libHarmonyLinkLibStatic.a"); - //Console.WriteLine("Dynamic Library Path: " + dynlibPath); - RuntimeDependencies.Add(dynlibPath); - } + string dllPath = Path.Combine(ModuleDirectory, "lib", platformString, "libHarmonyLinkLibStatic_clang++.a"); + //string dllTargetPath = "$(TargetOutputDir)/libHarmonyLinkLibShared.so"; + //Console.WriteLine("Library Path: " + libPath); + PublicAdditionalLibraries.Add(dllPath); + + // Ensure the proper linking of standard C++ libraries + //PublicSystemLibraries.Add("stdc++"); + //PublicSystemLibraries.Add("c++abi"); + //PublicSystemLibraries.Add("m"); // Math library + //PublicSystemLibraries.Add("pthread"); // POSIX threads library + + // Add the C++ standard library explicitly if needed + PublicSystemLibraries.Add("c++"); + + // Ensure linking with libc and other necessary libraries + //PublicSystemLibraries.Add("dl"); // Dynamic linking loader + //PublicSystemLibraries.Add("rt"); // Real-time library + + // Add any other libraries that might be needed + //PublicSystemLibraries.Add("gcc_s"); // GCC support library + //PublicSystemLibraries.Add("gcc"); // GCC compiler support library + } } } diff --git a/Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLibShared.so b/Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLibShared.so index 81f0188..7f4480a 100644 --- a/Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLibShared.so +++ b/Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLibShared.so @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7690f748eb883b77813eab76bb41e6264584c2c477ad19e0ce977378b11004a1 -size 252920 +oid sha256:f4a3966f9c7018d84e684baf61183d07758e13633decea1bd84daa44cf2b8ca1 +size 813728 diff --git a/Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic_clang++.a b/Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic_clang++.a new file mode 100644 index 0000000..27b9163 --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic_clang++.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6977100139b596b50b1b46bb91fb1979b43c3fc991ddcf5b6f4e4f4de1c992db +size 1775982 diff --git a/Source/ThirdParty/HarmonyLinkLib/lib/Win64/HarmonyLinkLibStatic.lib b/Source/ThirdParty/HarmonyLinkLib/lib/Win64/HarmonyLinkLibStatic.lib index 0d13dd8..b820888 100644 --- a/Source/ThirdParty/HarmonyLinkLib/lib/Win64/HarmonyLinkLibStatic.lib +++ b/Source/ThirdParty/HarmonyLinkLib/lib/Win64/HarmonyLinkLibStatic.lib @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9808e911e50ebb5d2ba8d9cc83254e99a1d26e9740a86bd78a5ceff7f868f06e -size 1346206 +oid sha256:ef8d92a66b36b8899e5fc2fe2e51e0753d11e7b161790013ee3c9a5c804fefa7 +size 1425358