[CMake] Best practices/preferred methods for linking external libraries

Michael Jackson mike.jackson at bluequartz.net
Mon Dec 5 17:56:56 EST 2011



On Dec 5, 2011, at 5:36 PM, Matthew LeRoy wrote:

> On Dec 4, 2011, at 11:59 AM, Michael Jackson wrote:
> 
>> On Dec 1, 2011, at 4:56 PM, Matthew LeRoy wrote:
>> 
>>> We began using CMake a few months ago for a couple of small cross-platform projects, and we're still
>>> learning all the ins and outs and capabilities CMake has to offer, as well as how to get the most
>>> out of CMake by using it "The Right Way". Right now, we're trying to figure out how to link
>>> to external libraries that don't have "find" modules or CMake config-mode files. After lots of
>>> reading in the wiki, mailing list, etc, it seems like there are several different ways to do
>>> this, like writing "find" modules and/or config-mode files ourselves, using the LINK_DIRECTORIES()
>>> command, importing/exporting targets, and others. What we're unsure of is, what is the "preferred"
>>> or "officially supported" method?
>>> 
>>> To be a little more specific, we have two different library projects (call them ProjectA and
>>> ProjectB) that both use CMake, but are developed independently. Further, ProjectB depends (or will
>>> depend) on ProjectA; we've just recently gotten to the point on ProjectB where we want to use some
>>> of the functionality in ProjectA, so we need to link to the ProjectA library(ies). At first we
>>> thought we needed to write a "find" module for ProjectA -- but we really have very little idea how
>>> to go about doing that. Other than the wiki page for finding libraries that talks a little about
>>> writing "find" modules (http://www.vtk.org/Wiki/CMake:How_To_Find_Libraries), is there any other
>>> documentation for writing a proper "find" module? Is there a particular module that ships with CMake
>>> that is well-written that we should look at as a guide?
>> 
>> I had a project that I developed a few years back which was very close to your situation. My project, call it "MXA", was the base library that got used in a number of other projects. What I ended up doing was creating a "FindMXA.cmake" file that got configured during the actual build of MXA to make sure all the proper library names and location of resource files were set correctly. Then I would install the MXA project into an external location on my system, say /Users/Shared/Toolkits (OS X). I would manually copy the FindMXA.cmake file to the other projects so that they could have the find module available. In the beginning this made for a lot of manual copying when MXA was changing a bunch but once MXA settled down to a consistent naming scheme the "FindMXA.cmake" file never changed and so I found I did not have to update the "FindMXA.cmake" file in the other projects that depended on MXA.
>> I think in more recent years the CMake developers would rather see people create the CMake Export files instead of developing the Find* module for my project. In the end I just didn't have the time to properly investigate and implement the CMake Export file so I never did it.
>> 
>> I think if the CMake community took a vote we could probably come up with an "Exemplar" Find*.cmake file that is good for someone trying to develop a new one. The issues that arise are that each of the projects that have a "Find*.cmake" file are usually different in subtle ways which leads to issues when you try to simply "copy/paste" from an existing module to create a new module. It really just depends on what your "ProjectA" has installed. I am going to provide my current "FindMXA.cmake" file at the end of this email and leave it open for criticism/corrections. Maybe it will spur a conversation that we can all benefit from.
> 
> Believe it or not, I've already been using your MXADataModel project as my main 'exemplar' CMake-based project. I had read several messages from you in the archives when I was first getting started with CMake, and I think at least one of them also mentioned MXA, so I went to your website and saw that the source was available so I thought I'd take a peek.
> 
> Anyway, let me clarify a little bit what we're trying to accomplish. We are indeed trying to treat ProjectA and ProjectB as completely independent projects (as Alan has suggested), and our plan is to version ProjectA and do drops at specific milestones. ProjectB will use only the binary distribution of ProjectA. We would like to make it so that ProjectB's source tree in version control is entirely self-contained, so that we can simply sync down a local copy in a fresh development environment and compile without having to 'install' ProjectA first. Better yet, we may want to sync multiple copies of ProjectB's source tree in separate locations on the same system, from different instances in time where the version of ProjectA in use is different, and be able to build and debug both separate copies of ProjectB without having to worry about having multiple versions of ProjectA 'installed'. Our thought here is to have part of ProjectA's source tree be a collection of binary distributions of the various independent components that is uses - one of which is ProjectA.
> 
> That being said, we are traditionally a Windows development shop and have little experience setting up source trees in anything other than the "Visual Studio" style of one root folder for the solution and subfolders for each "project" in the solution, where everything is somewhat idiot-proof. I realize that it's a bit beyond the scope of the CMake mailing list to be discussing the finer points of source tree structure for general C++ programming, but we're open to whatever suggestions (or pointers to other references) anyone may have as to the best way to go about accomplishing what we're after, CMake-related or otherwise.
> 
> For the time being, I'll take a look at the FindMXA.cmake file to get an idea of how I might write a Find* module for our ProjectA, since it sounds like using CMake EXPORT files to accomplish what I described above may not be possible. Your comments regarding the recent preference of using CMake EXPORT files instead of Find* modules are exactly the kind of info I was looking for originally, however.
> 
> Matt

What version control system are you using? Does it support "submodules" or sub projects? I still think having a binary distribution is a bad thing but in your case it may just work out ok.

 The other fleeting thought I had was in ProjectB's Main CMakeLists.txt file get the location of ProjectA and then do a "add_subdirectory(${ProjectA_SOURCE_DIR})" and just plain build ProjectA inside of ProjectB. Assuming of course ProjectA is small enough that including it in a build will not overly slow things down. I have done that in some other projects and it has turned out to work just fine.
  There are lots of examples where "add_external_project()" is used in this way to bring in a build things like Zip, Tiff, Jpeg or other small projects.

Hope that helps
--
Mike Jackson <www.bluequartz.net>


More information about the CMake mailing list