Setting an item metadata using a property - tfs

I have been trying to make a task in my TFS builds more generic, and one of the things I am trying to do is copy some files to different directories depending on the build using the task. I toyed with the idea of using properties, but I couldn't think of a way to do that cleanly, so I tried to go with using item metadata, as I've been able to do so in another place in the same target file I'm working on, only this time, I'd like to use properties.
Here's what I want to do:
<ItemGroup>
<DestinationParent Include="$(DeploymentPath)">
<DestinationParentPath>$(DeploymentPath)</QuartzParentPath>
</DestinationParent>
</ItemGroup>
And later in the build, I tried to copy some files to the destination folder by referencing the item metadata:
<Copy SourceFiles="#(FilesToCopy)" DestinationFiles="#(FilesToCopy->'%(DestinationParentPath)\Destination\%(RecursiveDir)%(Filename)%(Extension)')" ContinueOnError="false" ></Copy>
Unfortunately, after the build runs, my BuildLog shows the following:
Copying file from "$(BinariesRoot)\%(ConfigurationToBuild.FlavorToBuild)\<File being copied>" to "\Destination\<File being copied>".
%(DestinationParentPath) had expanded to an empty string, for whatever reason. Using %(DestinationParent.DestinationParentPath) produced an error, telling me that I should simply be using %(DestinationParentPath). $(DeploymentPath) is expanded to the correct string as expected in several other places in the build.
Another source of confusion is that using %(ConfigurationToBuild.FlavorToBuild) yielded the correct value, i.e. Test, as can be seen in the following:
EDIT: this is defined under the root node Project, whereas the ItemGroup with DestinationParentPath is defined under a Target node. Does this also make a difference?
<ItemGroup>
<ConfigurationToBuild Include="Test|Any CPU">
<FlavorToBuild>Test</FlavorToBuild>
<PlatformToBuild>Any CPU</PlatformToBuild>
</ConfigurationToBuild>
</ItemGroup>
It does not seem as though the Include attribute is relevant when you're only interested in the string in the item's metadata since I'm pretty sure "Test|Any CPU" does not reference any actual file.
So once again, why is %(DestinationParentPath) expanding to an empty string?
EDIT: I forgot to mention that I also tried hard-coding the actual path for DestinationParentPath, but this still resulted in %(DestinationParentPath) expanding to an empty string.

EDIT: this is defined under the root node Project, whereas the ItemGroup with DestinationParentPath is defined under a Target node. Does this also make a difference?
Yes, it makes a difference. The ability to define an ItemGroup inside a Target is new to msbuild 3.5. Despite looking declarative, it's actually executed at runtime just as if you'd called the old style CreateItem / CreateProperty tasks. That alone leads to potential issues: you need to consider when the containing task is (first) called. Order of operations is not always obvious to the naked eye. May be wise to make the task where you use %(DestinationParentPath) dependent on the task where it's created, even if there's no "logical" dependency.
In addition, there are the age-old msbuild scoping quirks/bugs. Dynamically created properties & items are not visible to "sibling" tasks. Also, items updated in nested builds aren't always bubbled up.
Check out the workarounds in the links, you should be able to find something that works for you even if it's icky.

Related

Declared include source C++ compile action invalidation

