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

New .csproj cannot reference a traditional .csproj #1730

Closed
jnm2 opened this issue Mar 10, 2017 · 36 comments
Closed

New .csproj cannot reference a traditional .csproj #1730

jnm2 opened this issue Mar 10, 2017 · 36 comments
Labels
Discussion/Question A discussion or question about the project that will not be treated as a bug or feature request.

Comments

@jnm2
Copy link

jnm2 commented Mar 10, 2017

[I can't find instructions on which repo to post this in. I'm happy to move it if need be.]

https://github.com/jnm2/misc-codesamples/raw/master/Bug%20reports/.NET/MSBuild%20old%20csproj%20issue.zip

Repro

To see the problem, build the .sln in Visual Studio. It fails with no errors.

Or, run the following from the VS2017 developer command prompt:

msbuild "MSBuild old csproj issue.sln" /t:restore
msbuild "MSBuild old csproj issue.sln" /t:clean

The clean fails (as do subsequent cleans and builds) with errors similar to:

"MSBuild old csproj issue.sln" (clean target) (1) ->
"NonGuiTestProject\NonGuiTestProject.csproj" (Clean target) (2) ->
"WinFormsLibrary\project.json" (Clean target) (4:2) ->
WinFormsLibrary\project.json(1,1): error MSB4025: The project file could not be loaded. Data at the root level is invalid. Line 1, position 1.

Dilemma

This is purely net462 stuff. .NET Core and .NET Standard are not in the picture here. This makes it difficult to search for help on this issue because .NET Core information is inapplicable. MSBuild 15 can build traditional .csproj + project.json just fine. And that's a very good thing.

The GUI projects can't migrate away from .csproj + project.json (NuGet v3) because CPS does not support them yet.
Moving back to packages.config (NuGet v2) is not an option for a plethora of reasons, not least of which is that our application depends on packages that require project.json or later.

The non-GUI test project should be free to move forward to CPS .csproj (NuGet v4). The reason I'm undertaking the migration now is that all the test projects fail to build under MSBuild 15. They contain boilerplate from the VS2015 template such as <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> which works fine with MSBuild 14 and fails with MSBuild 15. Our new build server purposely has only Visual Studio 2017 installed, not VS2015, but this forces me to change all the test projects to play well with MSBuild 15. Since I have to spend time learning how to clean them up, I intended to save time by making our planned move to CPS now.

I have no idea what's going on. Please provide a workaround and a fix. I have been planning and anticipating for ages to be able to migrate our console, class library and test projects to the new .csproj. It solves a number of issues for us. Not being able to move forward at all is incredibly disappointing.

@jnm2
Copy link
Author

jnm2 commented Mar 11, 2017

Updated repro steps. This bug only occurs after the initial package restore.

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

I found a workaround: every new .csproj project must directly reference every transitively-referenced project.json project to avoid this bug. That's better than not being able to move forward but it's a lot of noise that does not truly represent necessary references.

@jmarolf
Copy link
Contributor

jmarolf commented Mar 13, 2017

@jnm2 Package References will work in your winforms projects even though they are not yet on CPS. I would recommend moving away from project.json entirely and using package references for the projects that need to reference nuget packages.

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

@jmarolf For some project.json projects that will work. For a number of them though, using a package reference instead of a project reference is quite awkward. I frequently need to step into and edit code in some of these projects. When I say frequently, I mean it'll be beyond aggravating to be working with binaries instead of a project.

@jmarolf
Copy link
Contributor

jmarolf commented Mar 13, 2017

@jnm2 can you give an example? Every project.json idiom should have a matching concept in package reference.

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

@jmarolf Not when you're using project.json simply as a necessary replacement for packages.config, if I understand you. @onovotny told me to start using project.json for all traditional .NET Framework .csprojs instead of packages.config when I was having issues with the new Humanizer packages. (He later wrote a guide: https://oren.codes/2016/02/08/project-json-all-the-things/) These project.json files do not create packages. They only hold public NuGet package references. A typical example:

{
  "dependencies": {
    "Humanizer.Core": "2.1.0"
  },
  "frameworks": {
    "net462": {}
  },
  "runtimes": {
    "win": {}
  }
}

Using project.json over packages.config solved some big issues for us, especially related to source control.

@jmarolf
Copy link
Contributor

jmarolf commented Mar 13, 2017

@jnm2 right, so delete the project.json and within the csproj file add the following:

  <ItemGroup>
    <PackageReference Include="Humanizer.Core" Version="2.1.0" />
  </ItemGroup>

This is equivalent to your project.json except it is specified in the csproj file

@clairernovotny
Copy link
Member

@jnm2 All project types can use PackageReference in VS 2017 so the new guidance is to use that everywhere and get rid of project.json. The only gotcha is that PackageReference is VS 2017+ only.

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

