Skip to content

Commit

Permalink
Add v4 boilerplate template for Unreal Engine 4.27
Browse files Browse the repository at this point in the history
  • Loading branch information
adamrehn committed Dec 2, 2021
1 parent 76ac727 commit 21dfb1d
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 2 deletions.
4 changes: 3 additions & 1 deletion conan_ue4cli/commands/boilerplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ def boilerplate(manager, argv):
templateVersion = 1
elif versionMajor == 4 and versionMinor >= 20 and versionMinor <= 23:
templateVersion = 2
else:
elif versionMajor == 4 and versionMinor >= 24 and versionMinor <= 26:
templateVersion = 3
else:
templateVersion = 4

# Determine the full path to the directory containing our templates
dataDir = join(dirname(dirname(abspath(__file__))), 'data')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
DO NOT EDIT THIS FILE! THIS FILE WAS GENERATED AUTOMATICALLY BY CONAN-UE4CLI VERSION ${VERSION}.
THIS BOILERPLATE CODE IS INTENDED FOR USE WITH UNREAL ENGINE VERSIONS 4.24 AND 4.25.
THIS BOILERPLATE CODE IS INTENDED FOR USE WITH UNREAL ENGINE VERSIONS 4.24, 4.25 AND 4.26.
*/
using System;
using System.IO;
Expand Down
211 changes: 211 additions & 0 deletions conan_ue4cli/data/boilerplate_templates/v4/Template.Build.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/*
DO NOT EDIT THIS FILE! THIS FILE WAS GENERATED AUTOMATICALLY BY CONAN-UE4CLI VERSION ${VERSION}.
THIS BOILERPLATE CODE IS INTENDED FOR USE WITH UNREAL ENGINE VERSION 4.27.
*/
using System;
using System.IO;
using UnrealBuildTool;
using System.Diagnostics;
using System.Collections.Generic;

//For Tools.DotNETCommon.JsonObject and Tools.DotNETCommon.FileReference
using Tools.DotNETCommon;

