I spent hours on this part and I want to share my solution with you.
- Open your plugin’s Build.cs file.
- Take an example from my code below.
- Correct the names and path according to your own project.
NVMLManagerLibrary.Build.cs (this is an external module)
using System.IO;
using UnrealBuildTool;
public class NVMLManagerLibrary : ModuleRules
{
public NVMLManagerLibrary(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
if (Target.Platform == UnrealTargetPlatform.Win64)
{
// Add any include paths for the plugin
PublicIncludePaths.Add(Path.Combine(ModuleDirectory));
// Add any import libraries or static libraries
PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "x64", "Release", "NVMLManagerLibrary.lib"));
// Delay-load the DLL, so we can load it from the right place first
PublicDelayLoadDLLs.Add("NVMLManagerLibrary.dll");
string sourcePath = "$(ProjectDir)/Plugins/DryreLUIEssentialsPlugin/Source/ThirdParty/NVML/NVMLManagerLibrary/x64/Release/NVMLManagerLibrary.dll";
string destinationPath = "$(ProjectDir)/Binaries/Win64/NVMLManagerLibrary.dll";
string buildPath = "$(BinaryOutputDir)/NVMLManagerLibrary.dll";
// Copy DLL to Binaries Folder
if (Target.Type == TargetType.Editor)
{
RuntimeDependencies.Add(destinationPath,sourcePath); // For Editor
// Plugin Directory
//string destinationPath = "$(ProjectDir)/Plugins/DryreLUIEssentialsPlugin/Binaries/ThirdParty/NVMLManagerLibrary/Win64/NVMLManagerLibrary.dll";
}
// Copy config file to shipped folder
if (Target.Type == TargetRules.TargetType.Game)
{
RuntimeDependencies.Add(buildPath, sourcePath); // For Build
}
}
}
}
RuntimeDependencies is required for Third Party Library. I created two target type, one for editor and the other one is for game build. This method is worked for me.
Since my module is external, I have to add this into main plugin Build.cs file, PublicDependencyModuleNames.AddRange() inside or PrivateDependencyModuleNames.AddRange(). Module name is “NVMLManagerLibrary” so I added this one.
Example:

Also I would like to show you how to DelayLoad your plugin when project launchs.
YourPluginName.h
// Copyright © 2024 - DryreL Design
#include "Modules/ModuleManager.h"
#include "DryreLUIEssentialsBPLibrary.h"
#include "Interfaces/IPluginManager.h"
#include "Misc/Paths.h"
#include "../../ThirdParty/NVML/NVMLManagerLibrary/NVMLManager.h"
#include "../../ThirdParty/ADL/ADLManagerLibrary/ADLManager.h"
#pragma once
class FDryreLUIEssentialsPluginModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
private:
/** Handle to the test dll we will load */
void* LibraryHandle;
};
YourPluginName.cpp
// Copyright © 2024 - DryreL Design
#include "DryreLUIEssentials.h"
#define LOCTEXT_NAMESPACE "FDryreLUIEssentialsPluginModule"
void FDryreLUIEssentialsPluginModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
// Get the base directory of this plugin
// Get a reference to the plugin manager
FString myPluginDir = IPluginManager::Get().FindPlugin("DryreLUIEssentialsPlugin")->GetBaseDir();
FString myprojectDir = FPaths::ProjectDir();
// DEVELOPER NOTE: Make sure to LibraryHande DLLs are in the Binaries folder!
if(IsRHIDeviceNVIDIA())
{
// Add on the relative location of the third party dll and load it
FString LibraryPathNVML;
#if PLATFORM_WINDOWS
LibraryPathNVML = FPaths::Combine(*myprojectDir, TEXT("/Binaries/Win64/NVMLManagerLibrary.dll"));
#endif // PLATFORM_WINDOWS
LibraryHandle = !LibraryPathNVML.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPathNVML) : nullptr;
}
else if(IsRHIDeviceAMD())
{
FString LibraryPathADL;
#if PLATFORM_WINDOWS
LibraryPathADL = FPaths::Combine(*myprojectDir, TEXT("/Binaries/Win64/ADLManagerLibrary.dll"));
#endif // PLATFORM_WINDOWS
LibraryHandle = !LibraryPathADL.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPathADL) : nullptr;
}
if (LibraryHandle)
{
if(IsRHIDeviceNVIDIA())
{
nvGPUInitializeNVML();
}
else if(IsRHIDeviceAMD())
{
adlInitializeADL();
}
else if(IsRHIDeviceIntel())
{
// Initialize Intel
}
else if(IsRHIDeviceApple())
{
// Initialize Apple
}
else
{
// Initialize Other Brand
}
}
else
{
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("DryreLUIEssentialsError", "Failed to load Third Party library"));
}
}
void FDryreLUIEssentialsPluginModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
if(IsRHIDeviceNVIDIA())
{
nvGPUShutdownNVML();
}
else if(IsRHIDeviceAMD())
{
adlGPUShutdownADL();
}
else if(IsRHIDeviceIntel())
{
// Shutdown Intel
}
else if(IsRHIDeviceApple())
{
// Shutdown Apple
}
else
{
// Shutdown Other Brand
}
// Free the dll handle
FPlatformProcess::FreeDllHandle(LibraryHandle);
LibraryHandle = nullptr;
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FDryreLUIEssentialsPluginModule, DryreLUIEssentialsPlugin)
Hope this helps! Modify the references and paths according to your plugin.
Also you can remove RHI if statements, it was required for my plugin but probably you don’t need it.