adamrehn / ue4cli

Command-line interface for Unreal Engine 4
https://docs.adamrehn.com/ue4cli/
MIT License
249 stars 45 forks source link

Packaging multiple plugins at the same time #24

Open tonymrakovcic opened 3 years ago

tonymrakovcic commented 3 years ago

Hello! I have been using u4cli for packaging my plugin and it has been working great! I am facing a problem now that I don't see a direct solution for from the docs

I have 2 plugins, that can depend on each other, let call them A and B I can build A, i can build B, independently everything works fine. But if I want to package plugin A that has a dependency on B (which is the case in real life) the problem is in the build procedure folder B is of course not moved to the dist folder, so the build fails as it cannot find its B dependency.

Is there a solution for such a scenario? Can I somehow move B maybe to the dist folder first? Will the creation overwrite it? B can be prebuilt in my case, it is not strictly necessary to build them both at the same time for me

adamrehn commented 3 years ago

Interesting, I've never actually used ue4 package to package a plugin that depends on other plugins and so had never considered the fact that the underlying Unreal AutomationTool BuildPlugin script doesn't provide any mechanism to copy dependencies into the temporary host project used for compilation. I'll investigate what options are available and see if I can come up with a workflow that accommodates this use case.

tonymrakovcic commented 3 years ago

Any workaround or possible solution to this that comes to mind? Workarounds that would work for me at the moment (ideas that could be easy to implement i guess) - a) don't overwrite dist/Project/Plugins folder if present - I would just create it beforehand and add the other plugin and I guess it would work b) If a plugin has a dependency stated in the uplugin file and is present in the Plugins folder, copy it to dist/plugins on packaging c) somehow state "just copy folder x to dist/plugins" before package compile

adamrehn commented 3 years ago

@tonymrakovcic in terms of an immediate workaround, the one option that's pretty much guaranteed to work is to copy the other plugins that your plugin depends on into the Unreal Engine's own plugins directory, since that will make them usable by all projects and plugins system-wide. (That's actually a common approach when doing CI/CD for Unreal projects inside containers, since pulling pre-packaged binaries for your plugins and injecting them into the Engine itself can save a decent chunk of build time and has no lasting effects once the container's ephemeral filesystem is destroyed.) That's not an approach I'd recommend outside of a container though, since on the host system's persistent filesystem you'd need to perform cleanup every time by removing the files you copied into the Engine.

Investigating a proper solution to this is still very much on my TODO list, but as I've noted elsewhere I have precious little free time at the moment, so it may be some time before I get a chance to sit down and look at this properly.

tonymrakovcic commented 3 years ago

No problem I understand :) The engine plugins system is a great idea, I am in a bigger build setup so a script for cleanup is not that big of a hassle, will try it out Thanks!

dskvr commented 3 years ago

@tonymrakovcic We were solving a different use case, but we wrote a bash script that creates the minimum for a blank host project and copies the files over. Here's a generalized piece of it, would need a bit of modification for your use case but it could be useful.

# Make a host project to test plugin in
##########################
cd "$ROOT"
if [ -d hostproject ]; then
  rm -rf hostproject # clean it
fi
mkdir hostproject
echo '{ "FileVersion": 3, "Plugins": [ { "Name": "'$PLUGIN_NAME'", "Enabled": true } ] }' > hostproject/hostproject.uproject
mkdir hostproject/Config
mkdir hostproject/Source
cat > hostproject/Source/hostproject.Target.cs << EOM
using UnrealBuildTool;
using System.Collections.Generic;
public class hostprojectTarget : TargetRules
{
    public hostprojectTarget( TargetInfo Target) : base(Target)
    {
        Type = TargetType.Game;
        DefaultBuildSettings = BuildSettingsVersion.V2;
        ExtraModuleNames.AddRange( new string[] { "hostproject" } );
    }
}
EOM
cat > hostproject/Source/hostprojectEditor.Target.cs << EOM
using UnrealBuildTool;
using System.Collections.Generic;
public class hostprojectEditorTarget : TargetRules
{
    public hostprojectEditorTarget( TargetInfo Target) : base(Target)
    {
        Type = TargetType.Editor;
        DefaultBuildSettings = BuildSettingsVersion.V2;
        ExtraModuleNames.AddRange( new string[] { "hostproject" } );
    }
}
EOM
mkdir hostproject/Source/hostproject
cat > hostproject/Source/hostproject/hostproject.cpp << EOM
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, hostproject, "hostproject" );
EOM
cat > hostproject/Source/hostproject/hostproject.Build.cs << EOM
using UnrealBuildTool;
public class hostproject : ModuleRules
{
    public hostproject(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
        PrivateDependencyModuleNames.AddRange(new string[] {  });
    }
}
EOM
# End host project
##########################

With <3 from @theiainteractive

tonymrakovcic commented 3 years ago

For people from the future, I ended up using the workaround with copying the files to the engine plugin folder. Works like a charm. The cleanup part, although it exists, is fairly straightforward to deal with as it's easy to track. Thanks for the idea!

sleeptightAnsiC commented 3 months ago

I don't think that copying plugin files to the Engine's directory would work for installations from EpicLauncher.

What Editor does while packaging a plugin is running the following:

RunUAT BuildPlugin -Plugin="/path/to/plugin.uplugin" -Package="/path/to/package/folder" -CreateSubFolder -nocompile -nocompileuat

ue4cli package does pretty much the same but without -CreateSubFolder -nocompile -nocompileuat flags

Perhaps, said discrepancy is causing an issue