x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Pre/Post build step in UBT

The question is simple: how to set up a Pre build event and a post build event properly as the Unreal devs intend to?

The current method I am using is not intended to be used like this, however pre/post/clean build steps are a very essential part of a build system, and therefore UBT must provide a way for developpers to implement them. Typically this is used to copy binaries (such as dlls) to the binary folder.

This is a follow up to my previous question : https://answers.unrealengine.com/questions/402327/alternative-to-unrealbuildtoolgetuprojectpath-in-4.html

Product Version: UE 4.11
Tags:
more ▼

asked Apr 26 '16 at 10:29 PM in Packaging & Deployment

avatar image

Kryofenix
110 5 9 11

avatar image Syed Aug 18 '16 at 01:03 PM

Yes I would like this feature too. Copy DLLs/PDB/EXE to certain folders after build is successful.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

4 answers: sort voted first

Hey so, I had to spend some time figuring this out, since everyones wrong-

 {
     "FileVersion": 3,
     "EngineAssociation": "{D6ABF944-42D3-E058-D1F4-5195E5D7E272}",
     "Category": "",
     "Description": "",
     "Modules": [
         {
             "Name": "Doomsday",
             "Type": "Runtime",
             "LoadingPhase": "Default",
             "AdditionalDependencies": [
                 "CoreUObject"
             ]
         }
     ],
     "PostBuildSteps":
         {
             "Win64": [
                 "copy \"C:\\dev\\projName\\Binaries\\Win64\\DoomsdayServer.exe\" \"C:\\dev\\Doomsday\\Binaries\\Win64\\WindowsNoEditor\\projName\\Binaries\\Win64\\\"", "echo Exported Server file successfully!"
             ]
         }
 }

This is JSON, we must treat it as so. Thank me later ;)

more ▼

answered Aug 06 '17 at 12:38 AM

avatar image

ConnorMursheX
31 3 1

avatar image FilAl Oct 19 '17 at 08:26 AM

Worked for me at UE4.16.2 ! Yeeeeei. Thank you for clarifying that UE has more JSON tags, than it actually generates.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

This feature already exists. You can add shell commands to the end of builds by adding something like this to your .uproject file:

 "PostBuildSteps":
 {
     "Win64": [
         "copy $(ProjectDir)\Binaries\$(TargetPlatform)\$(TargetName).exe D:\SomeDir"
     ]
 }

There's a PreBuildSteps section too. Check out WriteCustomBuildStepScripts in UEBuildTarget.cs in UBT to see all the available variables.

more ▼

answered Aug 30 '16 at 01:40 PM

avatar image

Ben Marsh STAFF
738 23 7 17

avatar image bknoth Sep 09 '16 at 04:14 PM

Where is this information?

Check out WriteCustomBuildStepScripts in UEBuildTarget.cs in UBT

I don't understand the reference and I'd like to add a pre-build step.

Thanks

avatar image Ben Marsh STAFF Sep 09 '16 at 04:17 PM

It's the name of a function in Engine\Source\Programs\UnrealBuildTool\Configuration\UEBuildTarget.cs which executes custom build steps. You can see all the variable names which can be used there.

                 Variables.Add("EngineDir", UnrealBuildTool.EngineDirectory.FullName);
                 Variables.Add("ProjectDir", ProjectDirectory.FullName);
                 Variables.Add("TargetName", TargetName);
                 Variables.Add("TargetPlatform", Platform.ToString());
                 Variables.Add("TargetConfiguration", Configuration.ToString());
                 Variables.Add("TargetType", TargetType.ToString());
                 if(ProjectFile != null)
                 {
                     Variables.Add("ProjectFile", ProjectFile.FullName);
                 }
                 if(Pair.Item2 != null)
                 {
                     Variables.Add("PluginDir", Pair.Item2.Directory.FullName);
                 }
avatar image bknoth Sep 09 '16 at 04:35 PM

I don't find that file (UEBuildTarget.cs) anywhere in my UE project folder or program folder. All I find is an UnrealHeaderTool I'm using UE4 (4.12).

