Using external (CMake) libraries as third party libraries?

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).

Thanks.

So I’ve seen recommendations in Answerhub answers on this topic that I use absolute paths to the libs in PublicAdditionalLibraries, but no change there unfortunately. Next I’ll be trying what’s written here (inc. the github link); How do you statically link an external DLL/dylib to your project? - Programming & Scripting - Epic Developer Community Forums

Surely someone’s got externally-built static libs that re-link when modified? Surely!

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:


"C:/Program Files/Epic Games/UE_4.16/Engine/Binaries/DotNET/UnrealBuildTool.exe" -projectfiles -project="C:/_Development/Repositories/rtg/UE4/rtg_client/rtg_client.uproject" -game -rocket -progress -2017

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.



PublicAdditionalLibraries.AddRange(new string { "my_lib.lib" });
PublicLibraryPaths.AddRange(new string { "path/to/lib/directory/" });


Becomes


PublicAdditionalLibraries.AddRange(new string { "path/to/lib/directory/my_lib.lib" });

Happy coding!

2 Likes