CmvrControlStation/scripts/build_grpc_mingw.ps1

182 lines
8.0 KiB
PowerShell
Raw Normal View History

2026-09-18 16:22:20 +08:00
param(
[ValidateRange(1, 32)]
[int]$Jobs = 4,
[switch]$Fresh
)
$ErrorActionPreference = "Stop"
. (Join-Path $PSScriptRoot "native_dep_versions.ps1")
$Cmake = Join-Path $CmakeRoot "bin\cmake.exe"
foreach ($required in @($Cmake, $Make, (Join-Path $MingwBin "gcc.exe"),
(Join-Path $MingwBin "g++.exe"), $GrpcSource)) {
if (-not (Test-Path -LiteralPath $required)) { throw "Required path not found: $required" }
}
function Enable-OldMingwProtobufCompatibility {
$protobufRoot = Join-Path $GrpcSource "third_party\protobuf\src\google\protobuf"
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
function Set-TextFile([string]$path, [string]$content) {
$current = [System.IO.File]::ReadAllText($path)
if ($current -ne $content) {
[System.IO.File]::WriteAllText($path, $content, $utf8NoBom)
}
}
$portDef = Join-Path $protobufRoot "port_def.inc"
$content = [System.IO.File]::ReadAllText($portDef)
$newline = if ($content.Contains("`r`n")) { "`r`n" } else { "`n" }
if (-not $content.Contains("PROTOBUF_MINGW_CONSTEXPR")) {
$anchor = "#define PROTOBUF_CONSTINIT${newline}#endif${newline}"
$macro = @(
"#define PROTOBUF_CONSTINIT",
"#endif",
"",
"#ifdef PROTOBUF_MINGW_CONSTEXPR",
"#error PROTOBUF_MINGW_CONSTEXPR was previously defined",
"#endif",
"#if defined(__MINGW32__) && __GNUC__ < 8",
"#define PROTOBUF_MINGW_CONSTEXPR",
"#else",
"#define PROTOBUF_MINGW_CONSTEXPR constexpr",
"#endif",
""
) -join $newline
if (-not $content.Contains($anchor)) { throw "Cannot patch Protobuf port_def.inc" }
Set-TextFile $portDef $content.Replace($anchor, $macro)
}
$portUndef = Join-Path $protobufRoot "port_undef.inc"
$content = [System.IO.File]::ReadAllText($portUndef)
$newline = if ($content.Contains("`r`n")) { "`r`n" } else { "`n" }
if (-not $content.Contains("#undef PROTOBUF_MINGW_CONSTEXPR")) {
$anchor = "#undef PROTOBUF_CONSTINIT${newline}"
if (-not $content.Contains($anchor)) { throw "Cannot patch Protobuf port_undef.inc" }
Set-TextFile $portUndef $content.Replace(
$anchor, "$anchor#undef PROTOBUF_MINGW_CONSTEXPR${newline}")
}
$mutexHeader = Join-Path $protobufRoot "stubs\mutex.h"
$content = [System.IO.File]::ReadAllText($mutexHeader)
$pattern = '(?s)(class GOOGLE_PROTOBUF_CAPABILITY\("mutex"\) PROTOBUF_EXPORT WrappedMutex \{\r?\n public:\r?\n).*?( void Lock)'
$content = [regex]::Replace(
$content, $pattern, '${1} PROTOBUF_MINGW_CONSTEXPR WrappedMutex() {}' + $newline + '${2}', 1)
if (-not $content.Contains("PROTOBUF_MINGW_CONSTEXPR WrappedMutex")) {
throw "Cannot patch Protobuf mutex.h"
}
Set-TextFile $mutexHeader $content
$mapFieldHeader = Join-Path $protobufRoot "map_field.h"
$content = [System.IO.File]::ReadAllText($mapFieldHeader)
$content = [regex]::Replace(
$content,
'(?s)#if defined\(__MINGW32__\) && __GNUC__ < 8\r?\n#define PROTOBUF_MAP_FIELD_CONSTEXPR.*?#endif\r?\n\r?\n(?=class PROTOBUF_EXPORT MapFieldBase)',
'')
$content = $content.Replace("PROTOBUF_MAP_FIELD_CONSTEXPR", "PROTOBUF_MINGW_CONSTEXPR")
$content = [regex]::Replace($content, '(?m)^#undef PROTOBUF_MINGW_CONSTEXPR\r?\n', '')
$content = [regex]::Replace(
$content,
'explicit constexpr (MapFieldBase|TypeDefinedMapFieldBase|MapField)\(ConstantInitialized',
'explicit PROTOBUF_MINGW_CONSTEXPR $1(ConstantInitialized')
if (([regex]::Matches($content, "PROTOBUF_MINGW_CONSTEXPR (MapFieldBase|TypeDefinedMapFieldBase|MapField)\(")).Count -ne 3) {
throw "Cannot patch Protobuf map_field.h"
}
Set-TextFile $mapFieldHeader $content
$cppMessage = Join-Path $protobufRoot "compiler\cpp\cpp_message.cc"
$content = [System.IO.File]::ReadAllText($cppMessage)
$content = $content.Replace('explicit constexpr $classname$(', 'explicit PROTOBUF_MINGW_CONSTEXPR $classname$(')
$content = $content.Replace('"explicit constexpr "', '"explicit PROTOBUF_MINGW_CONSTEXPR "')
$content = $content.Replace('"constexpr $classname$::$classname$(', '"PROTOBUF_MINGW_CONSTEXPR $classname$::$classname$(')
Set-TextFile $cppMessage $content
$cppFile = Join-Path $protobufRoot "compiler\cpp\cpp_file.cc"
$content = [System.IO.File]::ReadAllText($cppFile)
$content = $content.Replace('" constexpr $1$()\n"', '" PROTOBUF_MINGW_CONSTEXPR $1$()\n"')
Set-TextFile $cppFile $content
foreach ($generatedRoot in @($GrpcSource, (Join-Path $GrpcBuild "gens"))) {
if (-not (Test-Path -LiteralPath $generatedRoot)) { continue }
foreach ($header in Get-ChildItem -LiteralPath $generatedRoot -Recurse -Filter "*.pb.h") {
$content = [System.IO.File]::ReadAllText($header.FullName)
$content = $content.Replace("explicit constexpr ", "explicit PROTOBUF_MINGW_CONSTEXPR ")
Set-TextFile $header.FullName $content
}
foreach ($source in Get-ChildItem -LiteralPath $generatedRoot -Recurse -Filter "*.pb.cc") {
$content = [System.IO.File]::ReadAllText($source.FullName)
$content = [regex]::Replace(
$content,
'(?m)^constexpr (?=[A-Za-z_][A-Za-z0-9_]*::[A-Za-z_][A-Za-z0-9_]*\()',
'PROTOBUF_MINGW_CONSTEXPR ')
$content = [regex]::Replace(
$content,
'(?m)^ constexpr (?=[A-Za-z_][A-Za-z0-9_]*DefaultTypeInternal\(\))',
' PROTOBUF_MINGW_CONSTEXPR ')
Set-TextFile $source.FullName $content
}
}
Write-Host "Applied Protobuf default-instance compatibility patch for MinGW GCC 7"
}
Enable-OldMingwProtobufCompatibility
New-Item -ItemType Directory -Force $GrpcBuild, $GrpcInstall | Out-Null
$env:PATH = "$MingwBin;$(Join-Path $CmakeRoot 'bin');$env:PATH"
$GrpcSourceCmake = $GrpcSource.Replace("\", "/")
$GrpcBuildCmake = $GrpcBuild.Replace("\", "/")
$GrpcInstallCmake = $GrpcInstall.Replace("\", "/")
$MingwBinCmake = $MingwBin.Replace("\", "/")
$MakeCmake = $Make.Replace("\", "/")
$configurePrefix = @()
if ($Fresh -or -not (Test-Path -LiteralPath (Join-Path $GrpcBuild "CMakeCache.txt"))) {
$configurePrefix += "--fresh"
}
& $Cmake @configurePrefix -S $GrpcSourceCmake -B $GrpcBuildCmake -G "MinGW Makefiles" `
"-DCMAKE_BUILD_TYPE=Release" `
"-DCMAKE_INSTALL_PREFIX=$GrpcInstallCmake" `
"-DCMAKE_C_COMPILER=$MingwBinCmake/gcc.exe" `
"-DCMAKE_CXX_COMPILER=$MingwBinCmake/g++.exe" `
"-DCMAKE_MAKE_PROGRAM=$MakeCmake" `
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON" `
"-DBUILD_SHARED_LIBS=OFF" `
"-DBUILD_TESTING=OFF" `
"-DgRPC_INSTALL=ON" `
"-DgRPC_BUILD_TESTS=OFF" `
"-DgRPC_BUILD_CODEGEN=ON" `
"-DgRPC_BUILD_GRPC_CPP_PLUGIN=ON" `
"-DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF" `
"-DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF" `
"-DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF" `
"-DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF" `
"-DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF" `
"-DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF" `
"-DgRPC_ABSL_PROVIDER=module" `
"-DgRPC_CARES_PROVIDER=module" `
"-DgRPC_PROTOBUF_PROVIDER=module" `
"-DgRPC_RE2_PROVIDER=module" `
"-DgRPC_SSL_PROVIDER=module" `
"-DgRPC_ZLIB_PROVIDER=module" `
"-DRE2_BUILD_TESTING=OFF" `
"-Dprotobuf_BUILD_TESTS=OFF" `
"-Dprotobuf_BUILD_SHARED_LIBS=OFF" `
"-DABSL_ENABLE_INSTALL=ON" `
"-DCARES_STATIC=ON" `
"-DCARES_SHARED=OFF" `
"-DCARES_BUILD_TOOLS=OFF" `
"-DOPENSSL_NO_ASM=ON"
if ($LASTEXITCODE -ne 0) { throw "gRPC configure failed" }
& $Cmake --build $GrpcBuild --target install --parallel $Jobs
if ($LASTEXITCODE -ne 0) { throw "gRPC build failed" }
$Protoc = Join-Path $GrpcInstall "bin\protoc.exe"
$GrpcPlugin = Join-Path $GrpcInstall "bin\grpc_cpp_plugin.exe"
if (-not (Test-Path -LiteralPath $Protoc) -or -not (Test-Path -LiteralPath $GrpcPlugin)) {
throw "gRPC build finished but protoc or grpc_cpp_plugin is missing"
}
Write-Host "gRPC and Protobuf installed to $GrpcInstall"