On 06/11/2010 12:27 PM, Torri, Stephen CIV NSWCDD, W15 wrote:
From: Ryan Pavlik [mailto:rpav...@iastate.edu]
Sent: Fri 6/11/2010 1:16 PM
To: Torri, Stephen CIV NSWCDD, W15
Cc: cmake@cmake.org
Subject: Re: [CMake] How to install a shared library on a windows system

From: cmake-boun...@cmake.org on behalf of Ryan Pavlik
Sent: Fri 6/11/2010 12:34 PM
To: cmake@cmake.org
Subject: Re: [CMake] How to install a shared library on a windows system


Stephen,

The catch is that windows searches for the DLL at runtime in specific
locations: http://msdn.microsoft.com/en-us/library/7d83bc18%28VS.80%29.aspx

I see that it searches the directories listed in the PATH variable. How can you 
tell CPACK to just always install itself to the PATH variable instead of asking?

You generally don't want to put your install directory in the PATH
environment variable system-wide (or install to c:\windows\system32):
you'll probably either want to a: install a launcher script that appends
to the path at run time (see my other recent mailing list post), or b:
use something like my example so your dll ends up in the same directory
as your exe.
The end goal of this project is to install a shared library than someone other 
than me can link against and use. I am used to programming on Linux where I can 
just install to /usr/lib, /lib, /opt/lib or some other directory like that 
where the OS knows to search. Now I read your last post again and concluded 
that I cannot put my library in the directory as the EXE since I don't know 
that directory another user will create. I hope understand I am coming from 
Linux and trying to convince Windows to play nice.

So I am trying to be the nice library developer and set things up the right 
way. Now that you know what I am doing and the audience I am serving how do you 
recommend I install my library so that a third-party can link against it and 
find it a runtime?

Would a phone call help?

Stephen

Welcome to the joy of programming on Windows - this is one of my most persistent headaches.

The burden is now on your developer: that said, if you install a -config.cmake file that, in addition to setting _INCLUDE_DIRS and _LIBRARIES, sets _RUNTIME_LIBRARIES and _RUNTIME_LIBRARY_DIRS, the consumer of the library can either a) generate a script that adds the runtime library dirs to the path, or b) copy the _RUNTIME_LIBRARIES into their binary directory. They can also then install(FILES ${whatever_RUNTIME_LIBRARIES} DESTINATION bin) so that their installers get a copy of the DLL.

I threw together a quick sample of what you might want to have in your library's project, based on a recent library I made - it's attached. Hopefully this helps.

Ryan

--
Ryan Pavlik
HCI Graduate Student
Virtual Reality Applications Center
Iowa State University

rpav...@iastate.edu
http://academic.cleardefinition.com

# Example of setting up CMake config files when developing a library
# 2009-2010 Ryan Pavlik <rpav...@iastate.edu>
# http://academic.cleardefinition.com/
# Iowa State University HCI Graduate Program/VRAC

cmake_minimum_required(VERSION 2.6.2)

# Set package properties
project(MyPackage)

set(BIN_DIR bin)
set(INCLUDE_DIR include)
set(ARCH_DIR lib)
if(WIN32)
        set(LIB_DIR bin)
else()
        set(LIB_DIR lib)
endif()

# Create a library
set(SOURCES
        MyLib1.cpp)

set(API
        MyLib1.h)

add_library(MyLib1 ${SOURCES} ${API})
set_target_properties(MyLib1 PROPERTIES PUBLIC_HEADER "${API}")
# target_link_libraries(MyLib1 ${WHATEVER_LIBRARIES}) # if needed

install(TARGETS MyLib1
        EXPORT mypackage-sdk
        RUNTIME DESTINATION ${BIN_DIR} COMPONENT runtime        # In case this 
becomes a shared library
        LIBRARY DESTINATION ${LIB_DIR} COMPONENT runtime        # In case this 
becomes a shared library
        ARCHIVE DESTINATION ${ARCH_DIR} COMPONENT sdk
        PUBLIC_HEADER DESTINATION include/MyPackage)

###
# Pretend this directory creates and installs another library, like above
add_subdirectory(mylib2)

###
# Set up use from build tree
set(BUILD_TREE_TARGETS MyLib1 MyLib2)

configure_file(mypackage-config-build-tree.cmake.in MyPackageConfig.cmake @ONLY)
export(TARGETS ${BUILD_TREE_TARGETS}
        NAMESPACE mypackage_buildtree_
        FILE mypackage-targets.cmake)
export(PACKAGE MyPackage)

###
# Set up use from install tree
if(WIN32)
        set(EXPORT_DIR cmake)
else()
        set(EXPORT_DIR ${LIB_DIR}/MyPackage)
endif()

install(EXPORT mypackage-sdk
        DESTINATION ${EXPORT_DIR}
        NAMESPACE mypackage_exported_
        FILE mypackage-targets.cmake)

configure_file(mypackage-config.cmake.in mypackage-config-for-install.cmake 
@ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mypackage-config-for-install.cmake
        RENAME mypackage-config.cmake
        DESTINATION ${EXPORT_DIR})

