This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit 0c56b7a88ac4fe91ae8568b8975d0b8fc96c265d
Author: Shad Storhaug <[email protected]>
AuthorDate: Thu Jan 6 13:28:43 2022 +0700

    Added bash script, build.ps1 script to process command arguments, and 
modified build.bat to only pass the arguments to build.ps1 without doing any 
processing, only checking for the existence of Powershell. Fixes #364.
---
 .build/azure-templates/install-dotnet-sdk.yml      |  42 +++
 .build/azure-templates/run-tests-on-os.yml         |  22 +-
 .build/runbuild.ps1                                | 285 +++++++--------------
 Directory.Build.targets                            |  11 +
 Lucene.Net.sln                                     |   3 +
 README.md                                          |  56 ++--
 TestTargetFramework.props                          |   4 +
 azure-pipelines.yml                                |  31 ++-
 build                                              |  55 ++++
 build.bat                                          | 109 +-------
 build.ps1                                          |  96 +++++++
 .../Lucene.Net.Analysis.Common.csproj              |   3 +-
 .../Lucene.Net.Analysis.Kuromoji.csproj            |   3 +-
 .../Lucene.Net.Analysis.Morfologik.csproj          |   3 +-
 .../Lucene.Net.Analysis.OpenNLP.csproj             |   3 +-
 .../Lucene.Net.Analysis.Phonetic.csproj            |   3 +-
 .../Lucene.Net.Analysis.SmartCn.csproj             |   3 +-
 .../Lucene.Net.Analysis.Stempel.csproj             |   3 +-
 .../Lucene.Net.Benchmark.csproj                    |   3 +-
 .../Lucene.Net.Classification.csproj               |   3 +-
 src/Lucene.Net.Codecs/Lucene.Net.Codecs.csproj     |   3 +-
 src/Lucene.Net.Demo/Lucene.Net.Demo.csproj         |   3 +-
 .../Lucene.Net.Expressions.csproj                  |   3 +-
 src/Lucene.Net.Facet/Lucene.Net.Facet.csproj       |   3 +-
 src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj |   3 +-
 .../Lucene.Net.Highlighter.csproj                  |   3 +-
 src/Lucene.Net.Join/Lucene.Net.Join.csproj         |   3 +-
 src/Lucene.Net.Memory/Lucene.Net.Memory.csproj     |   3 +-
 src/Lucene.Net.Misc/Lucene.Net.Misc.csproj         |   3 +-
 src/Lucene.Net.Queries/Lucene.Net.Queries.csproj   |   3 +-
 .../Lucene.Net.QueryParser.csproj                  |   3 +-
 .../Lucene.Net.Replicator.csproj                   |   3 +-
 src/Lucene.Net.Sandbox/Lucene.Net.Sandbox.csproj   |   3 +-
 src/Lucene.Net.Spatial/Lucene.Net.Spatial.csproj   |   3 +-
 src/Lucene.Net.Suggest/Lucene.Net.Suggest.csproj   |   3 +-
 .../Lucene.Net.TestFramework.csproj                |   3 +-
 .../Lucene.Net.Tests.Analysis.OpenNLP.csproj       |   5 +
 src/Lucene.Net/Lucene.Net.csproj                   |   3 +-
 src/dotnet/Lucene.Net.ICU/Lucene.Net.ICU.csproj    |   3 +-
 .../Lucene.Net.Replicator.AspNetCore.csproj        |   3 +-
 .../Lucene.Net.Tests.CodeAnalysis.csproj           |   1 +
 .../Lucene.Net.Tests.Cli.csproj                    |   1 +
 42 files changed, 418 insertions(+), 387 deletions(-)

diff --git a/.build/azure-templates/install-dotnet-sdk.yml 
b/.build/azure-templates/install-dotnet-sdk.yml
new file mode 100644
index 0000000..4737996
--- /dev/null
+++ b/.build/azure-templates/install-dotnet-sdk.yml
@@ -0,0 +1,42 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Installs the .NET SDK and disables telemetry
+
+parameters:
+  sdkVersion: '' # The .NET SDK version to install
+
+steps:
+- pwsh: |
+    function EnsureNotNullOrEmpty([string]$param, [string]$nameOfParam) {
+        if ([string]::IsNullOrEmpty($param)) {
+            Write-Host "##vso[task.logissue type=error;]Missing template 
parameter \"$nameOfParam\""
+            Write-Host "##vso[task.complete result=Failed;]"
+        }
+    }
+    EnsureNotNullOrEmpty('${{ parameters.sdkVersion }}', 'sdkVersion')
+  displayName: 'Validate Template Parameters'
+
+- bash: |
+    echo "##vso[task.setvariable variable=DOTNET_NOLOGO;]1"
+    echo "##vso[task.setvariable variable=DOTNET_CLI_TELEMETRY_OPTOUT;]1"
+
+- task: UseDotNet@2
+  displayName: 'Use .NET SDK ${{ parameters.sdkVersion }}'
+  inputs:
+    packageType: 'sdk'
+    version: '${{ parameters.sdkVersion }}'
\ No newline at end of file
diff --git a/.build/azure-templates/run-tests-on-os.yml 
b/.build/azure-templates/run-tests-on-os.yml
index 0f975bf..9dfa28e 100644
--- a/.build/azure-templates/run-tests-on-os.yml
+++ b/.build/azure-templates/run-tests-on-os.yml
@@ -33,6 +33,7 @@ parameters:
   maximumParallelJobs: 8
   maximumAllowedFailures: 0
   where: '' # A test filter expression, as defined by dotnet vstest
+  dotNetSdkVersion: '' # The .NET SDK version to install
   
 steps:
 - checkout: none # self represents the repo where the initial Pipelines YAML 
file was found
@@ -54,6 +55,7 @@ steps:
     EnsureNotNullOrEmpty('${{ parameters.testResultsFileName }}', 
'testResultsFileName')
     EnsureNotNullOrEmpty('${{ parameters.maximumParallelJobs }}', 
'maximumParallelJobs')
     EnsureNotNullOrEmpty('${{ parameters.maximumAllowedFailures }}', 
'maximumAllowedFailures')
+    EnsureNotNullOrEmpty('${{ parameters.dotNetSdkVersion }}', 
'dotNetSdkVersion')
   displayName: 'Validate Template Parameters'
 
 
@@ -73,23 +75,9 @@ steps:
 
 #- pwsh: Get-ChildItem -Path $(System.DefaultWorkingDirectory) # Uncomment for 
debugging
 
-- task: UseDotNet@2
-  displayName: 'Use .NET Core sdk 3.1.412'
-  inputs:
-    version: 3.1.412
-  condition: and(succeeded(), contains('${{ parameters.framework }}', 
'netcoreapp3.'))
-
-- task: UseDotNet@2
-  displayName: 'Use .NET sdk 5.0.400'
-  inputs:
-    version: 5.0.400
-  condition: and(succeeded(), contains('${{ parameters.testTargetFrameworks 
}}', 'net5.'))
-
-- task: UseDotNet@2
-  displayName: 'Use .NET sdk 6.0.100'
-  inputs:
-    packageType: 'sdk'
-    version: '6.0.100'
+- template: 'install-dotnet-sdk.yml'
+  parameters:
+    sdkVersion: '${{ parameters.dotNetSdkVersion }}'
 
 #- template: 'show-all-files.yml' # Uncomment for debugging
 - pwsh: |
diff --git a/.build/runbuild.ps1 b/.build/runbuild.ps1
index 2680a8a..a62d460 100644
--- a/.build/runbuild.ps1
+++ b/.build/runbuild.ps1
@@ -18,20 +18,20 @@
 # 
