Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trouble building via NuGet on build agent #955

Closed
uecasm opened this issue Nov 14, 2022 · 2 comments
Closed

Trouble building via NuGet on build agent #955

uecasm opened this issue Nov 14, 2022 · 2 comments

Comments

@uecasm
Copy link

uecasm commented Nov 14, 2022

My SHFB doc projects are building on a local machine with SHFB installed just fine, and also building ok via TeamCity on an agent which has the matching version of SHFB installed. However I've been having endless issues trying to get them to work on an agent which has the wrong version installed, or does not have it installed (or more specifically, previously installed it to get all the dependencies, then uninstalled).

I have the following in my .shfbproj:

(at the top)

  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />

(at the bottom)

  <ItemGroup>
    <PackageReference Include="EWSoftware.SHFB">
      <Version>2022.10.15</Version>
    </PackageReference>
    <PackageReference Include="EWSoftware.SHFB.NETFramework">
      <Version>4.8.0.2</Version>
    </PackageReference>
  </ItemGroup>
  <!-- Import the common build targets during NuGet restore because before the packages are being installed, $(SHFBROOT) is not set yet -->
  <Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="'$(MSBuildRestoreSessionId)' != ''"/>
  <!-- Import the SHFB build targets during build -->
  <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" Condition="'$(MSBuildRestoreSessionId)' == ''"/>

The build process is separately running msbuild /t:Restore and msbuild /t:Rebuild, using VS2022 build tools.

(I was originally using nuget restore but that produced different errors during the restore process.)


The first problem is that if the SHFBROOT environment variable is defined externally (e.g. the build agent does have some version of SHFB installed, but not necessarily the right one) then it will just use that version regardless of the nuget package. The whole point of trying to use nuget packages is so that different projects/branches that were developed with specific SHFB versions in the past will build with the exact same version they were designed with, not whatever happens to be installed on the build agent at the time.

The second problem is that if it's not defined, then the build fails with:

error MSB4019: The imported project "C:\SandcastleHelpFileBuilder.targets" was not found. Confirm that the expression in the Import declaration "\SandcastleHelpFileBuilder.targets" is correct, and that the file exists on disk.

In an attempt to fix these, I tried to use GeneratePathProperty="true" on the reference and then use $(PkgEWSoftware_SHFB)tools\ instead of $(SHFBROOT) (or to define SHFBROOT to that within the project) but these didn't help, as it didn't appear to actually define these properties, or at least not early enough in the build to actually use them properly. Perhaps this needs some additional condition, but I couldn't work out what it should be. (The examples for GeneratePathProperty suggest that it is probably only valid during target execution but not at import time.)

(The suggested method in the nuget readme.txt can't be used because PackageReference does not produce a solution-local packages folder.)

The first problem could be ignored if I ensure that none of the build agents do have SHFB installed/define that environment variable, which is inconvenient but possible. I'm not sure what the correct solution to the second issue is; I've tried several variations on the theme; some of them produce different errors, but I haven't had a successful build yet.

One such attempt was to use an exists check instead (as suggested in another issue):

  <Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="!Exists('$(SHFBROOT)\SandcastleHelpFileBuilder.targets')" />
  <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" Condition="Exists('$(SHFBROOT)\SandcastleHelpFileBuilder.targets')" />

but this fails with:

error MSB4057: The target "CreateManifestResourceNames" does not exist in the project.

The way that most packages solve these sorts of issues is to define a build\ID.targets file inside the nuget package itself, which then gets evaluated at the correct time, instead of having an import in the project file (or perhaps only importing the common targets in the project file). Is there some reason this does not? Is there something I'm missing to get this working as is?

@uecasm
Copy link
Author

uecasm commented Nov 14, 2022

My apologies; it turns out the main issue was a configuration error on my end during the Restore build that meant it was not doing the nuget restore on the .shfbproj projects. After correcting this, problem 2 is fixed, although problem 1 remains.

Since this also fixed the missing PkgEWSoftware_SHFB property, I've tried adding this immediately above the imports in an attempt to fix problem 1 as well:

  <PropertyGroup Condition="'$(PkgEWSoftware_SHFB) != '' AND '$(BuildingInsideVisualStudio)' != 'true'">
    <SHFBROOT>$(PkgEWSoftware_SHFB)\tools\</SHFBROOT>
  </PropertyGroup>

This appears to work as expected on both an agent without SHFB and an agent with older SHFB (although the former logs a warning about SHFBROOT not being set in the environment and the latter does not, which makes me a little nervous that the latter might be looking in the wrong path if it actually uses the environment variable for anything, but at least all the paths it logs appear to be correct).

It also appears to build correctly (using the installed SHFB regardless of nuget version, per #920) from VS or the SHFB GUI.

(The former condition fixes an issue loading in VS, while the latter is intended for VS/IDE builds, though I haven't tested a mismatch. It is deliberately ignoring if SHFBROOT is already set from the environment or not.)

Does this seem safe and reasonable, or am I overlooking some issue? Perhaps it should be the default behaviour?
(Making it the default would be easy -- you could just change build\EWSoftware.SHFB.props to check for BuildingInsideVisualStudio instead of an empty SHFBROOT; it already sets the "right" value.)

@EWSoftware
Copy link
Owner

I've made the change to the properties file to use the BuildingInsideVisualStudio property instead. It will ignore the SHFB package inside Visual Studio and the standalone GUI but will use it when building from the command line. I tested it with the latest release of SHFB installed using an older package reference and everything worked as expected. It used the latest release in Visual Studio and the standalone GUI and the older package when built from the command line.

It will take effect with the SHFB package for the next release. However, you'll still need your workaround in place for the projects using the older packages. I did some testing with the workaround and it appeared to work okay as long as the package reference in the project had been restored and was present. In the case of a missing or invalid package version it defaulted to the latest package it could find or the installed version if SHFBROOT was defined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants