Here is a solution taking the second approach:
The project contains the following build configurations and template:
The Shared Build Number Generator is the first build in the chain. It does nothing other than create a build number that the dependent builds will share. I am using the TeamCity-referenced plugin Shared Build Number by Nicholas Williams.
And here are the notable configurations in the build template:
Note the build number is coming from the build ID of the Shared Build Number Generator mentioned above. So, in my case, that build's ID is 14. Also note the variable %TargetFrameworkVersion% in the artifact path. Fortunately, TeamCity supports variable interpolation almost everywhere.
In order for the template to leverage the build number, it must have a snapshot dependency on that build configuration:
And, finally (regarding the template), the build parameters are nearly identical to the parameters in my preferred solution. Note the additional Configuration Parameter, however. This is what will be overridden by the inheriting build configurations:
Then, in the dependent builds, you must wire up a snapshot dependency so that the build number (inherited from the template) actually works by also taking a dependency on the shared build number build configuration:
And, of course, you need to set the actual targeted framework:
With the actual builds configured, you can now configure the NuGet pack build configuration. You do not need to attach to a VCS root:
But you do need to configure a bunch of dependencies (both snapshot and artifact):
And, finally, you're done.