[CMake] [CMAKE] Handling External Libraries and Resources
Patrik Gornicz
gornicz_p at hotmail.com
Wed May 12 18:12:20 EDT 2010
I've been tasked with developing a new build system for projects at my work
place. We decided to use CMake and have been quite pleased thus far. However,
we've run into a requirement we haven't been able to satisfy to our satisfaction.
The requirement is with respect to handling external libraries and resources
when building. By external libraries I mean libraries that the CMake system
itself does not build (ex. boost, third party libraries, etc.) but we want to
use without having to install them on the system (ie. keep them local to our
build tree). By resources I mean anything else that our binaries require to
function normally (ex. images, music, audio clips, localized text files, etc.)
Essentially, we want a directory, say targetdir, were all our runtime required
files get built or copied into such that the program can execute in a developer
friendly way using both XCode and Visual Studio.
What is the best way to do this with CMake?
Requirements:
* Must work well with XCode on the Mac, GNU Make on the Mac, and Visual
Studio on Windows.
* Updating resources and/or external libraries should cause their versions in
the targetdir to get updated (ie. Dependency tracking)
Reasons for desiring a targetdir:
* Our application loads resources (ex. images) using paths relative to the
main executable. (rather common, no?)
* On Windows there is no rpath option to tell Windows where to search for
dlls (at least to the best of my knowledge there isn't), hence, dlls need
to be side-by-side with our main executable.
* Its nice to have everything required to run a program in one location so an
installer can be created without having everything scattered around a build
tree.
What we are currently doing:
* Build all of our shared libraries and binaries into this target directory.
* Ex. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/targetdir")
* Ex. set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/targetdir")
* Manually keeping track of and copying external libraries and resources into
this target directory.
* CON: There doesn't seem to be a way to create custom commands and have a
non custom target use/execute them.
* Hence, we've created an addition target (called App-build-resources)
which is a custom target and runs our custom copying code and the App
target depends on this addition target.
* CON: Currently we only have resources associated with applications
(binaries), but it would be nice to have resources associated with
libraries.
* ie. It would be nice if a library copied resources it needs into the
location it is being built. Currently this would require a
Lib-build-resources target per library which is quite ugly.
* PRO: A developer can select the App target (ex. Set As StartUp Project in
Visual Studio) and simply build knowing that the custom target will
run before the App target is considered up to data.
* PRO: A developer can simply execute the App target after building
directly because the App target creates the main executable.
* CON: The CMake code is rather ugly due to the large amount of manual work going on.
* Keeping track of what external file to link against and making targets
link against it.
* Keeping track of what external file and resources need to be copied
into the targetdir.
Other things we've tried or considered:
* Using an INSTALL target that copies all of the built binaries, libraries,
external libraries and resources into a directory that is within the source
tree.
* CON: Both XCode and Visual Studio cannot easily execute the installed versions.
* ex. The binary copied by INSTALL is not the target of the Visual Studio
project, hence, trying to run it from within Visual Studio results
in a "The system cannot find the path specified error".
* Using the IMPORTED property for external libraries.
* CON: Does not solve the issue with respect to resources.
* Why shouldn't the ideal solution be able to handle resources just as easily?
* CON: We seemed to run into a scoping issue where an IMPORTED library
could only be referenced in the directory (and subdirectories) where
a non IMPORTED library is global. (is this a bug?)
* Due to the layout of our source tree this was problematic. (we worked
around it by using includes instead of add_subdirectorys, though we
didn't like that very much)
* Instead of doing the copying at build time (ie. by XCode/Visual Studio) do
the copying at build generation time (ie. by CMake)
* CON: XCode and Visual Studio have per-configuration output directories,
hence, CMake has to copy the files into each of these directories.
* CON: Dependencies aren't really tracked.
* If one developer updates an image another developer has to remember to
manually run CMake when they sync to trigger the copy. (The ZERO_CHECK
CMake run doesn't get triggered by such an update)
* Custom target that always runs and executes a GNU Makefile to handle
copying of resources and external libraries.
* CON: Shouldn't really be necessary, and would require extra work.
Essentially, I'd like to hear your views on handling resource copying. Is
there an obvious method I've overlooked? What are other projects doing to
handle resources? Any ideas with respect to other methods of handling resources?
Thanks for your time,
Patrik Gornicz
_________________________________________________________________
30 days of prizes: Hotmail makes your day easier! Enter Now.
http://go.microsoft.com/?linkid=9729710
More information about the CMake
mailing list