@jmarolf @onovotny Yes, and like I said above, I've converted all possible project.json projects to CPS .csproj with PackageReference already. These remaining project.json projects cannot use the CPS .csproj because it messes up Windows Forms designers. These projects are stuck on the old .csproj.

@clairernovotny
Copy link
Member

You don't need to use the CPS projects to use PackageReference. All of the existing project types support it, just add the line manually the first time. Once you do, NuGet will add/update others.

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

That's awesome! VS2017-only is not a problem, but I didn't know I could do that. Is there a document detailing which CPS .csproj features can be used in traditional .csprojs with VS2017?

@clairernovotny
Copy link
Member

All PackageReference features work for packages. Transitive project-to-project references don't work, so your legacy project will need a p2p ref for each of those that it needs -- just like today.

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

The next thing that comes to mind is... can VS2017 handle globbing in legacy projects just like it does in CPS projects? Besides PackageReference and globbing, what else can I use in the legacy projects?

@clairernovotny
Copy link
Member

MSBuild can always handle globs...but VS will mess them up if you edit the project file :)

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

@onovotny So PackageReference is the only new thing that came to legacy projects in VS2017?

@clairernovotny
Copy link
Member

pretty much

@jnm2
Copy link
Author

jnm2 commented Mar 13, 2017

@jmarolf @onovotny Thank you both very much.

@dsplaisted
Copy link
Member

