C/C++ plugin suite
------------------
Key: MOJO-1705
URL: https://jira.codehaus.org/browse/MOJO-1705
Project: Mojo
Issue Type: New Feature
Components: _Plugin Submission
Reporter: Daniel Franzen
Attachments: cpp-plugins.zip
Sorry for the repost, I bumbled the first submission.
This is a suite of three plugins currently used for C/C++ projects at Ericsson,
as previously described in [email protected].
Rationale
If I were you I'd be asking "Isn't there already a plugin for that? Why another
one?". I hope that question is answered in detail below, but the long and the
short of it is we felt that the need for better performance, less verbose
configuration and built-in support for multiple targets - both common and
exotic ones - motivated an attempt at rolling our own.
- Speed
What triggered the development of these plugins earlier this year were the
problems we were having with existing plugins for native code. Perhaps the
fault was with us not understanding how to use them properly, but it eventually
got to a point where people started writing alternative Boost.Build scripts for
building and unit testing. Maven was also generally perceived as slow and
unable to compete with "real C/C++ tools". Thus the plugins were developed to
answer the question: Can we match the speed of Boost.Build, yet bring all the
goodness of Maven to C/C++ projects? While build benchmarking is a tricky
business, from my experience with the projects where we have deployed the
plugins, I would say the answer is yes. How the project is structured plays a
role, though: sometimes Boost.Build is faster, sometimes the Maven plugins are
faster.
How it works
- Three plugins
Currently the suite consists of cpp-compiler-maven-plugin (the workhorse),
cpp-tester-maven-plugin (runs any executables produced by the compiler) and
car-maven-plugin (zips the output into a ".car" artifact).
cpp-compiler-maven-plugin defines a custom lifecycle for packaging type "car",
invoking itself and the other plugins in phases compile, test-compile, test and
package.
- Multi-target
Which targets to build for is controlled by putting e.g.
<targetEnvironments>linux_32,linux_64,win_32</targetEnvironments> in the plugin
configuration. Compilation and linking flags can then be specified per target
and/or for all targets.
- Bundles
We'd like to support any combination of host to target environments, and any
oddities of the target environment shouldn't bleed through to the POM. To this
end we introduced "bundles", which are essentially plugins to the plugin. When
the plugin needs to build for a given target it asks the bundles on its
classpath: Given the current host environment, can you build for this target?
If one and only one bundle answers yes it will get the job. This allows for
clean configuration of multiple exotic, proprietary, in-house targets with
custom toolchains along with standard Linux x86/Windows targets. Included in
the donation is only our Linux 32/64 bundle using GCC.
- Multi-threading
The plugin spawns as many compiler threads as there are logical cores, each
thread polling a common pool of objects to build. The pool is populated by the
main thread, which determines what needs to be built and what's up to date.
That is, compilation starts as soon as the first object has been put up for
building. To reduce overhead the compiler is fed batches of files, but to avoid
single threads overshooting the others dynamic batch sizes are used.
Essentially each thread only picks up as many objects to build as it's
confident to complete before the other threads have finished off the rest of
the pool.
- Incremental builds
The plugin uses a mechanism determined by the responsible bundle (our Linux
bundle uses the GCC pre-processor) to decide whether an object is up to date or
not. Any up-to-date include dependency information left over from previous
builds is reused to minize the incremental build time.
- Dependency extraction
The .car artifacts are zips of static libraries and/or headers for each
supported target. As dependencies are needed during the project lifecycle they
are extracted from the local repository into the target directory, but only the
parts needed are extracted (e.g. you don't need to extract targets you yourself
are not building for). Any existing extracted dependencies are checked before
extraction - if the correct non-SNAPSHOT version of a dependency has already
been extracted it will be reused. SNAPSHOT dependencies are replaced if a newer
version exists in the local repository.
- Linking
Linking executables and test executables is done for separate and/or all
targets by specifying which code files contain the main function(s). A syntax
example of this would be:
<executables><all>myExec=src/main/cpp/MyExec.cc;myOtherExec=src/main/cpp/MyOtherExec.cc,src/main/cpp/Other*cc</all><linux_64>[]=src/linux/main/cpp/entry-points/*.cc</linux_64></executables>.
This would create a myExec and a myOtherExec for every target. In addition,
for linux_64 a separate executable will be linked for each file matching the
pattern. This is very useful when doing one-executable-per-test style unit
tests.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email