public class ${MODULE} : ModuleRules
{
//Returns the identifier string for the given target, which includes its platform, architecture (if specified), and debug CRT status
private string TargetIdentifier(ReadOnlyTargetRules target)
{
//Append the target's architecture to its platform name if an architecture was specified
string id = (target.Architecture != null && target.Architecture.Length > 0) ?
String.Format("{0}-{1}", target.Platform.ToString(), target.Architecture) :
target.Platform.ToString();

//Append a debug suffix for Windows debug targets that actually use the debug CRT
bool isDebug = (target.Configuration == UnrealTargetConfiguration.Debug || target.Configuration == UnrealTargetConfiguration.DebugGame);
if (isDebug && target.bDebugBuildsActuallyUseDebugCRT) {
id += "-Debug";
}

return id;
}

//Determines if a target's platform is a Windows target platform
private bool IsWindows(ReadOnlyTargetRules target) {
return target.IsInPlatformGroup(UnrealPlatformGroup.Windows);
}

//Returns the version string for the Unreal Engine being used to build this module
private string GetEngineVersion()
{
//Attempt to parse the version JSON file
string versionFile = Path.Combine(EngineDirectory, "Build", "Build.version");
JsonObject version = JsonObject.Read(new FileReference(versionFile));

//Return a version string including the major and minor version numbers, without the patch level
return String.Format("{0}.{1}", version.GetIntegerField("MajorVersion"), version.GetIntegerField("MinorVersion"));
}

//Processes the JSON data produced by Conan that describes our dependencies
private void ProcessDependencies(string depsJson, ReadOnlyTargetRules target, string stagingDir)
{
//We need to ensure libraries end with ".lib" under Windows
string libSuffix = ((this.IsWindows(target)) ? ".lib" : "");

//Attempt to parse the JSON file
JsonObject deps = JsonObject.Read(new FileReference(depsJson));

//Process the list of dependencies
foreach (JsonObject dep in deps.GetObjectArrayField("dependencies"))
{
//Add the header and library paths for the dependency package
PublicIncludePaths.AddRange(dep.GetStringArrayField("include_paths"));
PublicSystemLibraryPaths.AddRange(dep.GetStringArrayField("lib_paths"));

//Add the preprocessor definitions from the dependency package
PublicDefinitions.AddRange(dep.GetStringArrayField("defines"));

//Link against the libraries from the package
string[] libs = dep.GetStringArrayField("libs");
foreach (string lib in libs)
{
string libFull = lib + ((libSuffix.Length == 0 || lib.EndsWith(libSuffix)) ? "" : libSuffix);
PublicAdditionalLibraries.Add(libFull);
}

//Ensure any shared libraries are staged alongside the binaries for the plugin
List<string> searchDirs = new List<string>();
searchDirs.AddRange(dep.GetStringArrayField("bin_paths"));
searchDirs.AddRange(dep.GetStringArrayField("lib_paths"));
foreach (string dir in searchDirs)
{
List<string> binaries = new List<string>();
binaries.AddRange(Directory.GetFiles(dir, "*.dll"));
binaries.AddRange(Directory.GetFiles(dir, "*.dylib"));
binaries.AddRange(Directory.GetFiles(dir, "*.so"));
foreach (string binary in binaries) {
RuntimeDependencies.Add(Path.Combine("$(BinaryOutputDir)", Path.GetFileName(binary)), binary, StagedFileType.NonUFS);
}
}

//Copy any data files needed by the package into our staging directory
string[] dataDirs = dep.GetStringArrayField("res_paths");
foreach (string dir in dataDirs)
{
string[] files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
foreach(string file in files) {
RuntimeDependencies.Add(Path.Combine(stagingDir, Path.GetFileName(file)), file, StagedFileType.NonUFS);
}
}
}
}

//Determines if we have precomputed dependency data for the specified target and Engine version, and processes it if we do
private bool ProcessPrecomputedData(ReadOnlyTargetRules target, string engineVersion, string stagingDir)
{
//Resolve the paths to the files and directories that will exist if we have precomputed data for the target
string targetDir = Path.Combine(ModuleDirectory, "precomputed", engineVersion, this.TargetIdentifier(target));
string flagsFile = Path.Combine(targetDir, "flags.json");
string includeDir = Path.Combine(targetDir, "include");
string libDir = Path.Combine(targetDir, "lib");
string binDir = Path.Combine(targetDir, "bin");
string dataDir = Path.Combine(targetDir, "data");

//If any of the required files or directories do not exist then we do not have precomputed data
if (!File.Exists(flagsFile) || !Directory.Exists(includeDir) || !Directory.Exists(libDir) || !Directory.Exists(binDir) || !Directory.Exists(dataDir)) {
return false;
}

//Add the precomputed include directory to our search paths
PublicIncludePaths.Add(includeDir);

//Link against all static library files (and import libraries for DLLs under Windows) in the lib directory
string libExtension = ((this.IsWindows(target)) ? ".lib" : ".a");
string[] libs = Directory.GetFiles(libDir, "*" + libExtension);
foreach(string lib in libs) {
PublicAdditionalLibraries.Add(lib);
}

//Under non-Windows platforms, link against all shared library files in the lib directory
if (this.IsWindows(target) == false)
{
List<string> sharedLibs = new List<string>();
sharedLibs.AddRange(Directory.GetFiles(libDir, "*.dylib"));
sharedLibs.AddRange(Directory.GetFiles(libDir, "*.so"));
foreach(string lib in sharedLibs) {
PublicAdditionalLibraries.Add(lib);
}
}

//Ensure any shared libraries are staged alongside the binaries for the plugin
string[] searchDirs = new string[]{ binDir, libDir };
foreach (string dir in searchDirs)
{
List<string> binaries = new List<string>();
binaries.AddRange(Directory.GetFiles(dir, "*.dll"));
binaries.AddRange(Directory.GetFiles(dir, "*.dylib"));
binaries.AddRange(Directory.GetFiles(dir, "*.so"));
foreach (string binary in binaries) {
RuntimeDependencies.Add(Path.Combine("$(BinaryOutputDir)", Path.GetFileName(binary)), binary, StagedFileType.NonUFS);
}
}

//Attempt to parse the JSON file containing any additional flags, modules and system libraries
JsonObject flags = JsonObject.Read(new FileReference(flagsFile));

//Link against any Unreal Engine modules for bundled third-party libraries
PrivateDependencyModuleNames.AddRange(flags.GetStringArrayField("unreal_modules"));

//Add any preprocessor definitions specified by the JSON file
PublicDefinitions.AddRange(flags.GetStringArrayField("defines"));

//Link against any system libraries specified by the JSON file, ensuring we add the file extension if it is missing under Windows
string[] systemLibs = flags.GetStringArrayField("system_libs");
foreach (string lib in systemLibs)
{
string libFull = lib;
if (this.IsWindows(target) && !libFull.EndsWith(libExtension)) {
libFull += libExtension;
}

PublicSystemLibraries.Add(libFull);
}

//Copy any data files needed by the package into our staging directory
string[] files = Directory.GetFiles(dataDir, "*", SearchOption.AllDirectories);
foreach(string file in files) {
RuntimeDependencies.Add(Path.Combine(stagingDir, Path.GetFileName(file)), file, StagedFileType.NonUFS);
}

return true;
}

public ${MODULE}(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;

//Ensure our staging directory exists prior to copying any dependency data files into it
string stagingDir = Path.Combine("$(ProjectDir)", "Binaries", "Data", "${MODULE}");
if (!Directory.Exists(stagingDir)) {
Directory.CreateDirectory(stagingDir);
}

//Determine if we have precomputed dependency data for the target that is being built
string engineVersion = this.GetEngineVersion();
if (this.ProcessPrecomputedData(Target, engineVersion, stagingDir) == false)
{
//No precomputed data detected, install third-party dependencies using Conan
Process.Start(new ProcessStartInfo
{
FileName = "conan",
Arguments = "install . -g=json --profile=ue" + engineVersion + "-" + this.TargetIdentifier(Target),
WorkingDirectory = ModuleDirectory,
UseShellExecute = false
})
.WaitForExit();

//Link against our Conan-installed dependencies
this.ProcessDependencies(Path.Combine(ModuleDirectory, "conanbuildinfo.json"), Target, stagingDir);
}
}
}

0 comments on commit 21dfb1d

Please sign in to comment.