Dependency Management for C++ With Maven and Nexus

Check out GitHub.

Veteran’s Choice

I tried Conan and found it to be fine overall, but a bit disappointing. I’ve used Conan on a project that needed development for a relatively short period, then it would stay for years with little development. At some point, after the development race took place, Jenkins builds started failing because IT upgraded the server, part of which was upgrading Python applications installed via pip, which includes Conan. It turns out that the upgraded Conan no longer works with the build files we had.

Part of the problem was that I originally set it up so that Conan was just for dependencies – while it had the ability to create CMake recipes, I felt it probably wouldn’t work for some unexpected reason. Another person on the team was the type who likes to do their best at all the poker chips on the tool and thinks it’s best to have a one-button solution that can pull files and create CMake files and use CMake to create Makefiles, run them, and produce artifact in one command .

It worked for a while, and then it didn’t (after he was gone, of course!). He’s a good developer and a smart guy, but I guess he didn’t fully appreciate at the time how such decisions can fail in the long run. In the end, it was better if he left it as is. Nobody was asking for a better solution as far as I know.

So I decided to do a future run with C++ on another project to try Maven, for the following reasons:

  • I know Maven has original archives
  • I really only need Maven to manage the dependency, and I don’t need to tie it to the compile process (let Make do that)
  • I thought Maven should really be able to be a generic build tool that can build anything (like Ant or Make)

With some research (and swearing needed), I found that I could use the following facilities of Maven to create a very simple system to manage dependencies for any arbitrary purpose (in this case C++ libraries and executables):

  • Boom packaging type, which can build basically anything, but you have to explicitly describe most of the steps
  • Minimum ~/.m2/settings.xml The file that only provides the ID, username and password of the repo to post to
  • Declare dependencies in the pom as normal with type and scope added (you don’t usually need to)
  • Define a profile in pom to set a value ${project.build.directory} Var for use elsewhere
  • Declare in pom where to dump dependencies
  • Declare in pom how to compile the code (use Make)
  • Declare in pom how the files are packaged (use Assembly.xml to declare what is being compressed)
  • We announce in Boom that we want to be able to publish
  • Declare the pom the server id and post url to it (probably the url will be moved to settings.xml)

The pom.xml file obviously contains things you don’t normally have to provide but it’s actually still smaller than the average pom.xml of a bloated Java project with 150 transitive dependencies, and it’s very easy to understand.

I actually only found one small problem: even though the compilation plugin is able to use better compression formats like bzip and gzip, the dependency extension just lets you say it’s a compressed format. Since it’s just a tiny amount of code being compressed, it wouldn’t matter anyway. Yes, the jar package type loads dependencies via jar files, but in terms of compression, a jar file is literally a zip file with a different extension – you can use Windows Explorer to compress a folder of code compiled in java into a zip file, rename it .jar and execute it with java – neighbor.

conclusion

I’m very happy with the result, the usual maven commands can be used to grab dependencies, compile, clean and publish. I would definitely use Maven for dependency management for C and C++ projects, or really in any other situation where you need it, and it isn’t already provided for whatever reason.

Maven is a good global dependency manager, packages, and deployment tool for pretty much anything you want to apply a copy to, and push it into the artifact repository.

It is also very easy to test an applet that depends on one library which in turn depends on another. Just run one short loop in bash:

for i in cpp3 cpp2 cpp1;do ( cd $i && mvn deploy ); done

That’s it – each project pulls any required partitions, and they are compiled, packaged, and deployed to nexus in one command. The README.adoc in the url provided at the beginning of this article also provides some simple commands to get your Nexus 3 up and running in the docker, ready to deploy to.

.

Leave a Comment