Download

SourceCode does not Compile properly as Plugin

Hey there.

I am currently trying to write an Unreal-Wrapper for the yaml-cpp library. But for some reason, whenever you try to use the plugin, Unreal has a hard time linking the code and you always get a bunch of Unresolved External Symbol Error Messages.

I added the same source files from the plugin in a fresh project directly as c++ files instead of a Plugin (In the Private/Public folder in the Source directory), which works flawlessly and compiles without any errors. But as soon as I put the files in a Plugin I get the linker errors again. The original library works with Exceptions and other std-classes, but since it compiles directly, I don’t see any particular reason why it shouldn’t be able to compile it in a Plugin.

I am probably just missing an option somewhere, but I can’t find it!

The whole Plugin can be found here, but I will post the most important files below:

UnrealYAML.uplugin:

{
	"FileVersion": 3,
	"Version": 1,
	"VersionName": "1.0",
	"FriendlyName": "UnrealYAML",
	"Category": "Other",
	"CanContainContent": true,
	"IsBetaVersion": false,
	"IsExperimentalVersion": false,
	"Installed": false,
	"Modules": [
		{
			"Name": "UnrealYAML",
			"Type": "Runtime",
			"LoadingPhase": "Default"
		}
	]
}

UnrealYaml.Build.cs

public class UnrealYAML : ModuleRules {
	public UnrealYAML(ReadOnlyTargetRules Target) : base(Target) {
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
		PublicDependencyModuleNames.AddRange(new[] {"Core", "Projects"});

		bEnableExceptions = true;
		bUseRTTI = true;

		PublicIncludePaths.Add(Path.Combine(PluginDirectory, "Source", "UnrealYAML", "yaml-cpp", "include"));
		PrivateIncludePaths.Add(Path.Combine(PluginDirectory, "Source", "UnrealYAML","yaml-cpp", "src"));
	}
}

UnrealYAML.h and UnrealYAML.cpp

class FUnrealYAMLModule : public IModuleInterface { };
    
IMPLEMENT_MODULE(FUnrealYAMLModule, UnrealYAML)

You need to add the relevant modules as private (or public) dependencies. Take a look at the linker errors, you’ll probably have a bunch - you can usually figure out which modules to include based on the path to the file where the missing functions/classes are declared.

Unreal code is organized like:

[Runtime|Editor]/.../<Module>/[Public|Private|Classes]/.../<source file>

Or:

Plugins/.../<Plugin>/<Module>/[Public|Private|Classes]/.../<source file>

You’re looking for the module name, the last directory before “Public”, “Private”, or “Classes” in the relevant source file’s path. Add that name (just the name) to your private dependencies:

PrivateDependencyModuleNames.AddRange(new[] {"Module1", "Module2"});

If you’re dependent on a plugin module, you should add that plugin as a dependency for your own by listing it in your uplugin file, e.g.:

	"Plugins": [
		{
			"Name": "SomeEnginePlugin",
			"Enabled": true
		}
	]

Excuse the long delay, but I didn’t get an email notification and only now came around checking for answers.

All linker errors I get are (as far as I can tell) from the Module “UnrealYAML” itself and not in some external Module. The .cpp files with the Code that is not linked are also definitely parsed and read by the compiler, but as soon as the linker wants to link the code, it can’t anymore!

It might help if you post examples of the linker errors that you’re getting?

Ok, so I wrote a small Function that uses the Plugin, so that there is actually something to link.

Here is the code I wrote:

void UMyBlueprintFunctionLibrary::Test() {
	FYamlNode Node;

	FYamlNode TestMap = YAML::Node();
	TestMap["Entry1"] = FString("Hello, World!");
	TestMap["Value"] = 17326.88165f;
	Node.push_back(TestMap);
}

An these are the errors I get when building:

