Need VS 2017to build plugins
最近做了个插件,想要打包发布,因为是新的电脑,只安装了最新的VS2019,编译UE源码或者项目啥的都没问题,结果在插件的时候,报了Visual Studio 2017 must be installed in order to build this target.这么个莫名其名的问题。UE打包插件为啥就需要VS 2017呢,在网上找了一下,发现UE从很早的版本就有这个问题了,但都没有人说清楚怎么回事,只好去看源码了。
首先是看C++的源码,从UE的运行log可以看到是执行了BuildPlugin命令行来实现插件打包的,所以全局搜索BuildPlugin,找到Engine\Plugins\Editor\PluginBrowser\Source\PluginBrowser\Private\SPlugin.cpp文件,
void SPluginTile::OnPackagePlugin()
{
FString DefaultDirectory;
FString OutputDirectory;
if ( !FDesktopPlatformModule::Get()->OpenDirectoryDialog(FSlateApplication::Get().FindBestParentWindowHandleForDialogs(AsShared()),LOCTEXT("PackagePluginDialogTitle", "Package Plugin...").ToString(), DefaultDirectory,OutputDirectory) )
{
return;
}
// Ensure path is full rather than relative (for macs)
FString DescriptorFilename = Plugin->GetDescriptorFileName();
FString DescriptorFullPath = FPaths::ConvertRelativePathToFull(DescriptorFilename);
OutputDirectory = FPaths::Combine(OutputDirectory,Plugin->GetName());
FString CommandLine = FString::Printf(TEXT("BuildPlugin -Plugin=\"%s\"-Package=\"%s\" -CreateSubFolder"), *DescriptorFullPath,*OutputDirectory);
#if PLATFORM_WINDOWS
FText PlatformName = LOCTEXT("PlatformName_Windows", "Windows");
#elif PLATFORM_MAC
FText PlatformName = LOCTEXT("PlatformName_Mac", "Mac");
#elif PLATFORM_LINUX
FText PlatformName = LOCTEXT("PlatformName_Linux", "Linux");
#else
FText PlatformName = LOCTEXT("PlatformName_Other", "Other OS");
#endif
IUATHelperModule::Get().CreateUatTask(CommandLine, PlatformName, LOCTEXT("PackagePluginTaskName", "Packaging Plugin"),
LOCTEXT("PackagePluginTaskShortName", "Package Plugin Task"), FEditorStyle::GetBrush(TEXT("MainFrame.CookContent")));
}
代码比较简单,只是生成一个命令行,交个UAT去执行了,关键的命令行参数是
FString CommandLine = FString::Printf(TEXT("BuildPlugin -Plugin=\"%s\"-Package=\"%s\" -CreateSubFolder"), *DescriptorFullPath,*OutputDirectory);
从这里看不出VS2017或者VS2019的什么关系,只好去UAT源码看了。
找到源码文件:
\Engine\Source\Programs\AutomationTool\Scripts\ BuildPluginCommand.Automation.cs
bool bVS2019 = ParseParam("VS2019");
……
// Clear the output directory ofexisting stuff
// Create a placeholder FilterPlugin.ini withinstructions on how to use it
// Create a host project for the plugin. Forscript generator plugins, we need to have UHT be able to load it, which canonly happen if it's enabled in a project.
// Read the plugin
// Get the arguments for the compile
// Compile the plugin for all the targetplatforms
FileReference[]BuildProducts = CompilePlugin(HostProjectFile, HostProjectPluginFile, Plugin,HostPlatforms, TargetPlatforms, AdditionalArgs.ToString(), bVS2019);
// Package up the final plugin data
PackagePlugin(HostProjectPluginFile,BuildProducts, PackageDir, ParseParam("unversioned"));
// Remove the host project
//Create the new project descriptor
// Get the plugin directory in thehost project, and copy all the files in
// Return the path to the pluginfile in the host project
// Add the game targets
可以看到源码里,通过bVS2019的变量来控制是否用VS 2017还是 VS 2019来打包的插件。这里我把代码删除,留下注释,可以看到这类工具类的代码,基本是一步一步的来操作,没事复杂的算法。从这里也可以看到,有些文章里说可以从log里把执行命令拷贝出来,去掉-2017参数执行就行了,从源码里看显然这种做法是不行的(我也入过这个坑,执行完命令后的插件打包结果还是不对的),因为执行命令后还有很多善后工作。
看到这里,解决办法就找到了,一种办法就是直接让变量bVS2019的值为true,不从参数读取了,把bool bVS2019 = ParseParam("VS2019");改成bool bVS2019 =true;另一个办法就是给传入一个参数,修改SPluginTile.cpp中,加入参数:
FString CommandLine = FString::Printf(TEXT("BuildPlugin -Plugin=\"%s\"-Package=\"%s\" -VS2019=true -CreateSubFolder"), *DescriptorFullPath, *OutputDirectory);