It appears that there is no way to reference the package version via a macro in .target/.props files when the package is being packed. Most developers use a hack with $(MSBuildThisFileDirectory), which only works when Import is used in .vcxproj files and backfires when package files are moved into solution folders because package constructs are inserted verbatim into vcxproj.filters files and in that context $(MSBuildThisFileDirectory) refers to the location of the .vcxproj.filters file and not the original target file. 
For example (and this is just one example), if I want to include a packaged library in a visible way (instead of jamming it into the additional dependencies), I would want something like this in the package:
  <ItemGroup>
    <Library Include="packages\$(NugetPkgID).$(NugetPkgVersion)\build\native\$(Platform)\$(Configuration)\mylib.lib" />
  </ItemGroup>
Instead, I'm forced now to use the package ID and version explicitly in .target files, which means that I have to update the version in multiple locations that results in extra maintenance and is quite error-prone. This approach works well with solution folders.
Can you please provide some way to reference the package ID and version in .target/.props files, similar to how you allow these in .nuspec files and MSBuild Nuget builds?
I am not sure I fully understand your scenario here.
I assume you're using packages.config to manage your projects.
What do you mean, there's no way to reference target/props when the package is being packed?
Whose props/targets?
The dependencies?
Do you know the NugetPkgID?
Can we take a step back and try to explain your scenario, and what you're trying to do, maybe there's a better way to achieve that.
Looking forward to hearing from you.
Thanks for a quick response. Let me clarify. I'm creating a native package. Let's say my .nuspec says this:
<package >
  <metadata>
    <id>ABC</id>
    <version>1.2.3</version>
  </metadata>
</package>
It's a native package, so my directory structure is something like this:
packages/build
              /native
                    /include
                    /lib
                    /bin
              ABC.targets
I want people to be able to reference files in the package. For example, if somebody wants to set up a post-build event, they should be able to reference the bin directory within my package, but they shouldn't have to know the version because versions may change when packages are updated, so I currently format ABC.targets as follows:
<Project>
  <PropertyGroup Label="UserMacros">
    <ABCLibName>libdb60d</ABCLibName>
    <ABCDir>packages\ABC.1.2.3\build\native\</ABCDir>
    <ABCLibDir>$(ABCDir)lib\$(Platform)\$(Configuration)\</ABCLibDir>
    <ABCBinDir>$(ABCDir)bin\$(Platform)\$(Configuration)\</ABCBinDir>
  </PropertyGroup>
  <ItemGroup>
    <Library Include="$(ABCLibDir)$(ABCLibName).lib" />
  </ItemGroup>
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalIncludeDirectories>$(ABCDir)include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
  </ItemDefinitionGroup>
</Project>
This way consumers of my package can see explicitly which libraries are added to their project and they can copy DLLs from the package bin directory using $(ABCBinDir) and avoid another commonly used hack to invoke a dummy Link command. People can also reference other package files, if required, and can safely include them in various solution folders, which changes .vcxproj.filters for affected projects. The only problem for me is that now package version is scattered across a few files within the package, which is error-prone.
Do you know the NugetPkgID?
This is a hypothetical tag I'm asking for, except that I chose this name because it was shorter for the post. Not something I would actually suggest if you introduce something along these lines.
PS. Sorry for all the updates - new keyboard.
I would like to second this feature being added. (I am also working in the native space and have a similar situation)
I have the same problem. I want to have way to specify package ID and version at my .targets file.
For example:
<ItemGroup>
    <Content Include="$(NuGetPackageRoot)$(NugetPkgID)\$(NugetPkgVersion)\build\lib.so">
    </Content>
</ItemGroup>
                    The ability for consumers of packages to references the install path (from the global packages folder) of the package has been added in https://github.com/NuGet/Home/issues/6949.
In packages.config an equivalent change would be a lot more involved.
PackageReference is fully integrated with MSBuild which allows for props/targets generated during the restore to function as powerful extensibility points.
@FullBoa
Are you referencing those assets as a consumer or a package author?
@nkolev92
I'm referencing as package author.
@FullBoa
And NuGetPkgID is someone else's package?
And you have that package as a dependency of your package or?
@nkolev92 I have some update on the ask and on how the new Visual Studio handles this.
When I created this issue, there was no separate .props and .targets files in a Nuget pakckage. I cannot remember the Nuget version for that, but this probably will give you some time line reference. 
At the time I would just use $(MSBuildThisFileDirectory) in that package properties file and it would appear exactly that way in the .filters file and Visual Studio was interpreting it as the directory of the .filters file, so package files (e.g. packaged libraries) always appeared outside of solution folders in the IDE when the solution was first loaded. Hence the issue. 
This behavior seems to have been changed with the split of the package properties file onto .props and .targets files. What I see now is that $(MSBuildThisFileDirectory) somehow is resolved into the correct package path, even if it appears in the .filters file. It looks very odd and misleading in the .filters file because _this file directory_ is not where the .filters file is, but it works. 
In order to avoid this odd look, I created user macros to conceal the $(MSBuildThisFileDirectory) macro, so it looks Ok in my packages now. 
Let me illustrate this with an example. I use the same import Nuget does, but just with text files to make it simpler. If this is my .props :
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="UserMacros">
    <ABCDir>$(MSBuildThisFileDirectory)</ABCDir>
  </PropertyGroup>