Thanks for your incredibly quick response to my last post.

avatar image Ben Marsh STAFF Sep 09 '16 at 04:40 PM

The source code for that program may only be available in GitHub. I posted the relevant section above though - to summarize, you can use the $(EngineDir), $(ProjectDir), $(TargetName), $(TargetConfiguration), $(TargetType), $(ProjectFile), $(PluginDir) variables in those commands..

avatar image RotemS Apr 19 '17 at 09:17 AM

How can we determine the target directory in the build step? e.g. copy a file from the project folder to the package folder.

avatar image Ben Marsh STAFF Apr 19 '17 at 12:10 PM

UnrealBuildTool just compiles stuff; packaging is done but a tool called AutomationTool (or UAT for short).

If you want to include a file from the source directory when it's packaged, you can mark it as a "runtime dependency" from a .build.cs file. There are plenty of examples of that if you search for "RuntimeDependencies.Add".

avatar image svaisanen Apr 26 '17 at 02:54 PM

I have a plugin that needs some runtime file resources.

in my ...Build.cs I've added those files a RuntimeDedepdency. When I hit Launch in UE4 and watch the log I can see that it tries to copy those files, but every time fails with "Access to the path .... is denied."

I've the path and it's correct.

Any ideas how to do this? Seems needlessly difficult.

Thanks.

avatar image Kryofenix Sep 09 '16 at 04:56 PM

Looks like what I need. I will check it out!

If I may comment on the general design of this feature though, it feels more like a "hack" in the sense that it isn't well integrated in the build system. Everything else is neatly defined in UBT c# files but these can only be command line arguments?

Ideally it's not only the project that should define these pre/post build steps but each module itself, in its Build.cs file, with full access to the UBT (c#) context of what is being built.

If i want to make a more complex, and more importantly platform independent post build step, it gets even worse!

I need to either use a platform agnostic scripting language and make sure all my team members have the environment setup on all their machines (overhead), or i need to compile an executable just for this. It would be so much better to have it all in C#, all in one place.

avatar image Ben Marsh STAFF Sep 09 '16 at 05:28 PM

It is not meant to be used for complex pre/post build steps. You can create your own program and run that if you need something elaborate; this is the same model that Visual Studio uses for per-project extensibility.

UBT does not have any sort of encapsulated public API, so encouraging people to write code against it would be a backwards compatibility nightmare. Maybe one day there will be, but there is little demand for it now.

If you want to encapsulate custom build steps with a module (or set of modules), the same syntax is supported from .uplugin files.

avatar image Kryofenix Sep 09 '16 at 05:38 PM

Maybe it is a matter of perspective.

Yes this is as limited as what MSVC proposes but this is one of the reasons people move on to CMake, ninja or others, more featured build systems. You get a lot more control, and especially when dealing with a large number of platforms and configurations, it becomes a nightmare to manage using only native files, whereas using a programmatic approach to generating build scripts (which would obviously include pre/post build steps) enables much more freedom while reducing complexity. Obviously i'm not teaching you anything, this is exactly why Unreal made UBT, but then why restrict ourselves? Having this all in one place keeps things simple and straightforward, and the portability of c# is especially suited for this.

We deal with backward compatibility issues very well with UE's API already. Having a similar approach (deprecating functionnality for a version or two before removing it completely) is more than enough and has native support in c#. I honestly don't see how this would be worse, especially considering the build system will eventually reach much more stability than the engine API will.

avatar image Ben Marsh STAFF Sep 09 '16 at 05:41 PM

UE4 is designed as an engine with established entry points, whereas UBT is not. There is no sort of API layer at all. Any refactoring (of which much is needed) would not be possible if everything had to be deprecated first.

What do you actually want to access inside UBT?

avatar image Kryofenix Sep 09 '16 at 05:51 PM

You already do have public API even if you do not see it as such. Each module has to implement ModuleRules and TargetRules, and all the parameters that are passed to those functions inherently need to be stable or you will break people's build scripts as they upgrade.