@emgarten Is this a NuGet issue? I also tried opting the GUI projects in the repro into PackageReference mode (NuGet/Home#4488), but then I got a different error:

"C:\Users\daplaist\Downloads\MSBuild old csproj issue\MSBuild old csproj issue.sln" (default target) (1) ->
"C:\Users\daplaist\Downloads\MSBuild old csproj issue\WinFormsApp\WinFormsApp.csproj" (default target) (2) ->
(ResolveNuGetPackageAssets target) ->
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\NuGet\15.0\Microsoft.NuGet.targets(197,5): error : The project.json is referencing the project 'C:\Users\daplaist\Downloads\MSBuild old csproj issue\WinFormsApp\WinFormsLibrary\WinFormsLibrary.csproj', but an output path was not specified on an item in the ProjectReferencesCreatingPackages property. [C:\Users\daplaist\Downloads\MSBuild old csproj issue\WinFormsApp\WinFormsApp.csproj]

@jmarolf
Copy link
Contributor

jmarolf commented Mar 14, 2017

@dsplaisted did you delete the old project.json file?

@dsplaisted
Copy link
Member

@jmarolf

@dsplaisted did you delete the old project.json file?

Yes

@emgarten
Copy link
Member

@dsplaisted the error you pasted is due to NuGet/Home#4532 it happens when a legacy csproj with PackageReference references another legacy csproj.

@jnm2
Copy link
Author

jnm2 commented Mar 14, 2017

I'm positive it was working before, but now it's saying:

"Solution.sln" (Build target) (1) ->
"Library3.csproj" (default target) (3) ->
"Library2.csproj" (default target) (4:2) ->
(ResolveNuGetPackageAssets target) ->
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\NuGet\15.0\Microsoft.NuGet.targets(197,5): error : The project.json is referencing the project 'MyLibrary.csproj', but an output path was not specified on an item in the ProjectReferencesCreatingPackages property.

None of the three libraries involved have a project.json. Library3 and Library2 use PackageReference and Library does not use NuGet at all.

@jmarolf
Copy link
Contributor

jmarolf commented Mar 14, 2017

@dsplaisted @jnm2 This sounds like a nuget bug if you do not have and project.json or project.lock.json files on your system

@emgarten
Copy link
Member

emgarten commented Mar 14, 2017

ProjectReferencesCreatingPackages error

This error happens with legacy csproj + PackageReference due to NuGet/Home#4532 You will hit this issue if you restore from the command line. If you restore from Visual Studio the issue will not come up, so that may explain why you are hitting it intermittently.

Invalid Line 1 error

WinFormsLibrary\project.json(1,1): error MSB4025: The project file could not be loaded. Data at the root level is invalid. Line 1, position 1.

Is caused by not having a direct reference to a transitive project. You can fix it by referencing all projects directly.

For example with these projects: A -> B -> C you must have A -> B, A -> C, B -> C to reference all projects directly.
dotnet/sdk#922

Suggestions

Using NETCore SDK projects with Legacy csproj + project.json works great as long as you work around dotnet/sdk#922 We are currently using this for the NuGet repository.

Legacy csproj + PackageReference shouldn't be used yet, it will be fixed soon in the next update of Visual Studio 2017.

@jnm2
Copy link
Author

jnm2 commented Mar 14, 2017

Legacy csproj + PackageReference shouldn't be used yet, it will be fixed soon in the next update of Visual Studio 2017.

Oh boy haha, so there's no workaround? I should roll back the upgrades?

@clairernovotny
Copy link
Member

We are using Legacy + PackageRef with MSAL here: https://github.com/azureAD/microsoft-authentication-library-for-dotnet

There are some workarounds needed, but it does work....

@jnm2
Copy link
Author

jnm2 commented Mar 15, 2017

This gives me hope for our Winforms projects. I'm not sure I want to go there yet, though.

@clairernovotny
Copy link
Member

@dsplaisted I put a workaround for the project.json issue based on code @bbowman wrote on this MyGet feed https://www.myget.org/F/msbuildsdkextras/api/v3/index.json. Install Microsoft.NuGet.Build.Tasks.Workaround

clairernovotny pushed a commit to clairernovotny/microsoft-authentication-library-for-dotnet that referenced this issue Mar 16, 2017
kpanwar pushed a commit to AzureAD/microsoft-authentication-library-for-dotnet that referenced this issue Mar 16, 2017
* clean up projects

* updated gitignore

* more clean up

* cleaned up test project

* remove UWP app from release build

* updated projects

* remove NSubstitute.

* add xforms ref

* rename sln folder to avoid conflict with proj name

* Add workaround for dotnet/project-system#1730
@jnm2
Copy link
Author

jnm2 commented Mar 16, 2017

At this point I am very confused. I stopped using PackageReference for legacy csproj and put back the project.json as instructed, and it built fine on the build server, but in Visual Studio on my dev machine and on the command line I'm getting the exact same error as when I was using PackageReference:

"Solution.sln" (Build target) (1) ->
"CpsLibrary3.csproj" (default target) (3) ->
"LegacyLibrary2.csproj" (default target) (4:2) ->
(ResolveNuGetPackageAssets target) ->
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\NuGet\15.0\Microsoft.NuGet.targets(197,5): error : The project.json is referencing the project 'CpsLibrary1.csproj', but an output path was not specified on an item in the ProjectReferencesCreatingPackages property.

Help?

@jnm2
Copy link
Author

jnm2 commented Mar 16, 2017

Apparently I need to delete my obj folder from each legacy project now that I've reverted their PackageReferences to project.json. msbuild /t:clean on its own before every try wasn't good enough.

@jnm2
Copy link
Author

jnm2 commented Mar 16, 2017

Nitpick: I'd like msbuild /t:clean to reset the state of the working tree in such a way that it's as though I'd never built before. It only has one job, right? It doesn't seem to be fulfilling it.

@davkean
Copy link
Member

davkean commented Mar 21, 2017

@jnm2 What's the state of this thread? It appears that we've got bugs on the issues you raised in thread with exception to msbuild /t:clean.

With regards to clean, feel free to open a bug over on github.com/microsoft/msbuild, but what your asking is quite difficult - it would require MSBuild to persist every single output ever produced from a tree.

@davkean davkean added the Discussion/Question A discussion or question about the project that will not be treated as a bug or feature request. label Mar 21, 2017
@jnm2
Copy link
Author

jnm2 commented Mar 21, 2017

@davkean

With regards to clean, feel free to open a bug over on github.com/microsoft/msbuild, but what your asking is quite difficult - it would require MSBuild to persist every single output ever produced from a tree.

Yes, I was thinking because of that difficulty, perhaps it should be the SDK's responsibility to clean itself up rather than MSBuild's. I'm not sure where the issue belongs.

What's the state of this thread?

Waiting for a fix. Right now there is a workaround, which is for the new csprojs to directly reference every transitively referenced legacy csproj. That is a bit obnoxious. It's not clear to me if you're saying legacy + PackageReference will be the only the answer once it's no longer buggy itself, or if this issue is waiting to be fixed with legacy + project.json. (To the uninitiated, it seems like a simple fix: don't treat the .json as an XML project.)

@davkean
Copy link
Member

davkean commented Mar 22, 2017

MSBuild would be the correct place to file this.

Given we've got NuGet bugs tracking your issue, I'll close this out.

@jnm2
Copy link
Author

jnm2 commented Apr 10, 2017

I'm looping back here from NuGet/Home#4532 to confirm that the ideal workaround, replacing project.json with PackageReference in all types of csproj, is now possible. I confirmed that this is working in 15.1.26303.3.

@gulbanana
Copy link

Unfortunately some project combinations are still affected, particularly when transitive references are involved - https://github.com/dotnet/cli/issues/6294

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Discussion/Question A discussion or question about the project that will not be treated as a bug or feature request.
Projects
None yet
Development

No branches or pull requests

7 participants