</Project>
, and this is my .targets:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Text Include="$(ABCDir)\abc-macro-in-targets.txt" />
    <Text Include="$(MSBuildThisFileDirectory)\abc-this-dir-in-targets.txt" />
  </ItemGroup>
</Project>
, and if I drag and drop these files into their solution folders, my .filters file will have this reference to these files:
  <ItemGroup>
    <Text Include="$(ABCDir)\abc-macro-in-targets.txt">
      <Filter>macro-in-targets</Filter>
    </Text>
    <Text Include="$(MSBuildThisFileDirectory)\abc-this-dir-in-targets.txt">
      <Filter>this-dir-in-targets</Filter>
    </Text>
    <Text Include="$(XYZDir)\xyz-macro-in-props.txt">
      <Filter>macro-in-props</Filter>
    </Text>
    <Text Include="$(MSBuildThisFileDirectory)\xyz-this-dir-in-props.txt">
      <Filter>this-dir-in-props</Filter>
    </Text>
  </ItemGroup>
There is that $(MSBuildThisFileDirectory) macros that looks odd, but works somehow. There's no detailed description for this on MSDN, but it appears it tracks internally the .props and .targets files somehow. 
The attached solution demonstrates text files included via  a.targets file (prefixed with abc) and via a .props file. They both work, so there must be a difference in how Visual Studio handles this now. 
Returning to the main issue topic. The behavior described in this post is not documented and is always under some risk of changing and breaking existing Nuget packages. If there was a way to reference package directory via Nuget-provided macros, that risk would be eliminated.
When I created this issue, I didn't realize that the package directory may be located anywhere and just asked for a version macro as a way to access package files without relying on $(MSBuildThisFileDirectory). For this to work, there would have to be either three macros - one for the packages directory, one for the package ID and one for version or just one for the package root location. 
Alternatively, if you can confirm that $(MSBuildThisFileDirectory) behaves as intended and will always work for Nuget packages as described above, then it would be sufficient for the purposes of being able to access package files. I tested this behavior with VS 2017 and VS 2015 and they appear to work the same way. 
I hope it clarifies the thinking behind my ask. Others may have different view on this. Please let me know if you have any questions.
@nkolev92
And NuGetPkgID is someone else's package?
And you have that package as a dependency of your package or?
No, at my .targets.
I have compiled c-library that is used from my C# package project.
For consumers it must work so: mylib.so (c-library) must be copied to consumer's project output folder during build. And consumer should not think about copy c-library to its build artifacts folder. I think so.
This is cause to use NuGetPkgID and some version substitution in my .targets.
Additionally.
It seems strange to create separated script to change versions at .targets.
Perhaps there are another ways to do it but I don't know it.
@FullBoa
You shouldn't need to use the NuGetPkgID if that's your package. You can just use a relative path from the target you are writing. That target will get imported as illustrated here:
https://docs.microsoft.com/en-us/nuget/create-packages/native-packages
I am not sure what you mean by:
It seems strange to create separated script to change versions at .targets.
Perhaps there are another ways to do it but I don't know it.
Can you please clarify?
@gh-andre
It's a loaded response, so I'll do my best to address as much as I can :)
When I created this issue, there was no separate .props and .targets files in a Nuget pakckage. I cannot remember the Nuget version for that, but this probably will give you some time line reference.
Build props/targets were added in 3.x, which came out in 2015, so they've been around for logner than this issue :) But that's not very important right now.
I don't have much context on vcxproj filters so I'd like to focus on how to address your issue with NuGet's capabilities of today.
$(MSBuildThisFileDirectory) is a reserved msbuild property.  See https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-reserved-and-well-known-properties?view=vs-2017
So MSBuildThisFileDirectory will always behave that way. What you are doing seems perfectly reasonable to me.
Note that docs.microsoft replaced msdn :)
To reiterate on the original ask. It seems like you have managed to find a solution for your problem with the current nuget state. Is my interpretation correct?
It's a loaded response
I'm just trying to be informative in case if others find it useful.
Build props/targets were added in 3.x, which came out in 2015, so they've been around for logner than this issue :)
While I appreciate the investigative part of this comment, I just know that .filters didn't work as described then - every time I reopened the project, solution folders wouldn't contain libraries because $(MSBuildThisFileDirectory) would be relative to the filters file, just as the name implies. I cannot tell why it was behaving this way or even reproduce now and the split or .props and .targets seemed to be the point in time, but this was just my guess where it could be changed. 
don't have much context on vcxproj filters so I'd like to focus on how to address your issue with NuGet's capabilities of today.
I find Nuget very useful for native projects, but it is quite discouraging that native targets are always on the back of everybody's priority list in Nuget documentation, discussions and features, like how the new symbol packages are being rolled out. I wish you guys would take C++ development a bit more seriously.
To reiterate on the original ask. It seems like you have managed to find a solution for your problem with the current nuget state. Is my interpretation correct?
The description for $(MSBuildThisFileFullPath) says this:
The absolute path of the project or targets file that contains the target that is running.
In the Nuget context this definition is very ambiguous because it may be attributed to the main project target, which has absolutely nothing to do with the location of Nuget package's .props and .targets files. It appears to be working now, but it is not based on a definitive description of how things are supposed to work, but rather on a trial-and-error approach. 
If Nuget instead provided a way to reference the actual active package path, wherever the package location is, it would be much more straightforward and would remove these ambiguities.
In the Nuget context this definition is very ambiguous because it may be attributed to the main project target, which has absolutely nothing to do with the location of Nuget package's .props and .targets files. It appears to be working now, but it is not based on a definitive description of how things are supposed to work, but rather on a trial-and-error approach.
That is msbuild. It's the targets/props file location. The context of NuGet is irrelevant.
If Nuget instead provided a way to reference the actual active package path, wherever the package location is, it would be much more straightforward and would remove these ambiguities.
Same as the above. That's an MSBuild guaranteed property, not NuGet.
That is msbuild. It's the targets/props file location. The context of NuGet is irrelevant.
That's the point. When $(MSBuildThisFileFullPath) appears outside of MSbuild context, such as the .filters file, its meaning is no longer well defined or even guaranteed and without such guarantee integrating Nuget packages into IDE in a usable way is a challenge. 
Note that what most people are doing, like shoving it into the library list, is a hack. That field is for standard libraries and it provides no visibility about library references and no time stamp checks. The new Nuget seems to provide some way for non-native packages to integrate into project references, but for native targets using the .filters file is the only way to make libraries visible and timestamp-checked. 
When you say filters, do you mean the following https://docs.microsoft.com/en-us/cpp/build/build-system-changes?view=vs-2017#vcxprojfilters-file ?
If so, they are in an msbuild context, so it's perfectly reasonable that you can use that.
If so, they are in an msbuild context, so it's perfectly reasonable that you can use that.
Yes, I mean those. I find it confusing that they are listed in the MSbuild section, I must say, because they make any sense and were created for the IDE, so solution folders are not present in the target files. I'm not quite sure the mere mention of .vcxproj.filters files in MSbuild docs quite guarantees how MSbuild macros are going to be processed. Are you saying this just from this docs page or it's how Microsoft defines in some internal docs how MSbuild interprets these macros in these files?
It's a combination of a lot of things.
It's the docs that I have linked and some public research for me to familiarize myself with filters (nothing internal).
Going through the history, filters were part of the vcproj (which is msbuild), so that was another hint.
Going through the history, filters were part of the vcproj (which is msbuild), so that was another hint.
"were" is the operative word here. It no longer is - hence my point.
nothing internal
That is what worries me. If this behavior was a well-understood behavior within Microsoft and there is ful intent to support it, that's one thing, but otherwise, if this behavior is just a lingering leftover from the times when it was a part of MSBuild, it's a different thing and it offers no guarantees of how it will behave even in the near future. Some assurances based on more than Google searches would be really helpful here.
@gh-andre
The bottom line is that is msbuild today and there is no indication it's changing in the immediate future.
I personally cannot make any commitments about how it will behave in the future, you can reach out here https://developercommunity.visualstudio.com, with those questions.
Going back to the original ask.
There is nothing actionable that needs to be done from a NuGet perspective, and there are no NuGet specific asks, do you agree?
There is nothing actionable that needs to be done from a NuGet perspective, and there are no NuGet specific asks, do you agree?
I cannot speak for others in this thread, but yes, what I described above works for a bunch of my C++ projects using Nuget.
Thanks for confirming your scenario @gh-andre
I'm happy to work with the rest if there are still things that are not clear, or if an ask comes out of the discussion.
For now, I'll close this issue.
Most helpful comment
I have the same problem. I want to have way to specify package ID and version at my .targets file.
For example: