We have observed that the WebSockets module (and only this module) is not properly loaded in a packaged build. To compare with a “good” module we are also loading the Http module (In our tests we loaded many more modules and only had issues with the WebSockets module).
We have setup an empty C++ project with the following *.Build.cs file:
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class WSTest : ModuleRules
{
public WSTest(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string] { "Core", "CoreUObject", "Engine", "InputCore", "Http", "WebSockets" });
PrivateDependencyModuleNames.AddRange(new string] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
And an Actor class that was added to the scene:
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyActor.h"
#include "WebSocketsModule.h"
#include "Http.h"
// Sets default values
AMyActor::AMyActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
#if WEBSOCKETS_PACKAGE==1
UE_LOG(LogTemp, Warning, TEXT("WEBSOCKETS_PACKAGE=1")); //prints in all cases
#endif
#if defined(WITH_WEBSOCKETS)
#if WEBSOCKETS_PACKAGE==1
UE_LOG(LogTemp, Warning, TEXT("WEBSOCKETS_PACKAGE=1")); //prints in all cases
#endif
#endif
#if defined(WITH_LIBWEBSOCKETS)
#if WITH_LIBWEBSOCKETS==1
UE_LOG(LogTemp, Warning, TEXT("WITH_LIBWEBSOCKETS=1")); //prints in all cases
#endif
#endif
FWebSocketsModule* wsModule = &FWebSocketsModule::Get();
if (wsModule == nullptr) {
UE_LOG(LogTemp, Warning, TEXT("wsModule is null")); //prints in packaged build
} else {
UE_LOG(LogTemp, Warning, TEXT("wsModule is valid")); //prints in editor
TMap<FString, FString> headers;
headers.Add("Upgrade", "Websocket");
TSharedPtr<IWebSocket> ws = wsModule->CreateWebSocket(TEXT("ws://whatever.com:80"), TEXT("NULL"), headers);
}
FHttpModule* Http = &FHttpModule::Get();
if (Http == nullptr) {
UE_LOG(LogTemp, Warning, TEXT("http is not valid"));
} else {
UE_LOG(LogTemp, Warning, TEXT("http is valid")); //prints in all cases
TSharedRef<IHttpRequest> Request = Http->CreateRequest();
}
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
This was tested in UE 4.22 (from source) and 4.24 (from standard Epic download)
We suspected there was an issue when populating the AdditionalLibraries list in the UnrealBuildTool so we added some Log.TraceWarning lines at the end of the protected virtual void SetupPublicLinkEnvironment function in UEBuildModule.cs:630 but the libWebSockets library was being loaded properly as per the libWebSockets.Build.cs
Running a debugger on our actor shows that this line:
FWebSocketsModule* wsModule = &FWebSocketsModule::Get();
returns null on packaged builds (in any deployment setting) but will work in editor.
But this line:
FHttpModule* Http = &FHttpModule::Get();
presents no issues.
The FWebSocketsModule::Get function does return the Singleton of the module but it would seem the singleton itself is not set. We suspect the void FWebSocketsModule::StartupModule() function is not getting called but there is a knowledge gap as to what calls it, how, and when. If anyone knows how modules are loaded and started help here would be a good way to point us in the right direction unless this is an outright bug.
In any case, since other modules load correctly except for this one, would this be something to file as a bug?
Any help appreciated,
thanks.