I’ve been on a mission to get the libraries I have in CMake working in my UE4 project, where the UE4 project will be able to link in targets, by name, including all transitive dependencies (if we specify LibA and it requires LibB and LibC, we need to link all three of them). This is the current structure:
Root('RTG')
CMakeLists.txt (the root file controlling the repo)
Build
Normal CMake build stuff
Libs
Client
Client_Core
...
Shared
Shared_Network
Shared_Physics
...
Src
Server
Test_Client
...
UE4 (not known to root CMakeLists.txt)
rtg_client (UE4 proj root)
Source
Intermediate
rtg_client.uproject
Most of my efforts to get UE4 to play nice with this structure have failed, but my current approach is;
In rtg_client.build.cs (basic version here), I specify the CMake targets I want by name, and pass them to a Python script that generates a CMakeLists.txt file in /UE4/rtg_client/Intermediate containing those targets as dependencies of a target ‘DummyClient’
The python script calls ‘cmake’ on that dir, which generates a .vcxproj for the DummyClient (we have to do this to flatten down the dependency tree - what if we specify LibA but it depends on LibB? The .vcxproj has all of this info)
We parse the DummyClient.vcxproj file to get all of the library paths, library names, and include paths
The above info is given to UE4 at the bottom of the .build.cs file via ‘PublicAdditionalLibraries’, ‘PublicLibraryPaths’, and ‘PublicIncludePaths’
There is a pre-build step in the .uproject file that triggers this .bat file (or something very similar):
cd "Intermediate/_build" && cmake --build . --target DummyClient
So that any changes to the libraries by the root-level CMake projects (‘Server’ etc) are built for the rtg_client project to use and link.
Can anyone come up with a better solution? I don’t want to modify much of the Root/CMakeLists.txt file since it’s UE4-agnostic mostly. Maybe someone else here has gotten a UE4 project to play nicer with CMake? Is there some CMake parsing support built-in somewhere? I doubt it but you never know. I’m open to changing UBT (and the engine in general) to make this easier! Seriously; give me some pointers if you think it can be done better!
The big one problem; even with bIgnoreOutdatedImportLibraries set to false, UE4 does not re-link modified libraries! All of this work and UE4 just ignores the lib changes! This means that if I make changes to e.g. the ‘Shared’ libraries via the Server’s project file, and then run the client, the client won’t pick up those changes without first touching its source to trigger a relink (I think that’s what it would take).
Okay, so I’m nearly there, with only a few issues remaining;
How can I pass compiler arguments without modifying UBT? https://answers.unrealengine.com/que…ng-overal.html suggests that there used to be a way, but that’s been removed. Has that functionality disappeared without any replacement?
Is it possible to regen my project files for VS2017 instead of VS2015 without calling UnrealBuildTool.exe manually? I have to use this for now:
but would like the right-click ‘Generate Visual Studio project files’ option to natively use 2017.
Still having the issue of not recompiling when libs change. I tried this variable from ModuleRules;
/// <summary>
/// External files which invalidate the makefile if modified. Relative paths are resolved relative to the .build.cs file.
/// </summary>
public List<string> ExternalDependencies = new List<string>();
but it didn’t make a difference - I gave it the lib paths+names but no re-link or regen when the lib files change. Can live without that for now, though.
The main issue is passing compiler flags without modifying UBT - my external libs use some C++17 features via the /std:c++latest flag. I need to pass that to UBT. Any ideas?
I can’t believe it’s been over a year! I have an update to one of the main issues in case anyone finds this thread later.
You CAN get UE4 to relink when third-party static libs change, you just need to give UBT the ABSOLUTE lib path instead of just the path of its directory and the library name separately.