cmake: install config-module

Installs a config module if CMake verion >= 2.8.12.
The config-module creates the import library targets
built in the project (glew, glew_s, glewmx, glewmx_s)
but in accordance with the FindGLEW module shipped with
CMake, it also creates GLEW::GLEW and GLEW::GLEWMX.

GLEW::GLEW and GLEW::GLEWMX will be simply copies of
glew/glewmx or glew_s/glewmx_s. If both versions are
available they alias the shared versions.

The default behaviour can be changed either when installing
or when using the package:

- Set BUILD_SHARED_LIBS to OFF or ON when building and
  installing GLEW. This controls which libraries
  (shared or static) will be installed (and not which
  will be built).
- Set GLEW_USE_STATIC_LIBS to OFF or ON before calling
  `find_package(GLEW CONFIG REQUIRED)` to force
  the config-module to create GLEW::GLEW and GLEWMX
  as aliases to glew/glewmx or glew_s/glewmx_s

The script ./cmake-testbuild.sh is added to test the
CMake build and config-module. See instructions there.
This commit is contained in:
Tamas Kenez 2015-06-22 14:06:50 +02:00
parent a4a87f9466
commit d2e6823451
8 changed files with 287 additions and 1 deletions

1
.gitattributes vendored
View File

@ -2,3 +2,4 @@
*.png binary
build/*/* text eol=crlf
CMakeLists.txt text eol=lf
build/cmake/* text eol=lf

1
.gitignore vendored
View File

@ -15,3 +15,4 @@
/bin
/lib
/tmp
/out

View File

@ -10,6 +10,8 @@ if (COMMAND cmake_policy)
cmake_policy (SET CMP0003 NEW)
endif()
set(CMAKE_DEBUG_POSTFIX d)
option (BUILD_UTILS "utilities" ON)
set (GLEW_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..)
@ -55,7 +57,29 @@ set_target_properties (glewmx_s PROPERTIES COMPILE_DEFINITIONS "GLEW_STATIC;GLEW
target_link_libraries (glewmx ${GLEW_LIBRARIES})
target_link_libraries (glewmx_s ${GLEW_LIBRARIES})
install ( TARGETS glew glew_s glewmx glewmx_s
if(CMAKE_VERSION VERSION_LESS 2.8.12)
set(MAYBE_EXPORT "")
else()
target_compile_definitions(glew_s INTERFACE "GLEW_STATIC")
target_compile_definitions(glewmx INTERFACE "GLEW_MX")
target_compile_definitions(glewmx_s INTERFACE "GLEW_STATIC;GLEW_MX")
foreach(t glew glew_s glewmx glewmx_s)
target_include_directories(${t} PUBLIC $<INSTALL_INTERFACE:include>)
endforeach()
set(MAYBE_EXPORT EXPORT glew-targets)
endif()
set(targets_to_install "")
if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS)
list(APPEND targets_to_install glew glewmx)
endif()
if(NOT DEFINED BUILD_SHARED_LIBS OR NOT BUILD_SHARED_LIBS)
list(APPEND targets_to_install glew_s glewmx_s)
endif()
install ( TARGETS ${targets_to_install}
${MAYBE_EXPORT}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX}
@ -95,3 +119,12 @@ install (FILES
${GLEW_DIR}/include/GL/glew.h
${GLEW_DIR}/include/GL/glxew.h
DESTINATION include/GL)
if(MAYBE_EXPORT)
install(EXPORT glew-targets DESTINATION lib/cmake/glew
NAMESPACE GLEW::)
install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/glew-config.cmake
${CMAKE_CURRENT_SOURCE_DIR}/CopyImportedTargetProperties.cmake
DESTINATION lib/cmake/glew)
endif()

View File

@ -0,0 +1,88 @@
#.rst:
# CopyImportedTargetProperties
# --------------------------
#
# Copies the `INTERFACE*` and `IMPORTED*` properties from a target
# to another one.
# This function can be used to duplicate an `IMPORTED` or an `ALIAS` library
# with a different name since ``add_library(... ALIAS ...)`` does not work
# for those targets.
#
# ::
#
# copy_imported_target_properties(<source-target> <destination-target>)
#
# The function copies all the `INTERFACE*` and `IMPORTED*` target
# properties from `<source-target>` to `<destination-target>`.
#
# The function uses the `IMPORTED_CONFIGURATIONS` property to determine
# which configuration-dependent properties should be copied
# (`IMPORTED_LOCATION_<CONFIG>`, etc...)
#
# Example:
#
# Internally the CMake project of ZLIB builds the ``zlib`` and
# ``zlibstatic`` targets which can be exported in the ``ZLIB::`` namespace
# with the ``install(EXPORT ...)`` command.
#
# The config-module will then create the import libraries ``ZLIB::zlib`` and
# ``ZLIB::zlibstatic``. To use ``ZLIB::zlibstatic`` under the standard
# ``ZLIB::ZLIB`` name we need to create the ``ZLIB::ZLIB`` imported library
# and copy the appropriate properties:
#
# add_library(ZLIB::ZLIB STATIC IMPORTED)
# copy_imported_target_properties(ZLIB::zlibstatic ZLIB::ZLIB)
#
function(copy_imported_target_properties src_target dest_target)
set(config_dependent_props
IMPORTED_IMPLIB
IMPORTED_LINK_DEPENDENT_LIBRARIES
IMPORTED_LINK_INTERFACE_LANGUAGES
IMPORTED_LINK_INTERFACE_LIBRARIES
IMPORTED_LINK_INTERFACE_MULTIPLICITY
IMPORTED_LOCATION
IMPORTED_NO_SONAME
IMPORTED_SONAME
)
# copy configuration-independent properties
foreach(prop
${config_dependent_props}
IMPORTED_CONFIGURATIONS
INTERFACE_AUTOUIC_OPTIONS
INTERFACE_COMPILE_DEFINITIONS
INTERFACE_COMPILE_FEATURES
INTERFACE_COMPILE_OPTIONS
INTERFACE_INCLUDE_DIRECTORIES
INTERFACE_LINK_LIBRARIES
INTERFACE_POSITION_INDEPENDENT_CODE
INTERFACE_SOURCES
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
)
get_property(is_set TARGET ${src_target} PROPERTY ${prop} SET)
if(is_set)
get_target_property(v ${src_target} ${prop})
set_target_properties(${dest_target} PROPERTIES ${prop} "${v}")
# message(STATUS "set_target_properties(${dest_target} PROPERTIES ${prop} ${v})")
endif()
endforeach()
# copy configuration-dependent properties
get_target_property(imported_configs ${src_target}
IMPORTED_CONFIGURATIONS)
foreach(config ${imported_configs})
foreach(prop_prefix ${config_dependent_props})
set(prop ${prop_prefix}_${config})
get_property(is_set TARGET ${src_target} PROPERTY ${prop} SET)
if(is_set)
get_target_property(v ${src_target} ${prop})
set_target_properties(${dest_target}
PROPERTIES ${prop} "${v}")
# message(STATUS "set_target_properties(${dest_target} PROPERTIES ${prop} ${v})")
endif()
endforeach()
endforeach()
endfunction()

View File

@ -0,0 +1,46 @@
# This config-module creates the following import libraries:
#
# - GLEW::glew and GLEW::glewmx shared libs
# - GLEW::glew_s and GLEW::glewmx_s static libs
#
# Additionally GLEW::GLEW and GLEW::GLEWMX will be created as an
# copy of either the shared (default) or the static libs.
#
# Dependending on the setting of BUILD_SHARED_LIBS at GLEW build time
# either the static or shared versions may not be available.
#
# Set GLEW_USE_STATIC_LIBS to OFF or ON to force using the shared
# or static libs for GLEW::GLEW and GLEW::GLEWMX
#
include(${CMAKE_CURRENT_LIST_DIR}/glew-targets.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CopyImportedTargetProperties.cmake)
# decide which import library (glew/glew_s and glewmx/glewmx_s)
# needs to be copied to GLEW::GLEW and GLEW::GLEWMX
set(_glew_target_postfix "")
set(_glew_target_type SHARED)
if(DEFINED GLEW_USE_STATIC_LIBS)
# if defined, use only static or shared
if(GLEW_USE_STATIC_LIBS)
set(_glew_target_postfix "_s")
endif()
# else use static only if no shared
elseif(NOT TARGET GLEW::glew AND TARGET GLEW::glew_s)
set(_glew_target_postfix "_s")
endif()
if(_glew_target_postfix STREQUAL "")
set(_glew_target_type SHARED)
else()
set(_glew_target_type STATIC)
endif()
# CMake doesn't allow creating ALIAS lib for an IMPORTED lib
# so create imported ones and copy the properties
foreach(_glew_target glew glewmx)
set(_glew_src_target "GLEW::${_glew_target}${_glew_target_postfix}")
string(TOUPPER "GLEW::${_glew_target}" _glew_dest_target)
add_library(${_glew_dest_target} ${_glew_target_type} IMPORTED)
# message(STATUS "add_library(${_glew_dest_target} ${_glew_target_type} IMPORTED)")
copy_imported_target_properties(${_glew_src_target} ${_glew_dest_target})
endforeach()

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 2.8.12)
project(glew-cmake-test)
find_package(GLEW REQUIRED CONFIG)
find_package(OpenGL REQUIRED)
add_executable(cmake-test main.c)
set_target_properties(cmake-test PROPERTIES DEBUG_POSTFIX _d)
target_link_libraries(cmake-test PRIVATE GLEW::GLEW ${OPENGL_LIBRARIES})
target_include_directories(cmake-test PRIVATE ${OPENGL_INCLUDE_DIR})
if(CMAKE_VERSION VERSION_LESS 3.0)
set(cgex $<CONFIG>)
else()
set(cgex $<CONFIGURATION>)
endif()
target_compile_definitions(cmake-test PRIVATE
-DGLEW_CMAKE_TEST_CONFIG=${cgex}
-DGLEW_CMAKE_TEST_TARGET_FILE_NAME=$<TARGET_FILE_NAME:GLEW::GLEW>
-DGLEW_CMAKE_TEST_TARGET_TYPE=$<TARGET_PROPERTY:GLEW::GLEW,TYPE>
)
install(TARGETS cmake-test DESTINATION bin)

View File

@ -0,0 +1,23 @@
#include <GL/glew.h>
#include <stdio.h>
#include <stdlib.h>
#define S(x) SS(x)
#define SS(x) #x
int main(int argc, char* argv[]) {
printf("GLEW CMake test, %s build\n",
S(GLEW_CMAKE_TEST_CONFIG));
printf("-- linked to %s which is %s\n",
S(GLEW_CMAKE_TEST_TARGET_FILE_NAME),
S(GLEW_CMAKE_TEST_TARGET_TYPE));
const GLubyte* v = glewGetString(GLEW_VERSION);
if(v) {
printf("-- glewGetString(GLEW_VERSION) returns %s\n-- test passed.\n", v);
return EXIT_SUCCESS;
} else {
printf("-- glewGetString(GLEW_VERSION) returns NULL\n-- test failed.\n");
return EXIT_FAILURE;
}
}

70
cmake-testbuild.sh Executable file
View File

@ -0,0 +1,70 @@
#!/bin/sh
# This script tests the CMake build:
#
# - builds the main CMakeLists.txt
# - builds and runs a small test app in a separate build tree so
# the config-module is tested, too
#
# Options (environment variables):
#
# - The variable BUILD_SHARED_LIBS will be forwarded to the CMake project
# that builds and installs the GLEW libraries. Set BUILD_SHARED_LIBS to
# ON or OFF to install only static or shared libs. Leave it unset to
# install both.
#
# Note: BUILD_SHARED_LIBS controls only what to install not what to build.
#
# - GLEW_USE_STATIC_LIBS will be forwarded to the test project that calls
# `find_package` to find GLEW. Set GLEW_USE_STATIC LIBS to ON or OFF force
# finding the shared or static versions of GLEW. Leave it unset to find
# the shared or what is available.
#
# Examples:
#
# Build & install shared + static, find default (shared)
#
# ./cmake-testbuild.shh
#
# Build & install shared + static, find static
#
# GLEW_USE_STATIC_LIBS=ON ./cmake-testbuild.sh
#
# Install static only (still build both)
#
# BUILD_SHARED_LIBS=OFF ./cmake-testbuild.sh
#
set -ex
rm -rf out/include
rm -rf out/lib*
rm -rf out/bin
if [ -n "$BUILD_SHARED_LIBS" ]; then
bsl=-DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS
else
bsl=-UBUILD_SHARED_LIBS
fi
if [ -n "$GLEW_USE_STATIC_LIBS" ]; then
gusl=-DGLEW_USE_STATIC_LIBS=$GLEW_USE_STATIC_LIBS
else
gusl=-UGLEW_USE_STATIC_LIBS
fi
cmake -Hbuild/cmake -Bout/build/glew -DCMAKE_INSTALL_PREFIX=${PWD}/out -DCMAKE_BUILD_TYPE=Debug $bsl
cmake --build out/build/glew --target install --config Debug
cmake out/build/glew -DCMAKE_BUILD_TYPE=Release
cmake --build out/build/glew --target install --config Release --clean-first
cmake -Hbuild/cmake/testbuild -Bout/build/cmake-testbuild -DCMAKE_INSTALL_PREFIX=${PWD}/out -DCMAKE_PREFIX_PATH=${PWD}/out -DCMAKE_BUILD_TYPE=Debug $gusl
cmake --build out/build/cmake-testbuild --target install --config Debug
cmake out/build/cmake-testbuild -DCMAKE_BUILD_TYPE=Release
cmake --build out/build/cmake-testbuild --target install --config Release --clean-first
export LD_LIBRARY_PATH=${PWD}/out/lib:$LD_LIBRARY_PATH
out/bin/cmake-test_d
out/bin/cmake-test