I'm rewriting our NAnt build scripts to make them cleaner and simpler, as well as more general purpose.
我正在重写我们的NAnt构建脚本,以使它们更简洁,更通用。
One of the steps in our build process is to package certain files into a zip file. Before we had created a fileset
with lots of included file types, trying to catch everything that might be in the project. This occasionally caused problems when we wanted to include a non-standard file type with the project.
我们构建过程中的一个步骤是将某些文件打包到一个zip文件中。在我们创建包含大量包含文件类型的文件集之前,尝试捕获可能在项目中的所有内容。当我们想要在项目中包含非标准文件类型时,偶尔会出现问题。
I was hoping that I could find a way to create a fileset
based on the files (and, also, a subset of the files) listed in the Visual Studio project file (.csproj). I could then use this fileset in a zip
task. I haven't found anything that does this automatically (though the now-deprecated SLiNgshoT
task in NAntContrib looked a little promising).
我希望我能找到一种基于Visual Studio项目文件(.csproj)中列出的文件(以及文件的子集)创建文件集的方法。然后,我可以在zip任务中使用此文件集。我没有发现任何自动执行此操作(尽管NAntContrib中现已弃用的SLiNgshoT任务看起来有点大有希望)。
I started down the path of trying to do this manually, but have gotten stuck. I have a target that gets the project from the solution (using regex
), then tries to get each Content file in the project using xmlpeek
(with the XPath query /n:Project/n:ItemGroup/n:Content/@Include
). The problem here is that xmlpeek
doesn't return every value, just the first. And, even if it did return every value, I'm not sure how I'd get it into a fileset
from here.
我开始尝试手动执行此操作,但已陷入困境。我有一个目标从解决方案中获取项目(使用正则表达式),然后尝试使用xmlpeek(使用XPath查询/ n:Project / n:ItemGroup / n:Content / @ Include)获取项目中的每个Content文件。这里的问题是xmlpeek不返回每个值,只返回第一个值。并且,即使它确实返回了所有值,我也不确定如何从此处将其放入文件集中。
Is there any way to salvage this track of thinking? Can I accomplish what I want with a custom NAnt task (I'd prefer not to have every project dependent on a custom task)? Is there some built-in way to do this that I'm not finding?
有没有办法挽救这种思维轨道?我可以使用自定义的NAnt任务完成我想要的任务(我不希望每个项目都依赖于自定义任务)吗?是否有一些内置的方法可以做到这一点,我找不到?
Please feel free to ask questions in the comments if something about my goal or method isn't clear.
如果我的目标或方法不明确,请随时在评论中提问。
Thanks!
UPDATE: To clarify, my point in all of this is to make the whole process much more seamless. While I can easily add all .xml files to a package, this often gets .xml files that live in the same folder but aren't really part of the project. When I already have a list of the files that the project uses (separated out between Content and other types, even), it seems a shame not to use that information. Ultimately, no one should have to touch the build file to change what gets included in a package. It doesn't seem like too much of a pipe dream to me...
更新:为了澄清,我在所有这一点上的观点是使整个过程更加无缝。虽然我可以轻松地将所有.xml文件添加到包中,但这通常会获得存在于同一文件夹中但实际上不属于项目的.xml文件。当我已经拥有项目使用的文件列表(在内容和其他类型之间分开,甚至)时,不使用该信息似乎是一种耻辱。最终,没有人应该触摸构建文件来更改包中包含的内容。对我来说,这对我来说似乎没什么梦想......
3 个解决方案
#1
See this related question. The microsoft.build.buildengine interface should let you get much better access to the information you need, but unfortunately I think you would have to build a custom task.
看到这个相关的问题。 microsoft.build.buildengine界面应该可以让您更好地访问所需的信息,但遗憾的是我认为您必须构建自定义任务。
But I think that parsing a project file to generate a fileset that is used elsewhere is ... a bit much to put all inside your build script. And since you seem to want to re-use this, I don't think that depending on a custom task is any worse than any other form of re-use (even if you can do it all in existing Nant tasks, you'd still need to have every project inherit that process somehow).
但我认为解析一个项目文件来生成一个在别处使用的文件集是......将所有内容都放在你的构建脚本中。而且由于您似乎想要重复使用它,我认为根据自定义任务而言,任何其他形式的重用都不会更糟(即使您可以在现有的Nant任务中完成所有任务,您也可以仍然需要让每个项目以某种方式继承该过程)。
#2
As far as reading your project files. I've done something like this before. I ended up just writing a program that read the project files and built a custom project by project build file.
至于阅读你的项目文件。我之前做过类似的事。我最后只编写了一个程序来读取项目文件,并通过项目构建文件构建了一个自定义项目。
However I was trying to compile my code base. Looks like you are trying to just zip it.
但是我试图编译我的代码库。看起来你试图只是压缩它。
Considering that the Zip task would allow you to run multiple filesets into it you could create some generic filesets and then just update for your specific ones rather easily.
考虑到Zip任务允许您在其中运行多个文件集,您可以创建一些通用文件集,然后只需轻松更新您的特定文件集。
So you could have something like this:
所以你可以这样:
<fileset id="project.source.objects">
<include name="**/*.cs"/>
<include name="**/*.xml"/>
<include name="**/*.resx"/>
</fileset>
<fileset id="project.misc.sources">
<include name="MyFile1.someext"/>
</fileset>
Then in your zip target just put:
然后在你的zip目标中放入:
<zip zipfile="myzip.zip">
<fileset refid="project.source.objects"/>
<fileset refid="project.misc.sources"/>
</zip>
Now if you wanted project specifics. There is one other thing you could do. If you are using VS2005 or greater search on T4. It's a template framework for creating plugins that allow you have extra files generated when you do something. Kind of like when you do a class diagram or have a XSD (and it gets it's code behind file, it's done this way).
现在,如果你想要项目细节。还有一件事你可以做。如果您在T4上使用VS2005或更高版本的搜索。它是一个用于创建插件的模板框架,允许您在执行某些操作时生成额外的文件。有点像你做一个类图或有一个XSD(它得到它的代码隐藏文件,它就是这样做的)。
In most projects that I've worked on we maintain a build file for each project and just keep it up to date. Since we have the generic filesets that's a start so we only really need to update the file for the obscure stuff.
在我参与的大多数项目中,我们为每个项目维护一个构建文件,并让它保持最新。由于我们的通用文件集是一个开始,所以我们只需要为隐藏的东西更新文件。
Hope that helps. If you could provide a little more detail I might be able to help further.
希望有所帮助。如果你能提供更多细节,我可能会进一步提供帮助。
#3
I like the first part of Josh's idea.
我喜欢乔希的想法的第一部分。
Write a small console app to pull the files from the .csproj (since it's just XML in there) and write the list out to a file.
编写一个小型控制台应用程序来从.csproj中提取文件(因为它只是那里的XML)并将列表写入文件。
Instead of NAnt's zip task, I would use 7-zip to create the archive with the list you generated in the previous step:
而不是NAnt的zip任务,我会使用7-zip创建存档,其中包含您在上一步中生成的列表:
(I'm creating a self extracting archive here)
(我在这里创建一个自解压存档)
<target name="ZipBuild">
<exec program="${SevenZip}" workingdir="${SolutionPath}/Installation/Build.Staging">
<arg value="a" />
<arg value="-sfx" />
<arg value="ReferenceBuild-${build.number}.exe" />
<arg value="@mycustomfilelist.txt" />
</exec>
</target>
Hope that helps,
希望有所帮助,
-jason
#1
See this related question. The microsoft.build.buildengine interface should let you get much better access to the information you need, but unfortunately I think you would have to build a custom task.
看到这个相关的问题。 microsoft.build.buildengine界面应该可以让您更好地访问所需的信息,但遗憾的是我认为您必须构建自定义任务。
But I think that parsing a project file to generate a fileset that is used elsewhere is ... a bit much to put all inside your build script. And since you seem to want to re-use this, I don't think that depending on a custom task is any worse than any other form of re-use (even if you can do it all in existing Nant tasks, you'd still need to have every project inherit that process somehow).
但我认为解析一个项目文件来生成一个在别处使用的文件集是......将所有内容都放在你的构建脚本中。而且由于您似乎想要重复使用它,我认为根据自定义任务而言,任何其他形式的重用都不会更糟(即使您可以在现有的Nant任务中完成所有任务,您也可以仍然需要让每个项目以某种方式继承该过程)。
#2
As far as reading your project files. I've done something like this before. I ended up just writing a program that read the project files and built a custom project by project build file.
至于阅读你的项目文件。我之前做过类似的事。我最后只编写了一个程序来读取项目文件,并通过项目构建文件构建了一个自定义项目。
However I was trying to compile my code base. Looks like you are trying to just zip it.
但是我试图编译我的代码库。看起来你试图只是压缩它。
Considering that the Zip task would allow you to run multiple filesets into it you could create some generic filesets and then just update for your specific ones rather easily.
考虑到Zip任务允许您在其中运行多个文件集,您可以创建一些通用文件集,然后只需轻松更新您的特定文件集。
So you could have something like this:
所以你可以这样:
<fileset id="project.source.objects">
<include name="**/*.cs"/>
<include name="**/*.xml"/>
<include name="**/*.resx"/>
</fileset>
<fileset id="project.misc.sources">
<include name="MyFile1.someext"/>
</fileset>
Then in your zip target just put:
然后在你的zip目标中放入:
<zip zipfile="myzip.zip">
<fileset refid="project.source.objects"/>
<fileset refid="project.misc.sources"/>
</zip>
Now if you wanted project specifics. There is one other thing you could do. If you are using VS2005 or greater search on T4. It's a template framework for creating plugins that allow you have extra files generated when you do something. Kind of like when you do a class diagram or have a XSD (and it gets it's code behind file, it's done this way).
现在,如果你想要项目细节。还有一件事你可以做。如果您在T4上使用VS2005或更高版本的搜索。它是一个用于创建插件的模板框架,允许您在执行某些操作时生成额外的文件。有点像你做一个类图或有一个XSD(它得到它的代码隐藏文件,它就是这样做的)。
In most projects that I've worked on we maintain a build file for each project and just keep it up to date. Since we have the generic filesets that's a start so we only really need to update the file for the obscure stuff.
在我参与的大多数项目中,我们为每个项目维护一个构建文件,并让它保持最新。由于我们的通用文件集是一个开始,所以我们只需要为隐藏的东西更新文件。
Hope that helps. If you could provide a little more detail I might be able to help further.
希望有所帮助。如果你能提供更多细节,我可能会进一步提供帮助。
#3
I like the first part of Josh's idea.
我喜欢乔希的想法的第一部分。
Write a small console app to pull the files from the .csproj (since it's just XML in there) and write the list out to a file.
编写一个小型控制台应用程序来从.csproj中提取文件(因为它只是那里的XML)并将列表写入文件。
Instead of NAnt's zip task, I would use 7-zip to create the archive with the list you generated in the previous step:
而不是NAnt的zip任务,我会使用7-zip创建存档,其中包含您在上一步中生成的列表:
(I'm creating a self extracting archive here)
(我在这里创建一个自解压存档)
<target name="ZipBuild">
<exec program="${SevenZip}" workingdir="${SolutionPath}/Installation/Build.Staging">
<arg value="a" />
<arg value="-sfx" />
<arg value="ReferenceBuild-${build.number}.exe" />
<arg value="@mycustomfilelist.txt" />
</exec>
</target>
Hope that helps,
希望有所帮助,
-jason