Hi! I've been involved in the development of a suite of Maven plugins for C/C++ at Ericsson. We'd like to make them open source, and if the Mojo project will have them we'll be happy to donate them :)
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. Is the Mojo project interested? If so I'll create a JIRA issue with the sources attached. Any comments on the overall design of the plugins would also be welcome - both for selfish and altruistic reasons we'd like to create the best tool we can :) Regards, Daniel Franzén DANIEL FRANZÉN MSc Software Developer Ericsson AB FJZ/TV Datalinjen 4 S-581 12 Linköping, Sweden Phone +46 10 711 5573 SMS/MMS +46 76 149 7573 [email protected] www.ericsson.com [http://www.ericsson.com/shared/images/Email.gif]<http://www.ericsson.com/> This Communication is Confidential. We only send and receive email on the basis of the terms set out at www.ericsson.com/email_disclaimer<http://www.ericsson.com/email_disclaimer>
<<inline: Email_line.gif>>
<<inline: Email.gif>>
