From d58450f2d66a5c80a91a94075f7c47d84c6bc309 Mon Sep 17 00:00:00 2001 From: ericstj Date: Thu, 2 May 2019 06:29:56 -0700 Subject: [PATCH 1/2] Improve usability of APICompat --- src/Microsoft.DotNet.ApiCompat/README.md | 37 ++++++++++ .../build/Microsoft.DotNet.ApiCompat.targets | 68 ++++++++++++------- 2 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 src/Microsoft.DotNet.ApiCompat/README.md diff --git a/src/Microsoft.DotNet.ApiCompat/README.md b/src/Microsoft.DotNet.ApiCompat/README.md new file mode 100644 index 00000000000..300495f1d14 --- /dev/null +++ b/src/Microsoft.DotNet.ApiCompat/README.md @@ -0,0 +1,37 @@ +# Microsoft.DotNet.ApiCompat + +APICompat is a tool which may be used to test API compatibility between a two .NET assemblies. + +When testing the tool will compare a *contract* to an *implementation*. + +The *contract* represents the API that's expected : for example a reference assembly or a previous version of an assembly. + +The *implementation* represents the API that's provided : for example the current version of an assembly. + +## Usage + +API Compat can be used by referencing this Microsoft.DotNet.ApiCompat package from the *implementation* project, and providing the path to the *contract* via a single `@(ResolvedMatchingContract)` item. All the depene + +When API Compat identifies an error + +## Required setting + +`@(ResolvedMatchingContract)` - should point to a single file that represents the contract to validate + %(DependencyPaths) - optional, specifies a semi-colon delimited set of paths that contain the assembly dependencies of this contract +`$(ContractDependencyPaths)` - optional, speicifies a semi-colon delimited set of paths that contain the assembly dependencies of this contract + +## Additional settings + +`$(RunApiCompat)` - true to run APICompat, defaults to true +`$(RunApiCompatForSrc)` - true to run APICompat treating project output as *implementation* and `@(ResolvedMatchingContract)` as *contract*, defaults to true. +`$(RunMatchingRefApiCompat)` - true to run APICompat treating project output as *contract* and `@(ResolvedMatchingContract)` as *implementation*, defaults to true. This is also known as reverse API compat and can help ensure that every public API defined in a project is exposed in `@(ResolvedMatchingContract)`. + +`$(ApiCompatExcludeAttributeList)` - Attributes to exclude from APICompat checks +`$(ApiCompatEnforceOptionalRules)` - true to enforce optional rules, default is false. An example of an optional rule is parameter naming which can break source compatibility but not binary compatibility. + + +`$(ApiCompatBaseline)` - path to baseline file used to suppress errors, defaults to a file in the project directory. +`$(BaselineAllAPICompatError)` - true to indicate that the baseline file should be rewritten suppressing all API compat errors. You may set this when building the project to conveniently update the baseline when you wish to suppress them, eg: `dotnet msbuild /p:BaselineAllAPICompatError=true` + +`$(MatchingRefApiCompatBaseline)` - same as `$(ApiCompatBaseline)` but for reverse API compat. +`$(BaselineAllMatchingRefApiCompatError)` - same as `$(BaselineAllAPICompatError)` but for reverse API compat. diff --git a/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets b/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets index 9b428e8fb35..8af4d2d33aa 100644 --- a/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets +++ b/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets @@ -12,35 +12,44 @@ <_ApiCompatCommand Condition="'$(MSBuildRuntimeType)' == 'core'">$(ToolHostCmd) "$(_ApiCompatPath)" <_ApiCompatCommand Condition="'$(MSBuildRuntimeType)' != 'core' and '$(OS)' == 'Windows_NT'">"$(_ApiCompatPath)" <_ApiCompatCommand Condition="'$(MSBuildRuntimeType)' != 'core' and '$(OS)' != 'Windows_NT'">mono --runtime=v4.0.30319 "$(_ApiCompatPath)" + + <_ApiCompatSemaphoreFile>$(MSBuildThisFileName).semaphore - false + + true + + $(RunApiCompat) + false - $(MSBuildProjectDirectory)\ApiCompatBaseline.$(TargetGroup).txt + <_apiCompatTargetSuffix>$(TargetGroup) + <_apiCompatTargetSuffix Condition="'$(_apiCompatTargetSuffix)' == ''">$(TargetFramework) + + $(MSBuildProjectDirectory)\ApiCompatBaseline.$(_apiCompatTargetSuffix).txt $(MSBuildProjectDirectory)\ApiCompatBaseline.txt - $(MSBuildProjectDirectory)\MatchingRefApiCompatBaseline.$(TargetGroup).txt + $(MSBuildProjectDirectory)\MatchingRefApiCompatBaseline.$(_apiCompatTargetSuffix).txt $(MSBuildProjectDirectory)\MatchingRefApiCompatBaseline.txt - true - - $(RunApiCompatForSrc) - - true $(TargetsTriggeredByCompilation);ValidateApiCompatForSrc $(TargetsTriggeredByCompilation);RunMatchingRefApiCompat + + + + - - - @(ResolvedMatchingContract) - + Condition="'$(RunApiCompatForSrc)' == 'true' and '$(RunApiCompat)' == 'true'"> + + + <_DependencyDirectoriesTemp Include="@(ReferencePath -> '%(RootDir)%(Directory)')" /> @@ -49,11 +58,12 @@ <_DependencyDirectories Condition="'%(_DependencyDirectoriesTemp.ReferenceSourceTarget)' == 'ProjectReference'" Include="%(_DependencyDirectoriesTemp.Identity)" /> <_DependencyDirectories Condition="'%(_DependencyDirectoriesTemp.ReferenceSourceTarget)' != 'ProjectReference'" Include="%(_DependencyDirectoriesTemp.Identity)" /> <_ContractDependencyDirectories Include="@(ResolvedMatchingContract -> '%(RootDir)%(Directory)')" /> - <_ContractDependencyDirectories Include="$(ContractOutputPath)" /> + <_ContractDependencyDirectories Include="@(ResolvedMatchingContract -> '%(DependencyPaths)')" /> + <_ContractDependencyDirectories Include="$(ContractDependencyPaths)" /> - $(ApiCompatArgs) "$(ReferenceAssembly)" + $(ApiCompatArgs) "@(ResolvedMatchingContract)" $(ApiCompatArgs) --contract-depends "@(_ContractDependencyDirectories, ',')," $(ApiCompatArgs) --exclude-attributes "$(ApiCompatExcludeAttributeList)" $(ApiCompatArgs) --enforce-optional-rules @@ -69,8 +79,7 @@ - @@ -79,16 +88,23 @@ - + + + + Condition="'$(RunMatchingRefApiCompat)' == 'true' and '$(RunApiCompat)' == 'true'" > + + + @(IntermediateAssembly) @@ -100,7 +116,8 @@ <_ContractDependencyDirectories Condition="'%(_ContractDependencyDirectoriesTemp.ReferenceSourceTarget)' == 'ProjectReference'" Include="%(_ContractDependencyDirectoriesTemp.Identity)" /> <_ContractDependencyDirectories Condition="'%(_ContractDependencyDirectoriesTemp.ReferenceSourceTarget)' != 'ProjectReference'" Include="%(_ContractDependencyDirectoriesTemp.Identity)" /> <_ImplementationDependencyDirectories Include="@(ResolvedMatchingContract -> '%(RootDir)%(Directory)')" /> - <_ImplementationDependencyDirectories Include="$(ContractOutputPath)" /> + <_ImplementationDependencyDirectories Include="@(ResolvedMatchingContract -> '%(DependencyPaths)')" /> + <_ImplementationDependencyDirectories Include="$(ContractDependencyPaths)" /> @@ -123,8 +140,7 @@ - @@ -133,9 +149,11 @@ - + + + From ec4b3ea2d99b5148ee4a31f50732c56396a47999 Mon Sep 17 00:00:00 2001 From: ericstj Date: Fri, 3 May 2019 16:20:25 -0700 Subject: [PATCH 2/2] Improve API Compat README.md --- src/Microsoft.DotNet.ApiCompat/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.ApiCompat/README.md b/src/Microsoft.DotNet.ApiCompat/README.md index 300495f1d14..d6070c5748c 100644 --- a/src/Microsoft.DotNet.ApiCompat/README.md +++ b/src/Microsoft.DotNet.ApiCompat/README.md @@ -2,7 +2,7 @@ APICompat is a tool which may be used to test API compatibility between a two .NET assemblies. -When testing the tool will compare a *contract* to an *implementation*. +When testing, the tool will compare a *contract* to an *implementation*. The *contract* represents the API that's expected : for example a reference assembly or a previous version of an assembly. @@ -10,9 +10,9 @@ The *implementation* represents the API that's provided : for example the curren ## Usage -API Compat can be used by referencing this Microsoft.DotNet.ApiCompat package from the *implementation* project, and providing the path to the *contract* via a single `@(ResolvedMatchingContract)` item. All the depene +API Compat can be used by referencing this Microsoft.DotNet.ApiCompat package from the *implementation* project, and providing the path to the *contract* via a single `@(ResolvedMatchingContract)` item. Dependencies of `@(ResolvedMatchingContract)` must be specified in either `DependencyPaths` metadata on the items themselves or via the `$(ContractDependencyPaths)` property. -When API Compat identifies an error +When API Compat identifies an error it will log the error and fail the build. If you wish to ignore the error you can copy the error text to a baseline file (see below). Take care when doing this as these errors represent compatibility problems between the *contract* and *implementation*. ## Required setting @@ -26,7 +26,7 @@ When API Compat identifies an error `$(RunApiCompatForSrc)` - true to run APICompat treating project output as *implementation* and `@(ResolvedMatchingContract)` as *contract*, defaults to true. `$(RunMatchingRefApiCompat)` - true to run APICompat treating project output as *contract* and `@(ResolvedMatchingContract)` as *implementation*, defaults to true. This is also known as reverse API compat and can help ensure that every public API defined in a project is exposed in `@(ResolvedMatchingContract)`. -`$(ApiCompatExcludeAttributeList)` - Attributes to exclude from APICompat checks +`$(ApiCompatExcludeAttributeList)` - Attributes to exclude from APICompat checks. This is a text file containing types in DocID format, EG: T:Namespace.TypeName. `$(ApiCompatEnforceOptionalRules)` - true to enforce optional rules, default is false. An example of an optional rule is parameter naming which can break source compatibility but not binary compatibility.