-----------------------------------------------------------------------------------
 
 properties {
-    [string]$base_directory   = Resolve-Path "../."
-    [string]$artifactsDirectory  = "$base_directory/_artifacts"
-    [string]$source_directory = "$base_directory"
-    [string]$tools_directory  = "$base_directory/lib"
-    [string]$nuget_package_directory = "$artifactsDirectory/NuGetPackages"
-    [string]$test_results_directory = "$artifactsDirectory/TestResults"
-    [string]$publish_directory = "$artifactsDirectory/Publish"
-    [string]$solutionFile = "$base_directory/Lucene.Net.sln"
+    [string]$baseDirectory   = Resolve-Path "../."
+    [string]$artifactsDirectory  = "$baseDirectory/_artifacts"
+    [string]$sourceDirectory = "$baseDirectory/src"
+    [string]$testDirectory = "$baseDirectory/src"
+    [string]$toolsDirectory  = "$baseDirectory/lib"
+    [string]$nugetPackageDirectory = "$artifactsDirectory/NuGetPackages"
+    [string]$testResultsDirectory = "$artifactsDirectory/TestResults"
+    [string]$publishDirectory = "$artifactsDirectory/Publish"
+    [string]$solutionFile = "$baseDirectory/Lucene.Net.sln"
     [string]$minimumSdkVersion = "6.0.100"
-    [string]$globalJsonFile = "$base_directory/global.json"
-    [string]$versionPropsFile = "$base_directory/version.props"
-    [string]$build_bat = "$base_directory/build.bat"
-    [string]$luceneReadmeFile = 
"$base_directory/src/Lucene.Net/readme-nuget.md"
-    [string]$luceneCLIReadmeFile = 
"$base_directory/src/dotnet/tools/lucene-cli/docs/index.md"
+    [string]$globalJsonFile = "$baseDirectory/global.json"
+    [string]$versionPropsFile = "$baseDirectory/version.props"
+    [string]$luceneReadmeFile = "$baseDirectory/src/Lucene.Net/readme-nuget.md"
+    [string]$luceneCLIReadmeFile = 
"$baseDirectory/src/dotnet/tools/lucene-cli/docs/index.md"
     [string]$rootWebsiteUrl = "https://lucenenet.apache.org";
     [string]$rootDocsWebsiteUrl = "$rootWebsiteUrl/docs"
 
@@ -42,23 +42,19 @@ properties {
     [string]$version          = Get-Version
     [string]$configuration    = $(if ($configuration) { $configuration } else 
{ if ($env:BuildConfiguration) { $env:BuildConfiguration } else { "Release" } 
})  #NOTE: Pass in as a parameter (not a property) or environment variable to 
override
     [string]$platform   = $(if ($platform) { $platform } else { if 
($env:BuildPlatform) { $env:BuildPlatform } else { "Any CPU" } })  #NOTE: Pass 
in as a parameter (not a property) or environment variable to override
-    [bool]$backup_files       = $true
+    [bool]$backupFiles       = $true
     [bool]$prepareForBuild    = $true
-    [bool]$generateBuildBat   = $false
     [bool]$zipPublishedArtifacts = $false
     [string]$publishedArtifactZipFileName = "artifact.zip"
 
-    [int]$maximumParalellJobs = 8
+    [int]$maximumParallelJobs = 8
     
-    #test paramters
-    [string]$frameworks_to_test = "net6.0,net5.0,netcoreapp3.1,net48,net461"
+    #test parameters
+    [string]$projectWithAllTestFrameworks = 
"$baseDirectory/src/Lucene.Net.Tests.Analysis.Common/Lucene.Net.Tests.Analysis.Common.csproj"
     [string]$where = ""
 }
 
 $backedUpFiles = New-Object System.Collections.ArrayList
-if ($IsWindows -eq $null) {
-    $IsWindows = $env:OS.StartsWith('Windows')
-}
 
 task default -depends Pack
 
@@ -66,7 +62,7 @@ task Clean -description "This task cleans up the build 
directory" {
     Write-Host "##teamcity[progressMessage 'Cleaning']"
     Write-Host "##vso[task.setprogress]'Cleaning'"
     Remove-Item $artifactsDirectory -Force -Recurse -ErrorAction 
SilentlyContinue
-    Get-ChildItem $base_directory -Include *.bak -Recurse | foreach ($_) 
{Remove-Item $_.FullName}
+    Get-ChildItem $baseDirectory -Include *.bak -Recurse | foreach ($_) 
{Remove-Item $_.FullName}
 }
 
 task UpdateLocalSDKVersion -description "Backs up the project.json file and 
pins the version to $minimumSdkVersion" {
@@ -94,21 +90,22 @@ task Init -depends CheckSDK, UpdateLocalSDKVersion 
-description "This task makes
     Write-Output "##myget[buildNumber '$packageVersion']"
     Write-Host "##vso[build.updatebuildnumber]$packageVersion"
 
-    & dotnet.exe --version
-    & dotnet.exe --info
-    Write-Host "Base Directory: $base_directory"
-    Write-Host "Release Directory: $artifactsDirectory"
-    Write-Host "Source Directory: $source_directory"
-    Write-Host "Tools Directory: $tools_directory"
-    Write-Host "NuGet Package Directory: $nuget_package_directory"
+    & dotnet --version
+    & dotnet --info
+    Write-Host "Base Directory: $(Normalize-FileSystemSlashes 
"$baseDirectory")"
+    Write-Host "Release Directory: $(Normalize-FileSystemSlashes 
"$artifactsDirectory")"
+    Write-Host "Source Directory: $(Normalize-FileSystemSlashes 
"$sourceDirectory")"
+    Write-Host "Test Directory: $(Normalize-FileSystemSlashes 
"$testDirectory")"
+    Write-Host "Tools Directory: $(Normalize-FileSystemSlashes 
"$toolsDirectory")"
+    Write-Host "NuGet Package Directory: $(Normalize-FileSystemSlashes 
"$nugetPackageDirectory")"
     Write-Host "BuildCounter: $buildCounter"
     Write-Host "PreReleaseCounterPattern: $preReleaseCounterPattern"
     Write-Host "VersionSuffix: $versionSuffix"
     Write-Host "Package Version: $packageVersion"
-    Write-Host "Version: $version"
+    Write-Host "File Version: $version"
     Write-Host "Configuration: $configuration"
     Write-Host "Platform: $platform"
-    Write-Host "MaximumParallelJobs: $($maximumParalellJobs.ToString())"
+    Write-Host "MaximumParallelJobs: $($maximumParallelJobs.ToString())"
     Write-Host "Powershell Version: $($PSVersionTable.PSVersion)"
 
     Ensure-Directory-Exists "$artifactsDirectory"
@@ -118,7 +115,7 @@ task Restore -description "This task restores the 
dependencies" {
     Write-Host "##teamcity[progressMessage 'Restoring']"
     Write-Host "##vso[task.setprogress]'Restoring'"
     Exec { 
-        & dotnet.exe restore $solutionFile --no-dependencies 
/p:TestFrameworks=true
+        & dotnet restore $solutionFile --no-dependencies /p:TestFrameworks=true
     }
 }
 
@@ -130,13 +127,9 @@ task Compile -depends Clean, Init, Restore -description 
"This task compiles the
             Prepare-For-Build
         }
 
-        $testFrameworks = [string]::Join(';', (Get-FrameworksToTest))
-
-        Write-Host "TestFrameworks set to: $testFrameworks" -ForegroundColor 
Green
-
         Exec {
             # NOTE: Version information is not passed in at the command line,
-            # instead it is output to the Version.props file. This file is then
+            # instead it is output to the version.props file. This file is then
             # used during a release to "freeze" the build at a specific version
             # so it is always a constant in release distributions.
             & dotnet build "$solutionFile" `
@@ -159,17 +152,17 @@ task Pack -depends Compile -description "This task 
creates the NuGet packages" {
     Write-Host "##teamcity[progressMessage 'Packing']"
     Write-Host "##vso[task.setprogress]'Packing'"
     #create the nuget package output directory
-    Ensure-Directory-Exists "$nuget_package_directory"
+    Ensure-Directory-Exists "$nugetPackageDirectory"
     Update-Lucene-Readme-For-Pack $packageVersion
     Update-LuceneCLI-Readme-For-Pack $packageVersion
 
     try {
         Exec {
             # NOTE: Package version information is not passed in at the 
command line,
-            # instead it is output to the Version.props file. This file is then
+            # instead it is output to the version.props file. This file is then
             # used during a release to "freeze" the build at a specific version
             # so it is always a constant in release distributions.
-            & dotnet.exe pack $solutionFile --configuration $configuration 
--output $nuget_package_directory --no-build
+            & dotnet pack $solutionFile --configuration $configuration 
--output $nugetPackageDirectory --no-build
         }
 
         $success = $true
@@ -177,7 +170,7 @@ task Pack -depends Compile -description "This task creates 
the NuGet packages" {
         #if ($success -ne $true) {
             Restore-Files $backedUpFiles
             #Remove Version.props, as we don't want it to be committed to the 
repository
-            if ($backup_files -eq $true -and (Test-Path -Path 
"$versionPropsFile") -eq $true) {
+            if ($backupFiles -eq $true -and (Test-Path -Path 
"$versionPropsFile") -eq $true) {
                 Remove-Item -Path "$versionPropsFile" -Force
             }
         #}
@@ -193,18 +186,18 @@ task Publish -depends Compile -description "This task 
uses dotnet publish to pac
 
     try {
         $frameworksToTest = Get-FrameworksToTest
-
+        
         if ($zipPublishedArtifacts) {
             $outDirectory = New-TemporaryDirectory
         } else {
-            $outDirectory = $publish_directory
+            $outDirectory = $publishDirectory
         }
         
         foreach ($framework in $frameworksToTest) {
 
             # Pause if we have queued too many parallel jobs
             $running = @(Get-Job | Where-Object { $_.State -eq 'Running' })
-            if ($running.Count -ge $maximumParalellJobs) {
+            if ($running.Count -ge $maximumParallelJobs) {
                 $running | Wait-Job -Any | Out-Null
             }
 
@@ -245,9 +238,9 @@ task Publish -depends Compile -description "This task uses 
dotnet publish to pac
         #Get-Job | Receive-Job
 
         if ($zipPublishedArtifacts) {
-            Ensure-Directory-Exists $publish_directory
+            Ensure-Directory-Exists $publishDirectory
             Add-Type -assembly "System.IO.Compression.Filesystem"
-            
[System.IO.Compression.ZipFile]::CreateFromDirectory($outDirectory, 
"$publish_directory/$publishedArtifactZipFileName")
+            
[System.IO.Compression.ZipFile]::CreateFromDirectory($outDirectory, 
"$publishDirectory/$publishedArtifactZipFileName")
         }
 
         $success = $true
@@ -263,52 +256,51 @@ task Test -depends CheckSDK, UpdateLocalSDKVersion, 
Restore -description "This t
     Write-Host "##vso[task.setprogress]'Testing'"
     Write-Host "Running tests..." -ForegroundColor DarkCyan
 
-    pushd $base_directory
-    $testProjects = Get-ChildItem -Path "$source_directory/**/*.csproj" 
-Recurse | ? { $_.Directory.Name.Contains(".Tests") }
+    pushd $baseDirectory
+    $testProjects = Get-ChildItem -Path "$testDirectory/**/*.csproj" -Recurse 
| ? { $_.Directory.Name.Contains(".Tests") }
     popd
 
     $testProjects = $testProjects | Sort-Object -Property FullName
-
+    
     $frameworksToTest = Get-FrameworksToTest
 
-    Write-Host "frameworksToTest: $frameworksToTest" -ForegroundColor Yellow
-
     [int]$totalProjects = $testProjects.Length * $frameworksToTest.Length
     [int]$remainingProjects = $totalProjects
 
-    Ensure-Directory-Exists $test_results_directory
+    Ensure-Directory-Exists $testResultsDirectory
 
     foreach ($testProject in $testProjects) {
+        $testName = $testProject.Directory.Name
+        
+        # Call the target to get the configured test frameworks for this 
project. We only read the first line because MSBuild adds extra output.
+        $frameworksString = $(dotnet build "$testProject" --verbosity minimal 
--nologo --no-restore /t:PrintTargetFrameworks /p:TestProjectsOnly=true 
/p:TestFrameworks=true)[0].Trim()
 
-        foreach ($framework in $frameworksToTest) {
-            $testName = $testProject.Directory.Name
+        Write-Host ""
+        Write-Host "Frameworks To Test for ${testProject}: $frameworksString" 
-ForegroundColor Yellow
 
-            # Special case - our CLI tool only supports .NET 6.0
-            if ($testName.Contains("Tests.Cli") -and 
(!$framework.StartsWith("net6."))) {
-                $totalProjects--
-                $remainingProjects--
-                continue
-            }
-            
-            # Special case - OpenNLP.NET is only tested on .NET Framework 4.8
-            if ($testName.Contains("Tests.Analysis.OpenNLP") -and 
(!$framework.StartsWith("net48"))) {
-                $totalProjects--
-                $remainingProjects--
-                continue
-            }
+        if ($frameworksString -eq 'none') {
+            Write-Host ""
+            Write-Host "Skipping project '$testProject' because it is not 
marked with `<IsTestProject`>true`<`/IsTestProject`> and/or it contains no test 
frameworks for the current environment." -ForegroundColor DarkYellow
+            continue
+        }
 
