VS/CSharp: Multiple issues with Link tag
Generating Link tags in C# projects has several issues, most of them related.
Given the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.25)
project(test LANGUAGES CSharp)
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/Generated.cs)
add_library(test SHARED ${CMAKE_CURRENT_BINARY_DIR}/Generated.cs)
-
If the build dir path happens to have the same prefix as the source dir path, then the Link tag ends up totally bogus. For example:
source dir: C:\dev\project
binary dir: C:\dev\projectBUILD
Link tag becomes: <Link>UILD\Generated.cs</Link>
This is becausecmVisualStudio10TargetGenerator::GetCSharpSourceLink()
usescmHasPrefix(fullFileName, srcDir)
(https://gitlab.kitware.com/cmake/cmake/-/blob/29fb1367b6b/Source/cmVisualStudio10TargetGenerator.cxx#L5509) to check if a file is in the source tree, but that happens to be true for a file in the binary dir in this case too, and so the Link becomes garbage.
A quick fix would be to append a slash to srcDir and binDir in that function.
(I have a broader concern about checks like these, see at the end...) -
Link tags are always generated for every source file in the case of out-of-source builds. This makes generated files inside the current binary dir disappear. VS also warns about this. See the above project, Generated.cs is not visible in VS IDE (make sure to use a build dir not like in point 1. to avoid that bug for the time being).
This has been reported apparently (#22104 (closed)), and supposedly fixed, but that's not the case. IncmVisualStudio10TargetGenerator::WriteSource()
(https://gitlab.kitware.com/cmake/cmake/-/blob/29fb1367b6b/Source/cmVisualStudio10TargetGenerator.cxx#L2413) a Link element is always added unconditionally for out-of-source builds. -
For in-source builds, if a project in a subdirectory adds a .cs file from an upper directory, no Link tag is generated. But, the file still does show up in VS IDE at the root, so apparently the Link tag doesn't even seem to be necessary at all in this case (unless the file wants to be grouped under some folder, in which case it is needed of course). I don't know if this is normal behaviour or not from VS (accept/show external files without a Link tag).
In general, I don't think whether the build is in-source or out-of-source should matter when determining the usage of Link tags (ie. checks like if(!this->InSourceBuild){...}
and such). The only thing what should matter is the location of files (whether they are in the source dir or the binary dir or anywhere else) relative to the .csproj file (whether it is in the source dir or the binary dir). Or am I missing something?
An additional question: The <Compile Include="path"> tags always contain path as absolute paths. Shouldn't they be relativized to the .csproj file in general?
Also, is point 1. a common way to check paths in CMake? Because if it is, then is it dangerous in general to use a build dir path, which has the same prefix as the source dir path?