Specify dll location using plugin in cooked project?

I have made a plugin to interact with some exotic hardware that we use internally. This plugin depends on a third party DLL file. Lets call this file my_exotic_hardware.dll. I have successfully made the plugin work in both the editor and in runtime. My only problem right now is when I package this project the plugin DLL end up in the wrong folder.

Right now the DLL file end up in the folder:

Engine\Plugins\Runtime\MyExoticHardwarePlugin\Source\ThirdParty\ExoticHardware\64\lib\my_exotic_hardware.dll

So I every developer is forced to manually move the file from this folder to the same directory as the game executable, i.e. the root of the above path.

How do I adapt my build script so that the DLL file gets copied into the correct library during packaging? I would like to avoid the manual copy.

This is a few months old, but since nobody has answered you, there are 2 steps:

  1. Copy the .dll file into the Binaries folder
  2. Adding the copied DLL to the runtime dependencies.

Everything below goes into your .build.cs file.

First, a couple helper functions to copy the DLL:

public string GetUProjectPath()
{
	return Path.Combine(ModuleDirectory, "../../../..");
}

private string CopyToProjectBinaries(string Filepath, ReadOnlyTargetRules Target)
{
	string BinariesDir = Path.Combine(GetUProjectPath(), "Binaries", Target.Platform.ToString());
	string Filename = Path.GetFileName(Filepath);

	//convert relative path 
	string FullBinariesDir = Path.GetFullPath(BinariesDir);

	if (!Directory.Exists(FullBinariesDir))
	{
		Directory.CreateDirectory(FullBinariesDir);
	}

	string FullExistingPath = Path.Combine(FullBinariesDir, Filename);
	bool ValidFile = false;

	//File exists, check if they're the same
	if (File.Exists(FullExistingPath))
	{
		ValidFile = true;
	}

	//No valid existing file found, copy new dll
	if (!ValidFile)
	{
		File.Copy(Filepath, Path.Combine(FullBinariesDir, Filename), true);
	}
	return FullExistingPath;
}

Next, make the DLL a dependency so it gets copied automatically:

string pluginDLLPath = PATH_TO_YOUR_DLL_FILE;
string binariesPath = CopyToProjectBinaries(pluginDLLPath, Target);
System.Console.WriteLine("Using Python DLL: " + binariesPath);
RuntimeDependencies.Add(binariesPath);

This is the only solution I’ve found thus far that properly copies DLL files for third party plugins to the packaged project’s Binaries folder. Thanks!

Thanks for posting this, it really helped me out.

This is super old, I know, but there’s a much, much easier way, so I am going to leave this answer for anyone else looking for an answer in the future.


RuntimeDepenencies.Add actually has a 2 argument overload: (read more here)

  1. Target destination for the DLL (in this case, the Binaries folder)
  2. Source location for the DLL (which is the argument you would normally pass into RuntimeDependencies.Add)

Additionally, UBT provides very useful string variables that point to specific directories (read more here). In this case, what you want are "$(BinaryOutputDir)" and "$(ModuleDir)". "$(PluginDir)" can also be used instead of "$(ModuleDir)", and it points to the directory that the .uplugin is in, instead of where the .build.cs is (in my case, they’re both in the same directory).

Example:

string Destination = Path.Combine("$(BinaryOutputDir)", "EOSSDK-Win64-Shipping.dll");
string Source = Path.Combine("$(ModuleDir)", "Bin", "EOSSDK-Win64-Shipping.dll");
RuntimeDependencies.Add(Destination, Source);




Side Note:

"$(ModuleDir)" and the other string variables only work for RuntimeDependencies.Add, so don’t try using it for PublicIncludePaths.Add or any other .build.cs functions. For those, the ModuleDirectory variable is all you have as far as I know.

Well, in the last part you say:

Next, make the DLL a dependency so it gets copied automatically:

 string pluginDLLPath = PATH_TO_YOUR_DLL_FILE;
 string binariesPath = CopyToProjectBinaries(pluginDLLPath, Target);
 System.Console.WriteLine("Using Python DLL: " + binariesPath);
 RuntimeDependencies.Add(binariesPath);

But the DLLs are being copied by your function CopyToProjectBinaries, not automatically by adding it with RuntimeDependency.Add() at line 4.

Do you know why do you need that last line yet?