Pipeline di build
Dove il pacchetto esegue Babel all’interno della pipeline di MSBuild, come spostare quel passo, i target a cui puoi agganciarti, che cosa succede in pubblicazione e come vengono selezionati gli strumenti di build.
Dove viene eseguito l’offuscamento
Per impostazione predefinita il pacchetto esegue Babel subito dopo CoreCompile, sull’assembly che il compilatore ha appena scritto nella cartella intermedia, $(IntermediateOutputPath)$(TargetFileName), cioè la cartella obj. Ogni passo successivo della build lavora quindi sull’assembly offuscato: la copia in bin, la generazione di .deps.json, gli assembly satellite e, in pubblicazione, il trimming, la creazione del bundle a file singolo, la compilazione ReadyToRun o NativeAOT e il confezionamento in un APK o in un bundle dell’app.
Questo ordine è il motivo per usare il pacchetto nei progetti in stile SDK. L’SDK .NET riscrive l’IL dopo la compilazione, e Babel deve vedere l’assembly prima che ciò avvenga; un assembly preso da bin o dalla cartella di pubblicazione ha già attraversato quei passi. Collocare a mano il task dopo CoreCompile è una soluzione fragile, perché la sequenza esatta dei target dipende dal tipo di progetto e dalla versione dell’SDK. Il pacchetto risolve il problema per te.
Altre due regole mantengono reattivo l’IDE:
- Le build in fase di progettazione vengono saltate. Visual Studio e gli analizzatori di codice eseguono continuamente build in background; il pacchetto non vi inserisce il passo di offuscamento.
- L’offuscamento viene eseguito solo quando è stato eseguito il compilatore. Una build incrementale che trova l’assembly aggiornato salta anche Babel, così l’assembly già offuscato in
objnon viene mai elaborato due volte.
Spostare il passo di offuscamento
Tre proprietĂ cambiano il punto di inserimento:
| ProprietĂ | Effetto |
|---|---|
RunBabelAfterBuild | Quando è true, Babel viene eseguito alla fine della build, dopo la copia dell’output in bin, ed elabora $(TargetPath) invece dell’assembly intermedio. |
BabelAfterTargets | Esegue il passo di offuscamento dopo il target MSBuild indicato. |
BabelBeforeTargets | Esegue il passo di offuscamento prima del target MSBuild indicato. |
Impostarne una qualsiasi disabilita il posizionamento predefinito dopo CoreCompile. Con BabelAfterTargets o BabelBeforeTargets Babel elabora comunque l’assembly intermedio; se il target scelto viene eseguito dopo la copia dell’output, fai puntare BabelInputFile e BabelOutputFile a $(TargetPath).
Un uso tipico è un’applicazione Windows Forms con risorse localizzate, in cui Babel deve essere eseguito dopo la generazione degli assembly satellite per poter elaborare anche quelli:
<PropertyGroup>
<BabelAfterTargets>CoreGenerateSatelliteAssemblies</BabelAfterTargets>
</PropertyGroup>Tutto ciò che viene eseguito tra la compilazione e il passo di offuscamento spostato vede l’assembly non offuscato. Mantieni il posizionamento predefinito per i progetti pubblicati con trimming, a file singolo o con AOT, e per qualsiasi progetto in cui un passo dell’SDK riscrive l’IL dopo la compilazione.
Sequenza dei target e punti di estensione
Il passo di offuscamento è il target ObfuscateBuild. Prima prepara la configurazione del task Babel, poi lo esegue:
ObfuscateBuild
├─ ObfuscateSettings
│ ├─ ObfuscateDefaultSettings renaming defaults, license lookup, babelRules.xml, search directories
│ ├─ ObfuscateFrameworkSettings selects the assembly to process (obj, or $(TargetPath))
│ ├─ ObfuscateSetupBabelFiles BabelInputFile / BabelOutputFile, GenerateDebug when a PDB exists
│ ├─ ObfuscateCustomSettings empty, yours to redefine
│ ├─ SetupObfuscate empty, yours to redefine
│ └─ ConfigureBabel empty, yours to redefine
└─ Obfuscate
├─ BeforeObfuscate empty, yours to redefine
├─ CoreObfuscate runs the Babel task
└─ AfterObfuscate empty, yours to redefineRidefinisci un target vuoto nel file di progetto per eseguire i tuoi passi in quel punto:
| Target | Quando viene eseguito | Usalo per |
|---|---|---|
ObfuscateCustomSettings, SetupObfuscate, ConfigureBabel | Dopo che il pacchetto ha calcolato i suoi valori predefiniti e i file di input e di output, prima dell’esecuzione di Babel | Sovrascrivere le proprietà calcolate, come BabelInputFile, BabelOutputFile, GenerateDebug o le cartelle di ricerca. |
BeforeObfuscate | Subito prima del task Babel | Offuscare prima una dipendenza, calcolare le impostazioni dai riferimenti risolti, generare le regole. |
AfterObfuscate | Subito dopo il task Babel | Copiare altrove il file map o il file di log, eseguire un controllo sull’assembly offuscato. |
CoreObfuscate pubblica due output che puoi leggere in AfterObfuscate: la proprietà BabelExitCode e l’elemento @(BabelCommandLineArgs), che contiene la riga di comando quando BabelProvideCommandLineArgs è true.
Sovrascrivere la configurazione del task
Il pacchetto configura il task Babel a partire dal progetto: le cartelle di ricerca ricavate dai riferimenti, la chiave con nome sicuro, il PDB, il file di regole. Quando i valori predefiniti non vanno bene, correggili in BeforeObfuscate. L’esempio seguente forza la generazione dei simboli di debug e sostituisce le cartelle di ricerca con la cartella di output:
<Target Name="BeforeObfuscate">
<!-- Override computed properties -->
<PropertyGroup>
<GenerateDebug>true</GenerateDebug>
</PropertyGroup>
<!-- Replace the Babel search directories -->
<ItemGroup>
<BabelSearchDirectories Remove="@(BabelSearchDirectories)" />
<BabelSearchDirectories Include="$(TargetDir)" />
</ItemGroup>
</Target>BeforeObfuscate è anche il punto in cui eseguire un secondo task Babel su una dipendenza prima che venga offuscato l’assembly principale, come fa l’esempio Pubblicare un’app .NET per rinominare l’interfaccia pubblica di un pacchetto NuGet con la ridenominazione cross-assembly.
Un target AfterObfuscate può raccogliere gli artefatti prodotti da Babel, per esempio il file map da copiare in una cartella condivisa usata dall’esempio Test unitari:
<PropertyGroup>
<GenerateMapOutFile>true</GenerateMapOutFile>
<BabelMapOutFile>$(IntermediateOutputPath)$(TargetFileName).map.xml</BabelMapOutFile>
</PropertyGroup>
<Target Name="AfterObfuscate">
<Copy SourceFiles="$(BabelMapOutFile)" DestinationFolder="$(SolutionDir)MapOut" />
</Target>Pubblicazione
Poiché l’offuscamento avviene prima dei passi di pubblicazione, dotnet publish e i profili di pubblicazione di Visual Studio producono un output offuscato senza configurazione aggiuntiva. Il pacchetto aggiunge tre adattamenti:
- Gli assembly uniti e incorporati vengono rimossi dall’insieme dei file da pubblicare. Il target
UpdateBabelFilesToPublish, eseguito dopoComputeFilesToPublish, toglie dai file da pubblicare ogni elementoMergeAssemblyedEmbedAssembly, insieme ai relativi file.pdbe.xml. ImpostaBabelPublishEnabledsufalseper mantenerli. - I file
.deps.jsonvengono aggiornati. I targetUpdateBabelBuildDependencyFileeUpdateBabelPublishDependencyFilerimuovono gli assembly uniti e incorporati, e il pacchetto stesso, dai manifesti delle dipendenze di build e di pubblicazione, così l’host non cerca assembly che non esistono più come file separati. ImpostaBabelUpdateDependencyFilesufalseper lasciare invariati i manifesti. - I simboli di debug non vengono pubblicati in Release. Il pacchetto imposta
CopyOutputSymbolsToPublishDirectorysufalseper la configurazione Release, a meno che non lo imposti il progetto, perché i file PDB danno a un attaccante i nomi dei file e i numeri di riga del codice originale. Impostalo sutrueper pubblicarli comunque.
La pubblicazione a file singolo, con trimming e con AOT funziona con l’assembly offuscato, con due avvertenze: il controllo delle manomissioni desktop non può verificare un’immagine a file singolo, e Babel lo segnala con un avviso (vedi Rilevamento delle manomissioni), e per .NET MAUI iOS il linker va impostato su Link SDK assemblies only, come spiegato in Offuscare .NET MAUI.
Selezionare gli strumenti di build
Il pacchetto include un set di strumenti di build di Babel per ogni host MSBuild e lo seleziona in base all’host che sta eseguendo la build:
| Host MSBuild | Cartella degli strumenti |
|---|---|
SDK .NET 6.0, 7.0, 8.0, 9.0 o 10.0 (dotnet build, Visual Studio) | tools\net6.0 … tools\net10.0, in base alla versione dell’SDK |
| Qualsiasi altra versione dell’SDK .NET | tools\net9.0 |
MSBuild di .NET Framework (MSBuild.exe) | tools\net472 |
| MSBuild di Mono | tools\Mono |
La cartella selezionata è esposta come BabelTaskDir, e BabelPackageDir punta alla radice del pacchetto estratto. Per forzare un set di strumenti diverso, imposta BabelTaskDir nel file di progetto:
<PropertyGroup>
<BabelTaskDir>$(BabelPackageDir)tools\net8.0\</BabelTaskDir>
</PropertyGroup>Impostalo nel file di progetto o in Directory.Build.targets, non in Directory.Build.props: il file .props del pacchetto viene importato dopo Directory.Build.props e sovrascriverebbe il valore.
Per eseguire un Babel installato al di fuori del pacchetto, per esempio lo strumento da riga di comando estratto da un pacchetto zip babel_net*, imposta BabelPath sulla sua cartella e, se serve, BabelExe sul nome dell’eseguibile (babel.exe o babel.dll).
Server di build
Nel pacchetto non c’è nulla che dipenda da un computer specifico, quindi un progetto che produce una build offuscata sul PC di uno sviluppatore la produce anche su qualsiasi agente in grado di ripristinare il pacchetto e di raggiungere una licenza. Gli esempi coprono i servizi più comuni:
- GitHub Actions: pacchetto su GitHub Packages, chiave di licenza da un segreto del repository.
- Azure DevOps: pacchetto su un feed Azure Artifacts, chiave di licenza da una variabile segreta della pipeline.
- AppVeyor: pacchetto sul feed dell’account, chiave di licenza da una variabile cifrata.
- Test unitari: test degli assembly offuscati nella stessa pipeline.
Gli agenti e i container Linux eseguono la build tools\netX.0 di Babel. Gli host con una configurazione FIPS di OpenSSL non funzionante richiedono le impostazioni descritte in ConformitĂ FIPS.