Can't build plugin in UE 4.12

Hello.

Trying to build my project in UE 4.12, but I have got error:

Running i:/UnrealEngine/Engine/Binaries/DotNET/UnrealBuildTool.exe MyGame Development Win64 -project="i:/MyGame/MyGame.uproject" -editorrecompile -progress -noubtmakefiles -NoHotReloadFromIDE
Messages while compiling i:\MyGame\Intermediate\Build\BuildRules\MyGameModuleRules.dll:
i:\MyGame\Plugins\SQLite3UE4Plugin\Source\SQLite3UE4Plugin\SQLite3UE4Plugin.Build.cs(8,66) : error CS0117: "UnrealBuildTool.RulesCompiler" ?? ᮤ?ন? ??।?????? ??? "GetModuleFilename"
ERROR: UnrealBuildTool encountered an error while compiling source files

Content of the SQLite3UE4Plugin.Build.cs file:

using UnrealBuildTool;
using System.IO;

public class SQLite3UE4Plugin : ModuleRules
{
    public SQLite3UE4Plugin(TargetInfo Target)
    {
        string ModulePath = Path.GetDirectoryName( RulesCompiler.GetModuleFilename( this.GetType().Name ) );
        string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "x64" : "x86";
        string ThirdPartyPath = Path.GetFullPath( Path.Combine( ModulePath, "../../ThirdParty/" ) );
        string LibrariesPath = Path.Combine(ThirdPartyPath, "SQLite3", "Lib");
        string IncludesPath = Path.Combine(ThirdPartyPath, "SQLite3", "Include");
        string LibraryName = Path.Combine(LibrariesPath, "SQLite3." + PlatformString + ".lib");

        PrivateIncludePaths.AddRange(new string[] { "SQLite3UE4Plugin/Private" });
        PublicIncludePaths.AddRange(new string[] { "SQLite3UE4Plugin/Public" });
        PublicAdditionalLibraries.Add(LibraryName);
        PublicIncludePaths.Add(IncludesPath);

        PublicDependencyModuleNames.AddRange(new string[] { "Engine", "Core", "CoreUObject" });
    }
}

Is it some changes in build system in 4.12, or this is a bug? In docs A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums RulesCompiler.GetModuleFilename still present…

I have a similar problem in 4.11 Preview 8

Severity Code Description Project File Line Suppression State
Warning CS0612 ‘UnrealBuildTool.RulesCompiler.GetModuleFilename(string)’ is obsolete

Build system code reworked in multiple commits. That changes starts from commit

Code refactoring starting from commit 
SHA-1: fc35305c51f256e3463f7f2a1f576f4347854eb4

* changes to allow two projects to have the same plugin name
UEB-258
#codereview ben.marsh

[CL 2611443 by Peter Sauerbrei in Main branch]

Solution is instead of

string ModulePath = Path.GetDirectoryName( RulesAssembly.GetModuleFilename( this.GetType().Name ) )

use

       RulesAssembly r;
		FileReference CheckProjectFile;
		UProjectInfo.TryGetProjectForTarget("MyGame", out CheckProjectFile);
		
		r = RulesCompiler.CreateProjectRulesAssembly(CheckProjectFile);
		FileReference f = r.GetModuleFileName( this.GetType().Name );
		//File.WriteAllText("c:/temp/qqq2.txt", f.CanonicalName );
		
        string ModulePath = Path.GetDirectoryName( f.CanonicalName );

Where MyGame - is yours project name. Not plugin name, but name of the main project, that contains your project.

Example:

using UnrealBuildTool;
using System.IO;

public class SQLite3UE4Plugin : ModuleRules
{
    public SQLite3UE4Plugin(TargetInfo Target)
    {
		//File.WriteAllText("c:/temp/qqq.txt", this.GetType().Name);
		//string ModulePath = Path.GetDirectoryName( RulesAssembly.GetModuleFilename( this.GetType().Name ) );
		
		RulesAssembly r;
		FileReference CheckProjectFile;
		UProjectInfo.TryGetProjectForTarget("MyGame", out CheckProjectFile);
		
		r = RulesCompiler.CreateProjectRulesAssembly(CheckProjectFile);
		FileReference f = r.GetModuleFileName( this.GetType().Name );
		//File.WriteAllText("c:/temp/qqq2.txt", f.CanonicalName );
		
        string ModulePath = Path.GetDirectoryName( f.CanonicalName );
        string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "x64" : "x86";
        string ThirdPartyPath = Path.GetFullPath( Path.Combine( ModulePath, "../../ThirdParty/" ) );
        string LibrariesPath = Path.Combine(ThirdPartyPath, "SQLite3", "Lib");
        string IncludesPath = Path.Combine(ThirdPartyPath, "SQLite3", "Include");
        string LibraryName = Path.Combine(LibrariesPath, "SQLite3." + PlatformString + ".lib");

        PrivateIncludePaths.AddRange(new string[] { "SQLite3UE4Plugin/Private" });
        PublicIncludePaths.AddRange(new string[] { "SQLite3UE4Plugin/Public" });
        PublicAdditionalLibraries.Add(LibraryName);
        PublicIncludePaths.Add(IncludesPath);

        PublicDependencyModuleNames.AddRange(new string[] { "Engine", "Core", "CoreUObject" });
    }
}

Many thanks for posting this. Clear, concise, and exactly what I needed.

For anyone looking at how to do this without having to specify the project name (for instance if you want this to be inside a project agnostic plugin/module), you can simply replace the string ModulePath code with the (not easily found) variable “ModuleDirectory”:

    private string ModulePath
    {
        get { return Path.GetDirectoryName( RulesCompiler.GetModuleFilename( this.GetType().Name ) ); }
    }
 
    private string ThirdPartyPath
    {
        get { return Path.GetFullPath( Path.Combine( ModulePath, "../../ThirdParty/" ) ); }
    }

becomes

    private string ModulePath
    {
        get { return ModuleDirectory; }
    }
 
    private string ThirdPartyPath
    {
        get { return Path.GetFullPath( Path.Combine( ModulePath, "../../ThirdParty/" ) ); }
    }

or simply

    private string ThirdPartyPath
    {
        get { return Path.Combine( ModuleDirectory, "../../ThirdParty/" ) ); }
    }

You saved my life! Thanks :smiley:

What about getting the path of another module (not the caller)?