我有一个大的c#解决方案文件(~100个项目),我正在努力改善构建时间.我认为"复制本地"在很多情况下对我们来说都是浪费,但我想知道最佳做法.
在我们的.sln中,我们有应用程序A取决于程序集B,它取决于程序集C.在我们的例子中,有几十个"B"和一些"C".由于这些都包含在.sln中,我们正在使用项目引用.所有程序集当前都构建为$(SolutionDir)/ Debug(或Release).
默认情况下,Visual Studio将这些项目引用标记为"复制本地",这会导致每个"C"被复制到$(SolutionDir)/ Debug中,对于构建的每个"B".这似乎很浪费.如果我只关闭"复制本地",会出现什么问题?大型系统的其他人做什么?
跟进:
很多响应建议将构建分解为较小的.sln文件......在上面的示例中,我将首先构建基础类"C",然后是大量模块"B",然后是一些应用程序,"一个".在这个模型中,我需要对来自B的C进行非项目引用.我遇到的问题是"Debug"或"Release"被添加到提示路径中,我最终构建了我的Release版本的"B"反对"C"的调试版本.
对于那些将构建拆分为多个.sln文件的人,如何管理这个问题?
我想知道什么时候设置copy-local=true
引用有任何启发式方法?
如果引用类型只在内部使用我可以设置copy-local
到true
,但如果被引用类型暴露作为参数和返回值我设置copy-local
到false
和指示时,应使用我的媒体库的依赖特定版本应参照?
谁能为我澄清一下这个?
TL; DR是否有任何官方文档详细描述<private>
/"复制本地"选项如何与MSBuild一起使用?应该考虑什么价值?
当你添加一个项目引用从一个项目在Visual Studio中的另一个,它会加入<ProjectReference Include=".....csproj">
到.csproj
的MSBuild文件.
当您将 Visual Studio中的一个项目的文件引用添加到文件系统中的程序集文件时,它将添加<Reference Include="Foo"> <HintPath>....Foo.dll</HintPath> ...
到.csproj
MSBuild文件.
在这两种情况下,Visual Studio的设置Copy Local = True|False
,一个子元素<Private>True</Private>
或<Private>False</Private>
将增加.
Reference
并且ProjectReference
似乎在Common MSBuild Project Items下记录:
Run Code Online (Sandbox Code Playgroud)<ProjectReference> Represents a reference to another project. Item Name Description ------------------------- Name ... Project ... Package ... <Reference> Represents an assembly (managed) reference in …
.net msbuild copy-local visual-studio msbuild-projectreference
我想知道copy-local = true对于引用究竟是什么.它是否将引用的程序集及其所有依赖项复制到输出目录?
我的方案如下:我有一个使用log4net的自定义日志包装器.我构建了MyLogWrapper.dll的发布程序集,其中log4net.dll引用设置为copy-local true.从复制本地设置为true的MyProject引用MyLogWrapper.dll会导致log4net.dll被复制吗?我只引用MyLogWrapper.dll,而不是MyProject中的任何依赖项.log4net.dll没有被复制到MyProject输出目录,但MyLogWrapper的所有其他依赖项都是.可能是什么问题呢?
我做了一些实验,似乎如果我从GAC中删除程序集(log4net.dll),它就会开始在本地复制.任何人都可以确认这是问题吗?
我有以下项目结构:
Library1 <--[project reference]-- Library2 <--[ref]-- Executable
-------- -------- ----------
ContentFile .cs files .cs files
.cs files
Run Code Online (Sandbox Code Playgroud)
所有项目引用都具有CopyLocal = true.
当我构建项目时,ContentFile
会将其复制到Library2
输出目录,而不是复制到Executable
输出目录,这意味着ContentFile
应用程序运行时缺少可执行文件.
为什么内容文件被复制到Library2
输出目录,但不是Executable
?有没有办法将它复制到后者(我想在没有构建事件的情况下这样做,因为我相信人们会忘记这一点)?
我正在寻找一个合理且可维护的解决方案; 在添加新项目或新的间接引用的内容文件时,只需要很少的工作,因此尽可能不要忘记这样做.
使用Post-Build事件(如xcopy ../Library/bin/Debug/SomeDll.dll bin/Debug
); 并手动设置项目的输出目录$(SolutionDir)/bin/...
而不是默认(每个项目),两者都很快变得一团糟.将内容文件添加为"主项目"中的链接也太乏味了.如果C#具有与Visual C++相同的输出文件的默认设置(即$SolutionDir/$Platform/$Configuration
),那就没问题了,但事实并非如此.
我也考虑过根本不使用标准的MSBuild程序并编写自定义构建目标(比如在Atmel Studio中使用gcc),但我没有做得太远.此外,我希望Visual Studio的标准"构建"和"调试"命令像往常一样工作.
以下是我正在做的更多细节.
我有一个Executable
项目的解决方案.此外,还有很多项目可以调用Plugin
.通过托管项目引用Executable
引用所有这些Plugin
.
由于插件项目是针对可执行文件定制的,但可能具有可重用的组件,因此主要功能通常在External
项目中实现,使Plugin
项目仅仅是包装器(并非总是如此).
所述External
项目有时使用由第三方提供的本机DLL.然后将这些DLL External
作为内容文件添加到项目中并Copy to output dir
设置为 …
从v3.9.43通过nuGet升级到ServiceStack v3.9.70之后,我注意到ServiceStack.Interfaces.dll
不再将其复制到依赖于使用ServiceStack的类库的项目.这会导致以下错误:
System.IO.FileNotFoundException: Could not load file or assembly 'ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
Run Code Online (Sandbox Code Playgroud)
所有其他ServiceStack dll都被复制,只缺少ServiceStack.Interfaces.所有引用都设置为Copy Local = True
,并且此StackOverflow帖子的建议无法解决问题.
我注意到这ServiceStack.Interfaces.dll
是唯一版本为1.0.0.0的版本,所有其他版本都设置为3.9.70.0.这可能是一个原因吗?
有没有人知道如何修复它而无需在引用我的类库的所有项目中手动引用ServiceStack.Interfaces.dll?
v3.9.71.0仍然存在问题.它确实与ServiceStack.Interfaces
程序集的版本保留为1.0.0.0而不是版本有关.
我克隆了ServiceStack的github存储库,并在build\build.proj
文件中更改了这一行并运行build\build.bat
.
<!-- Exclude versioning future strong-named libs -->
<RegexTransform Include="$(BuildSolutionDir)/src/**/AssemblyInfo.cs"
Exclude="$(SrcDir)/ServiceStack.Interfaces*/Properties/AssemblyInfo.cs">
<Find>\d+\.\d+\.\d+\.\d+</Find>
<ReplaceWith>$(Version)</ReplaceWith>
</RegexTransform>
Run Code Online (Sandbox Code Playgroud)
为此(注意到删除的排除)
<RegexTransform Include="$(BuildSolutionDir)/src/**/AssemblyInfo.cs">
<Find>\d+\.\d+\.\d+\.\d+</Find>
<ReplaceWith>$(Version)</ReplaceWith>
</RegexTransform> …
Run Code Online (Sandbox Code Playgroud)