Skip to content

Instantly share code, notes, and snippets.

@galeone
Created February 16, 2022 08:30
Show Gist options
  • Save galeone/f8bdf0fb4fafc517a4f65537b2ae2634 to your computer and use it in GitHub Desktop.
Save galeone/f8bdf0fb4fafc517a4f65537b2ae2634 to your computer and use it in GitHub Desktop.
Enable code coverage support on Unreal Built Tool Linux Toolchain
--- a/Engine/Source/Programs/UnrealBuildTool/Configuration/ModuleRules.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Configuration/ModuleRules.cs
@@ -606,6 +606,10 @@ namespace UnrealBuildTool
{
get
{
+ if (bCodeCoverage) {
+ return CodeOptimization.Never;
+ }
+
if (OptimizeCodeOverride.HasValue)
return OptimizeCodeOverride.Value;
@@ -703,6 +707,11 @@ namespace UnrealBuildTool
/// </summary>
public bool bUseRTTI = false;
+ /// <summary>
+ /// Enable code coverage compilation/linking support.
+ /// </summary>
+ public bool bCodeCoverage = false;
+
/// <summary>
/// Direct the compiler to generate AVX instructions wherever SSE or AVX intrinsics are used, on the platforms that support it.
/// Note that by enabling this you are changing the minspec for the PC platform, and the resultant executable will crash on machines without AVX support.
diff --git a/Engine/Source/Programs/UnrealBuildTool/Configuration/TargetRules.cs b/Engine/Source/Programs/UnrealBuildTool/Configuration/TargetRules.cs
index b3dac4efa6c..e0b6e130e9c 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Configuration/TargetRules.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Configuration/TargetRules.cs
@@ -1083,6 +1083,13 @@ namespace UnrealBuildTool
[XmlConfigFile(Category = "BuildConfiguration")]
public bool bPGOOptimize = false;
+ /// <summary>
+ /// Whether the target requires code coverage compilation and linking.
+ /// </summary>
+ [CommandLine("-CodeCoverage", Value = "true")]
+ [XmlConfigFile(Category = "BuildConfiguration")]
+ public bool bCodeCoverage;
+
/// <summary>
/// Whether to support edit and continue. Only works on Microsoft compilers.
/// </summary>
@@ -2493,6 +2500,11 @@ namespace UnrealBuildTool
get { return Inner.bPGOOptimize; }
}
+ public bool bCodeCoverage
+ {
+ get {return Inner.bCodeCoverage; }
+ }
+
public bool bSupportEditAndContinue
{
get { return Inner.bSupportEditAndContinue; }
diff --git a/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildBinary.cs b/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildBinary.cs
index 4809ab00135..ccdaa77f718 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildBinary.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildBinary.cs
@@ -184,6 +184,7 @@ namespace UnrealBuildTool
// Setup linking environment.
LinkEnvironment BinaryLinkEnvironment = SetupBinaryLinkEnvironment(Target, ToolChain, LinkEnvironment, CompileEnvironment, SpecificFilesToCompile, WorkingSet, ExeDir, Graph);
+ BinaryLinkEnvironment.bCodeCoverage = CompileEnvironment.bCodeCoverage;
// If we're generating projects, we only need include paths and definitions, there is no need to run the linking logic.
if (ProjectFileGenerator.bGenerateProjectFiles)
@@ -231,6 +232,7 @@ namespace UnrealBuildTool
ConsoleAppLinkEvironment.bIsBuildingConsoleApplication = true;
ConsoleAppLinkEvironment.WindowsEntryPointOverride = "WinMainCRTStartup"; // For WinMain() instead of "main()" for Launch module
ConsoleAppLinkEvironment.OutputFilePaths = ConsoleAppLinkEvironment.OutputFilePaths.Select(Path => GetAdditionalConsoleAppPath(Path)).ToList();
+ ConsoleAppLinkEvironment.bCodeCoverage = CompileEnvironment.bCodeCoverage;
// Link the console app executable
FileItem[] ConsoleAppOutputFiles = ToolChain.LinkAllFiles(ConsoleAppLinkEvironment, false, Graph);
@@ -700,6 +702,7 @@ namespace UnrealBuildTool
private LinkEnvironment SetupBinaryLinkEnvironment(ReadOnlyTargetRules Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CppCompileEnvironment CompileEnvironment, List<FileReference> SpecificFilesToCompile, ISourceFileWorkingSet WorkingSet, DirectoryReference ExeDir, IActionGraphBuilder Graph)
{
LinkEnvironment BinaryLinkEnvironment = new LinkEnvironment(LinkEnvironment);
+ BinaryLinkEnvironment.bCodeCoverage = CompileEnvironment.bCodeCoverage;
HashSet<UEBuildModule> LinkEnvironmentVisitedModules = new HashSet<UEBuildModule>();
List<UEBuildBinary> BinaryDependencies = new List<UEBuildBinary>();
diff --git a/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildModuleCPP.cs b/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildModuleCPP.cs
index 481bb6db1f2..a1caeec2253 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildModuleCPP.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildModuleCPP.cs
@@ -624,6 +624,7 @@ namespace UnrealBuildTool
CompileEnvironment.PrecompiledHeaderAction = PrecompiledHeaderAction.Create;
CompileEnvironment.PrecompiledHeaderIncludeFilename = WrapperFile.Location;
CompileEnvironment.bOptimizeCode = ModuleCompileEnvironment.bOptimizeCode;
+ CompileEnvironment.bCodeCoverage = ModuleCompileEnvironment.bCodeCoverage;
// Create the action to compile the PCH file.
CPPOutput Output;
@@ -822,6 +823,7 @@ namespace UnrealBuildTool
private void CopySettingsForSharedPCH(CppCompileEnvironment ModuleCompileEnvironment, CppCompileEnvironment CompileEnvironment)
{
CompileEnvironment.bOptimizeCode = ModuleCompileEnvironment.bOptimizeCode;
+ CompileEnvironment.bCodeCoverage = ModuleCompileEnvironment.bCodeCoverage;
CompileEnvironment.bUseRTTI = ModuleCompileEnvironment.bUseRTTI;
CompileEnvironment.bEnableExceptions = ModuleCompileEnvironment.bEnableExceptions;
CompileEnvironment.ShadowVariableWarningLevel = ModuleCompileEnvironment.ShadowVariableWarningLevel;
@@ -1238,9 +1240,13 @@ namespace UnrealBuildTool
/// <param name="Setting">The optimization setting from the rules file</param>
/// <param name="Configuration">The active target configuration</param>
/// <param name="bIsEngineModule">Whether the current module is an engine module</param>
+ /// <param name="bCodeCoverage">Whether the current module should be compiled with code coverage support</param>
/// <returns>True if optimization should be enabled</returns>
- public static bool ShouldEnableOptimization(ModuleRules.CodeOptimization Setting, UnrealTargetConfiguration Configuration, bool bIsEngineModule)
+ public static bool ShouldEnableOptimization(ModuleRules.CodeOptimization Setting, UnrealTargetConfiguration Configuration, bool bIsEngineModule, bool bCodeCoverage)
{
+ if (bCodeCoverage) {
+ return false;
+ }
switch(Setting)
{
case ModuleRules.CodeOptimization.Never:
@@ -1275,7 +1281,8 @@ namespace UnrealBuildTool
// Override compile environment
Result.bUseUnity = Rules.bUseUnity;
- Result.bOptimizeCode = ShouldEnableOptimization(Rules.OptimizeCode, Target.Configuration, Rules.bTreatAsEngineModule);
+ Result.bCodeCoverage = Target.bCodeCoverage; // From Target!
+ Result.bOptimizeCode = ShouldEnableOptimization(Rules.OptimizeCode, Target.Configuration, Rules.bTreatAsEngineModule, Result.bCodeCoverage);
Result.bUseRTTI |= Rules.bUseRTTI;
Result.bUseAVX = Rules.bUseAVX;
Result.bEnableBufferSecurityChecks = Rules.bEnableBufferSecurityChecks;
@@ -1348,8 +1355,9 @@ namespace UnrealBuildTool
{
CppCompileEnvironment CompileEnvironment = new CppCompileEnvironment(BaseCompileEnvironment);
- // Use the default optimization setting for
- CompileEnvironment.bOptimizeCode = ShouldEnableOptimization(ModuleRules.CodeOptimization.Default, Target.Configuration, Rules.bTreatAsEngineModule);
+ // Use the default optimization setting for
+ CompileEnvironment.bOptimizeCode = ShouldEnableOptimization(ModuleRules.CodeOptimization.Default, Target.Configuration, Rules.bTreatAsEngineModule, Rules.bCodeCoverage);
+ CompileEnvironment.bCodeCoverage = Rules.bCodeCoverage;
// Override compile environment
CompileEnvironment.bIsBuildingDLL = !Target.ShouldCompileMonolithic();
diff --git a/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildTarget.cs b/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildTarget.cs
index 97a937d41af..2b401a4f326 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildTarget.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Configuration/UEBuildTarget.cs
@@ -3439,6 +3439,7 @@ namespace UnrealBuildTool
GlobalCompileEnvironment.bHideSymbolsByDefault = !Rules.bPublicSymbolsByDefault;
GlobalCompileEnvironment.CppStandard = Rules.CppStandard;
GlobalCompileEnvironment.AdditionalArguments = Rules.AdditionalCompilerArguments;
+ GlobalCompileEnvironment.bCodeCoverage = Rules.bCodeCoverage;
GlobalLinkEnvironment.bIsBuildingConsoleApplication = Rules.bIsBuildingConsoleApplication;
GlobalLinkEnvironment.bOptimizeForSize = Rules.bCompileForSize;
@@ -3456,6 +3457,7 @@ namespace UnrealBuildTool
GlobalLinkEnvironment.bUseFastPDBLinking = Rules.bUseFastPDBLinking ?? false;
GlobalLinkEnvironment.bPrintTimingInfo = Rules.bPrintToolChainTimingInfo;
GlobalLinkEnvironment.AdditionalArguments = Rules.AdditionalLinkerArguments;
+ GlobalLinkEnvironment.bCodeCoverage = Rules.bCodeCoverage;
if (Rules.bPGOOptimize && Rules.bPGOProfile)
{
diff --git a/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/LinuxToolChain.cs b/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/LinuxToolChain.cs
index fb38ffe34fe..ba6b28f48d0 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/LinuxToolChain.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/LinuxToolChain.cs
@@ -170,6 +170,7 @@ namespace UnrealBuildTool
bIsCrossCompiling = true;
bHasValidCompiler = DetermineCompilerVersion();
+ CompilerRTPath = Path.Combine(Path.Combine(BaseLinuxPath, String.Format("lib/clang/{0}/lib/linux/", CompilerVersionString)));
}
if (!bHasValidCompiler)
@@ -767,8 +768,13 @@ namespace UnrealBuildTool
}
}
- // optimization level
- if (!CompileEnvironment.bOptimizeCode)
+ if (CompileEnvironment.bCodeCoverage)
+ {
+ Result += " -O0";
+ Result += " -fprofile-arcs -ftest-coverage"; // gcov
+ //Result += " -fprofile-instr-generate -fcoverage-mapping"; // llvm-cov
+ }
+ else if (!CompileEnvironment.bOptimizeCode) // optimization level
{
Result += " -O0";
}
@@ -1019,6 +1025,15 @@ namespace UnrealBuildTool
Result += " -Wl,--gdb-index";
}
+ if (LinkEnvironment.bCodeCoverage)
+ {
+ // Unreal Separates the linking phase and the compilation phase.
+ // We pass to clang the flag `--coverage` during the compile time
+ // And we link the correct compiler-rt library (shipped by UE, and part of the LLVM toolchain)
+ // to every binary produced.
+ Result += string.Format(" -L{0} -l{1}", CompilerRTPath, "clang_rt.profile-x86_64"); // gcov
+ // Result += " -fprofile-instr-generate"; // llvm-cov
+ }
// RPATH for third party libs
Result += " -Wl,-rpath=${ORIGIN}";
Result += " -Wl,-rpath-link=${ORIGIN}";
@@ -1142,6 +1157,7 @@ namespace UnrealBuildTool
protected string BaseLinuxPath;
protected string ClangPath;
protected string GCCPath;
+ protected string CompilerRTPath;
protected string ArPath;
protected string LlvmArPath;
protected string RanlibPath;
@@ -1270,6 +1286,11 @@ namespace UnrealBuildTool
Log.TraceInformation(" Prefix for PGO data files='{0}'", CompileEnvironment.PGOFilenamePrefix);
}
+ if (CompileEnvironment.bCodeCoverage)
+ {
+ Log.TraceInformation("Using --coverage build flag");
+ }
+
if (CompileEnvironment.bPGOProfile)
{
Log.TraceInformation("Using PGI (profile guided instrumentation).");
diff --git a/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/UEBuildLinux.cs b/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/UEBuildLinux.cs
index d8b35ac02ab..de3fc2d944e 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/UEBuildLinux.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Platform/Linux/UEBuildLinux.cs
@@ -526,6 +526,8 @@ namespace UnrealBuildTool
LinkEnvironment.PGOFilenamePrefix = CompileEnvironment.PGOFilenamePrefix;
}
+ LinkEnvironment.bCodeCoverage = CompileEnvironment.bCodeCoverage;
+
// For consistency with other platforms, also enable LTO whenever doing profile-guided optimizations.
// Obviously both PGI (instrumented) and PGO (optimized) binaries need to have that
if (CompileEnvironment.bPGOProfile || CompileEnvironment.bPGOOptimize)
diff --git a/Engine/Source/Programs/UnrealBuildTool/System/CppCompileEnvironment.cs b/Engine/Source/Programs/UnrealBuildTool/System/CppCompileEnvironment.cs
index 189954552a3..f56830c64d2 100644
--- a/Engine/Source/Programs/UnrealBuildTool/System/CppCompileEnvironment.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/System/CppCompileEnvironment.cs
@@ -221,6 +221,11 @@ namespace UnrealBuildTool
/// </summary>
public bool bOptimizeCode = false;
+ /// <summary>
+ /// True if the compilation should produce tracing output for code coverage.
+ /// </summary>
+ public bool bCodeCoverage = false;
+
/// <summary>
/// Whether to optimize for minimal code size
/// </summary>
@@ -428,6 +433,7 @@ namespace UnrealBuildTool
bUndefinedIdentifierWarningsAsErrors = Other.bUndefinedIdentifierWarningsAsErrors;
bEnableUndefinedIdentifierWarnings = Other.bEnableUndefinedIdentifierWarnings;
bOptimizeCode = Other.bOptimizeCode;
+ bCodeCoverage = Other.bCodeCoverage;
bOptimizeForSize = Other.bOptimizeForSize;
bCreateDebugInfo = Other.bCreateDebugInfo;
bIsBuildingLibrary = Other.bIsBuildingLibrary;
diff --git a/Engine/Source/Programs/UnrealBuildTool/System/LinkEnvironment.cs b/Engine/Source/Programs/UnrealBuildTool/System/LinkEnvironment.cs
index 610e4b3db4d..9a94a6b4388 100644
--- a/Engine/Source/Programs/UnrealBuildTool/System/LinkEnvironment.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/System/LinkEnvironment.cs
@@ -196,6 +196,11 @@ namespace UnrealBuildTool
/// </summary>
public bool bOptimizeForSize = false;
+ /// <summary>
+ /// Wether to link code coverage / tracing libs
+ /// </summary>
+ public bool bCodeCoverage = false;
+
/// <summary>
/// Whether to omit frame pointers or not. Disabling is useful for e.g. memory profiling on the PC
/// </summary>
@@ -349,6 +354,7 @@ namespace UnrealBuildTool
DefaultStackSize = Other.DefaultStackSize;
DefaultStackSizeCommit = Other.DefaultStackSizeCommit;
bOptimizeForSize = Other.bOptimizeForSize;
+ bCodeCoverage = Other.bCodeCoverage;
bOmitFramePointers = Other.bOmitFramePointers;
bSupportEditAndContinue = Other.bSupportEditAndContinue;
bUseIncrementalLinking = Other.bUseIncrementalLinking;
@CanisHelix
Copy link

This is really awesome, and appreciate the efforts put into this.

I have errors when compiling a project with a UE5 Source with the above changes. The engine itself builds fine with the changes but not the project. I believe Clang has not changed between UE4.27 and UE5.0, do you have any idea what the errors could be? This only occurs when using the -CodeCoverage flag.

[1/1981] Link (lld) libUnrealEditor-BuildSettings.so
ld.lld: error: undefined symbol: llvm_gcda_start_file
>>> referenced by BuildSettings.cpp:39 (Runtime/BuildSettings/Private/BuildSettings.cpp:39)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/BuildSettings/BuildSettings.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_emit_function
>>> referenced by BuildSettings.cpp:39 (Runtime/BuildSettings/Private/BuildSettings.cpp:39)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/BuildSettings/BuildSettings.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_emit_arcs
>>> referenced by BuildSettings.cpp:39 (Runtime/BuildSettings/Private/BuildSettings.cpp:39)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/BuildSettings/BuildSettings.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_summary_info
>>> referenced by BuildSettings.cpp:39 (Runtime/BuildSettings/Private/BuildSettings.cpp:39)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/BuildSettings/BuildSettings.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_end_file
>>> referenced by BuildSettings.cpp:39 (Runtime/BuildSettings/Private/BuildSettings.cpp:39)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/BuildSettings/BuildSettings.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcov_init
>>> referenced by BuildSettings.cpp:39 (Runtime/BuildSettings/Private/BuildSettings.cpp:39)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/BuildSettings/BuildSettings.cpp.o:(__llvm_gcov_init)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
[2/1981] Link (lld) libUnrealEditor-TraceLog.so
ld.lld: error: undefined symbol: llvm_gcda_start_file
>>> referenced by Module.TraceLog.cpp:0 (/home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp:0)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_emit_function
>>> referenced by Module.TraceLog.cpp:0 (/home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp:0)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_emit_arcs
>>> referenced by Module.TraceLog.cpp:0 (/home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp:0)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_summary_info
>>> referenced by Module.TraceLog.cpp:0 (/home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp:0)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcda_end_file
>>> referenced by Module.TraceLog.cpp:0 (/home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp:0)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp.o:(__llvm_gcov_writeout)

ld.lld: error: undefined symbol: llvm_gcov_init
>>> referenced by Module.TraceLog.cpp:0 (/home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp:0)
>>>               /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/TraceLog/Module.TraceLog.cpp.o:(__llvm_gcov_init)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

@galeone
Copy link
Author

galeone commented Apr 9, 2022

That's strange! The symbols missing are in the library we link here: https://gist.github.com/galeone/f8bdf0fb4fafc517a4f65537b2ae2634#file-engine-coverage-patch-L199

Maybe you can try to pass the -coverage flag, instead of directly passing the library as I did, and thus let the compiler use the right library. Perhaps something changed in the toolchain, I haven't checked ue5 yet

@CanisHelix
Copy link

It's entirely possible the toolchain changed, I just re-compiled 4.27 to check and that worked fine. Re-compiling 5.0 again, and I'll try -coverage and let you know how it works.

So Result += string.Format(" -L{0} -l{1} -coverage", CompilerRTPath, "clang_rt.profile-x86_64"); // gcov might be a better try?

@galeone
Copy link
Author

galeone commented Apr 9, 2022

Nope, I mean only passing the --coverage flag without explicitly link the library. Thus

Result += " --coverage"; // gcov

@CanisHelix
Copy link

That works, albeit a strange issue where I need to run it twice.

[136/2101] Compile Module.Chaos.1_of_7.cpp
[136/2101]Compile Module.Chaos.1_of_7.cpp - Error but no output
[136/2101]Compile Module.Chaos.1_of_7.cpp - 137 /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Source /home/administrator/Applications/Epic/UE_5.0_Source/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v19_clang-11.0.1-centos7/x86_64-unknown-linux-gnu/bin/clang++  @"/home/administrator/Applications/Epic/UE_5.0_Source/Engine/Intermediate/Build/Linux/B4D820EA/UnrealEditor/Development/Chaos/Module.Chaos.1_of_7.cpp.o.rsp"

Appears the first time, but compiles okay on the second run.

@galeone
Copy link
Author

galeone commented Apr 11, 2022

Cool! Anyway, you shouldn't compile the whole engine with the -CodeCoverage flag enabled, but it's better to have an installed version of the engine (with the UBT modified) and compile the project/module you want to measure the coverage only - otherwise, compiling the whole engine with optimization disabled will slow down the development a lot

@CanisHelix
Copy link

I've only been passing in -CodeCoverage when compiling the project/module and not the engine. UE5 is doing half the engine on the first project compile using the engine build, 2nd/3rd projects are actually fine too, just seems like a first project only issue. Next fun part is trying to see if I can get this into ue4-docker to automate more. The flag works with ue4cli no problem.

Thanks for all the help so far. I'll write it up if I get the docker images working too.

@galeone
Copy link
Author

galeone commented Apr 14, 2022

awesome, keep me posted!

@jeevcat
Copy link

jeevcat commented Jul 20, 2022

Awesome work @galeone! Have you considered submitting this as a PR?

@galeone
Copy link
Author

galeone commented Jul 20, 2022 via email

@CanisHelix
Copy link

@galeone Really awesome to see this implemented in 5.3.0 as part of CL 25794147 and documented here: https://docs.unrealengine.com/5.3/en-US/static-code-analysis-in-unreal-engine/

@galeone
Copy link
Author

galeone commented Oct 9, 2023

@CanisHelix but these are the sanitizers, it's not the code coverage support

@tomdell13
Copy link

@galeone I will be testing shortly, but trying to apply the patch to 5.3.1, it looks like your changes are finally included in the Unreal release!

@galeone
Copy link
Author

galeone commented May 16, 2024

Verified. The merged it in 5.4.1 for sure (just tested). They modified this a little bit (for no reason). So instead of ForceQuit, you must use Quit. And instead of Quit, you must use SoftQuit

All the rest is the same

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment