Resolved : LNK2001 Error ("unresolved external symbol GInternalProjectName") Due to Module Naming Issue in a Plugin Project

Hi everyone,

I wanted to share the solution to a rather tricky packaging error I encountered when developing an Unreal Engine plugin. I was receiving several linker errors during packaging (for Windows) such as:

UATHelper: Packaging (Windows): Module.SomeModule.cpp.obj : error LNK2001: unresolved external symbol "wchar_t * GInternalProjectName" (?GInternalProjectName@@3PA_WA)

After investigating for a while, I discovered that the root of the problem was due to an incorrect module configuration. In my case, the project had the same name as my plugin, which led to some confusion in the build process. Essentially, my target files were only including the game module and were missing the plugin module.

The solution was to explicitly include both the game module and the plugin module in the target definitions.

In my test project’s target files, I added both "TestDemo" (the game module) and "ModuleDemo" (the plugin module) to the ExtraModuleNames array. This might seem a bit convoluted when the names overlap, but it ensures that both modules are compiled and linked correctly.

To simplify the issue and pinpoint the solution, I created a working example with the following folder structure and file contents. You can use this as a reference for setting up your project.

  • Summary

    • Problem:
      Encountered linker errors such as
      LNK2001: unresolved external symbol “wchar_t * GInternalProjectName”
      during packaging.

    • Cause:
      The error was caused by the project not including the correct modules. Since the project name was the same as the plugin name, only the game module was being added, which meant the plugin module was missing during the build.

    • Solution:
      Update both the game and editor target files to include both modules (the game module and the plugin module) by adding them to the ExtraModuleNames array.
      This ensures that all necessary components are compiled and linked correctly.

  • Working Folder Structure

TestDemo/
├── TestDemo.uproject
├── Source/
│   └── TestDemo/
│       ├── Private/
│       │   └── TestDemo.cpp
│       ├── Public/
│       │   └── TestDemo.h
│       └── TestDemo.Build.cs
├── TestDemo.Target.cs
├── TestDemoEditor.Target.cs
└── Plugins/
    └── PluginDemo/
        └── Source/
            ├── ModuleDemo/
            │   ├── Private/
            │   │   └── ModuleDemo.cpp
            │   ├── Public/
            │   │   └── ModuleDemo.h
            │   └── ModuleDemo.Build.cs
            └── PluginDemo.uplugin

  • TestDemo.uproject :
{
	"FileVersion": 3,
	"EngineAssociation": "5.5",
	"Category": "",
	"Description": "",
	"Plugins": [
		{
			"Name": "PluginDemo",
			"Enabled": true
		}
	]
}
  • TestDemo.cpp :
#include "TestDemo.h"
#include "Modules/ModuleManager.h"

IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, TestDemo, "TestDemo");
  • TestDemo.h :
#pragma once 

#include "CoreMinimal.h"
  • TestDemo.Build.cs :
using UnrealBuildTool;

public class TestDemo : ModuleRules
{
    public TestDemo(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        // These modules are needed in both runtime and editor builds.
        PublicDependencyModuleNames.AddRange(new string[] {
            "Core",
            "CoreUObject",
            "Engine",
            "ModuleDemo"
        });
    }
}
  • TestDemo.Target.cs :
using UnrealBuildTool;
using System.Collections.Generic;

public class TestDemoTarget : TargetRules
{
	public TestDemoTarget(TargetInfo Target) : base(Target)
	{
		Type = TargetType.Game;
		DefaultBuildSettings = BuildSettingsVersion.V5;
		IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_5;
        ExtraModuleNames.AddRange(new string[] { "TestDemo" });
        ExtraModuleNames.AddRange(new string[] { "ModuleDemo" });
    }
}
  • TestDemoEditor.Target.cs :
using UnrealBuildTool;
using System.Collections.Generic;

public class TestDemoEditorTarget : TargetRules
{
	public TestDemoEditorTarget( TargetInfo Target) : base(Target)
	{
		Type = TargetType.Editor;
		DefaultBuildSettings = BuildSettingsVersion.V5;
		IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_5;
        ExtraModuleNames.AddRange(new string[] { "TestDemo" });
        ExtraModuleNames.AddRange(new string[] { "ModuleDemo" });
    }
}
  • ModuleDemo.cpp :
#include "ModuleDemo.h"
#include "Modules/ModuleManager.h"

// Registers the module with Unreal Engine.
IMPLEMENT_MODULE(FModuleDemoModule, ModuleDemo)
  • ModuleDemo.h :
#pragma once

#include "CoreMinimal.h"

 class FModuleDemoModule : public IModuleInterface
{
public:
    virtual void StartupModule() override {}
    virtual void ShutdownModule() override {}
};
  • ModuleDemo.Build.cs :
using UnrealBuildTool;

public class ModuleDemo : ModuleRules
{
    public ModuleDemo(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        // These modules are needed in both runtime and editor builds.
        PublicDependencyModuleNames.AddRange(new string[] {
            "Core",
            "CoreUObject",
            "Engine"
        });
	}
}
  • PluginDemo.uplugin :
{
	"FileVersion": 3,
	"Version": 1,
	"VersionName": "1.0",
	"FriendlyName": "Plugin Demo",
	"Description": "Test",
	"Category": "Test",
	"CanContainContent": true,
	"EnabledByDefault": false,
	"Modules": [
		{
			"Name": "ModuleDemo",
			"Type": "Runtime",
			"LoadingPhase": "PostEngineInit"
		}
	],
	"CreatedBy": "",
	"CreatedByURL": "",
	"DocsURL": "",
	"MarketplaceURL": "",
	"SupportURL": "",
	"IsBetaVersion": true,
	"IsExperimentalVersion": false,
	"Installed": false
}

I hope this detailed explanation along with the complete file listings and folder structure helps anyone who might run into a similar issue. Feel free to ask any questions or provide feedback!