Azure / azure-sdk-tools

Tools repository leveraged by the Azure SDK team.
MIT License
114 stars 180 forks source link

Integrate ApiView check with C++ CI pipelines #3369

Closed antkmsft closed 2 years ago

antkmsft commented 2 years ago

It would be great if ApiView integration was available for C++ SDK.

antkmsft commented 2 years ago

cc @praveenkuttappan

antkmsft commented 2 years ago

I have the Powershell script that makes a command line:

#Usage: ApiViewCommandLine.ps1 .\azure-sdk-for-cpp azure-identity
#Or: ..\ApiViewCommandLine.ps1 . azure-core
#Or: ApiViewCommandLine.ps1 ..\.. azure-security-attestation
#Or: C:\src\ApiViewCommandLine.ps1 c:\src\azure-sdk-for-cpp azure-identity
param($RepoPath, $LibName)

[String]$SdkRoot = Resolve-Path ($RepoPath + "\sdk")

[String[]]$AllIncDirs = Get-ChildItem -Directory -Filter "inc" -Recurse $SdkRoot | Select-Object -ExpandProperty FullName

[String[]]$AllIncDirsWithoutInc = $AllIncDirs | Select-Object @{ Label="Substr"; Expression = { $_.Substring(0, $_.Length - "inc".Length) } } | Select-Object -ExpandProperty Substr

[String[]]$AllLibIncDirs = @()
for($i = 0; $i -lt $AllIncDirsWithoutInc.Length; $i++) {
    $isLibDir = $true
    $libDir = $AllIncDirsWithoutInc[$i]
    for($j = 0; $j -lt $AllIncDirsWithoutInc.Length; $j++) {
        if ($i -eq $j) {
            continue
        }

        $StartsWith = $AllIncDirsWithoutInc[$j] + "*"
        if ($libDir -Like $StartsWith) {
            $isLibDir = $false
            break
        }
    }

    if ($isLibDir){
        $AllLibIncDirs += $libDir + "inc"
    }
}

[String]$LibIncDir = $AllLibIncDirs | Where-Object {$_ -Match ("\\" + $LibName + "\\inc") } | Select-Object -First 1

[String[]]$LibHeaders = Get-ChildItem -File -Recurse $LibIncDir | Select-Object -ExpandProperty FullName

$CmdLine = "clang++"
foreach ($header in $LibHeaders) {
    $CmdLine += " " + $header
}

$CmdLine += " -Xclang -ast-dump"

foreach ($incDir in $AllLibIncDirs) {
    $CmdLine += " -I " + $incDir
}

$CmdLine

You give it the path to azure-sdk-for-cpp repo, and a library name, such as azure-core, azure-identity, etc.

It generates the command line with all the header files for the given library - which is good because even if people forget to add some directory to the all-include file, the entities from it will still be present.

And it lists all the include directories for all libraries, which makes it a bit longer to run, but it is harmless - the stuff that was referenced stil ends up not being included in review. As example, I generated APIview for azure-identity which only depends on core. But I fed it all the include directories for all libraries, including, for example, Storage. But in the resulting AST tree, and in ApiView, no entity from Storage was ever listed. Which is great, because we don't have to implement the logic that figures out the dependencies, we simply list all the libraries and let clang++ to take care of including only the relevant ones.

benbp commented 2 years ago

Resolved by https://github.com/Azure/azure-sdk-for-cpp/pull/3763