I now see Ant has both an <include> task and an <import> task.
According to the descriptions:
Include
Include another build file into the current project.
and
Import
Imports another build file into the current project.
So, why use one over the other?
Here's my actual problem:
In our current build system, we are concatenating a bunch of JavaScripts and then minimizing them. The JavaScripts are located in a dozen different directories, and we are taking batches from each directory and concatenating them into five or six super minimized JavaScripts. Some of these files are copied into multiple super JavaScripts.
In order to make debugging easier, and the build a bit more flexible, I want to copy all of the files into the target/work/resources2 directory with each sub-directory under there representing a different super minimized JavaScript. For debugging purposes, we'll include the non-minimized super JavaScript and the originals. The build script isn't complex, but the whole section is taking up a lot of lines. I was thinking of putting the <copy> stuff into a separate XML file, so the whole thing looks like this:
<target name="process-resources"
description="Concatenate and minimize the JavaScripts (using Maven lifecycle names for our targets">
<!-- The following include the copying stuff -->
<here.be.dragons file="${basedir}/reservations.xml"/>
<here.be.dragons file="${basedir}/date.xml"/>
<here.be.dragons file="${basedir}/select.xml"/>
<for param="concat.dir">
<fileset dir="${work.dir]/resources2"/>
<sequential>
<here.I.am.concatenating.and.minimizing/>
</sequential>
</for>
</target>
I see there are four possibilities:
Use <ant/> to call the files that do the copying
Use <import/> (which might not work because it might not be able to be included inside a target)
Use <include/> (which might not work because it might not be able to be included inside a target)
Use the Entity Include.
I am never crazy about using <ant/> or <antcall> although this might be a good time to do this. The Entity Include idea will work, but that's something most people don't understand, and I am afraid it will cause confusion for people who have to support what I'm doing. The <import> and <include> may not be able to be used in this situation, but I'm still curious what the differences are.
The documentation of import explains the difference:
How is import different from include?
The short version: Use import if you intend to override a target, otherwise use include.
When using import the imported targets are available by up to two names. Their "normal" name without any prefix and potentially with a prefixed name (the value of the as attribute or the imported project's name attribute, if any).
When using include the included targets are only available in the prefixed form.
When using import, the imported target's depends attribute remains unchanged, i.e. it uses "normal" names and allows you to override targets in the dependency list.
When using include, the included targets cannot be overridden and their depends attributes are rewritten so that prefixed names are used. This allows writers of the included file to control which target is invoked as part of the dependencies.
It is possible to include the same file more than once by using different prefixes, it is not possible to import the same file more than once.
Related
Is there any bazel convention for defining all of a project's test targets in some subfolder tests with its own BUILD file. Is that layout preferred to one main BUILD file that combines everything in one place: bins, libs, and tests?
An all in one build file could get lengthy, but it has the benefit of using in-package sibling target references, ie the ":siblingTarget" references.
Short answer: Yes.
Why would you like to couple your test with the implementation? You should always try to reduce dependencies between different parts of your code. That makes it easier to understand. See also here.
Imaging you find some BUILD file that contains implementation and test rules (e.g. cc_library, cc_binary, cc_test). Imagine some developer needed for some test some library - and only for testing proposes (e. g. cc_library(name="some_lib"). How would you know if this library is only needed for testing? If it is in a BUILD file contained in test folder then it would be clear from the folder structure that there is a high probability that this lib is only needed for testing proposes.
I am aware that bazel accepts both BUILD and BUILD.bazel as valid filenames.
The android tools seem to also have a BUILD.tools file.
In general, does bazel have any restrictions for a BUILD file's extension? For example, could i have BUILD.generated to delineate generate BUILD files from non-generated BUILD files?
The .tools extension is part of building Bazel itself. From the perspective of Bazel, it's just any ordinary file. It gets picked up here: https://github.com/bazelbuild/bazel/blob/bbc8ed16aee07c3ba9321d58aa4c0ffc55fa2ba9/tools/android/BUILD#L197
then eventually gets processed here: https://github.com/bazelbuild/bazel/blob/c816b89a2224c3c318f1228755ef41c53975f45c/src/create_embedded_tools.py#L74
For the use case you mention, one way to go about it is to generate a .bzl file with a meaningful name that contains a macro that you can call from a BUILD or BUILD.bazel file. That way you can separate the generated rules from manually maintained rules. This is similar to how generate_workspace works: https://docs.bazel.build/versions/master/generate-workspace.html
I'm writing a post-build tool that needs the location of a list of target's jar files.
For these locations I have an aspect that runs on a list of targets (separately for each target using --aspects) and fetch the jar file path for each of them.
I've managed to get each jar file path in a custom output file (e.g. jar.txt) in each target's output folder.
But this will mean I would need to go over each jar.txt file separately to get the location.
Is there a way to accumulate the jar files paths in a single file?
Something like:
Try and write to the same output folder with append command in the aspect. I'm not sure if a shared output folder is possible.
Create a synthetic target which depends on all the relevant targets, then run an aspect on this target and accumulate the jars and only write them at the root after the recursion is back.
Are 1. or 2. valid options?
What is the recommended strategy to accumulate data in bazel aspects output files?
Bazel doesn't provide facitlities in Skylark for accumulating information between targets that are not related to each other in the target graph (e.g. ones that are mentioned on the command line next to each other).
One possibility would be to write a Skylark rule that depends on all the targets you usually mention on the command line and built that one; that rule will be able to collate the classpaths from each Java target to a single file.
Another possibility is to tell Bazel to write build events (that includes all the outputs of all targets the specified build pattern expands to) to a file using the --experimental_build_event_{json,text,binary}_file. (The "experimental" will be removed soon.). The files contain instances of this message:
https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
Natan,
If I understand correctly, you want to transitively propagate the information from each aspect node out into a single result. To do this, build the transitive set in your aspect rule implementation and pass it via the "provider" mechanism [^1]. I wrote up some examples on bazel aspects, perhaps you'll find it useful[^2].
https://github.com/pcj/bazel_aspects/blob/master/aspects.bzl#L94-L104
https://github.com/pcj/bazel_aspects
I have a build with multiple interlinked dependencies, Several projects have common dependencies that are currently compiled more than once. I think in Ant we can tell it not to re-build something if its already just done it as part of the same task, can anyone please advise
ant's javac task will only compile if the source files are newer than the target files. So that should save you some time.
You can also look into ivy for a bit more formal dependency management.
Like leonm says, the compiler will do the right thing. But that won't stop Ant from rebuilding loads of artifacts. What I'd suggest is:
where you can, make targets have a defined output. So a target that builds a jar file from sources can be skipped if those sources haven't been updated since the jar file was built.
how do you implement this? use the uptodate task to set a property if something is actually up to date.
I'd suggest that any targets that do checks be prefixed with a hyphen so they can't be run on their own
And finally, use the 'unless' attribute of the target element to prevent the target running.
I have 2 build files into separate projects,
build_common.xml,
build.xml which is the main build file.
I am trying to import a property from build_common.xml without importing the whole file. Is there a way to do that if I know the path to the build_common.xml?
Thanks
If you only want to import certain properties, they probably SHOULD be in separate files (broken apart by common use). That said, maybe one of your ant tasks could use grep, or some other collection of utilities to transform build_common.xml into a NEW file, that only contains what you want, and then import THAT?
I really don't think it's the BEST way to approach the problem, but I think it could work.