I’ve been working on a set of plugins for UE to interface to a third party AI lib for robotics. I have the third party libraries compiling in both Windows and Linux, and I also have been able to get the package options working for Windows (64 bit target). However, I cannot get the Linux build to link to UE4 objects properly in one of the 4 plugins I’ve been working on. In the 4th plugin, the one that creates classes that subclass UE4 classes like AActor, APlayerController, etc., it spits out linking errors like this from linking against the default generated file GamsAgents.cpp (which is default generated). Here are the steps I am currently going through and seeing an error:
Generating and Building with Make
The Link Errors that occur during Make on Ubuntu 18.04 and UE4.24 from source
The GamsAgent.cpp file
The GamsAgent.Build.cs file (shows Engine as a dependency)
I feel like I’m missing something basic in the module dependencies somewhere. You can see the full project and build instruction to replicate here (if you need to see the other Build.cs files for the 4 plugins in the repo):
Moving the plugin into a module folder instead (i.e., Source/<Name> instead of Plugins/<Name>/Source/<Name>), but the same typeinfo errors persist
Removed the plugin and the errors went away (it’s definitely in this specific plugin)
Modified all derived classes (from UE types that are reporting errors) to call the super’s constructors in the BMI of the derived classes, just in case some weird RTTI-related issues were coming up in that
This kind of typeinfo error seems pretty rare in clang and tends to be related to a pure virtual method having no implementation. Is there some reason that these derived classes of UE4 classes like AActor, UGameInstance, etc. are registering as abstract in UE4.24. I looked through AActor and only saw virtual declarations but not pure virtual.
I believe I’ve fixed these issues today, so I thought I would come back and share some notes on what the problem was and how to fix this for anyone who finds this thread later.
As far as I’m able to tell, UE4 doesn’t actually support RTTI on Linux.There are posts out there that claim that building UE4 with RTTI enabled is possible since 4.14. However, over the past several months of false starts with Linux support (way before I made the above post), I tried multiple methods or scattered notes that I found online, including this one from people messing with ROS on Linux. In that case, the LinuxToolChain.cs file has moved into the Platforms directory (not the one the note discusses), and changing that method resulted in a build error for me when I tried to make it always return “-frtti”, even when I added the XML forceEnableRTTI to the BuildConfiguration.xml. I wasn’t able to find a way to build UE4 with RTTI, and I gave up on it after a while. Perhaps UE will officially support this on Linux someday, but I wouldn’t count on it if I were you. And probably more importantly, out-of-the-box, UE4 on Linux is not going to support RTTI, so you might as well setup your programming process for plugins and/or uproject code to use a non-RTTI, if at all possible, so tech supporting users with your plugins is as seamless and easy as possible (especially if you’re expecting entry-level programmers or students).
My solution to this RTTI-less requirement was to fundamentally change several libraries and their interactions within my set of plugins. I removed any RTTI-related activity that occurs within header files, especially, which was the case with the cereal serialization library that we had included as a convenience header library for martialling types and such in our C++ libraries. UE4 can’t stop you from compiling a library externally with clang-8 (for UE4.24) or clang-9 for later and then creating a ThirdParty library that is linked in. And that fact is the way you can get around the RTTI issues. UE4’s problem is not that you can’t use RTTI in your linked libraries. It just won’t let you portably do so across the Windows/Linux/Android/etc. boundaries within the Plugin or Source directories of your UE4 plugins or projects. If you need RTTI, e.g. if you are developing libraries that use dynamic_cast or type-related functions for superclass/subclass access, you simply need to make sure these functions are implemented within source/implementation files rather than headers or inline files in your compiled external library. You want to compile your dll, dylib, so files so that the implementation that uses RTTI is in that dll, dylib, or so file and not being compiled by the UE4 build system. If your libraries don’t need RTTI at all and you can safely remove parts of it and implement it differently, this is a good opportunity to streamline, though.
Set any bUseRTTI=false within your Build.cs files (the Build.cs files that are in the Source folders of your project or plugin directories)
Avoid direct STL usage in your plugin/project. You can still use it to implement your external libraries, but if your functions are returning STL classes (which is how any modern C++ is taught today in universities to adhere to intuitive RAII), it’s going to segfault spectacularly in ways that are difficult to debug for anyone who doesn’t have experience with these kinds of portability issues in past compiles (thankfully, I had seen this kind of thing before). On Linux, it’s actually less of a problem because of the declared clang and clib usage. On Windows, even if you use the same compiler in both your project/code and the UE4 engine build, it appears that UE4 breaks STL compatibility, and I can only surmise this is intentional. Would definitely prefer some official guidance on how to setup VS for using a STL that UE4 will allow on Windows, rather than what is currently going on. My solution to this right now is to provide methods within my libraries that circumvent the C++ STL by, for instance, creating concrete classes that encapsulate something like a std::string and providing copy methods for the underlying c_str to an UE4 managed buffer that are implemented inside the lib (VERY IMPORTANT) and not done through any header file interactions. This is pretty inconvenient, but this is how I got rid of some of my biggest headaches (the kind without debug messages and just random segfaults in code that any C++ programmer would expect to work). How to get around std::map though is going to be a bit more involved, and unfortunately, you can’t just make a UE4 class to std mapping because memory malloced by the STL will eventually cause segfaults in the UE4 code/plugin/helper class when it tries to force the FMalloc free of memory that it hasn’t seen before. To make a helper plugin, you basically want to just force everything into a lib that saves raw char * and hope the user on the other side cleans things up correctly with UE4’s mechanisms (not RAII). Regardless, fun stuff to debug. Very fun stuff.