Ideally I'd want to make all my scripts as abstracted as possible. In my current example of copying the binaries (oftentimes DLL for third party libs) into the binary folder, i still have to create "hacks" to determine where is the output directory from the module directory. If you change anything in how the path to my binaries is generated, which you should be able to as these are temporary directories, i need to update my logic as well. There could be more examples but this is one.

You can't tell me that using something like this is pretty :

   public string GetUProjectPath()
   {
         return Directory.GetParent(ModulePath).Parent.Parent.ToString();
   }

AFAIK there is no other clean way for me to determine output directory in my build.cs file, and therefore my module is no longer working independently of its context.

Basically instead of doing string replaces in command line arguments and having a very limited set of variables, let me access a certain set of internals from a part of UBT that is explicitly designed to be a public API. Give me methods to override for Pre/Post build steps and whatever else I would need to customize (selecting which files to include and overriding filters come to mind).

You would get a much better design, with everything pertaining to a module's build process all in one file, all in one language, all platform agnostic. Note that this is how other popular meta-build systems work.

Honestly, even if you don't expose anything more than you already do, having it all in c# trumps all just because it will run similarly on all platforms. I'm not sure how I could even make different scripts for different platforms with what you are giving me now.

avatar image Ben Marsh STAFF Sep 09 '16 at 06:11 PM

The ModuleRules and TargetRules do form a stable API, you're right.

The problem with copying files from that location is that UBT will cache the actions needed to build a target in a makefile, so it will not always compile and construct your .build.cs file at runtime. It is not fast to do that runtime compilation, and there have always been distant plans to move away from using C# to specify module rules as a result.

The current shell command are cached out as a list of commands into the makefile, so can be executed without reconstructing the target dependency graph.

For the pattern you're talking about, we always submit the binaries to their final locations in source control so no post-build steps are needed in the first place.

avatar image Kryofenix Sep 09 '16 at 06:16 PM

Yes of course you could submit binaries to source control but that seems a bit strange to me as, again, my third party modules are now no longer self-contained and portable as a single folder.

For me, Binaries is as a core a temporary folder, which should not be under source control. I can safely delete this and temporaries and expect to get the same output if I perform a rebuild. I suspect most people have it excluded in their source control by nature.

I'd be glad to give as much input as much as you like especially if you guys are planning a refactor of UBT. I do believe it is a tool with great potential, and I have myself developped and used similar (c#) custom build systems within other game companies, so this is definitely achievable.

Anyway, to get back on track: with shell commands only, how can I make my pre/post build step either platform agnostic, or specialized for a platform? Shell commands are by definition not portable.

avatar image Ben Marsh STAFF Sep 09 '16 at 06:22 PM

The example I posted above shows how you execute a custom build step for the Win64 host platform. You can add another section for Mac or Linux as required.

You can run any other program you like from there, or spawn a language-agnostic scripting language like Python if you like.

avatar image Kryofenix Sep 09 '16 at 06:26 PM

Oh right, I did not read properly. Well my bad. Thanks for all the help!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Hello,

I've entered a feature request for the ability to re-locate those files to new folders, which you can track the status of here: https://issues.unrealengine.com/issue/UE-34899

Have a great day

more ▼

answered Aug 18 '16 at 05:24 PM

avatar image

Sean L ♦♦ STAFF
44.6k 482 138 425

avatar image Kryofenix Aug 18 '16 at 06:13 PM

Hi Sean. Thanks for following up on this. Honestly having a specific ability to move files is great, but having a place to code a pre/post build step is even better. It is a basic functionnality of most if not all build systems out there, and as such is it paramount that UBT supports it.

avatar image Sean L ♦♦ STAFF Aug 18 '16 at 06:15 PM

Thanks for the response. I'll go ahead and add that info to the request.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Yes besides move/copy files there are other useful stuff such as the ability to run certain script eg to play beep after a long build time. Just keep it open.

more ▼

answered Aug 21 '16 at 12:15 PM

avatar image

Syed
21 2 2

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question