[CMake] Package installation conundrum
Michael Wild
themiwi at gmail.com
Wed May 9 02:07:24 EDT 2012
On 05/08/2012 11:13 PM, Dave Abrahams wrote:
>
> on Tue May 08 2012, Alexander Neundorf <a.neundorf-work-hi6Y0CQ0nG0-AT-public.gmane.org> wrote:
>
>> On Tuesday 08 May 2012, Dave Abrahams wrote:
>>
>>> Here's another one!
>>>
>>> Scenario:
>>>
>>> * I am running CMake under 0install to build and install libraries
>>>
>>> * Each library builds a package SomePackage for the library binaries
>>> and another package SomePackage-dev for the library headers (and
>>> import libraries on Windows)
>>>
>>> * The FindSomePackage.cmake file is part of the -dev package
>>>
>>> * After building, 0install moves each package's build products into a
>>> mostly-unpredictable subdirectory of its otherwise-read-only "cache"
>>> (~/.cache/0install.net/). The subdirectory's name is determined by a
>>> hash of the files.
>>>
>>> * To get this working, I followed the scheme discussed here:
>>>
>>> http://news.gmane.org/find-root.php?message_id=%3cm2lil6s8jq.fsf%40pluto.l
>>> uannocracy.com%3e
>>>
>>> Summary:
>>>
>>> 1. Create a 0install "SomePackage-preinstall" package. Building this
>>> package involves CMake building and installing both SomePackage and
>>> SomePackage-dev into separate subdirectories (main/ and dev/) of
>>> some prefix. 0install thereafter moves the whole directory tree
>>> into its cache in a directory called sha1=someuglyhash
>>>
>>> 2. SomePackage's 0installation procedure is to copy
>>> sha1=someuglyhash/main/ into its distribution directory (which then ends
>>> up in
>>> ~/.cache/0install.net/sha1=otheruglyhash)
>>>
>>> 3. SomePackage-dev's 0installation procedure is to copy
>>> sha1=someuglyhash/dev/ into its distribution directory
>>>
>>> Problem: FindSomePackageConfig.cmake now has the wrong path to the
>>> library binaries.
>>>
>>> Any help most appreciated.
>>
>> Can you please summarize what you actually want to achieve ?
>
> Well, I tried to, above.
>
> In short, I want to create separate main and -dev packages without
> building twice, under the constraints imposed by 0install.
>
>> Do you say that libFoo installs a FindFoo.cmake as part of libFoo-devel ?
>>
>> If that's the case, then this is wrong.
>
> I'm sorry, that *is* wrong. It installs a FooConfig.cmake as part of libFoo.devel
>
>> FindFoo.cmake must be part of the using software, not of the software to be
>> searched.
>>
>> Why do you have to find the installed library in this cache directory
>> ?
>
> Because, in a 0install world, that's where things go when you "install"
> them.
>
Ok, how you do it along these lines:
CMakeLists.txt:
#-------------- BOF
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Foo)
set(FOO_VERSION 1.2.3)
# initialize (absolute) installation directory variables
set(INSTALL_BIN_DIR bin CACHE PATH "Install path for binaries")
set(INSTALL_LIB_DIR lib CACHE PATH "Install path for libraries")
set(INSTALL_INCLUDE_DIR include CACHE PATH "Install path for headers")
# this is for UNIX systems, see docs of find_package() for the search
# paths on APPLE and WIN32
set(INSTALL_CMAKE_DIR lib/foo-${FOO_VERSION}/cmake CACHE PATH
"Install path for CMake files")
foreach(t BIN LIB INCLUDE CMAKE)
if(NOT IS_ABSOLUTE ${INSTALL_${t}_DIR})
set(INSTALL_${t}_DIR ${CMAKE_INSTALL_PREFIX}/${INSTALL_${t}_DIR})
endif()
mark_as_advanced(INSTALL_${t}_DIR)
endforeach()
# configure FooConfig.cmake and friends. FooConfig.cmake must be able
# to locate FooExports.cmake and FOO_INCLUDE_DIR relative to its own
# directory without using absolute paths.
configure_file(cmake/FooConfig.cmake.in
${PROJECT_BINARY_DIR}/FooConfig.cmake @ONLY)
configure_file(cmake/FooConfigVersion.cmake.in
${PROJECT_BINARY_DIR}/FooConfigVersion.cmake @ONLY)
# configure the headers into the build tree so the package can be used
# without installing it and not hard-coding the source/build directory
# information into FooConfig.cmake
configure_file(include/foo.h
${PROJECT_BINARY_DIR}/include/foo.h COPYONLY)
# build targets
add_library(foo src/foo.cpp include/foo.h)
set_target_properties(foo PROPERTIES
PUBLIC_HEADER include/foo.h
VERSION ${FOO_VERSION}
SOVERSION 1.0)
add_executable(bar bar.cpp)
target_link_libraries(bar foo)
# install targets and files
install(TARGETS foo bar
EXPORT FooExports
RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT bin
ARCHIVE DESTINATION ${INSTALL_LIB_DIR} COMPONENT dev
PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDE_DIR} COMPONENT dev)
install(FILES
${PROJECT_BINARY_DIR}/FooConfig.cmake
${PROJECT_BINARY_DIR}/FooConfigVersion.cmake
DESTINATION ${INSTALL_CMAKE_DIR} COMPONENT dev)
# export targets to build and install tree
export(TARGETS foo bar NAMESPACE Foo_
FILE ${PROJECT_BINARY_DIR}/FooExports.cmake)
export(PACKAGE Foo)
install(EXPORT FooExports
DESTINATION ${INSTALL_CMAKE_DIR}
NAMESPACE Foo_
COMPONENT dev)
#-------------- EOF
With such a setup, you do something like the following for the
installation into the cache directories:
mkdir /path/to/build-tree
cd /path/to/build-tree
cmake /path/to/source-tree
make
DESTDIR=/path/to/bin-cache cmake -DCOMPONENT=bin -P cmake_install.cmake
DESTDIR=/path/to/dev-cache cmake -DCOMPONENT=dev -P cmake_install.cmake
Note that the -D options must be *before*the -P option, otherwise the
definitions will not be passed to the cmake_install.cmake script.
Now you have everything installed into different cache directories, but
still containing correct path information for the final installation
that is to be performed by 0install.
More information about the CMake
mailing list