Skip to content

Commit

Permalink
Add functionality to generate KSP assembly attributes (#27)
Browse files Browse the repository at this point in the history
* Add functionality to calculate the current version from git tags

* Rework GetVersionFromGit a bit

* KSP attribute generation

* Allow specifying versions for CKAN dependencies

* Update comment for GetVersionFromGit

* Fix version sometimes reverting to 1.0.0

* Add docs to readme

* Use FileVersion isntead of Version

FileVersion doesnt have the suffix. I could use a custom task and regex but meh

* Remove GetVersionFromGit

I've changed my mind, MinVer is the way to go.

* update changelog

* Cache ckan install script for more predictable incrementality

---------

Co-authored-by: JonnyOThan <[email protected]>
  • Loading branch information
drewcassidy and JonnyOThan authored Sep 5, 2024
1 parent 9b8624f commit dd57d2b
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 16 deletions.
86 changes: 70 additions & 16 deletions KSPCommon.targets
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,37 @@
</Target>

<!-- Use CKAN to install mods for any references tagged with a CKAN Identifier -->
<Target Name="CKANInstall" BeforeTargets="_GenerateRestoreProjectSpec;Restore">
<Target Name="CKANInstallScriptGen" BeforeTargets="_GenerateRestoreProjectSpec;Restore">
<Message Text="IntermediateOutputPath: $(Test)"/>
<ItemGroup>
<_CKANCompatibleVersionItems Include="$(CKANCompatibleVersions.Split(' '))"/>
<_CKANDependency Include="%(Reference.CKANIdentifier)"/>
<_CKANDependency Include="%(Reference.CKANIdentifier)" Condition="%(Reference.CKANVersion) == ''"/>
<_CKANDependency Include="%(Reference.CKANIdentifier)=%(Reference.CKANVersion)" Condition="%(Reference.CKANVersion) != ''"/>
<_CKANDependency Include="@(CKANDependency)"/>
</ItemGroup>

<PropertyGroup>
<_TempStagingFolder>$([System.IO.Path]::Combine($([System.IO.Path]::GetTempPath()), $([System.IO.Path]::GetRandomFileName())))</_TempStagingFolder>
<_CKANCommandFile>$(_TempStagingFolder)/ckan_commands.txt</_CKANCommandFile>
<_CKANDependencyList>@(_CKANDependency, ' ')</_CKANDependencyList>
<CKANDependencyList>@(_CKANDependency, ' ')</CKANDependencyList>
<CKANCommandFile>$(IntermediateOutputPath)CKANCommands</CKANCommandFile>
</PropertyGroup>

<ItemGroup>
<!-- Not using `ckan compat set` because as of 2024-08-16 it is still only available in the dev branch -->
<_CKANCommands Include="compat add --gamedir &quot;$(KSPROOT)&quot; %(_CKANCompatibleVersionItems.Identity)"
Condition=" '$(CKANCompatibleVersions)' != '' "/>
Condition=" '$(CKANCompatibleVersions)' != '' "/>

<_CKANCommands Include="install --no-recommends --gamedir &quot;$(KSPROOT)&quot; $(_CKANDependencyList)"/>
<_CKANCommands Include="install --no-recommends --gamedir &quot;$(KSPROOT)&quot; $(CKANDependencyList)" Condition="$(CKANDependencyList) != ''"/>
</ItemGroup>

<Message Text="Writing CKAN commands to $(_CKANCommandFile)"/>
<Message Text="Writing CKAN commands to $(CKANCommandFile)"/>
<Message Text="@(_CKANCommands, '%0a')" Importance="Low"/>
<WriteLinesToFile File="$(_CKANCommandFile)" Lines="@(_CKANCommands)"/>
<Exec Command="cat '$(_CKANCommandFile)' | ckan prompt --headless"
Condition="'$(_CKANDependencyList)' != ''"/>
<RemoveDir Directories="$(_TempStagingFolder)"/>
<WriteLinesToFile File="$(CKANCommandFile)" Lines="@(_CKANCommands)" Overwrite="true" WriteOnlyWhenDifferent="true"/>
</Target>

<!-- Execute generated CKAN command list -->
<Target Name="CKANInstall" DependsOnTargets="CKANInstallScriptGen" BeforeTargets="_GenerateRestoreProjectSpec;Restore" Inputs="$(CKANCommandFile)" Outputs="$(KSPRoot)/CKAN/registry.json">
<Exec Command="cat '$(CKANCommandFile)' | ckan prompt --headless" Condition="'$(CKANDependencyList)' != ''"/>
</Target>

<Target Name="CKANClean" AfterTargets="Clean">
<Delete Files="$(IntermediateOutputPath)CKANCommands"/>
</Target>

<!-- For use like so: `msbuild -t:"GetRequiredExternalTools" -verbosity:minimal -nologo`, then pipe into your destination of choice -->
Expand All @@ -65,6 +69,56 @@
<Message Text="@(RequiredExternalTool)" Importance="high"/>
</Target>

<!--
Generate the KSPAssembly attribute based on the FileVersion property
-->
<Target Name="GenerateKSPAssemblyAttribute" BeforeTargets="CoreGenerateAssemblyInfo"
Condition="$(GenerateKSPAssemblyAttribute)">
<ItemGroup>
<AssemblyAttribute Include="KSPAssembly">
<_Parameter1>$(AssemblyName)</_Parameter1>
<_Parameter1_TypeName>System.String</_Parameter1_TypeName>
<_Parameter2>$(FileVersion.Split('.')[0])</_Parameter2>
<_Parameter2_TypeName>System.Int32</_Parameter2_TypeName>
<_Parameter3>$(FileVersion.Split('.')[1])</_Parameter3>
<_Parameter3_TypeName>System.Int32</_Parameter3_TypeName>
<_Parameter4>$(FileVersion.Split('.')[2])</_Parameter4>
<_Parameter4_TypeName>System.Int32</_Parameter4_TypeName>
</AssemblyAttribute>
</ItemGroup>
</Target>

<!--
Generate the KSPAssemblyDependency attributes based on input references
Reference items must have a CKANIdentifier or a KSPAssemblyName.
KSPAssemblyVersion can be optionally specified.
Otherwise CKANVersion is used.
Otherwise 0.0.0 is used (no minimum version)
-->
<Target Name="GenerateKSPAssemblyDependencyAttributes" BeforeTargets="CoreGenerateAssemblyInfo"
Condition="$(GenerateKSPAssemblyDependencyAttributes) == 'true'">
<ItemGroup>
<Reference Update="%(Reference.identity)" Condition="'%(Reference.CKANIdentifier)%(Reference.KSPAssemblyName)' != ''">
<KSPAssemblyName Condition="%(Reference.KSPAssemblyName) == ''">$([System.String]::Copy('%(Reference.identity)').Split(',')[0])</KSPAssemblyName>
<KSPAssemblyVersion Condition="%(Reference.KSPAssemblyVersion) == ''">%(Reference.CKANVersion)</KSPAssemblyVersion>
<KSPAssemblyVersion Condition="%(Reference.KSPAssemblyVersion) == ''">0.0.0</KSPAssemblyVersion>
</Reference>
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="KSPAssemblyDependency" Condition="%(Reference.KSPAssemblyName) != ''">
<_Parameter1>%(Reference.KSPAssemblyName)</_Parameter1>
<_Parameter1_TypeName>System.String</_Parameter1_TypeName>
<_Parameter2>$([System.String]::Copy('%(Reference.KSPAssemblyVersion)').Split('.')[0])</_Parameter2>
<_Parameter2_TypeName>System.Int32</_Parameter2_TypeName>
<_Parameter3>$([System.String]::Copy('%(Reference.KSPAssemblyVersion)').Split('.')[1])</_Parameter3>
<_Parameter3_TypeName>System.Int32</_Parameter3_TypeName>
<_Parameter4>$([System.String]::Copy('%(Reference.KSPAssemblyVersion)').Split('.')[2])</_Parameter4>
<_Parameter4_TypeName>System.Int32</_Parameter4_TypeName>
</AssemblyAttribute>
</ItemGroup>
</Target>

<ItemDefinitionGroup>
<KSPVersionFile>
<Name>$(SolutionName)</Name>
Expand Down Expand Up @@ -112,4 +166,4 @@
<Message Text="Writing JSON version file to %(KSPVersionFile.Destination)"/>
<Message Text="Contents:%0a$(_JSON)" Importance="low"/>
</Target>
</Project>
</Project>
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ Here's an example from [kOS](https://github.com/KSP-KOS/KOS/blob/22808556c090ebe

Note that `KSPCommon.targets` makes use of `KSPCommon.props` for advanced users, which sets all the below properties but does not include the build targets. If you only want the properties and not the targets, you can use `KSPCommon.props` instead.

### Versioning

[MinVer](https://github.com/adamralph/minver) is recommended for versioning mods. KSPCommon.targets will use the generated version correctly.

### Customization

Properties can be customized at several points:
Expand Down Expand Up @@ -98,6 +102,14 @@ Default value: `1.12 1.11 1.10 1.9 1.8`

Used by the `CKANInstall` target to set additional KSP versions to treat as compatible when installing dependencies.

#### `GenerateKSPAssemblyAttribute`

If set to `true`, automatically generates the `KSPAssembly` for your assembly from the `Version` property.

#### `GenerateKSPAssemblyDependencyAttributes`

If set to `true`, automatically generates `KSPAssemblyDependency` attributes for each dependency. Dependencies should have either the `CKANIdentifier` metadata or `KSPAssemblyName` metadata. Versions can be supplied with `CKANVersion` or `KSPAssemblyVersion`. See [Referencing Dependencies](#referencing-dependencies) below.

### Referencing Dependencies

Referencing assemblies (DLLs) from other mods should be done with a HintPath relative to `$(KSPRoot)`. These should be placed *after* importing `KSPCommon.targets` so that `$(KSPRoot)` will be defined. In addition, you can include the CKAN identifier of the mod to make it installable when restoring the project. Dependencies should have the private flag set to false, unless they are intended to be included alongside the main dll.
Expand Down

0 comments on commit dd57d2b

Please sign in to comment.