(From https://groups.google.com/d/msg/bazel-discuss/HEpui0DLvnA/RzuwICDmBgAJ)
Forgive me if this has been asked and answered by the group/devs.
The list of "Declared include source" files is a component of the action key for C++ compiles.
This means that the addition of a header-extension file to srcs or hdrs of a cc_* target results in the invalidation of all compile actions which can see the declared list contents (in the hdrs case, transitively).
Can anyone explain how this could be necessary, when include pruning should be providing the minimal set of possible invalidation sources for a compile?
Reputation prevents me from commenting on your answer and the repost means that I don't own the question, but there is more to the problem than just a 're-validation':
Declared inclusion sources are transitively derived, resulting in action invalidation and reexecution (not simply re-validated, the definition of which is fuzzy at best for me) of all compiles in dependent targets.
The point of this post was to discuss (hence bazel-discuss) whether there is any way that previous compiled outputs could be affected, logistically, by adding (not discussing removal of) the definition of a header file, without changing any source related to the previous compilation. The inputs set, which would have been pruned to match the used header files, should (must) be an accurate enough depiction of the only possible triggers for action reexecution. The capacity of any compile to depend upon the newly added header is nil without further changes to the actual content of the input set of an action.
When the rule's definition changes (you add a file to srcs/hdrs), Bazel must assume that change may affect the compilation result, even if none of the other files changed. (For example you just added a header that was missing before.)
If you rebuild the target Bazel reruns the compilation action. If the output of that (the object file) is the same as the last time Bazel ran the action, it's going to re-validate downstream actions without re-executing them.

Relative pathing syntax involving dot-dot-slash

I saw this statement while looking up relative pathing for ant and was quite bewildered:
<pathelement location="../../../../../../programs/jdk1.5.0/lib/tools.jar"/>
I know that .. refers to going up one directory, so my guess is that the ../../../../../../ portion is referencing up six directories, but I'm at a loss for what purpose it serves.
There are some instances where using an absolute path simply does not work.
We have two build server clusters; the old is set up according to one convention where the base directory for all workspaces is:
/work/storage/project/build/myid/workspace
The new cluster is set up with workspaces in:
/builds/myid/workspace
If there's a "common directory", in our case:
.../builds/tools/
.../build/tools/
It is a convenient way to access "tools", knowing it is "up 6, then down the other leg, without knowing the true location.
Of course, I agree with user2864740 that in your example the reference is to a "known" location, which should be accessed via java.home; otherwise, changing your java version can have unpredictable results or involve a lot of search/replace.

How do I find a particular sub directory using Ant and then use it to create a symlink?

I need to create a symlink to a sub-directory using Ant. The issue is that I don't know where the target sub-directory is.
To create a symlink with ant I do this:
<symlink link="${parent.dir}/FOO/linkname" resource="${parent.dir}/BAR/target"/>
But I don't know what BAR is called in advance so I need to do a search for "target" under parent.dir and then pass the one result into the resource.
Is this possible using fileset? Or another way?
It might be possible to use a fileset but that might give you several symlinks or none.
A much better approach is to define the path to BAR in a property. If there is a dynamic part in this path, change the code so that Ant evaluates the dynamic part and everyone else uses Ant's value.
The typical example here is that the path contains a version or timestamp. Define those in your build file so you can use them everywhere. If a Java process needs the values, pass them to the process as a system property (-D...).

Dynamic basedir for Ant in Eclipse

The title might not be the best so let me explain what I am trying to do.
I have made an Ant buildfile that will help me with Maven goals. It's so much easier having to scope to Ant view and choose what I want to do. The biggest benefit with this is that I can use it in almost any project. Whether I deploy to tomcat or jboss or sakai(:deploy) or I handle mutiple instaces of the same server or skip tests... worst case I just change some path properties.
The drawback right now is that I have to keep a copy of this buildfile in every project.
What I am trying to do is have only 1 buildfile, in the workspace, and dinamicaly optain, from eclipse, the current project that I am working on. Be it module or parent I can refine that later.
So basically change the basedir for ant tasks based on the selected project in eclipse.
I have tried Ant Runtime Properties but for some reason properties like
${project_path}
fail to give me what their description say. I get this:
Variable references empty selection: ${project_path}
I hope it is clear what I am trying to do. So my question, I know it's possible, I'm just missing something and I hope some of you can help me with this.
I believe the trouble is in the Ant Runtime properties. I'm not 100% sure how I should use those.
Thank you!
EDIT after comment and further investigation..
Make the projectdir available as basedir property for ant like that :
Window > Preferences > Ant > Runtime > Properties
and create a property named basedir with value either :
${project_loc}
or
${workspace_loc}/${project_name}
and
<project basedir="${basedir}">
<echo>$${basedir} = ${basedir}</echo>
</project>
will work as expected, means echoing eclipse/yourworkspace/projectdir
Maybe there are other ways, i.e. via Ant Addon Ant4Eclipse, which aims to make Eclipse settings available for ant, never used it.

Can I compile 2 build templates in the same solution?

I've got a class library project set up to do template editing and wanted to drop in another copy and customize it. However I get
The type 'TfsBuild.Process' already contains a definition for '_contentLoaded'
and 22 more of the same with the other _ names.
Also Type 'TfsBuild.Process' already defines a member called 'Process' with the same parameter types C:\Projects\MSBuild.Tasks\TechnicalDebtTaskLib\BuildProcessTemplate\obj\Release\CodeMetric.g.cs 62 16 BuildProcessTemplate
i've tried hand editing different parts of the xaml to try to find what key might need to be more unique, but no luck.
How do I work on multiple build process templates in the same solution or copy a process template that makes it unique?
Summary:
<activity mc:ignorable="sap" x:class="Tfs2008Template.Process" ... xmlns:this="clr-namespace:Tfs2008Template">
two tags must be changed for example:
<activity mc:ignorable="sap" x:class="Tfs2008Template2.Process" ... xmlns:this="clr-namespace:Tfs2008Template2">
For whatever reasoning the two tags that are related and need to be in sync are usually at the beginning and end of a very long list of attributes.
Full Article on my blog

Resources