正确引用第三方module
正确的引用方法是在M1的M1.build.cs文件中设定如下字段:
PublicDependencyModuleNames或PrivateDependencyModuleNames中添加M3,如果引用M3中功能的代码是在M1的Public源码中,则加到PublicDependency里,反之,如果是在M1的Private源码中引用M3中的功能,则加到PrivateDependency里。如果在M1的Public和Private源码中均引用了M3中的功能,则应该把M3同时添加到PublicDependency和PrivateDependency中。
上面对DependencyModule的设置对应toolchain里的静态链接,即保证M1对M3中的对象或功能的引用能找到实现。但是它不完全解决头文件包含层面的问题。不完全的意思是有时候不用处理头文件包含的事情也没问题发生,有时候不处理头文件包含的事情就有问题发生。不用处理也没有问题发生的情形是:M3中的功能实现,其对应的头文件都加到了M3的PublicIncludePaths中,那么M1中引用M3的该功能时,不用额外处理头文件包含事宜。相应的,有问题的情形是:M3中实现了某个功能,但其相关头文件没有加入到M3的PublicIncludePaths中。此时M1的某个cpp中调用M3里的一个函数时,编译器会报告找不到函数声明。这种有问题的情况,可以通过将M3中相应的路径加到M1的PublicIncludePaths或PrivateIncludePaths中来解决:
假设M3的某项功能实现在M3/Private中。当在M1的Public源码中使用M3的这项功能时,可将M3/Private添加到M1的PublicIncludePaths中。当在M1的Private源码中使用M3的这项功能时,可将M3/Private添加到M1的PrivateIncludePaths中。同时,在cpp中需用#include "M3/Private/xxx.h"来引用头文件。
PrivateIncludePaths.AddRange( new string[] { // ... add other private include paths required here ... System.IO.Path.Combine(GetModuleDirectory("LevelEditor"), "Private"), } );
还有一种需求:引用第三方module里的C++模板定义或抽象接口等,一般就是一些类模板和函数模板的C++头文件。这些头文件由于只包括模板或抽象接口,所以是功能完备且独立的,此种需求下,我们只需要访问这些模板或抽象接口,不需要除此之外的整个第三方module,那就可以设置PrivateIncludePathModuleNames和PublicIncludePathModuleNames这两个属性。这两个属性给予对第三方module里某些路径的代码访问权限,同时不会将第三方module的dll或lib链接到最终的exe中。
module的build.cs文件里的bPrecompile要设置为true
当以二进制方式发布插件时,对于4.22.0(不包括4.22.0)之后的版本,需要显式的设置
bPrecompile = true
然后对插件进行package操作,这样在插件的Intermediate目录中会生成对应的.precompiled文件,该文件用于指明obj文件。
发布后,还需要设置:
bUsePrecompiled = true
这样,用户端就能直接Link precompiled文件中指明的obj了,不依赖插件源码来打包。
在UE4.27里经过实测:package出来的Plugins,可以删除Intermediate目录,可以删除Binaries目录下的pdb文件,在module.build.cs里需要添加bUsePrecompiled=true;如此操作后,即便在visual studio里rebuild工程,也不会将插件rebuild,因此是安全的,但是rebuild操作会将插件Binaries目录下的dll文件删除,因此rebuild后需要将这些被删除的dll还原,无需其他操作。且整个过程中bPrecompile字段不是必须的。但与此同时,在保持这些设置的前提下,对整个工程进行打包时,又会提示找不到precompiled manifest文件,因此针对打包工程的需求,仍然需要插件的Intermediate目录。
UE4.20开始,包括UE4.20发布二进制插件
bUsePrecompiled = true;
module.build.cs文件常见字段
string path = Path.Combile(p1, p2, p3);
string absolutePath = Path.GetFullPath(path);
string absolutePath = Path.GetFullPath(path);
//https://docs.unrealengine.com/4.27/en-US/ProductionPipelines/BuildTools/UnrealBuildTool/ThirdPartyLibraries/
RuntimeDependencies.Add(Path.GetFullPath(absolutePath), StagedFileType.NonUFS);
RuntimeDependencies.Add(Path.GetFullPath(absolutePath), StagedFileType.NonUFS);
PublicDependencyModuleNames/PrivateDependencyModuleNames属于静态链接,通常其PublicIncludePaths/PrivateIncludePaths会自行处理正确。
PublicIncludePathModuleNames/PrivateIncludePathModuleNames与DynamicallyLoadedModuleNames配合属于动态链接,因此如果你使用了非抽象函数,则会提示无法找到链接符号。这一对配置的典型用法参考 #474,一般就是LoadModuleChecked,然后调用接口的抽象函数。
PublicIncludePathModuleNames/PrivateIncludePathModuleNames与DynamicallyLoadedModuleNames配合属于动态链接,因此如果你使用了非抽象函数,则会提示无法找到链接符号。这一对配置的典型用法参考 #474,一般就是LoadModuleChecked,然后调用接口的抽象函数。
关于PublicSystemLibraryPaths,PublicAdditionalLibraries,PublicLibraryPaths的问题
在(<)UE4.24的版本中,指定lib文件的方法跟visual studio里使用的方式一致:
- PublicLibraryPaths用于添加lib文件所在的目录
- PublicAdditionalLibraries用于添加lib文件,不包括路径信息
- 忽略PublicLibraryPaths字段,且PublicAdditionalLibraries字段直接添加lib文件绝对路径。
如果仍坚持老的使用方式,则会报Warning,用以下方式可以消除这个Warning,但并不能消除老的方式的效率低下的问题:
- 用PublicSystemLibraryPaths取代PublicLibraryPaths,用于添加lib文件所在的目录
- 用PublicSystemLibraries来添加库文件,但只需要库的名字即可,不需要后缀。或者直接在cpp中用#pragma comment(lib,"avcodec.lib")这种写法,会从PublicSystemLibraryPaths指定的目录下去寻找