4.25.2Mac 打包的 metal-ar 错误

在 4.25.2 引擎版本,使用 Mac 打包时提示 metal-ar 错误,Log 中有执行 metal-ar 的报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
UATHelper: Packaging (iOS):   LogShaders: Error: Archiving failed: metal-ar failed with code 2: Couldn't posix_spawn: error 7
UATHelper: Packaging (iOS): LogShaders: Error: Archiving failed: metal-ar failed with code 2: Couldn't posix_spawn: error 7
UATHelper: Packaging (iOS): LogShaders: Error: Archiving failed: metal-ar failed with code 2: Couldn't posix_spawn: error 7
UATHelper: Packaging (iOS): LogShaders: Error: Archiving failed: no valid input for metallib.
UATHelper: Packaging (iOS): LogShaders: Error: Archiving failed: no valid input for metallib.
UATHelper: Packaging (iOS): LogShaders: Error: Archiving failed: no valid input for metallib.
UATHelper: Packaging (iOS): LogZipArchiveWriter: Display: Closing zip file with 25491 entries.
UATHelper: Packaging (iOS): CookResults: Error: Package Native Shader Library failed for IOS.
UATHelper: Packaging (iOS): LogCook: Display: Saved scl.csv /Users/buildmachine/Documents/BuildWorkspace/workspace/PackageClient/Client/Saved/Cooked/IOS/FGame/Metadata/PipelineCaches/ShaderStableInfo-Global-SF_METAL.scl.csv for platform IOS
UATHelper: Packaging (iOS): LogCook: Display: Saved scl.csv /Users/buildmachine/Documents/BuildWorkspace/workspace/PackageClient/Client/Saved/Cooked/IOS/FGame/Metadata/PipelineCaches/ShaderStableInfo-FGame-SF_METAL.scl.csv for platform IOS
PackagingResults: Error: Archiving failed: metal-ar failed with code 2: Couldn't posix_spawn: error 7
PackagingResults: Error: Archiving failed: metal-ar failed with code 2: Couldn't posix_spawn: error 7
PackagingResults: Error: Archiving failed: metal-ar failed with code 2: Couldn't posix_spawn: error 7
PackagingResults: Error: Archiving failed: no valid input for metallib.
PackagingResults: Error: Archiving failed: no valid input for metallib.
PackagingResults: Error: Archiving failed: no valid input for metallib.
PackagingResults: Error: Package Native Shader Library failed for IOS.

引擎中调用 metal-ar 的代码如下:

感觉错误的问题像是传递给 metal-ar 的参数太长了导致的,把 metal-ar 参数打出来发现确实非常长:

解决办法,把在 Mac 上 GetMaxArgLength 的返回值改成一个较小的值或者从环境变量中获取即可:

Developer\Apple\MetalShaderFormat\Private\MetalShaderCompiler.cpp
1
2
3
4
5
6
7
8
9
10
11
static uint32 GetMaxArgLength()
{
#if PLATFORM_MAC && !UNIXLIKE_TO_MAC_REMOTE_BUILDING
// 引擎中原始代码为返回 ARG_MAX
// return ARG_MAX;
return 4096;
#else
// Ask the remote machine via "getconf ARG_MAX"
return 1024;
#endif
}

在官方版本的 4.25.2 中已经修复:Use runtime evaluation of ARG_MAX instead of the compile-time constant (which in Xcode 12 is now 1m)

Developer\Apple\MetalShaderFormat\Private\MetalShaderCompiler.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
static uint32 GetMaxArgLength()
{
#if PLATFORM_MAC && !UNIXLIKE_TO_MAC_REMOTE_BUILDING
static uint32 MaxLength = 0;
if (!MaxLength)
{
// It's dangerous to use "ARG_MAX" directly because it's a compile time constant and may not be compatible with the running OS.
// It's safer to get the number from "getconf ARG_MAX" and only use the constant as the fallback
FString StdOut, StdError;
if (ExecRemoteProcess(TEXT("/usr/bin/getconf"), TEXT("ARG_MAX"), nullptr, &StdOut, &StdError))
{
MaxLength = FCString::Atoi(*StdOut);
check(MaxLength > 0);
UE_LOG(LogMetalShaderCompiler, Display, TEXT("Set MaxArgLength to %d via getconf"), MaxLength);
}
else
{
MaxLength = FMath::Min(ARG_MAX, 256 * 1024);
UE_LOG(LogMetalShaderCompiler, Warning, TEXT("Failed to determine MaxArgLength via getconf: %s\nSet it to %d which is the lesser of MAX_ARG and the value from the 10.15 SDK"), *StdError, MaxLength);
}
}
return MaxLength;
#else
// Ask the remote machine via "getconf ARG_MAX"
return 1024;
#endif
}