###
# Include the packaging system now that we have it all set up
include(CPack)
# 2009-2010 Ryan Pavlik <rpav...@iastate.edu>
# http://academic.cleardefinition.com/
# Iowa State University HCI Graduate Program/VRAC
#
# Will set:
#  MYPACKAGE_LIBRARIES
#  MYPACKAGE_MYLIB1_LIBRARIES
#  MYPACKAGE_MYLIB2_LIBRARIES
#  MYPACKAGE_INCLUDE_DIRS
#  MYPACKAGE_RUNTIME_LIBRARIES and MYPACKAGE_RUNTIME_LIBRARY_DIRS if applicable
#  MYPACKAGE_FOUND

include(mypackage-targets.cmake)

set(MYPACKAGE_LIBRARIES)
set(MYPACKAGE_RUNTIME_LIBRARIES)
set(MYPACKAGE_RUNTIME_LIBRARY_DIRS)
foreach(_lib MyLib1 MyLib2)
        set(_explib mypackage_exported_${_lib}) # The exported target name

        string(TOUPPER MYPACKAGE_${_lib}_LIBRARIES _libvar) # Upper case 
variable name
        set(${_libvar} ${_explib})

        list(APPEND MYPACKAGE_LIBRARIES ${_explib})

        # Runtime library info - only useful for shared libraries
        get_property(_type TARGET ${_explib} PROPERTY TYPE)
        if(_type STREQUAL "SHARED_LIBRARY")
                get_property(_configs TARGET ${_explib} PROPERTY 
IMPORTED_CONFIGURATIONS)
                foreach(_config ${_configs})
                        get_property(_libloc TARGET ${_explib} PROPERTY 
IMPORTED_LOCATION_${_config})
                        if(EXISTS "${_libloc}")
                                list(APPEND MYPACKAGE_RUNTIME_LIBRARIES 
"${_libloc}")

                                get_filename_component(_libpath "${_libloc}" 
PATH)
                                list(APPEND MYPACKAGE_RUNTIME_LIBRARY_DIRS 
${_libpath})
                        endif()
                endforeach()
        endif()
endforeach()

if(MYPACKAGE_RUNTIME_LIBRARIES)
        list(REMOVE_DUPLICATES MYPACKAGE_RUNTIME_LIBRARIES)
endif()

if(MYPACKAGE_RUNTIME_LIBRARY_DIRS)
        list(REMOVE_DUPLICATES MYPACKAGE_RUNTIME_LIBRARY_DIRS)
endif()

# Compute the installation prefix relative to this file.
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
if(NOT WIN32)
        get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
endif()

set(MYPACKAGE_INCLUDE_DIRS "${_IMPORT_PREFIX}/include")
set(_IMPORT_PREFIX)

set(MYPACKAGE_FOUND ON)
# 2009-2010 Ryan Pavlik <rpav...@iastate.edu>
# http://academic.cleardefinition.com/
# Iowa State University HCI Graduate Program/VRAC
#
# Will set:
#  MYPACKAGE_LIBRARIES
#  MYPACKAGE_MYLIB1_LIBRARIES
#  MYPACKAGE_MYLIB2_LIBRARIES
#  MYPACKAGE_INCLUDE_DIRS
#  MYPACKAGE_RUNTIME_LIBRARIES and MYPACKAGE_RUNTIME_LIBRARY_DIRS if applicable
#  MYPACKAGE_FOUND

set(MYPACKAGE_INCLUDE_DIRS
        "@CMAKE_CURRENT_SOURCE_DIR@")

include("@CMAKE_CURRENT_BINARY_DIR@/mypackage-targets.cmake")

set(MYPACKAGE_LIBRARIES)
set(MYPACKAGE_RUNTIME_LIBRARIES)
set(MYPACKAGE_RUNTIME_LIBRARY_DIRS)
foreach(_lib MyLib1 MyLib2)
        set(_explib mypackage_buildtree_${_lib}) # The exported target name
        
        string(TOUPPER MYPACKAGE_${_lib}_LIBRARIES _libvar) # Upper case 
variable name
        set(${_libvar} ${_explib})
        
        list(APPEND MYPACKAGE_LIBRARIES ${_explib})
        
        # Runtime library info - only useful for shared libraries
        get_property(_type TARGET ${_explib} PROPERTY TYPE)
        if(_type STREQUAL "SHARED_LIBRARY")
                get_property(_configs TARGET ${_explib} PROPERTY 
IMPORTED_CONFIGURATIONS)
                foreach(_config ${_configs})
                        get_property(_libloc TARGET ${_explib} PROPERTY 
IMPORTED_LOCATION_${_config})
                        if(EXISTS "${_libloc}")
                                list(APPEND MYPACKAGE_RUNTIME_LIBRARIES 
"${_libloc}")
                                
                                get_filename_component(_libpath "${_libloc}" 
PATH)
                                list(APPEND MYPACKAGE_RUNTIME_LIBRARY_DIRS 
${_libpath})
                        endif()
                endforeach()
        endif()
endforeach()

if(MYPACKAGE_RUNTIME_LIBRARIES)
        list(REMOVE_DUPLICATES MYPACKAGE_RUNTIME_LIBRARIES)
endif()

if(MYPACKAGE_RUNTIME_LIBRARY_DIRS)
        list(REMOVE_DUPLICATES MYPACKAGE_RUNTIME_LIBRARY_DIRS)
endif()

set(MYPACKAGE_FOUND ON)
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Follow this link to subscribe/unsubscribe:
http://www.cmake.org/mailman/listinfo/cmake

Reply via email to