Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any best practices for writing build scripts in Ant or MSBuild

I am trying to automate the build process of my projects (both java and .net) using Ant and MSBuild. I’ve read about them and know how to write build scripts in Ant and MSBuild. But I wonder, is there any guidelines or best practices for writing build scripts in general? Here are two that I’ve found, but I would like to hear more from other developers.

  • In writing a build script, just rely on the items that are located in the source control and are available in the working folder while checking out the sources. Do NOT write build scripts that are dependent on items that are not kept on source control.
  • If a project contains a set of sub-systems and each sub-system has its own build scripts, the build file of the project should just call the build scripts of sub-systems. In addition, these files should import a common build file that contain targets such as compile, test, package etc.

I've seen this post as well, but it is detailed on the way of writing tasks. I need more high level guidelines, as mentioned above.

Here are the guidelines I collected from answers:

  1. Run every build in a clean environment. It means that each build script needs a clean target.
  2. Build scripts should usually include compile, package and test targets.
  3. If a product have different development lines (e.g. dev , release), all of them should have the same build script. But, different parameters should be passed to these scripts.
  4. Builds performed on development lines usually contain compiling, packaging, deploying and installing steps. But builds on release lines include further steps, such as tagging the product and generating change-logs/release notes.
  5. Build scripts should be kept on source control as well.
  6. try to keep all build information in build scripts, not on continuous integration server (Bamboo, TeamCity, etc.)
  7. If your build uses a parameter that may change in future (e.g the network address to copy the build results), do not hardcode it into your build script. instead, use build parameters to control it more easily.
like image 885
Gupta Avatar asked Sep 07 '11 06:09

Gupta


3 Answers

If you're building VisualStudio applications, you are better off using msbuild over Ant. The msbuild command will do the build using the solution file your developers created, and basically emulate the same build they do.

If you truly want to automate everything, take a look at Jenkins. It has a plugin that can execute msbuild and will automatically trigger a build every time someone makes a change. I use a combination fo msbuild and Ant with Jenkins. I do the build using msbuild, then use Ant to gather up and zip up all of my built artifacts. Then, people can download the built artifacts directly from Jenkins.

Now, with your Java applications, you'll have to use Ant. I use the following guidelines

  • Each build script needs a clean target. This target removes any files that were added during the build process, returning the working directory to a state before the clean took place.
  • I follow what Maven does when using target names, so my targets are names things like clean, compile, and package.
  • Also following Maven guidelines, all of my built files are placed in the target directory. That way, my clean command can simply do a <delete dir="${target.dir}/> and cleans everything up nice and sparkly.
  • If I have sub-project, each sub-project has its own build.xml file. My master build.xml file simply calls all of the sub-projects' build.xml files.
  • Use Ivy. It's easy to setup and easy to use. You no longer have the problem of storing jar files in your source repository, or losing what versions of what jar files you're dependent upon.
  • Heck, if you can, use Maven and be done with it. Unfortunately, most older projects are harder to mavenize than it's worth.
  • Do your builds using Jenkins as a continuous build server. And, all builds that leave the department (UAT, QA, and protection builds) must be a Jenkins build.
  • Encourage your developers to write Unit tests. In fact, Jenkins can execute unit tests and display their results on its build page.
  • Use other things like checkstyle, PMD, CPD, Findbugs, and other code verification products. And, of course, Jenkins can run each of these and display pretty graphs that can be used to show your manager how hard you're working.
like image 128
David W. Avatar answered Nov 10 '22 21:11

David W.


Just a comment on the second bullet point you mentioned above:

If a project contains a set of sub-systems and each sub-system has its own build scripts, the build file of the project should just call the build scripts of sub-systems.

Each subsystem should have its own build file but that file should import a common build file. The common build file would contain targets such as compile, test, package etc.

http://ant.apache.org/manual/Tasks/import.html

The subsystem build files are then very simple, don't contain duplication and only contain information that is specific to that subsystem (e.g. compile.classpath).

like image 25
KevinS Avatar answered Nov 10 '22 21:11

KevinS


In MSBuild, targets should specify inputs and outputs, wherever possible (to enable dependency calculation). If necessary, make use of the Returns attribute to specify a target that returns different items than the ones used for dependency calculation.

The input and output items for a given target should be generated using either item transforms (for simple, path-based transformations), or another target (for more sophisticated transformations).

For MSBuild pre-4.x, for targets you define in a .targets file, consider using the following pattern to enable consumers to inject their own targets before the ones you are defining:

<PropertyGroup>
  <MyTargetDependsOn>
    Target1;
    Target2;
    SomeOtherTarget
  </MyTargetDependsOn>
</PropertyGroup>
<Target
  Name="MyTarget"
  DependsOnTargets="$(MyTargetDependsOn)">

</Target>

This enables consumers to inject their own targets before the specified target simply by modifying the value of the MyTargetsDependsOn property:

<PropertyGroup>
  <MyTargetDependsOn>
    $(MyTargetDependsOn);
    YetAnotherTarget
  </MyTargetDependsOn>
</PropertyGroup>
<Target
  Name="YetAnotherTarget">

</Target>

In MSBuild 4.x, you can simply use the BeforeTargets and AfterTargets attributes.

like image 1
tintoy Avatar answered Nov 10 '22 21:11

tintoy