tools/helper.psm1 (245 lines of code) (raw):

# # Copyright (c) Microsoft. All rights reserved. # Licensed under the MIT license. See LICENSE file in the project root for full license information. # using namespace System.Runtime.InteropServices $IsWindowsEnv = [RuntimeInformation]::IsOSPlatform([OSPlatform]::Windows) $RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path $DotnetSDKVersionRequirements = @{ # .NET SDK 3.1 is required by the Microsoft.ManifestTool.dll tool '3.1' = @{ MinimalPatch = '426' DefaultPatch = '426' } '8.0' = @{ MinimalPatch = '405' DefaultPatch = '405' } } $GrpcToolsVersion = '2.50.0' # grpc.tools $GoogleProtobufToolsVersion = '3.21.9' # google.protobuf.tools function Find-Dotnet { $listSdksOutput = dotnet --list-sdks $installedDotnetSdks = $listSdksOutput | ForEach-Object { $_.Split(" ")[0] } Write-Log "Detected dotnet SDKs: $($installedDotnetSdks -join ', ')" foreach ($majorMinorVersion in $DotnetSDKVersionRequirements.Keys) { $minimalVersion = "$majorMinorVersion.$($DotnetSDKVersionRequirements[$majorMinorVersion].MinimalPatch)" $firstAcceptable = $installedDotnetSdks | Where-Object { $_.StartsWith("$majorMinorVersion.") } | Where-Object { [System.Management.Automation.SemanticVersion]::new($_) -ge [System.Management.Automation.SemanticVersion]::new($minimalVersion) } | Select-Object -First 1 if (-not $firstAcceptable) { throw "Cannot find the dotnet SDK for .NET Core $majorMinorVersion. Version $minimalVersion or higher is required. Please specify '-Bootstrap' to install build dependencies." } } } function Install-Dotnet { [CmdletBinding()] param( [string]$Channel = 'release' ) try { Find-Dotnet return # Simply return if we find dotnet SDk with the correct version } catch { } $obtainUrl = "https://raw.githubusercontent.com/dotnet/install-scripts/main/src" try { $installScript = if ($IsWindowsEnv) { "dotnet-install.ps1" } else { "dotnet-install.sh" } Invoke-WebRequest -Uri $obtainUrl/$installScript -OutFile $installScript foreach ($majorMinorVersion in $DotnetSDKVersionRequirements.Keys) { $version = "$majorMinorVersion.$($DotnetSDKVersionRequirements[$majorMinorVersion].DefaultPatch)" Write-Log "Installing dotnet SDK version $version" -Warning if ($IsWindowsEnv) { & .\$installScript -Channel $Channel -Version $Version -InstallDir "$env:ProgramFiles/dotnet" } else { bash ./$installScript -c $Channel -v $Version --install-dir /usr/share/dotnet } } } finally { Remove-Item $installScript -Force -ErrorAction SilentlyContinue } } function New-gRPCAutoGenCode { [CmdletBinding()] param( [switch] $Force ) if ($Force -or -not (Test-Path "$RepoRoot/src/Messaging/protobuf/FunctionRpc.cs") -or -not (Test-Path "$RepoRoot/src/Messaging/protobuf/FunctionRpcGrpc.cs")) { Write-Log "Generate the CSharp code for gRPC communication from protobuf" Resolve-ProtoBufToolPath $outputDir = "$RepoRoot/src/Messaging/protobuf" Remove-Item $outputDir -Recurse -Force -ErrorAction SilentlyContinue New-Item $outputDir -ItemType Directory -Force -ErrorAction Stop > $null $allProtoFiles = Get-ChildItem -Path $Script:protobuf_dir_Path -Filter "*.proto" -Recurse $fileList = $allProtoFiles.FullName & $Script:protoc_Path $fileList ` --csharp_out $outputDir ` --grpc_out=$outputDir ` --plugin=protoc-gen-grpc=$Script:grpc_csharp_plugin_Path ` --proto_path=$Script:protobuf_dir_Path ` --proto_path=$Script:google_protobuf_tools_Path if ($LASTEXITCODE -ne 0) { throw "Failed to generate the CSharp code for gRPC communication." } } } function Resolve-ProtoBufToolPath { if (-not $Script:protoc_Path) { Write-Log "Resolve the protobuf tools for auto-generating code" $nugetPath = Get-NugetPackagesPath $toolsPath = "$RepoRoot/tools" if (-not (Test-Path "$toolsPath/obj/project.assets.json") -or -not (Test-Path "$nugetPath/grpc.tools/$GrpcToolsVersion")) { dotnet restore $toolsPath --verbosity quiet if ($LASTEXITCODE -ne 0) { throw "Cannot resolve protobuf tools. 'dotnet restore $toolsPath' failed." } } if ($IsWindowsEnv) { $plat_arch_Name = "windows_x64" $protoc_Name = "protoc.exe" $grpc_csharp_plugin_Name = "grpc_csharp_plugin.exe" } else { $plat_arch_Name = if ($IsLinux) { "linux_x64" } else { "macosx_x64" } $protoc_Name = "protoc" $grpc_csharp_plugin_Name = "grpc_csharp_plugin" } $Script:protoc_Path = Resolve-Path "$nugetPath/grpc.tools/$GrpcToolsVersion/tools/$plat_arch_Name/$protoc_Name" | ForEach-Object Path if (-not $Script:protoc_Path) { throw "Couldn't find the executable 'protoc'. Check if the package 'grpc.tools' has been restored." } $Script:grpc_csharp_plugin_Path = Resolve-Path "$nugetPath/grpc.tools/$GrpcToolsVersion/tools/$plat_arch_Name/$grpc_csharp_plugin_Name" | ForEach-Object Path if (-not $Script:grpc_csharp_plugin_Path) { throw "Couldn't find the executable 'grpc_csharp_plugin'. Check if the package 'grpc.tools' has been restored." } $Script:google_protobuf_tools_Path = Resolve-Path "$nugetPath/google.protobuf.tools/$GoogleProtobufToolsVersion/tools" | ForEach-Object Path if (-not $Script:google_protobuf_tools_Path) { throw "Couldn't find the protobuf tools. Check if the package 'google.protobuf.tools' has been restored." } $Script:protobuf_dir_Path = "$RepoRoot/protobuf/src/proto" } } function Write-Log { param( [string] $Message, [switch] $Warning, [switch] $Indent ) $foregroundColor = if ($Warning) { "Yellow" } else { "Green" } $indentPrefix = if ($Indent) { " " } else { "" } Write-Host -ForegroundColor $foregroundColor "${indentPrefix}${Message}" } function Get-NugetPackagesPath { if ($env:NUGET_PACKAGES) { return $env:NUGET_PACKAGES } if ($IsWindowsEnv) { return "${env:USERPROFILE}\.nuget\packages" } else { return "${env:HOME}/.nuget/packages" } } #region Start-ResGen $generated_code_template = @' //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a running 'Start-ResGen' from tools\helper.psm1. // To add or remove a member, edit your .resx file then rerun 'Start-ResGen'. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ using System; using System.Reflection; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> internal class {0} {{ private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager {{ get {{ if (object.ReferenceEquals(resourceMan, null)) {{ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Functions.PowerShellWorker.resources.{0}", typeof({0}).Assembly); resourceMan = temp; }} return resourceMan; }} }} /// <summary> /// Overrides the current threads CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture {{ get {{ return resourceCulture; }} set {{ resourceCulture = value; }} }} {1} }} '@ $individual_resource_string_proprety = @' /// <summary> /// Looks up a localized string similar to /// {0} /// </summary> internal static string {1} {{ get {{ return ResourceManager.GetString("{1}", resourceCulture); }} }} '@ function Start-ResGen { param([switch] $Force) $sourceDir = (Resolve-Path -Path "$PSScriptRoot/../src").Path $genDir = Join-Path -Path $sourceDir -ChildPath gen if (Test-Path -Path $genDir -PathType Container) { if ($Force) { Remove-Item -Path $genDir -Recurse -Force } else { return } } $resourceDir = Join-Path -Path $sourceDir -ChildPath resources $resxFiles = Get-ChildItem -Path $resourceDir -Filter *.resx $null = New-Item -Path $genDir -ItemType Directory -Force foreach ($resx in $resxFiles) { $typeName = [System.IO.Path]::GetFileNameWithoutExtension($resx.FullName) $resXml = [xml] (Get-Content $resx.FullName) $properties = [System.Text.StringBuilder]::new() foreach ($data in $resXml.root.data) { $name = $data.name $value = $data.value -replace "`n","\n" $property = $individual_resource_string_proprety -f $value, $name $null = $properties.Append($property) } $typeCode = $generated_code_template -f $typeName, $properties.ToString() $typeFile = Join-Path -Path $genDir "$typeName.cs" Set-Content -Path $typeFile -Value $typeCode } } #endregion Start-ResGen