Running CTest after project has completed - cmake

I currently have a rather large codebase that builds a number of applications each as their own seperate projects underneath one global project.
I want to be able to run CTest on this global project as part of the regular build, so if a user tries to build the codebase ("make", "make -j4", "make -C gui") that the CTest framework will always run at the very end of the project, once every target under the main project has been completed.
Is it possible to do this? I considered whether it would be possible to add another project and use add_custom_command and make it depend on the global project so that it would only run after that had completed. However, I don't think this is possible?
Are there any suggestions on a better way to achieve this? My main goal is that once a user runs "make", the very last step must be to run CTest, regardless of if you build an individual directory, target or using multiple jobs.

Related

Why there are two buttons in GUI Configure and Generate when CLI does all in one command

I understand that cmake is build generator. It mean that it can generate appropriate builds (makefiles, Visual Studio project etc.) based on instructions from CMakeLists.txt. But I do not understand two things which I guess are related:
Why there are two buttons "Configure" and "Generate" in cmake-gui? In command line tutorials that I've read (e.g. this one) usual process was done with one cmake command.
What is cache in cmake world? AFAIK it is state when "Configure" button was pressed but "Generate" button was not pressed. But why is this useful? What all those variables that pops-up after pressing "Configure" mean? Why I'm supposed to edit them? Isn't the only allowed configuration done via CMakeLists.txt?
Thanks
There are two stages when CMake is run, as reflected by the two buttons in the CMake GUI. The first stage is the configure step where the CMakeLists.txt file is read in. CMake builds up an internal representation of the project during this stage. After that, the second stage called generation occurs where the project files are written out based on that internal representation.
In CMake GUI, the two stages can be run separately. When you run the configure step, the GUI shows all cache variables (see below) which changed their values since the last time configure was run or since CMake GUI was started if this is the first configure run. Normal practice is to re-run the configure stage until no variables are highlighted red. Once configure leaves no variables in red, you can press the generate button and the build tool's native project files will be created and you are good to go starting your builds, etc.
The command line cmake tool doesn't allow you to separate out running the configure and generate steps individually. Rather, it always runs configure and then generate.
For simple projects, the distinction between configuration and generation is not all that important. Simple tutorials will often just lump the two together since the reader can get away without understanding the distinction for basic project arrangements. There are, however, some CMake features which rely on this distinction. In particular, generator expressions are a generation-time feature where decisions about certain aspects of the build are delayed to generation time rather than being fully handled at configure time. One example of this is configuration-specific content such as compiler flags, source files only compiled in for some configurations, etc. The build configuration isn't always known at CMake's configure step (e.g. Xcode and Visual Studio are multi configuration build tools, so there can be more than one and it is selected by the user at build time). The generation step will process generator expressions for each build type and the result can be different for each configuration. You might also find this answer informative regarding this particular example. For a more advanced example of a technique which takes advantage of the distinction between configure and generation stages, see this post, but be aware it is not a common technique.
Regarding your other question about what is the cache, CMake records information between runs in the variable cache. At the end of the run, it updates a file called CMakeCache.txt in the build directory. When you next run CMake, it reads in that cache to pre-populate various things so it doesn't have to recompute them (like finding libraries and other packages) and so that you don't have to supply custom options you want to override each time. You wouldn't typically edit CMakeCache.txt by hand (although it's okay to do so). Rather, you can modify the variables you want in CMake GUI and then re-run the configure step (don't forget to then also run generate to create updated project files). You can also define or modify cache variables at the cmake command line with the -D option.

Running rsvars.bat before Teamcity build starts

I have a C++ Builder 2010 project that's being built using TeamCity. I noticed some strange errors and after reading up on them I understand that I have to set a few variables located in rsvars.bat. I would like the build script to execute the bat file to set up the environment before performing the actual build. How do I best accomplish this?
Can I just use a <exec /> command at the very beginning of the file or is there a better way?
One way would be to run wrap the build in a script that calls rsvars.bat AND build commands. That would make the variables survive during the execution of the build.
But since I use TeamCity I like it to be a real msbuild step and not msbuild wrapped in something else. I was thinking of having the buildscript setting the variables from rsvars.bat into Machine or User at the start of the build and then remove them at the end, not nice though.
I finally just went with just adding the configurations to the Build Agents environment configuration in TeamCity and keeping installation paths identical between agents.
You can create a new build step and then specify a custom build step order so a new build step will be the first one.
See Configuring Build Steps
Add them as Build Parameters -> Environment Variables (in the build configuration), straight forward and generally works. The build parameter/environment variables will be setup automatically as environment variables on the build agent running the job.
You can then make a template of the build and reuse it.
Assumes that the 'paths' are the same on all build agents, which is generally the case. If not your suggestion of doing it by build agent is the way to go.

How can I tell Hudson to build the modules instead of the jobs?

I have a alot of jobs on Hudson, most of which are really small and consist of just a few modules. But one is big and consist of several modules.
When ever I make a commit to our subversion repository for any of those several modules in that big job, Hudson builds the entire job instead of just the module that have changed.
It doesn't matter if I just scm-polling or a subversion hook, the result is the same.
It seems to me like it would be better if the modules where built instead of the jobs since the other modules in other jobs have dependencies to the modules and not to the jobs.
Can this be configured or do I have to create several jobs instead of the big one? And if so, can I configure the big job to never build when any of it's modules are being triggered but still build when it's own pom.xml is changed?
Thanks.
Hudson has an "Incremental Build" option in the Maven area of the job configuration.
It's hidden in the "Advanced" area.
You could make use of the reactor plugin. For example:
mvn reactor:make-scm-changes
This will only build those modules that have been changed in the SCM. Follow the link for other examples.
Doesn't your compiler offers you the incremental compile option? The java 1.6 compiler usually searches for class and source files and decides using the timestamp to determine whether to use the source or class file. Just leave out the clean goal when building your code.
Another option would be to first run a batch/shell script to determine what files changed and delete the corresponding class files so that the compiler incrementally builds the class files that are missing.

Using a variable obtained using a pre-build shell command to set an option for the Maven build in Hudson

I have a Hudson job that runs a maven goal. Before this maven goal is executed I have added a step to run before the build starts, it is a shell script that obtains the version number that I want to use in the 'Goals and options' field.
So in my job configuration, under Build Environment I have checked the Configure M2 Extra Build Steps box and added a shell script before the build. The script looks like this:
export RELEASE={command to extract release version}
echo $RELEASE
And then under the Build section I point to my 'root pom'. In the Goals and options I then want to be able to do something like this:
-Dbuild.release.version=${RELEASE} deploy
Where build.release.version is a maven property referenced in the POM. However since the shell doesn't seem to make its variables global it doesn't work. Any ideas?
The only one I have is to install the Envfile plugin and get the shell script to write out the RELEASE property to a file and then get the plugin to read the file, but the order in which everything is run may cause problems and it seems like there must be simpler way...is there?
Thanks in advance.
I recently wanted to do the same, but AFAIK it's not possible to export values from a pre-build shell to the job environment. If there is a Hudson Plugin for this I've missed it.
What did work, however, was a setup similar to what you were suggesting: having the pre-build shell script write the desired value(s) to a property-file in the workspace, and then using the Parametrized Trigger Plugin to trigger another job that actually does the work (in your case, invoke the Maven job). The plugin can be configured to read the parameters it passes from the property file. So the first job has just the shell script and the post-build triggers, and the second one does the actual work, having the correct parameters available as environment variables.
General idea of the shell script:
echo "foo=bar
baz=`somecmd`" > build.properties
And for your Goals and options, something like:
-Dbuild.release.version=${foo} deploy
Granted, this isn't as elegant as one might want but worked really well for us, since our build was broken into several jobs to begin with, and we can actually reuse the other jobs that the first one triggers (that is, invoke them with different parameters).
When you say it doesn't work, do you mean that your RELEASE variable is not passed to the maven command? I believe the problem is that by default, each line of the shell script is executed separately, so environment variables get lost.
If you want the entire shell script to execute as if it was one script file, make the first line:
#!/bin/sh
I think this is described in the Help information alongside the shell script build step (and if I'm wrong, that's a good place to look for the right syntax).

Pre-Pre-build Steps in Hudson

I'm in a bit of a pickle. I'm trying to run some environmental scripts before I run the build in a m2 project, but it seems no matter how hard I try - the 'pre' build script are never run early enough.
Before the 'pre-build' scripts are run, the project checks to see if the correct files are in the workspace - files that won't be there until the scripts I've written are executed.
To make them 'pre-build', I'm using the M2 Extra Steps plugin - but's it's not 'pre' enough.
Has anyone got any suggestions as to how I can carry out what I want to do?
Cheers.
Have you considered breaking it up into two projects, and setting the pre-build project to be upstream of the build project?
e.g.,
Foo Pre-build
Foo Build
After Foo Pre-build runs, cause "Foo Build" to run.
I have used this, admittedly in different scenarios than yours, quite successfully. This has the added benefit (if you need it) of allowing you to manually run a build without going through the pre-build steps, if you know they aren't necessary.
You should use the free form project type and not the maven project type.
If this is a problem (ie, there are projects that are expecting to be triggered by or triggering from), consider using a custom workspace location and having a free form project execute in this workspace before the maven project runs. The free form project can be used as the trigger for the maven project.
Does adding another build step as a shell script work?
My problem stemmed from the fact I wanted to set-up my workspace before I ran anything due to an issue with Dynamic Views (ClearCase) not being accessible from the workspace - I wanted to add a symlink to fix this.
However, Andrew Bayer has made a change to the plugin that I'm currently testing that should fix this...so the question is probably invalid in it's current form.
Will edit it once we come to a conclusion.