Hi guys,
I’m trying for weeks to integrate a third-party library (GDAL) into a plugin.
This library depends from many other libraries (like PROJ for exemple).
Her is my code structure :
Binaries/ThirdParty/Win64 contains all dlls needed (gdal and all its dependencies)
Source/ThirdParty/Gdal/Include/ contains all header files of gdal and all its dependencies
Source/ThirdParty/Gdal/Lib/ contains all libs needed (gdal and all its dependencies)
TerrainLoader.Build.cs
public class TerrainLoader : ModuleRules
{
public TerrainLoader(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"CoreUObject",
"Engine",
"Projects",
"Gdal",
"UElibPNG",
"zlib",
"OpenSSL"
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"MeshConversion",
"MeshDescription",
"StaticMeshDescription"
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
“UElibPNG”, zlib" and “OpenSSL” are 3 dependencies of GDAL allready used by the engine, so instead of reimporting them, i had these modules as dependencies.
public class Gdal : ModuleRules
{
public Gdal(ReadOnlyTargetRules Target) : base(Target)
{
bEnableUndefinedIdentifierWarnings = false;
Type = ModuleType.External;
// Header files (platform independent)
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Include"));
PublicSystemIncludePaths.Add(Path.Combine(ModuleDirectory, "Include"));
// Libs
List<string> publicAdditionalLibsNames = new List<string>();
publicAdditionalLibsNames.Add("charset.lib");
publicAdditionalLibsNames.Add("freexl.lib");
publicAdditionalLibsNames.Add("gdal.lib");
publicAdditionalLibsNames.Add("geos.lib");
publicAdditionalLibsNames.Add("geos_c.lib");
publicAdditionalLibsNames.Add("geotiff_i.lib");
publicAdditionalLibsNames.Add("gif.lib");
publicAdditionalLibsNames.Add("hdf5.lib");
publicAdditionalLibsNames.Add("hdf5_cpp.lib");
publicAdditionalLibsNames.Add("hdf5_hl.lib");
publicAdditionalLibsNames.Add("hdf5_hl_cpp.lib");
publicAdditionalLibsNames.Add("iconv.lib");
publicAdditionalLibsNames.Add("jpeg.lib");
publicAdditionalLibsNames.Add("json-c.lib");
publicAdditionalLibsNames.Add("json-c-static.lib");
// publicAdditionalLibsNames.Add("libcrypto.lib");
publicAdditionalLibsNames.Add("libcurl.lib");
publicAdditionalLibsNames.Add("libecpg.lib");
publicAdditionalLibsNames.Add("libecpg_compat.lib");
publicAdditionalLibsNames.Add("libexpat.lib");
publicAdditionalLibsNames.Add("libpgcommon.lib");
publicAdditionalLibsNames.Add("libpgport.lib");
publicAdditionalLibsNames.Add("libpgtypes.lib");
// publicAdditionalLibsNames.Add("libpng16.lib");
publicAdditionalLibsNames.Add("libpq.lib");
// publicAdditionalLibsNames.Add("libssl.lib");
publicAdditionalLibsNames.Add("libxml2.lib");
publicAdditionalLibsNames.Add("lz4.lib");
publicAdditionalLibsNames.Add("lzma.lib");
publicAdditionalLibsNames.Add("netcdf.lib");
publicAdditionalLibsNames.Add("openjp2.lib");
publicAdditionalLibsNames.Add("pcre2-8.lib");
publicAdditionalLibsNames.Add("pcre2-16.lib");
publicAdditionalLibsNames.Add("pcre2-32.lib");
publicAdditionalLibsNames.Add("pcre2-posix.lib");
publicAdditionalLibsNames.Add("proj.lib");
publicAdditionalLibsNames.Add("qhull_r.lib");
publicAdditionalLibsNames.Add("qhullcpp.lib");
publicAdditionalLibsNames.Add("spatialite.lib");
publicAdditionalLibsNames.Add("sqlite3.lib");
publicAdditionalLibsNames.Add("szip.lib");
publicAdditionalLibsNames.Add("tiff.lib");
publicAdditionalLibsNames.Add("turbojpeg.lib");
publicAdditionalLibsNames.Add("webp.lib");
publicAdditionalLibsNames.Add("webpdecoder.lib");
publicAdditionalLibsNames.Add("webpmux.lib");
// publicAdditionalLibsNames.Add("zlib.lib");
publicAdditionalLibsNames.Add("zstd.lib");
string LibFolder = Path.Combine(ModuleDirectory, "Lib", "Win64");
foreach (string publicAdditionalLibsName in publicAdditionalLibsNames)
{
string libPath = Path.Combine(LibFolder, publicAdditionalLibsName);
if (!File.Exists(libPath))
{
string err = $"Library '{libPath}' not found.";
System.Console.WriteLine(err);
throw new BuildException(err);
}
PublicAdditionalLibraries.Add(libPath);
}
// Dlls
List<string> runtimeModuleNames = new List<string>();
runtimeModuleNames.Add("gdal.dll");
runtimeModuleNames.Add("charset-1.dll");
runtimeModuleNames.Add("freexl-1.dll");
runtimeModuleNames.Add("geos.dll");
runtimeModuleNames.Add("geos_c.dll");
runtimeModuleNames.Add("geotiff.dll");
runtimeModuleNames.Add("gif.dll");
runtimeModuleNames.Add("hdf5.dll");
runtimeModuleNames.Add("hdf5_hl.dll");
runtimeModuleNames.Add("hdf5_cpp.dll");
runtimeModuleNames.Add("hdf5_hl_cpp.dll");
runtimeModuleNames.Add("iconv-2.dll");
runtimeModuleNames.Add("jpeg62.dll");
runtimeModuleNames.Add("turbojpeg.dll");
runtimeModuleNames.Add("json-c.dll");
// runtimeModuleNames.Add("libcrypto-3-x64.dll");
runtimeModuleNames.Add("libcurl.dll");
runtimeModuleNames.Add("libexpat.dll");
runtimeModuleNames.Add("liblzma.dll");
// runtimeModuleNames.Add("libpng16.dll");
// runtimeModuleNames.Add("libssl-3-x64.dll");
// runtimeModuleNames.Add("legacy.dll");
runtimeModuleNames.Add("libxml2.dll");
runtimeModuleNames.Add("libecpg.dll");
runtimeModuleNames.Add("libecpg_compat.dll");
runtimeModuleNames.Add("libpgtypes.dll");
runtimeModuleNames.Add("libpq.dll");
runtimeModuleNames.Add("lz4.dll");
runtimeModuleNames.Add("netcdf.dll");
runtimeModuleNames.Add("openjp2.dll");
runtimeModuleNames.Add("pcre2-8.dll");
runtimeModuleNames.Add("pcre2-16.dll");
runtimeModuleNames.Add("pcre2-32.dll");
runtimeModuleNames.Add("pcre2-posix.dll");
runtimeModuleNames.Add("proj.dll");
runtimeModuleNames.Add("qhull_r.dll");
runtimeModuleNames.Add("spatialite.dll");
runtimeModuleNames.Add("sqlite3.dll");
runtimeModuleNames.Add("tiff.dll");
runtimeModuleNames.Add("webp.dll");
runtimeModuleNames.Add("webpmux.dll");
runtimeModuleNames.Add("webpdecoder.dll");
runtimeModuleNames.Add("webpdemux.dll");
// runtimeModuleNames.Add("zlib1.dll");
runtimeModuleNames.Add("zstd.dll");
runtimeModuleNames.Add("szip.dll");
string binFolder = Path.Combine(PluginDirectory, "Binaries", "ThirdParty", "Win64");
foreach (string runtimeModuleName in runtimeModuleNames)
{
string modulePath = Path.Combine(binFolder, runtimeModuleName);
if (!File.Exists(modulePath))
{
string err = $"Module '{modulePath}' not found.";
System.Console.WriteLine(err);
throw new BuildException(err);
}
RuntimeDependencies.Add(Path.Combine(binFolder, runtimeModuleName));
}
// Delay load GDAL dll
PublicDelayLoadDLLs.Add("gdal.dll");
// Stage GDAL data files
RuntimeDependencies.Add(Path.Combine(binFolder, "gdal/*"), StagedFileType.SystemNonUFS);
// Stage Proj data files
RuntimeDependencies.Add(Path.Combine(binFolder, "proj/*"), StagedFileType.SystemNonUFS);
}
}
Commented lines are the modules already existing in the engine (as said above).
Everythings works find in the editor but when i compile and launch the app, I got a fatal error telling me that the dll that are not delay loaded (all dlls except gdal.dll) are not found.
I assume that its expected as windows doesn’t know these dlls. So do i need to DelayLoad all dlls but then i need to use GetDllHandle on all dlls before GetDllHandle on “gdal.dll” ?
Any ideas or examples to make this work ?
Corentin