<div bgcolor="#ffffff" text="#000000">
Not a problem - figured putting together some clean templates could probably help me and my colleagues out too, anyway.<br><br>Your comment about the syntax makes me understand a bit better... "MyPackage" isn't a name, it's a placeholder for one of the many general packages of third party functionality that you use. I am guessing that you're putting the detection for every library that your app can/must use into one "find" module, when you actually probably should have a directory in your source tree added to your CMAKE_MODULE_PATH that contains a large number of find modules, some of which are interdependent (just like how the example I sent uses find_package(BLAS) - which is a module that comes bundled with cmake). Once you make enough cmake-based build systems, you'll probably find yourself hanging on to a repository of assorted find modules.<br>
<br>I've pasted a simple example here, since it pretty well meshes with a common use case.<br>The sample project uses OpenSceneGraph (plus its optional components osgDB and osgUtil), as well as a large suite of libraries with internal dependencies known as VR Juggler 2.2. OSG has modules that come with CMake, while I had to make my own for VR Juggler.<br>
<br>-------------<br><br>cmake_minimum_required(VERSION 2.6)<br>project(minimal-vrjuggler-osg)<br><br># Locally-developed modules dist'ed with this app<br>list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)<br><br>
# This should handle all dependencies, including OpenGL, GMTL, and so on<br>find_package(VRJuggler22 REQUIRED)<br><br>find_package(OpenSceneGraph REQUIRED osgUtil osgDB)<br><br># Search for includes in these directories<br>
include_directories(<br> ${OPENSCENEGRAPH_INCLUDE_DIRS}<br> ${VRJUGGLER22_INCLUDE_DIRS})<br><br># Build the project<br>set(SOURCES<br> main.cpp<br> theapp.cpp<br> theapp.h)<br><br>add_executable(example ${SOURCES})<br>
target_link_libraries(example ${OPENSCENEGRAPH_LIBRARIES} ${VRJUGGLER22_LIBRARIES})<br><br>-----------<br><br>That's an entire functional CMakeLists.txt file - though behind the scenes we're linking to a ton of libraries in a ton of different directories. (Read through the cmake docs online a few times - you got the imported target thing but missed the "REQUIRED" flag that you can pass to find_package... If you use the FindPackageHandleDefaultArgs call as suggested by the readme.txt, it takes care of handling QUIET and REQUIRED for you.)<br>
<br>So, I made a separate FindWhatever.cmake file for each library that belongs to VR Juggler, and set it up like the examples from the last email, treating them each as a separately-usable library (since they are). Since most of the time, however, if you're writing a VR Juggler app, you're going to want a large chunk of the tree by default, I made a FindVRJuggler22.cmake "meta-module" sort of thing: means that for most folks, all that's needed in the cmakelists is find_package(VRJuggler22 REQUIRED) or at most find_package(VRJuggler22 COMPONENTS VRJOGL22 Tweek12). So, I have a whole bundle of find modules written (actually, in total, I have ~20 find modules in a directory I share between all my projects, with another ~20 modules that provide functions: some utilities for find scripts, some for use directly by a cmakelists) that I share between my projects, but because each find module knows its own dependencies, it works it out. In that sense, more files is better: it means you're keeping your find modules well-focused and modular. (If the library comes in a separate zip/targz file, it probably should have a separate find module - don't just smush them all into one massive file.)<br>
<br>Here's the dependency tree for the VR Juggler find modules - each node is a separate .cmake file that goes in a directory in my source tree, and each of those find modules are set up just like the examples from the last email. (in graphviz/DOT format) : <br>
<br>digraph {<br> // a module that, when included, provides a function definition that can remove duplicate<br> // libraries from a _LIBRARIES list safely, without breaking the DEBUG RELEASE GENERAL annotations<br> // I wrote this one, so it's in my project in a directory with the custom find modules<br>
CleanLibraryList;<br><br> subgraph cluster_bundled {<br> label = "Included with cmake 2.8.0";<br> FindBoost;<br> FindOpenSceneGraph -> { FindOpenThreads; FindosgALL; }<br> }<br>
<br>subgraph cluster_vrjuggler22 {<br> label = "VR Juggler 2.2 suite: All require CleanLibraryList and CleanDirectoryList, and recommend FindFlagpoll";<br> FindTweek12 -> FindVPR20;<br> FindJCCL12 -> FindVPR20;<br>
FindGadgeteer12 -> { FindJCCL12; FindVPR20; }<br> FindSonix12 -> FindVPR20;<br> FindVRJ22 -> { FindJCCL12; FindGadgeteer12; FindSonix12; FindVPR20; }<br> FindVRJOGL22 -> FindVRJ22;<br>
FindVRJuggler22 -> FindVRJOGL22;<br> } // commented out to make the diagram easier to read -> {FindFlagpoll; CleanLibraryList; CleanDirectoryList;}<br> FindVPR20 -> { FindBoost; FindCPPDOM; }<br>
FindGadgeteer12 -> FindGMTL;<br> FindSonix12 -> FindGMTL;<br>}<br><br>Hope this helps!<br><br>Ryan<br>
<br>
<br>
<br>
On 1/7/10 5:13 PM, Nico Schlömer wrote:
<blockquote type="cite">
<pre>Wow, thanks for the elaborate answer!
I learn a lot just going through the examples.
One thing for me to understand first:
</pre>
<blockquote type="cite">
<pre>Ah, so if those components are always necessary (that is, A always needs B,
and B always needs C), there's no need to use the "components" option.
</pre>
</blockquote>
<pre>Ah, I found the components thing neat for its syntax, as one can
(quite semantically) say
FIND_PACKAGE( MyPackage COMPONENTS coolCompOfMyPackage anotherOne )
# very much like done in FindBoost.cmake
Of course there's not only a,b,c, but a whole set of libraries a,...,z
under the roof of MyPackage with a more or less complicated dependency
tree. Also, it would depend on the installation of MyPackage whether
all the libraries are actually there; for example, and installation
with only "b" and "c" would be possible.
Anyway, instead of hardcoding a,b,c one could possible FOREACH through
a (hardcoded) list of components, such as
SET( ALL_LIBS "a" "b" "c" "d" [...] "z" )
I guess how one would do that with the above suggestion is to further
define MYPACKAGE_{$LIB}_FOUND, and then in the CMakeLists.txt
FIND_PACKAGE( MyPackage )
IF( MYPACKAGE_a_FOUND )
# add the necessary stuff to TARGET_LINK_LIBRARIES, for example
ELSE()
MESSAGE( FATAL_ERROR "Too bad, we need a." )
END()
The disadvantage I see here is that FindMypackage.cmake had to be
adapted every time a new library makes it into MyPackage. Also, the
code in CMakeLists.txt would get longer than what I thought would be
nice [being:
FIND_PACKAGE( MyPackage COMPONENTS "a" "g" "t" )
# FATAL_ERRORing out if either of a, g, t hasn't been found,
# otherwise providing a slim ${MyPACKAGE_LIBRARIES} to be appended to
# TARGET_LINK_LIBRARIES or something.
].
Cheers,
Nico
</pre>
</blockquote>
<br>
<br>
<pre cols="72">--
Ryan Pavlik
Human-Computer Interaction Graduate Student
Virtual Reality Applications Center
Iowa State University
<a href="mailto:rpavlik@iastate.edu" target="_blank">rpavlik@iastate.edu</a>
<a href="http://academic.cleardefinition.com/" target="_blank">http://academic.cleardefinition.com/</a></pre>
</div>