-            # Special case - Code analysis is only tested on .NET 5
-            if ($testName.Contains("Tests.CodeAnalysis") -and 
(!$framework.StartsWith("net5."))) {
+        $frameworks = 
[System.Collections.Generic.HashSet[string]]::new($frameworksString -split 
'\s*;\s*')
+        foreach ($framework in $frameworksToTest) {
+            
+            # If the framework is not valid for this configuration, we need to 
adjust our
+            # initial estimate and skip the combination.
+            if (-not $frameworks.Contains($framework)) {
                 $totalProjects--
                 $remainingProjects--
                 continue
             }
-
+            
+            Write-Host ""
             Write-Host "  Next Project in Queue: $testName, Framework: 
$framework" -ForegroundColor Yellow
 
             # Pause if we have queued too many parallel jobs
             $running = @(Get-Job | Where-Object { $_.State -eq 'Running' })
-            if ($running.Count -ge $maximumParalellJobs) {
+            if ($running.Count -ge $maximumParallelJobs) {
                 Write-Host ""
                 Write-Host "  Running tests in parallel on $($running.Count) 
projects out of approximately $totalProjects total." -ForegroundColor Cyan
                 Write-Host "  $remainingProjects projects are waiting in the 
queue to run. This will take a bit, please wait..." -ForegroundColor Cyan
@@ -316,11 +308,11 @@ task Test -depends CheckSDK, UpdateLocalSDKVersion, 
Restore -description "This t
             }
             $remainingProjects -= 1
 
-            $testResultDirectory = 
"$test_results_directory/$framework/$testName"
+            $testResultDirectory = "$testResultsDirectory/$framework/$testName"
             Ensure-Directory-Exists $testResultDirectory
 
             $testProjectPath = $testProject.FullName
-            $testExpression = "dotnet.exe test $testProjectPath 
--configuration $configuration --framework $framework --no-build"
+            $testExpression = "dotnet test $testProjectPath --configuration 
$configuration --framework $framework --no-build"
             $testExpression = "$testExpression --no-restore --blame  
--blame-hang --blame-hang-dump-type mini --blame-hang-timeout 15minutes 
--results-directory $testResultDirectory"
 
             # Breaking change: We need to explicitly set the logger for it to 
work with TeamCity.
@@ -353,7 +345,7 @@ task Test -depends CheckSDK, UpdateLocalSDKVersion, Restore 
-description "This t
             #Invoke-Expression $testExpression
             ## fail the build on negative exit codes (NUnit errors - if 
positive it is a test count or, if 1, it could be a dotnet error)
             #if ($LASTEXITCODE -lt 0) {
-            #  throw "Test execution failed"
+            #   throw "Test execution failed"
             #}
         }
     }
