打包插件必须安装vs 2017?

Visual Studio 2017 must be installed in order to build this target

· UE技术分享

 

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