0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: virtual __cdecl YAML::Exception::~Exception(void)" (??1Exception@YAML@@UEAA@XZ) referenced in function "public: virtual void * __cdecl YAML::Exception::`scalar deleting destructor'(unsigned int)" (??_GException@YAML@@UEAAPEAXI@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: virtual __cdecl YAML::RepresentationException::~RepresentationException(void)" (??1RepresentationException@YAML@@UEAA@XZ) referenced in function "public: virtual void * __cdecl YAML::RepresentationException::`scalar deleting destructor'(unsigned int)" (??_GRepresentationException@YAML@@UEAAPEAXI@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: virtual __cdecl YAML::InvalidNode::~InvalidNode(void)" (??1InvalidNode@YAML@@UEAA@XZ) referenced in function "public: virtual void * __cdecl YAML::InvalidNode::`scalar deleting destructor'(unsigned int)" (??_GInvalidNode@YAML@@UEAAPEAXI@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: virtual __cdecl YAML::BadSubscript::~BadSubscript(void)" (??1BadSubscript@YAML@@UEAA@XZ) referenced in function "public: virtual void * __cdecl YAML::BadSubscript::`scalar deleting destructor'(unsigned int)" (??_GBadSubscript@YAML@@UEAAPEAXI@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: class YAML::detail::node & __cdecl YAML::detail::memory::create_node(void)" (?create_node@memory@detail@YAML@@QEAAAEAVnode@23@XZ) referenced in function "public: __cdecl YAML::Node::Node<char const *>(char const * const &)" (??$?0PEBD@Node@YAML@@QEAA@AEBQEBD@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: void __cdecl YAML::detail::memory_holder::merge(class YAML::detail::memory_holder &)" (?merge@memory_holder@detail@YAML@@QEAAXAEAV123@@Z) referenced in function "private: static class YAML::detail::node & __cdecl YAML::detail::node_data::convert_to_node<char [6]>(char const (&)[6],class std::shared_ptr<class YAML::detail::memory_holder>)" (??$convert_to_node@$$BY05D@node_data@detail@YAML@@CAAEAVnode@12@AEAY05$$CBDV?$shared_ptr@Vmemory_holder@detail@YAML@@@std@@@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: void __cdecl YAML::detail::node_data::mark_defined(void)" (?mark_defined@node_data@detail@YAML@@QEAAXXZ) referenced in function "public: void __cdecl YAML::detail::node::mark_defined(void)" (?mark_defined@node@detail@YAML@@QEAAXXZ)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: void __cdecl YAML::detail::node_data::set_null(void)" (?set_null@node_data@detail@YAML@@QEAAXXZ) referenced in function "private: void __cdecl YAML::Node::EnsureNodeExists(void)const " (?EnsureNodeExists@Node@YAML@@AEBAXXZ)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: void __cdecl YAML::detail::node_data::set_scalar(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?set_scalar@node_data@detail@YAML@@QEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: __cdecl YAML::Node::Node<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$?0V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Node@YAML@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: void __cdecl YAML::detail::node_data::push_back(class YAML::detail::node &,class std::shared_ptr<class YAML::detail::memory_holder> const &)" (?push_back@node_data@detail@YAML@@QEAAXAEAVnode@23@AEBV?$shared_ptr@Vmemory_holder@detail@YAML@@@std@@@Z) referenced in function "public: void __cdecl YAML::Node::push_back(class YAML::Node const &)" (?push_back@Node@YAML@@QEAAXAEBV12@@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "public: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const & __cdecl YAML::detail::node_data::empty_scalar(void)" (?empty_scalar@node_data@detail@YAML@@SAAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) referenced in function "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const & __cdecl YAML::Node::Scalar(void)const " (?Scalar@Node@YAML@@QEBAAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "private: void __cdecl YAML::detail::node_data::insert_map_pair(class YAML::detail::node &,class YAML::detail::node &)" (?insert_map_pair@node_data@detail@YAML@@AEAAXAEAVnode@23@0@Z) referenced in function "public: class YAML::detail::node & __cdecl YAML::detail::node_data::get<char [6]>(char const (&)[6],class std::shared_ptr<class YAML::detail::memory_holder>)" (??$get@$$BY05D@node_data@detail@YAML@@QEAAAEAVnode@12@AEAY05$$CBDV?$shared_ptr@Vmemory_holder@detail@YAML@@@std@@@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2019 : unresolved external symbol "private: void __cdecl YAML::detail::node_data::convert_to_map(class std::shared_ptr<class YAML::detail::memory_holder> const &)" (?convert_to_map@node_data@detail@YAML@@AEAAXAEBV?$shared_ptr@Vmemory_holder@detail@YAML@@@std@@@Z) referenced in function "public: class YAML::detail::node & __cdecl YAML::detail::node_data::get<char [6]>(char const (&)[6],class std::shared_ptr<class YAML::detail::memory_holder>)" (??$get@$$BY05D@node_data@detail@YAML@@QEAAAEAVnode@12@AEAY05$$CBDV?$shared_ptr@Vmemory_holder@detail@YAML@@@std@@@Z)
0>MyBlueprintFunctionLibrary.cpp.obj: Error LNK2001 : unresolved external symbol "private: static struct std::atomic<unsigned __int64> YAML::detail::node::m_amount" (?m_amount@node@detail@YAML@@0U?$atomic@_K@std@@A)
0>C:\...\Unreal Projects\YamlCppTest\Binaries\Win64\UE4Editor-YamlCppTest.dll: Error LNK1120 : 14 unresolved externals

Check if the linking is correct. Maybe you need to move the headers to Public instead of Private or add <MYPLUGINNAME>_API before the externals that are not visibile (as I can see there is only __cdecl in your error message so I think that these are not exported from the DLL)

1 Like

Yeah I think you’re trying to use code that’s not been exported from your module (which is a DLL). You might want to wrap library code in more unreal-friendly classes which are exported, or you might get away with exporting the library classes since it sounds like you’re also compiling the library from source as part of your module. That just means adding UNREALYAML_API to class declarations (exporting all methods of the class) or to individual functions.

1 Like

That was indeed the problem. The code already had a YAML_CPP_API macro, but it was wrongly defined:

#ifdef YAML_CPP_DLL
	#ifdef yaml_cpp_EXPORTS 
		#define YAML_CPP_API __declspec(dllexport)
	#else 
		#define YAML_CPP_API __declspec(dllimport)
	#endif 
#else 
	#define YAML_CPP_API
#endif  

Normally YAML_CPP_DLL and yaml_cpp_EXPORTS would have been declared somewhere in the CMake script, but since I used the UBT, I needed to define those manually (via PublicDefinitions in the Build.cs).

After that, all the linker errors disappeared and the project was built without any errors!

Thank you very much for the Help!

1 Like

You’re welcome. Keep up the good work.