Relative pathing syntax involving dot-dot-slash - ant

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.

Related

Project level environment variable in source path

I'd like to specify an environment variable for use in the source path (library path) at a project level.
We often have a couple of versions checked out of our SVN repository at the same time in different directories, and I'd like to specify the repository root for a project in relative terms at a project level. I could then use that path in a project's source path and I wouldn't have to include indecipherable dot dot slashes (..\) in paths.
For example, say I have checked out trunk to c:\projects\trunk. Then underneath there I have a project in <repositoryroot>\Foo\Bar\ under trunk which uses the Delphi Spring framework under <repositoryroot>\components\external\Spring4d. I end up with a whole bunch of directories in the search path with ..\..\External\Spring4D\Source at the beginning. For example ..\..\External\Spring4D\Source\Base\Collections. I would like to be able to be able to use ${Spring4D} instead, producing ${Spring4D}\Base\Collections\, which is much less wordy and it means that if you move a project or component you can change one value and it updates all paths.
I know that you can do this on a Delphi level by specifying paths in Delphi's environment variables, but I would like to achieve the same thing on a project level or repository level.
Does anyone have any ideas on how to achieve this? Are there any settings or even add-ins that would allow this sort of functionality?
You can manually edit your project file (.dproj) and add a variable there:
<PropertyGroup>
<MyVariableName>MyVariableContent</MyVariableName>
</PropertyGroup>
Later on, you can refer to the content of that variable:
<DCC_UnitSearchPath>C:\Components;$(MyVariableName)</DCC_UnitSearchPath>
You can also define a new environment variable (SystemPropertiesAdvanced.exe -> Environment variables -> Add) and then refer to that variable using the same syntax, e.g.:
<DCC_UnitSearchPath>C:\Components;$(PATH)</DCC_UnitSearchPath>
(Note that it is a very bad idea to use PATH here, it's only an example of a variable which will exist in your environment.)
You could also employ some cmd script magic to to create environment variables that point to those subdirectories and at the end call the IDE, so these environment variables are available in the IDE in the same way as global environment variables would be (see pepak's answer for that).
Pointers:
%0 is the name of the current cmd file
use tilde for file name parts

how to find and deploy the correct files with Bazel's pkg_tar() in Windows?

please take a look at the bin-win target in my repository here:
https://github.com/thinlizzy/bazelexample/blob/master/demo/BUILD#L28
it seems to be properly packing the executable inside a file named bin-win.tar.gz, but I still have some questions:
1- in my machine, the file is being generated at this directory:
C:\Users\John\AppData\Local\Temp_bazel_John\aS4O8v3V\execroot__main__\bazel-out\x64_windows-fastbuild\bin\demo
which makes finding the tar.gz file a cumbersome task.
The question is how can I make my bin-win target to move the file from there to a "better location"? (perhaps defined by an environment variable or a cmd line parameter/flag)
2- how can I include more files with my executable? My actual use case is I want to supply data files and some DLLs together with the executable. Should I use a filegroup() rule and refer its name in the "srcs" attribute as well?
2a- for the DLLs, is there a way to make a filegroup() rule to interpret environment variables? (e.g: the directories of the DLLs)
Thanks!
Look for the bazel-bin and bazel-genfiles directories in your workspace. These are actually junctions (directory symlinks) that Bazel updates after every build. If you bazel build //:demo, you can access its output as bazel-bin\demo.
(a) You can also set TMP and TEMP in your environment to point to e.g. c:\tmp. Bazel will pick those up instead of C:\Users\John\AppData\Local\Temp, so the full path for the output directory (that bazel-bin points to) will be c:\tmp\aS4O8v3V\execroot\__main__\bazel-out\x64_windows-fastbuild\bin.
(b) Or you can pass the --output_user_root startup flag, e.g. bazel--output_user_root=c:\tmp build //:demo. That will have the same effect as (a).
There's currently no way to get rid of the _bazel_John\aS4O8v3V\execroot part of the path.
Yes, I think you need to put those files in pkg_tar.srcs. Whether you use a filegroup() rule is irrelevant; filegroup just lets you group files together, so you can refer to the group by name, which is useful when you need to refer to the same files in multiple rules.
2.a. I don't think so.

How to split Bazel file path into external dependency directory and relative path?

I'm working on a custom rule in skylark that is trying to use the proto compiler. Due to intricacies of how it works, I need to split a path into a directory for the external dependency and the path part that is relative to that.
Example1:
File:[/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19[source]]external/googleapis/google/devtools/build/v1/build_status.proto
I want the paths:
/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19/external/googleapis/
google/devtools/build/v1/build_status.proto
Example2:
File:[[/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19/execroot/bes_example]bazel-out/darwin_x86_64-fastbuild/genfiles]external/com_google_protobuf/google/protobuf/any.proto
I want the paths:
/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19/execroot/bes_example/bazel-out/darwin_x86_64-fastbuild/genfiles/external/com_google_protobuf
google/protobuf/any.proto
The issue is that bazel allows accessing the root and root relative parts of the path, but doesn't give insight into if the path has the 'external/' part or not. The protocol buffer compiler needs this because it needs to know the directories that correspond to the root directories from the user's point of view so that it can use relative paths from the source.
Is there a principled way of detecting this other than hackily looking at the path to see if it has 'external' in it?
I'm afraid I cannot give you a really great answer here :( Eventually, we'd like to remove the "external" path segment, but it hasn't happened yet. The current rule is that you have it for source artifacts, but you don't have it for generated artifacts.
Thus, what I'd do is exactly what you suggest -- check if the first path segment is "external".

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...).

Setting an item metadata using a property

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.

Resources