@@ -386,7 +378,7 @@ function Get-Package-Version() {
         return $env:PackageVersion
     } else {
         #Get the version info
-        $versionFile = "$base_directory/Directory.Build.props"
+        $versionFile = "$baseDirectory/Directory.Build.props"
         $xml = [xml](Get-Content $versionFile)
 
         $versionPrefix = 
([string]$xml.Project.PropertyGroup.VersionPrefix).Trim()
@@ -421,16 +413,11 @@ function Get-Version() {
 }
 
 function Get-FrameworksToTest() {
-    $frameworksToTest = New-Object Collections.Generic.List[string]
-    $frameworks = $frameworks_to_test -split "\s*?,\s*?"
-    foreach ($framework in $frameworks) {
-        if ($IsWindows) {
-            $frameworksToTest.Add($framework)
-        } elseif ($framework.StartsWith('netcore') -or 
$framework.StartsWith('net5.') -or $framework.StartsWith('net6.')) {
-            $frameworksToTest.Add($framework)
-        }
-    }
-    return [System.Linq.Enumerable]::ToArray($frameworksToTest)
+    # Call the target to get the configured test frameworks for a project 
known to contain all of them. We only read the first line because MSBuild adds 
extra output.
+    $frameworksString = $(dotnet build "$projectWithAllTestFrameworks" 
--verbosity minimal --nologo --no-restore /t:PrintTargetFrameworks 
/p:TestProjectsOnly=true /p:TestFrameworks=true)[0].Trim()
+    $frameworksToTest = $frameworksString -split '\s*;\s*'
+    Assert($frameworksToTest.Length -gt 0) "The project at 
$(Normalize-FileSystemSlashes "$projectWithAllTestFrameworks") contains no 
target frameworks. Please configure a project that includes all testable target 
frameworks."
+    return $frameworksToTest
 }
 
 function Prepare-For-Build() {
@@ -443,10 +430,10 @@ function Prepare-For-Build() {
     Write-Host "Assembly version set to: $assemblyVersion" -ForegroundColor 
Green
 
     $informationalVersion = $packageVersion
-    #check for presense of Git
-    & where.exe git.exe
+
+    # Only update the version if git is present and the command to read the 
commit succeeds
+    $gitCommit = ((git rev-parse --verify --short=10 head) | Out-String).Trim()
     if ($LASTEXITCODE -eq 0) {
-        $gitCommit = ((git rev-parse --verify --short=10 head) | 
Out-String).Trim()
         $informationalVersion = "$packageVersion commit:[$gitCommit]"
     }
 
@@ -464,15 +451,10 @@ function Prepare-For-Build() {
         -PackageVersion $packageVersion `
         -File $versionPropsFile
     Update-Constants-Version $packageVersion
-
-    if ($generateBuildBat -eq $true) {
-        Backup-File $build_bat
-        Generate-Build-Bat $build_bat
-    }
 }
 
 function Update-Constants-Version([string]$version) {
-    $constantsFile = "$base_directory/src/Lucene.Net/Util/Constants.cs"
+    $constantsFile = "$baseDirectory/src/Lucene.Net/Util/Constants.cs"
 
     Backup-File $constantsFile
     (Get-Content $constantsFile) | % {
@@ -520,7 +502,7 @@ $fileText = "{
     $dir = [System.IO.Path]::GetDirectoryName($file)
     Ensure-Directory-Exists $dir
 
-    Write-Host "Generating global.json file: $file"
+    Write-Host "Generating global.json file: $(Normalize-FileSystemSlashes 
"$file")"
     Out-File -filePath $file -encoding UTF8 -inputObject $fileText
 }
 
@@ -560,92 +542,10 @@ $fileText = "<!--
     $dir = [System.IO.Path]::GetDirectoryName($file)
     Ensure-Directory-Exists $dir
 
-    Write-Host "Generating Version.props file: $file"
+    Write-Host "Generating version.props file: $(Normalize-FileSystemSlashes 
"$file")"
     Out-File -filePath $file -encoding UTF8 -inputObject $fileText
 }
 
-function Generate-Build-Bat {
-param(
-    [string]$file = $(throw "file is a required parameter.")
-)
-  $buildBat = "
-@echo off
-GOTO endcommentblock
-:: 
-----------------------------------------------------------------------------------
-::
-:: Licensed to the Apache Software Foundation (ASF) under one or more
-:: contributor license agreements.  See the NOTICE file distributed with
-:: this work for additional information regarding copyright ownership.
-:: The ASF licenses this file to You under the Apache License, Version 2.0
-:: (the ""License""); you may not use this file except in compliance with
-:: the License.  You may obtain a copy of the License at
-:: 
-:: http://www.apache.org/licenses/LICENSE-2.0
-:: 
-:: Unless required by applicable law or agreed to in writing, software
-:: distributed under the License is distributed on an ""AS IS"" BASIS,
-:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-:: See the License for the specific language governing permissions and
-:: limitations under the License.
-::
-:: 
-----------------------------------------------------------------------------------
-::
-:: This file will build Lucene.Net and create the NuGet packages.
-::
-:: Syntax:
-::   build[.bat] [<options>]
-::
-:: Available Options:
-::
-::   --Test
-::   -t - Run the tests.
-::
-::   --MaximumParallelJobs
-::   -mp - Set the maxumum number of parallel jobs to run during testing. If 
not supplied, the default is 8.
-::
-:: 
-----------------------------------------------------------------------------------
-:endcommentblock
-setlocal enabledelayedexpansion enableextensions
-set runtests=false
-set maximumParallelJobs=8
-FOR %%a IN (%*) DO (
-    FOR /f ""useback tokens=*"" %%a in ('%%a') do (
-        set value=%%~a
-        
-        set test=!value:~0,2!
-        IF /I !test!==-t (
-            set runtests=true
-        )
-        set test=!value:~0,6!
-        IF /I !test!==--test (
-            set runtests=true
-        )
-        set test=!value:~0,4!
-        IF /I !test!==-mp: (
-            set maximumParallelJobs=!value:~4!
-        )
-        set test=!value:~0,22!
-        IF /I !test!==--maximumparalleljobs: (
-            set maximumParallelJobs=!value:~22!
-        )
-    )
-)
-set tasks=""Default""
-if ""!runtests!""==""true"" (
-    set tasks=""Default,Test""
-)
-powershell -ExecutionPolicy Bypass -Command ""& { Import-Module 
.\.build\psake.psm1; Invoke-Psake .\.build\runbuild.ps1 -Task %tasks% 
-properties 
@{prepareForBuild='false';backup_files='false';maximumParalellJobs=%maximumParallelJobs%}
 }""
-endlocal
-"
-    $dir = [System.IO.Path]::GetDirectoryName($file)
-    Ensure-Directory-Exists $dir
-
-    Write-Host "Generating build.bat file: $file"
-    #Out-File -filePath $file -encoding UTF8 -inputObject $buildBat -Force
-    $Utf8EncodingNoBom = New-Object System.Text.UTF8Encoding $false
-    [System.IO.File]::WriteAllLines($file, $buildBat, $Utf8EncodingNoBom)
-}
-
 function New-CountersObject ([string]$project, [string]$outcome, [int]$total, 
[int]$executed, [int]$passed, [int]$failed, [int]$warning, [int]$inconclusive) {
     $counters = New-Object -TypeName PSObject
     $fields = 
[ordered]@{Project=$project;Outcome=$outcome;Total=$total;Executed=$executed;Passed=$passed;Failed=$failed;Warning=$warning;Inconclusive=$inconclusive}
@@ -655,9 +555,15 @@ function New-CountersObject ([string]$project, 
[string]$outcome, [int]$total, [i
 
 function Summarize-Test-Results([string[]]$frameworksToTest) {
 
+    # Workaround for issue when ForeGroundColor cannot be read. 
https://stackoverflow.com/a/26583010
+    $defaultForeground = (Get-Host).UI.RawUI.ForegroundColor
+    if ($defaultForeground -eq -1) {
+        $defaultForeground = 'White'
+    }
+
     foreach ($framework in $frameworksToTest) {
-        pushd $base_directory
-        $testReports = Get-ChildItem -Path 
"$test_results_directory/$framework" -Recurse -File -Filter "*.trx" | 
ForEach-Object {
+        pushd $baseDirectory
+        $testReports = Get-ChildItem -Path "$testResultsDirectory/$framework" 
-Recurse -File -Filter "*.trx" | ForEach-Object {
             $_.FullName
         }
         popd
@@ -745,16 +651,16 @@ function 
Summarize-Test-Results([string[]]$frameworksToTest) {
         Write-Host ""
         Write-Host "Total: $totalCountForFramework"
         Write-Host "Executed: $executedCountForFramework"
-        $foreground = if ($failedCountForFramework -gt 0) { 'Green' } else { 
(Get-Host).UI.RawUI.ForegroundColor }
+        $foreground = if ($failedCountForFramework -gt 0) { 'Green' } else { 
$defaultForeground }
         Write-Host "Passed: " -NoNewline; Write-Host 
"$passedCountForFramework" -ForegroundColor $foreground
-        $foreground = if ($failedCountForFramework -gt 0) { 'Red' } else { 
(Get-Host).UI.RawUI.ForegroundColor }
+        $foreground = if ($failedCountForFramework -gt 0) { 'Red' } else { 
$defaultForeground }
         Write-Host "Failed: " -NoNewline; Write-Host 
"$failedCountForFramework" -ForegroundColor $foreground
-        $foreground = if ($failedCountForFramework -gt 0) { 'Yellow' } else { 
(Get-Host).UI.RawUI.ForegroundColor }
+        $foreground = if ($failedCountForFramework -gt 0) { 'Yellow' } else { 
$defaultForeground }
         Write-Host "Warning: " -NoNewline; Write-Host 
"$warningCountForFramework" -ForegroundColor $foreground
-        $foreground = if ($failedCountForFramework -gt 0) { 'Cyan' } else { 
(Get-Host).UI.RawUI.ForegroundColor }
+        $foreground = if ($failedCountForFramework -gt 0) { 'Cyan' } else { 
$defaultForeground }
         Write-Host "Inconclusive: " -NoNewline; Write-Host 
"$inconclusiveCountForFramework" -ForegroundColor $foreground
         Write-Host ""
-        Write-Host "See the .trx logs in $test_results_directory/$framework 
for more details." -ForegroundColor DarkCyan
+        Write-Host "See the .trx logs in $(Normalize-FileSystemSlashes 
"$testResultsDirectory/$framework") for more details." -ForegroundColor DarkCyan
     }
 }
 
@@ -765,7 +671,7 @@ function Backup-Files([string[]]$paths) {
 }
 
 function Backup-File([string]$path) {
-    if ($backup_files -eq $true) {
+    if ($backupFiles -eq $true) {
         Copy-Item $path "$path.bak" -Force
         $backedUpFiles.Insert(0, $path)
     } else {
@@ -780,7 +686,7 @@ function Restore-Files([string[]]$paths) {
 }
 
 function Restore-File([string]$path) {
-    if ($backup_files -eq $true) {
+    if ($backupFiles -eq $true) {
         if (Test-Path "$path.bak") {
             Move-Item "$path.bak" $path -Force
         }
@@ -798,4 +704,9 @@ function New-TemporaryDirectory {
     $parent = [System.IO.Path]::GetTempPath()
     [string] $name = [System.Guid]::NewGuid()
     New-Item -ItemType Directory -Path (Join-Path $parent $name)
+}
+
+function Normalize-FileSystemSlashes([string]$path) {
+    $sep = [System.IO.Path]::DirectorySeparatorChar
+    return $($path -replace '/',$sep -replace '\\',$sep)
 }
\ No newline at end of file
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 79b4b8d..d7c6e22 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -137,6 +137,17 @@
     </ItemGroup>
   </Target>
 
+  <Target Name="PrintTargetFrameworks" Label="Prints the value for the 
$(TargetFrameworks) property or 'none' if no frameworks apply. Pass 
TestProjectsOnly=true to get results only if this is a test project.">
+    <PropertyGroup>
+      <DoOutputTargetFrameworks Condition=" '$(TestProjectsOnly)' != 'true' Or 
('$(TestProjectsOnly)' == 'true' And '$(IsTestProject)' == 
'true')">true</DoOutputTargetFrameworks>
+      <OutputTargetFrameworks Condition=" '$(DoOutputTargetFrameworks)' == 
'true' ">$(TargetFramework)</OutputTargetFrameworks>
+      <!-- Fallback to TargetFrameworks field if TargetFramework is empty -->
+      <OutputTargetFrameworks Condition=" '$(DoOutputTargetFrameworks)' == 
'true' And '$(OutputTargetFrameworks)' == '' 
">$(TargetFrameworks)</OutputTargetFrameworks>
+      <OutputTargetFrameworks Condition=" '$(OutputTargetFrameworks)' == '' 
">none</OutputTargetFrameworks>
+    </PropertyGroup>
+    <Message Text="$(OutputTargetFrameworks)" Importance="high"/>
+  </Target>
+
   <!-- Global PackageReferences -->
   <ItemGroup>
     <!-- This is to allow the .NET Framework references to be 
machine-indepenedent so builds can happen without installing prerequisites -->
diff --git a/Lucene.Net.sln b/Lucene.Net.sln
index c80f1ab..e3a427b 100644
--- a/Lucene.Net.sln
+++ b/Lucene.Net.sln
@@ -20,6 +20,7 @@ VisualStudioVersion = 16.0.29806.167
 MinimumVisualStudioVersion = 15.0.26730.8
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azure-templates", 
"azure-templates", "{05CE3A39-40D4-452D-AFE0-E57E536A08C6}"
        ProjectSection(SolutionItems) = preProject
+               .build\azure-templates\install-dotnet-sdk.yml = 
.build\azure-templates\install-dotnet-sdk.yml
                .build\azure-templates\publish-nuget-packages.yml = 
.build\azure-templates\publish-nuget-packages.yml
                .build\azure-templates\publish-test-binaries.yml = 
.build\azure-templates\publish-test-binaries.yml
                
.build\azure-templates\publish-test-results-for-test-projects.yml = 
.build\azure-templates\publish-test-results-for-test-projects.yml
@@ -37,7 +38,9 @@ EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".build", ".build", 
"{4016BDAB-6C33-4D1E-9439-57B416EA45D5}"
        ProjectSection(SolutionItems) = preProject
                azure-pipelines.yml = azure-pipelines.yml
+               build = build
                build.bat = build.bat
+               build.ps1 = build.ps1
                .build\runbuild.ps1 = .build\runbuild.ps1
                .build\dependencies.props = .build\dependencies.props
                .build\nuget.props = .build\nuget.props
diff --git a/README.md b/README.md
index 93a2b11..579a548 100644
--- a/README.md
+++ b/README.md
@@ -171,25 +171,35 @@ Before you start working on a pull request, please read 
our [Contributing](https
 
 ### Command Line
 
-Building on the Command Line is currently only supported on Windows.
-
 ##### Prerequisites
 
-1. 
[Powershell](https://msdn.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell)
 3.0 or higher (see [this 
question](http://stackoverflow.com/questions/1825585/determine-installed-powershell-version)
 to check your Powershell version)
+1. 
[PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell)
 3.0 or higher (see [this 
question](http://stackoverflow.com/questions/1825585/determine-installed-powershell-version)
 to check your PowerShell version)
 2. [.NET 6.0 SDK or 
higher](https://dotnet.microsoft.com/download/visual-studio-sdks)
 
 ##### Execution
 
 > **NOTE:** If the project is open in Visual Studio, its background restore 
 > may interfere with these commands. It is recommended to close all instances 
 > of Visual Studio that have `Lucene.Net.sln` open before executing.
 
-To build the source, clone or download and unzip the repository. From the 
repository root, execute the `build.bat` file from a command prompt and include 
the desired options from the build options table below:
+To build the source, clone or download and unzip the repository. For specific 
releases, download and unzip the `.src.zip` file from the [download page of the 
specific version](https://lucenenet.apache.org/download/download.html). From 
the repository or distribution root, execute the **build** command from a 
command prompt and include the desired options from the build options table 
below:
+
+###### Windows
 
 ```
 > build [options]
 ```
 
+###### Linux or macOS
+
+```
+./build [options]
+```
+
+> **NOTE:** The `build` file will need to be given permission to run using the 
command `chmod u+x build` before the first execution.
+
 ##### Build Options
 
+The following options are case-insensitive. Each option has both a short form 
indicated by a single `-` and a long form indicated by `--`. The options that 
require a value must be followed by a space and then the value, similar to 
running the [dotnet CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/).
+
 <table>
     <tr>
         <th>Short</th>
@@ -199,43 +209,51 @@ To build the source, clone or download and unzip the 
repository. From the reposi
     </tr>
     <tr>
         <td>&#8209;config</td>
-        <td>&#8209;&#8209;Configuration</td>
+        <td>&#8209;&#8209;configuration</td>
         <td>The build configuration ("Release" or "Debug").</td>
-        <td>build&nbsp;&#8209;&#8209;Configuration:Debug</td>
+        <td>build&nbsp;&#8209;&#8209;configuration Debug</td>
     </tr>
     <tr>
         <td>&#8209;mp</td>
-        <td>&#8209;&#8209;MaximumParallelJobs</td>
+        <td>&#8209;&#8209;maximum-parallel-jobs</td>
         <td>The maximum number of parallel jobs to run during testing. If not 
supplied, the default is 8.</td>
-        <td>build&nbsp;&#8209;t&nbsp;&#8209;mp:10</td>
+        <td>build&nbsp;&#8209;t&nbsp;&#8209;mp 10</td>
     </tr>
     <tr>
         <td>&#8209;pv</td>
-        <td>&#8209;&#8209;PackageVersion</td>
+        <td>&#8209;&#8209;package-version</td>
         <td>The NuGet package version. If not supplied, will use the version 
from the Version.proj file.</td>
-        <td>build&nbsp;&#8209;pv:4.8.0&#8209;beta00001</td>
+        <td>build&nbsp;&#8209;pv 4.8.0&#8209;beta00001</td>
     </tr>
     <tr>
         <td>&#8209;t</td>
-        <td>&#8209;&#8209;Test</td>
-        <td>Runs the tests after building. Note that testing typically takes 
around 40 minutes with 8 parallel jobs.</td>
+        <td>&#8209;&#8209;test</td>
+        <td>Runs the tests after building. This option does not require a 
value. Note that testing typically takes around 40 minutes with 8 parallel 
jobs.</td>
         <td>build&nbsp;&#8209;t</td>
     </tr>
     <tr>
-        <td>&#8209;v</td>
-        <td>&#8209;&#8209;Version</td>
-        <td>The assembly file version. If not supplied, will use the 
PackageVersion (excluding any pre-release tag).</td>
-        <td>build&nbsp;&#8209;pv:4.8.0&#8209;beta00001&nbsp;&#8209;v:4.8.0</td>
+        <td>&#8209;fv</td>
+        <td>&#8209;&#8209;file-version</td>
+        <td>The assembly file version. If not supplied, will use the 
--package-version (excluding any pre-release tag). The assembly version is 
generated as the major version of this value without the minor, build, or 
revision compoenents.</td>
+        <td>build&nbsp;&#8209;pv 4.8.0&#8209;beta00001&nbsp;&#8209;fv 
4.8.0</td>
     </tr>
 </table>
 
-For example the following command creates a Release build with NuGet package 
version 4.8.0‑ci00015 and assembly file version 4.8.0:
+For example the following command creates a Release build with NuGet package 
version 4.8.0‑ci00015 and file version 4.8.0. Assembly version will be equal to 
the passed in major version (in this case 4.0.0).
+
+###### Windows
+
+```
+> build ‑‑configuration Release ‑pv 4.8.0‑ci00015 ‑fv 4.8.0
+```
+
+###### Linux or macOS
 
 ```
-> build ‑‑Configuration:Release ‑pv:4.8.0‑ci00015 ‑v:4.8.0
+./build ‑‑configuration Release ‑pv 4.8.0‑ci00015 ‑fv 4.8.0
 ```
 
-In the above example we are using "ci" in the package version to indicate this 
is not a publically released beta version but rather the ouput of a continuous 
integration build from master which occured after beta00014 but before 
beta00015 was released.  
+In the above example we are using "ci" in the package version to indicate this 
is not a publicly released beta version but rather the output of a continuous 
integration build from master which occurred after beta00014 but before 
beta00015 was released.
 
 NuGet packages are output by the build to the `/_artifacts/NuGetPackages/` 
directory. Test results (if applicable) are output to the 
`/_artifacts/TestResults/` directory.
 
diff --git a/TestTargetFramework.props b/TestTargetFramework.props
index 88c4d5d..fd7e237 100644
--- a/TestTargetFramework.props
+++ b/TestTargetFramework.props
@@ -49,6 +49,10 @@
     <IsPublishable>true</IsPublishable>
   </PropertyGroup>
 
+  <PropertyGroup Label="Test Settings">
+    <IsTestProject>true</IsTestProject>
+  </PropertyGroup>
+
   <PropertyGroup Label="Warnings to be Disabled in Test Projects">
     <NoWarn Label="Nested types should not be 
visible">$(NoWarn);CA1034</NoWarn>
     <NoWarn Label="Use Literals Where Appropriate">$(NoWarn);CA1802</NoWarn>
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index a24ca7c..a530ac4 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -54,7 +54,7 @@ name: 'vNext$(rev:.r)' # Format for build number (will be 
overridden)
 variables:
 - name: BuildCounter
   value: 
$[counter(variables['VersionSuffix'],coalesce(variables['BuildCounterSeed'], 
1250))]
-- name: BuildSDKVersion
+- name: DotNetSDKVersion
   value: '6.0.100'
 - name: DocumentationArtifactName
   value: 'docs'
@@ -122,29 +122,24 @@ stages:
         Write-Host "##vso[task.setvariable variable=RunPack;]$runPack"
       displayName: 'Setup Default Variable Values'
 
-    - task: UseDotNet@2
-      displayName: 'Use .NET Core sdk $(BuildSDKVersion)'
-      inputs:
-        packageType: 'sdk'
-        version: '$(BuildSDKVersion)'
+    - template: '.build/azure-templates/install-dotnet-sdk.yml'
+      parameters:
+        sdkVersion: '$(DotNetSDKVersion)'
 
     - pwsh: |
         Import-Module "$(BuildDirectory)/psake/psake.psm1"
-        $generateBuildBat = $env:ISRELEASE
         $primaryCommand = if ($env:RUNPACK -ne 'false') { 'Pack' } else { 
'Compile' }
         $parameters = @{}
         $properties = @{
-            backup_files='false';
-            publish_directory='$(PublishTempDirectory)';
-            nuget_package_directory='$(NuGetArtifactDirectory)';
-            # Lock the build.bat so it only builds this version in the release 
distribution
-            generateBuildBat=$generateBuildBat
+            backupFiles='false';
+            publishDirectory='$(PublishTempDirectory)';
+            nugetPackageDirectory='$(NuGetArtifactDirectory)'
         }
         [string[]]$tasks = @($primaryCommand)
         if ($env:RunTests -ne 'false') {
             [string[]]$tasks = $primaryCommand,'Publish'
         }
-        Invoke-psake $(BuildDirectory)/runbuild.ps1 -Task $tasks -properties 
$properties -parameters $parameters
+        Invoke-Psake $(BuildDirectory)/runbuild.ps1 -Task $tasks -properties 
$properties -parameters $parameters
         exit !($psake.build_success)
       displayName: 'PSake Build, Pack, and Publish'
 
@@ -360,6 +355,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_net6_0_x86 # Only run Nightly or if explicitly enabled with 
RunX86Tests
     condition: and(succeeded(), ne(variables['RunTests'], 'false'), 
or(eq(variables['IsNightly'], 'true'), eq(variables['RunX86Tests'], 'true')))
@@ -394,6 +390,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_net5_0_x64
     condition: and(succeeded(), ne(variables['RunTests'], 'false'))
@@ -428,6 +425,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_net5_0_x86 # Only run Nightly or if explicitly enabled with 
RunX86Tests
     condition: and(succeeded(), ne(variables['RunTests'], 'false'), 
or(eq(variables['IsNightly'], 'true'), eq(variables['RunX86Tests'], 'true')))
@@ -462,6 +460,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_netcoreapp3_1_x64
     condition: and(succeeded(), ne(variables['RunTests'], 'false'))
@@ -496,6 +495,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_netcoreapp3_1_x86 # Only run Nightly or if explicitly enabled 
with RunX86Tests
     condition: and(succeeded(), ne(variables['RunTests'], 'false'), 
or(eq(variables['IsNightly'], 'true'), eq(variables['RunX86Tests'], 'true')))
@@ -530,6 +530,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_net461_x64
     condition: and(succeeded(), ne(variables['RunTests'], 'false'))
@@ -554,6 +555,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_net461_x86 # Only run Nightly or if explicitly enabled with 
RunX86Tests
     condition: and(succeeded(), ne(variables['RunTests'], 'false'), 
or(eq(variables['IsNightly'], 'true'), eq(variables['RunX86Tests'], 'true')))
@@ -578,6 +580,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: $(maximumParallelJobs)
         maximumAllowedFailures: $(maximumAllowedFailures)
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_net48_Windows_x64
     condition: and(succeeded(), ne(variables['RunTests'], 'false'))
@@ -595,6 +598,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: 8
         maximumAllowedFailures: 0 # Maximum allowed failures for a successful 
build
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
   - job: Test_net48_Windows_x86 # Only run Nightly or if explicitly enabled 
with RunX86Tests
     condition: and(succeeded(), ne(variables['RunTests'], 'false'), 
or(eq(variables['IsNightly'], 'true'), eq(variables['RunX86Tests'], 'true')))
@@ -612,6 +616,7 @@ stages:
         testResultsArtifactName: '$(TestResultsArtifactName)'
         maximumParallelJobs: 8
         maximumAllowedFailures: 0 # Maximum allowed failures for a successful 
build
+        dotNetSdkVersion: '$(DotNetSDKVersion)'
 
 
 - stage: Publish_Stage
diff --git a/build b/build
new file mode 100644
index 0000000..5c93df5
--- /dev/null
+++ b/build
@@ -0,0 +1,55 @@
+#! /usr/bin/env bash
+# 
-----------------------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the ""License""); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an ""AS IS"" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# 
-----------------------------------------------------------------------------------
+#
+# This file will build Lucene.Net and create the NuGet packages.
+#
+# Syntax:
+#   build[.bat] [<options>]
+#
+# Available Options:
+#
+#   --file-version <FileVersion>
+#   -fv <FileVersion> - File version number. If not supplied, the file version 
will be the same
+#                  as PackageVersion (excluding any pre-release tag). This 
value is not allowed
+#                  if there is a version.props file (which is included in the 
release distribution).
+#
+#   --package-version <PackageVersion>
+#   -pv <PackageVersion> - Nuget package version. Default is the value defined 
in Directory.Build.props.
+#                  This value is not allowed if there is a version.props file 
(which is included in the
+#                  release distribution).
+#
+#   --configuration <Configuration>
+#   -config <Configuration> - MSBuild configuration for the build.
+#
+#   --test
+#   -t - Run the tests.
+#
+#   --maximum-parallel-jobs
+#   -mp - Set the maxumum number of parallel jobs to run during testing. If 
not supplied, the default is 8.
+#
+#   All options are case insensitive.
+#
+# 
-----------------------------------------------------------------------------------
+if ! command -v pwsh &> /dev/null
+then
+    echo "Powershell Core could not be found. Please install version 3 or 
higher."
+    exit
+fi
+pwsh -ExecutionPolicy bypass -Command "& './build.ps1'" "$@"
\ No newline at end of file
diff --git a/build.bat b/build.bat
index 856cce7..a6e5a63 100644
--- a/build.bat
+++ b/build.bat
@@ -26,109 +26,28 @@ GOTO endcommentblock
 ::
 :: Available Options:
 ::
-::   --Version:<Version>
-::   -v:<Version> - Assembly version number. If not supplied, the version will 
be the same 
-::                  as PackageVersion (excluding any pre-release tag).
+::   --file-version <FileVersion>
+::   -fv <FileVersion> - File version number. If not supplied, the file 
version will be the same
+::                  as PackageVersion (excluding any pre-release tag). This 
value is not allowed
+::                  if there is a version.props file (which is included in the 
release distribution).
 ::
-::   --PackageVersion:<PackageVersion>
-::   -pv:<PackageVersion> - Nuget package version. Default is 0.0.0, which 
instructs the script to use the value in Version.proj.
+::   --package-version <PackageVersion>
+::   -pv <PackageVersion> - Nuget package version. Default is the value 
defined in Directory.Build.props.
+::                  This value is not allowed if there is a version.props file 
(which is included in the
+::                  release distribution).
 ::
-::   --Configuration:<Configuration>
-::   -config:<Configuration> - MSBuild configuration for the build.
+::   --configuration <Configuration>
+::   -config <Configuration> - MSBuild configuration for the build.
 ::
-::   --Test
+::   --test
 ::   -t - Run the tests.
 ::
-::   --MaximumParallelJobs
+::   --maximum-parallel-jobs
 ::   -mp - Set the maxumum number of parallel jobs to run during testing. If 
not supplied, the default is 8.
 ::
 ::   All options are case insensitive.
 ::
-::   To escape any of the options, put double quotes around the entire value, 
like this:
-::   "-config:Release"
-::
 :: 
-----------------------------------------------------------------------------------
 :endcommentblock
-setlocal enabledelayedexpansion enableextensions
-
-REM Default values
-IF "%version%" == "" (
-       REM  If version is not supplied, our build script should parse it
-       REM  from the %PackageVersion% variable. We determine this by checking
-       REM  whether it is 0.0.0 (uninitialized).
-       set version=0.0.0
-)
-IF "%PackageVersion%" == "" (
-    set PackageVersion=0.0.0
-)
-set configuration=Release
-IF NOT "%config%" == "" (
-       set configuration=%config%
-)
-set runtests=false
-set maximumParallelJobs=8
-
-FOR %%a IN (%*) DO (
-       FOR /f "useback tokens=*" %%a in ('%%a') do (
-               set value=%%~a
-
-               set test=!value:~0,3!
-               IF /I !test! EQU -v: (
-                       set version=!value:~3!
-               )
-
-               set test=!value:~0,10!
-               IF /I !test! EQU --version: (
-                       set version=!value:~10!
-               )
-               
-               set test=!value:~0,4!
-               IF /I !test!==-pv: (
-                       set packageversion=!value:~4!
-               )
-
-               set test=!value:~0,17!
-               IF /I !test!==--packageversion: (
-                       set packageversion=!value:~17!
-               )
-
-               set test=!value:~0,8!
-               IF /I !test!==-config: (
-                       set configuration=!value:~8!
-               )
-
-               set test=!value:~0,16!
-               IF /I !test!==--configuration: (
-                       set configuration=!value:~16!
-               )
-               
-               set test=!value:~0,2!
-               IF /I !test!==-t (
-                       set runtests=true
-               )
-
-               set test=!value:~0,6!
-               IF /I !test!==--test (
-                       set runtests=true
-               )
-
-               set test=!value:~0,4!
-               IF /I !test!==-mp: (
-                       set maximumParallelJobs=!value:~4!
-               )
-
-               set test=!value:~0,22!
-               IF /I !test!==--maximumparalleljobs: (
-                       set maximumParallelJobs=!value:~22!
-               )
-       )
-)
-
-set tasks="Default"
-if "!runtests!"=="true" (
-       set tasks="Default,Test"
-)
-
-powershell -ExecutionPolicy Bypass -Command "& { Import-Module 
.\.build\psake\psake.psm1; Invoke-Psake .\.build\runbuild.ps1 %tasks% 
-properties 
@{configuration='%configuration%';maximumParalellJobs=%maximumParallelJobs%} 
-parameters @{ packageVersion='%PackageVersion%';version='%version%' } }"
-
-endlocal
+where pwsh >nul 2>nul
+if %ERRORLEVEL% NEQ 0 (echo "Powershell could not be found. Please install 
version 3 or higher.") else (pwsh -ExecutionPolicy bypass -Command "& 
'%~dpn0.ps1'" %*)
\ No newline at end of file
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..ed490e3
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,96 @@
+# Parses and validates the command arguments and bootstraps the Psake build 
script with the cleaned values
+
+# 
-----------------------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the ""License""); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an ""AS IS"" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# 
-----------------------------------------------------------------------------------
+
+function Get-NextArg([string[]]$arguments, [int]$i, [string]$argName) {
+    $i++
+    if ($arguments.Length -gt $i -and -not $($arguments[$i]).StartsWith('-')) {
+        return $arguments[$i]
+    } else {
+        throw $("'$argName' requires a value to be passed as the next 
argument.")
+    }
+}
+
+# Default values, if not supplied as args
+[string]$packageVersion = ''
+[string]$fileVersion = ''
+[string]$configuration = 'Release'
+[bool]$runTests = $false
+[int]$maximumParallelJobs = 8
+
+# If the version.props file exists at the repository root, it is used to 
"lock" the version
+# to the current release (this happens in the official release distribution at
+# https://dist.apache.org/repos/dist/release/lucenenet/). In this case, we 
will not process
+# any version values that are passed, and the user will get an error. Note we 
don't do any
+# validation to ensure it has the values we need to produce a build (that part 
is automated
+# as part of the release).
+[string]$versionPropsFile = "$PSScriptRoot/version.props"
+[bool]$versionPropsExists = Test-Path $versionPropsFile
+
+# Analyze the args that were passed and process them
+for ([int]$i = 0; $i -lt $args.Length; $i++) {
+    $arg = $args[$i]
+    $loweredArg =  "$arg".ToLowerInvariant()
+    
+    if ($loweredArg -eq '-t' -or $loweredArg -eq '--test') {
+        $runTests = $true
+    } elseif ($loweredArg -eq '-mp' -or $loweredArg -eq 
'--maximum-parallel-jobs' -or $loweredArg -eq '--maximumparalleljobs') {
+        [string]$mpjStr = Get-NextArg $args $i $arg
+        [int]$mpjInt = $null
+        if (-not [int]::TryParse($mpjStr, [ref]$mpjInt)) { throw $("The '$arg' 
value must be a 32 bit integer. Got: $mpjStr.") }
+        $maximumParallelJobs = $mpjInt
+        $i++
+    } elseif ($loweredArg -eq '-pv' -or $loweredArg -eq '--package-version' 
-or $loweredArg -eq '--packageversion') {
+        if ($versionPropsExists) { throw $("'$arg' is not valid when 
$versionPropsFile exists.") }
+        $packageVersion = Get-NextArg $args $i $arg
+        $i++
+    } elseif ($loweredArg -eq '-fv' -or $loweredArg -eq '--file-version' -or 
$loweredArg -eq '--fileversion') {
+        if ($versionPropsExists) { throw $("'$arg' is not valid when 
$versionPropsFile exists.") }
+        $fileVersion = Get-NextArg $args $i $arg
+        $i++
+    } elseif ($loweredArg -eq '-config' -or $loweredArg -eq '--configuration') 
{
+        $configuration = Get-NextArg $args $i $arg
+        $i++
+    } else {
+        throw $("Unrecognized argument: '$arg'")
+    }
+}
+
+# Build the call to the Psake script using the captured/default args
+[string[]]$task = 'Default'
+if ($runTests) {
+    $task = 'Default','Test'
+}
+$parameters = @{}
+$properties = @{}
+
+$properties.maximumParallelJobs = $maximumParallelJobs
+if (-not [string]::IsNullOrWhiteSpace($packageVersion)) {
+    $properties.packageVersion=$packageVersion
+}
+if (-not [string]::IsNullOrWhiteSpace($fileVersion)) {
+    $properties.version=$fileVersion
+}
+if (-not [string]::IsNullOrWhiteSpace($configuration)) {
+    $properties.configuration=$configuration
+}
+
+Import-Module "$PSScriptRoot/.build/psake/psake.psm1"
+Invoke-Psake "$PSScriptRoot/.build/runbuild.ps1" -task $task -properties 
$properties -parameters $parameters
\ No newline at end of file
diff --git a/src/Lucene.Net.Analysis.Common/Lucene.Net.Analysis.Common.csproj 
b/src/Lucene.Net.Analysis.Common/Lucene.Net.Analysis.Common.csproj
index d6e87bb..7fe2cfe 100644
--- a/src/Lucene.Net.Analysis.Common/Lucene.Net.Analysis.Common.csproj
+++ b/src/Lucene.Net.Analysis.Common/Lucene.Net.Analysis.Common.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Analysis.Common</AssemblyTitle>
     <PackageTags>$(PackageTags);analysis</PackageTags>
diff --git 
a/src/Lucene.Net.Analysis.Kuromoji/Lucene.Net.Analysis.Kuromoji.csproj 
b/src/Lucene.Net.Analysis.Kuromoji/Lucene.Net.Analysis.Kuromoji.csproj
index 90419eb..1e3c81e 100644
--- a/src/Lucene.Net.Analysis.Kuromoji/Lucene.Net.Analysis.Kuromoji.csproj
+++ b/src/Lucene.Net.Analysis.Kuromoji/Lucene.Net.Analysis.Kuromoji.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Analysis.Kuromoji</AssemblyTitle>
     <PackageTags>$(PackageTags);analysis;japanese</PackageTags>
diff --git 
a/src/Lucene.Net.Analysis.Morfologik/Lucene.Net.Analysis.Morfologik.csproj 
b/src/Lucene.Net.Analysis.Morfologik/Lucene.Net.Analysis.Morfologik.csproj
index f0a39c4..99ccef6 100644
--- a/src/Lucene.Net.Analysis.Morfologik/Lucene.Net.Analysis.Morfologik.csproj
+++ b/src/Lucene.Net.Analysis.Morfologik/Lucene.Net.Analysis.Morfologik.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
 
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net451</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net451</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Analysis.Morfologik</AssemblyTitle>
     <RootNamespace>Lucene.Net.Analysis</RootNamespace>
diff --git a/src/Lucene.Net.Analysis.OpenNLP/Lucene.Net.Analysis.OpenNLP.csproj 
b/src/Lucene.Net.Analysis.OpenNLP/Lucene.Net.Analysis.OpenNLP.csproj
index a3e7a42..7fc3a8e 100644
--- a/src/Lucene.Net.Analysis.OpenNLP/Lucene.Net.Analysis.OpenNLP.csproj
+++ b/src/Lucene.Net.Analysis.OpenNLP/Lucene.Net.Analysis.OpenNLP.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
 
   <PropertyGroup>
-    <!--<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>-->
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net451</TargetFrameworks>
+    <TargetFramework>net451</TargetFramework>
 
     <AssemblyTitle>Lucene.Net.Analysis.OpenNLP</AssemblyTitle>
     
<PackageTags>$(PackageTags);analysis;natural;language;processing;opennlp</PackageTags>
diff --git 
a/src/Lucene.Net.Analysis.Phonetic/Lucene.Net.Analysis.Phonetic.csproj 
b/src/Lucene.Net.Analysis.Phonetic/Lucene.Net.Analysis.Phonetic.csproj
index 39506a6..b5d0668 100644
--- a/src/Lucene.Net.Analysis.Phonetic/Lucene.Net.Analysis.Phonetic.csproj
+++ b/src/Lucene.Net.Analysis.Phonetic/Lucene.Net.Analysis.Phonetic.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
 
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Analysis.Phonetic</AssemblyTitle>
     
<PackageTags>$(PackageTags);analysis;soundex;double;metaphone;sounds;like;beider;morse;cologne;caverphone;nysiis;match;rating</PackageTags>
diff --git a/src/Lucene.Net.Analysis.SmartCn/Lucene.Net.Analysis.SmartCn.csproj 
b/src/Lucene.Net.Analysis.SmartCn/Lucene.Net.Analysis.SmartCn.csproj
index 4f81991..53eaab5 100644
--- a/src/Lucene.Net.Analysis.SmartCn/Lucene.Net.Analysis.SmartCn.csproj
+++ b/src/Lucene.Net.Analysis.SmartCn/Lucene.Net.Analysis.SmartCn.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net451</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net451</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Analysis.SmartCn</AssemblyTitle>
     <PackageTags>$(PackageTags);analysis;chinese;smart</PackageTags>
diff --git a/src/Lucene.Net.Analysis.Stempel/Lucene.Net.Analysis.Stempel.csproj 
b/src/Lucene.Net.Analysis.Stempel/Lucene.Net.Analysis.Stempel.csproj
index edfc360..1db417e 100644
--- a/src/Lucene.Net.Analysis.Stempel/Lucene.Net.Analysis.Stempel.csproj
+++ b/src/Lucene.Net.Analysis.Stempel/Lucene.Net.Analysis.Stempel.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Analysis.Stempel</AssemblyTitle>
     <PackageTags>$(PackageTags);analysis;polish</PackageTags>
diff --git a/src/Lucene.Net.Benchmark/Lucene.Net.Benchmark.csproj 
b/src/Lucene.Net.Benchmark/Lucene.Net.Benchmark.csproj
index 020308c..5ffa901 100644
--- a/src/Lucene.Net.Benchmark/Lucene.Net.Benchmark.csproj
+++ b/src/Lucene.Net.Benchmark/Lucene.Net.Benchmark.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
 
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net451</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net451</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Benchmark</AssemblyTitle>
     <PackageTags>$(PackageTags);benchmark</PackageTags>
diff --git a/src/Lucene.Net.Classification/Lucene.Net.Classification.csproj 
b/src/Lucene.Net.Classification/Lucene.Net.Classification.csproj
index 999ed68..51d909d 100644
--- a/src/Lucene.Net.Classification/Lucene.Net.Classification.csproj
+++ b/src/Lucene.Net.Classification/Lucene.Net.Classification.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Classification</AssemblyTitle>
     <PackageTags>$(PackageTags);classification</PackageTags>
diff --git a/src/Lucene.Net.Codecs/Lucene.Net.Codecs.csproj 
b/src/Lucene.Net.Codecs/Lucene.Net.Codecs.csproj
index aa1451a..006f88d 100644
--- a/src/Lucene.Net.Codecs/Lucene.Net.Codecs.csproj
+++ b/src/Lucene.Net.Codecs/Lucene.Net.Codecs.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Codecs</AssemblyTitle>
     <PackageTags>$(PackageTags);codec</PackageTags>
diff --git a/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj 
b/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj
index 5d35886..3c089cb 100644
--- a/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj
+++ b/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj
@@ -24,8 +24,7 @@
   <!-- Demo is deployed through the dotnet/tools/lucene-cli package -->
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Demo</AssemblyTitle>
     <Description>Simple example code for the Lucene.Net full-text search 
engine library from The Apache Software Foundation.</Description>
diff --git a/src/Lucene.Net.Expressions/Lucene.Net.Expressions.csproj 
b/src/Lucene.Net.Expressions/Lucene.Net.Expressions.csproj
index a67f8bc..2a1c8ef 100644
--- a/src/Lucene.Net.Expressions/Lucene.Net.Expressions.csproj
+++ b/src/Lucene.Net.Expressions/Lucene.Net.Expressions.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Expressions</AssemblyTitle>
     <PackageTags>$(PackageTags);expression</PackageTags>
diff --git a/src/Lucene.Net.Facet/Lucene.Net.Facet.csproj 
b/src/Lucene.Net.Facet/Lucene.Net.Facet.csproj
index d92940d..a692ad9 100644
--- a/src/Lucene.Net.Facet/Lucene.Net.Facet.csproj
+++ b/src/Lucene.Net.Facet/Lucene.Net.Facet.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Facet</AssemblyTitle>
     <PackageTags>$(PackageTags);facet;faceted</PackageTags>
diff --git a/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj 
b/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj
index 82a5f19..7bac191 100644
--- a/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj
+++ b/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Grouping</AssemblyTitle>
     <PackageTags>$(PackageTags);grouping;group</PackageTags>
diff --git a/src/Lucene.Net.Highlighter/Lucene.Net.Highlighter.csproj 
b/src/Lucene.Net.Highlighter/Lucene.Net.Highlighter.csproj
index ca07678..e00876a 100644
--- a/src/Lucene.Net.Highlighter/Lucene.Net.Highlighter.csproj
+++ b/src/Lucene.Net.Highlighter/Lucene.Net.Highlighter.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Highlighter</AssemblyTitle>
     <PackageTags>$(PackageTags);highlight;highlighter</PackageTags>
diff --git a/src/Lucene.Net.Join/Lucene.Net.Join.csproj 
b/src/Lucene.Net.Join/Lucene.Net.Join.csproj
index c2d0745..b7b1ff8 100644
--- a/src/Lucene.Net.Join/Lucene.Net.Join.csproj
+++ b/src/Lucene.Net.Join/Lucene.Net.Join.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <RootNamespace>Lucene.Net.Search.Join</RootNamespace>
     
diff --git a/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj 
b/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj
index 7ee103c..23500bc 100644
--- a/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj
+++ b/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
     
     <AssemblyTitle>Lucene.Net.Memory</AssemblyTitle>
     <PackageTags>$(PackageTags);memory</PackageTags>
diff --git a/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj 
b/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj
index 592f4f1..5c8f907 100644
--- a/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj
+++ b/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Misc</AssemblyTitle>
     <PackageTags>$(PackageTags);miscellaneous</PackageTags>
diff --git a/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj 
b/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj
index c9db56c..c9a3d12 100644
--- a/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj
+++ b/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Queries</AssemblyTitle>
     <PackageTags>$(PackageTags);query;queries</PackageTags>
diff --git a/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj 
b/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
index 0978558..eec75a1 100644
--- a/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
+++ b/src/Lucene.Net.QueryParser/Lucene.Net.QueryParser.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <RootNamespace>Lucene.Net.QueryParsers</RootNamespace>
     
diff --git a/src/Lucene.Net.Replicator/Lucene.Net.Replicator.csproj 
b/src/Lucene.Net.Replicator/Lucene.Net.Replicator.csproj
index 5c8cbbd..fb4c4fe 100644
--- a/src/Lucene.Net.Replicator/Lucene.Net.Replicator.csproj
+++ b/src/Lucene.Net.Replicator/Lucene.Net.Replicator.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Replicator</AssemblyTitle>
     <PackageTags>$(PackageTags);files;replication;replicate</PackageTags>
diff --git a/src/Lucene.Net.Sandbox/Lucene.Net.Sandbox.csproj 
b/src/Lucene.Net.Sandbox/Lucene.Net.Sandbox.csproj
index 0f120ee..75852eb 100644
--- a/src/Lucene.Net.Sandbox/Lucene.Net.Sandbox.csproj
+++ b/src/Lucene.Net.Sandbox/Lucene.Net.Sandbox.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Sandbox</AssemblyTitle>
     <PackageTags>$(PackageTags);sandbox</PackageTags>
diff --git a/src/Lucene.Net.Spatial/Lucene.Net.Spatial.csproj 
b/src/Lucene.Net.Spatial/Lucene.Net.Spatial.csproj
index b024670..9848aa4 100644
--- a/src/Lucene.Net.Spatial/Lucene.Net.Spatial.csproj
+++ b/src/Lucene.Net.Spatial/Lucene.Net.Spatial.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Spatial</AssemblyTitle>
     <PackageTags>$(PackageTags);spatial;geo;geospatial;2d</PackageTags>
diff --git a/src/Lucene.Net.Suggest/Lucene.Net.Suggest.csproj 
b/src/Lucene.Net.Suggest/Lucene.Net.Suggest.csproj
index 162b53a..43fbcdc 100644
--- a/src/Lucene.Net.Suggest/Lucene.Net.Suggest.csproj
+++ b/src/Lucene.Net.Suggest/Lucene.Net.Suggest.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Suggest</AssemblyTitle>
     <PackageTags>$(PackageTags);suggest;suggestion</PackageTags>
diff --git a/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj 
b/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj
index 849423a..08f2314 100644
--- a/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj
+++ b/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
 
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net451</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net451</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.TestFramework</AssemblyTitle>
     <RootNamespace>Lucene.Net</RootNamespace>
diff --git 
a/src/Lucene.Net.Tests.Analysis.OpenNLP/Lucene.Net.Tests.Analysis.OpenNLP.csproj
 
b/src/Lucene.Net.Tests.Analysis.OpenNLP/Lucene.Net.Tests.Analysis.OpenNLP.csproj
index d2bc905..1a3bbbc 100644
--- 
a/src/Lucene.Net.Tests.Analysis.OpenNLP/Lucene.Net.Tests.Analysis.OpenNLP.csproj
+++ 
b/src/Lucene.Net.Tests.Analysis.OpenNLP/Lucene.Net.Tests.Analysis.OpenNLP.csproj
@@ -32,6 +32,11 @@
 
     <IsPublishable>false</IsPublishable>
     <IsPublishable Condition=" '$(TargetFramework)' == 'net48' 
">true</IsPublishable>
+
+    <!-- Workaround since there are no targets on non-Windows OS. We need at 
least 1 TargetFramework
+        registered or MSBuild's validation will fail, so we explicitly disable 
it as a test project instead. -->
+    <IsTestProject>false</IsTestProject>
+    <IsTestProject 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">true</IsTestProject>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/src/Lucene.Net/Lucene.Net.csproj b/src/Lucene.Net/Lucene.Net.csproj
index f82a7d7..09d76cb 100644
--- a/src/Lucene.Net/Lucene.Net.csproj
+++ b/src/Lucene.Net/Lucene.Net.csproj
@@ -24,8 +24,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net45</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net45</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net</AssemblyTitle>
     <Description>Lucene.Net is a full-text search engine library capable of 
advanced text analysis, indexing, and searching. It can be used to easily add 
search capabilities to applications. Lucene.Net is a C# port of the popular 
Java Lucene search engine framework from The Apache Software Foundation, 
targeted at .NET Framework and .NET Core users.</Description>
diff --git a/src/dotnet/Lucene.Net.ICU/Lucene.Net.ICU.csproj 
b/src/dotnet/Lucene.Net.ICU/Lucene.Net.ICU.csproj
index 8ef38a4..8f2bfd2 100644
--- a/src/dotnet/Lucene.Net.ICU/Lucene.Net.ICU.csproj
+++ b/src/dotnet/Lucene.Net.ICU/Lucene.Net.ICU.csproj
@@ -30,8 +30,7 @@
   <Import Project="$(SolutionDir).build/nuget.props" />
 
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net451</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net451</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.ICU</AssemblyTitle>
     <PackageTags>$(PackageTags);icu;international;unicode</PackageTags>
diff --git 
a/src/dotnet/Lucene.Net.Replicator.AspNetCore/Lucene.Net.Replicator.AspNetCore.csproj
 
b/src/dotnet/Lucene.Net.Replicator.AspNetCore/Lucene.Net.Replicator.AspNetCore.csproj
index 2800f70..17fd672 100644
--- 
a/src/dotnet/Lucene.Net.Replicator.AspNetCore/Lucene.Net.Replicator.AspNetCore.csproj
+++ 
b/src/dotnet/Lucene.Net.Replicator.AspNetCore/Lucene.Net.Replicator.AspNetCore.csproj
@@ -25,8 +25,7 @@
   <!--<Import Project="$(SolutionDir).build/nuget.props" />-->
   
   <PropertyGroup>
-    <TargetFrameworks>net6.0;netstandard2.1;netstandard2.0</TargetFrameworks>
-    <TargetFrameworks 
Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);net461</TargetFrameworks>
+    
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net461</TargetFrameworks>
 
     <AssemblyTitle>Lucene.Net.Replicator.AspNetCore</AssemblyTitle>
     <Description>AspNetCore integration of Lucene.Net.Replicator for the 
Lucene.Net full-text search engine library from The Apache Software 
Foundation.</Description>
diff --git 
a/src/dotnet/Lucene.Net.Tests.CodeAnalysis/Lucene.Net.Tests.CodeAnalysis.csproj 
b/src/dotnet/Lucene.Net.Tests.CodeAnalysis/Lucene.Net.Tests.CodeAnalysis.csproj
index 90b3d09..fc66c90 100644
--- 
a/src/dotnet/Lucene.Net.Tests.CodeAnalysis/Lucene.Net.Tests.CodeAnalysis.csproj
+++ 
b/src/dotnet/Lucene.Net.Tests.CodeAnalysis/Lucene.Net.Tests.CodeAnalysis.csproj
@@ -27,6 +27,7 @@
     
     <IsPublishable>false</IsPublishable>
     <IsPublishable Condition=" '$(TargetFramework)' == 'net5.0' 
">true</IsPublishable>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
 
   
diff --git a/src/dotnet/tools/Lucene.Net.Tests.Cli/Lucene.Net.Tests.Cli.csproj 
b/src/dotnet/tools/Lucene.Net.Tests.Cli/Lucene.Net.Tests.Cli.csproj
index 7a92962..dfd8068 100644
--- a/src/dotnet/tools/Lucene.Net.Tests.Cli/Lucene.Net.Tests.Cli.csproj
+++ b/src/dotnet/tools/Lucene.Net.Tests.Cli/Lucene.Net.Tests.Cli.csproj
@@ -27,6 +27,7 @@
 
     <IsPublishable>false</IsPublishable>
     <IsPublishable Condition=" '$(TargetFramework)' == 'net6.0' 
">true</IsPublishable>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
 
   <ItemGroup>

Reply via email to