Skip to content

Commit

Permalink
Add config-style support for find_package(shapefile).
Browse files Browse the repository at this point in the history
Also fix installation directories so that the package is relocatable.
  • Loading branch information
cffk committed May 4, 2020
1 parent 51b2b52 commit 20ce540
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 28 deletions.
96 changes: 68 additions & 28 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ project(shapelib C)
message(STATUS "CMake version = ${CMAKE_VERSION}")
message(STATUS "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")

# Version 2.8.5 or above of cmake is currently required for all platforms.
cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR)
# Version 3.7 or above of cmake is currently required for all platforms.
cmake_minimum_required(VERSION 3.7 FATAL_ERROR)

set (PROJECT_VERSION_MAJOR 1)
set (PROJECT_VERSION_MINOR 5)
set (PROJECT_VERSION_PATCH 0)
set (PROJECT_VERSION
"${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")

# libraries are all shared by default.
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
Expand All @@ -48,33 +54,44 @@ set(PACKAGE shp)

# Set up install locations.
set(
CMAKE_INSTALL_BINDIR
${CMAKE_INSTALL_PREFIX}/bin
CMAKE_INSTALL_BINDIR bin
CACHE PATH "install location for user executables"
)

set(
CMAKE_INSTALL_LIBDIR
${CMAKE_INSTALL_PREFIX}/lib
CMAKE_INSTALL_LIBDIR lib
CACHE PATH "install location for object code libraries"
)

set(
CMAKE_INSTALL_INCLUDEDIR
${CMAKE_INSTALL_PREFIX}/include
CMAKE_INSTALL_INCLUDEDIR include
CACHE PATH "install location for C header files"
)

set(
CMAKE_INSTALL_SHP_DATADIR
${CMAKE_INSTALL_PREFIX}/share/${PACKAGE}
CMAKE_INSTALL_CMAKEDIR share/${PROJECT_NAME}
CACHE PATH "install location for read-only architecture-independent shp data"
)

file (RELATIVE_PATH RELATIVE_LIBDIR
${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}
${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})

message (STATUS "CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}")

if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
# Set a default build type for single-configuration cmake generators
# if no build type is set.
set (CMAKE_BUILD_TYPE Release)
endif ()

# Export build information to help other projects link installed
# shapelib software. Only one of these signatures is required
# for the export_shp name.
install(EXPORT export_shp DESTINATION ${CMAKE_INSTALL_SHP_DATADIR})
install(EXPORT targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_CMAKEDIR}
FILE "${PROJECT_NAME}-targets.cmake")

# Initial boilerplate done, now build library and executables.

Expand All @@ -94,10 +111,13 @@ if(SHP_DROP_UNABLE_TO_OPEN_MSG)
)
endif(SHP_DROP_UNABLE_TO_OPEN_MSG)

add_library(shp ${lib_SRC})
add_library(${PACKAGE} ${lib_SRC})

target_include_directories (${PACKAGE} INTERFACE
$<INSTALL_INTERFACE:include>)

if(WIN32 AND NOT CYGWIN)
set_target_properties(shp
set_target_properties(${PACKAGE}
PROPERTIES
COMPILE_DEFINITIONS SHAPELIB_DLLEXPORT
)
Expand All @@ -106,28 +126,28 @@ endif(WIN32 AND NOT CYGWIN)
if(UNIX)
find_library(M_LIB m)
if(M_LIB)
TARGET_LINK_LIBRARIES(shp -lm)
TARGET_LINK_LIBRARIES(${PACKAGE} -lm)
endif()
endif(UNIX)

set(shp_SOVERSION 1)
set(shp_VERSION 1.5.0)
set_target_properties(shp
set(shp_VERSION ${PROJECT_VERSION})
set_target_properties(${PACKAGE}
PROPERTIES
SOVERSION ${shp_SOVERSION}
VERSION ${shp_VERSION}
INSTALL_NAME_DIR "${CMAKE_INSTALL_LIBDIR}"
)

if(USE_RPATH)
set_target_properties(shp
set_target_properties(${PACKAGE}
PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_LIBDIR}"
)
endif(USE_RPATH)

install(TARGETS shp
EXPORT export_shp
install(TARGETS ${PACKAGE}
EXPORT targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
Expand All @@ -153,6 +173,8 @@ else(BASH_EXECUTABLE AND SED_EXECUTABLE)
message(STATUS "WARNING: sed or bash not available so disabling testing")
endif(BASH_EXECUTABLE AND SED_EXECUTABLE)

set (BUILD_TEST OFF)

# For the first series of tests, the user needs to have downloaded
# from http://dl.maptools.org/dl/shapelib/shape_eg_data.zip, unpacked
# that file, and specified the location of that directory with
Expand All @@ -166,25 +188,41 @@ if(BUILD_TEST)
endif(EG_DATA)
endif(BUILD_TEST)

if (NOT MSVC)
# Set the run time path for shared libraries for non-Windows machines.
set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# See also INSTALL_RPATH property on the tools.
set (CMAKE_MACOSX_RPATH ON)
else ()
# Use relative path so that package is relocatable
set (CMAKE_INSTALL_RPATH "\$ORIGIN/${RELATIVE_LIBDIR}")
endif ()
endif ()

foreach(executable ${executables})
add_executable(${executable} ${executable}.c)
target_link_libraries(${executable} shp)
if(USE_RPATH)
set_target_properties(${executable}
PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_LIBDIR}"
)
endif(USE_RPATH)
target_link_libraries(${executable} ${PACKAGE})
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# Ensure that the package is relocatable
set_target_properties (${TOOLS} PROPERTIES
INSTALL_RPATH "@loader_path/${RELATIVE_LIBDIR}")
endif ()
if(BUILD_TEST)
get_target_property(${executable}_LOC ${executable} LOCATION)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/script.sed "s?\\./${executable}?${${executable}_LOC}?\n")
endif(BUILD_TEST)
install(TARGETS ${executable} DESTINATION ${CMAKE_INSTALL_BINDIR})
endforeach(executable ${executables})

install(TARGETS ${executables}
EXPORT targets DESTINATION ${CMAKE_INSTALL_BINDIR})

# Install header
install(FILES shapefil.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# For compatibility with older installation
install(FILES shapefil.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/shapelib)

if(BUILD_TEST)
# Set up tests:

Expand All @@ -193,7 +231,7 @@ if(BUILD_TEST)
# Other executables to be built to facilitate tests.
foreach(executable shptest shputils)
add_executable(${executable} ${executable}.c)
target_link_libraries(${executable} shp)
target_link_libraries(${executable} ${PACKAGE})
get_target_property(${executable}_LOC ${executable} LOCATION)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/script.sed "s?\\./${executable}?${${executable}_LOC}?\n")
endforeach(executable shptest shputils)
Expand Down Expand Up @@ -235,3 +273,5 @@ if(BUILD_TEST)
COMMAND ${BASH_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/sed_scripted_test3.sh
)
endif(BUILD_TEST)

add_subdirectory (cmake)
39 changes: 39 additions & 0 deletions cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# config file support for find_package (shapelib).

# Variables needed by ${PROJECT_NAME}-config-version.cmake
if (MSVC)
# For checking the compatibility of MSVC_TOOLSET_VERSION; see
# https://docs.microsoft.com/en-us/cpp/porting/overview-of-potential-upgrade-issues-visual-cpp
# Assume major version number is obtained by dropping the last decimal
# digit.
math (EXPR MSVC_TOOLSET_MAJOR "${MSVC_TOOLSET_VERSION}/10")
else ()
set (MSVC_TOOLSET_VERSION 0)
set (MSVC_TOOLSET_MAJOR 0)
endif ()
if (CMAKE_CROSSCOMPILING)
# Ensure that all "true" (resp. "false") settings are represented by
# the same string.
set (CMAKE_CROSSCOMPILING_STR "ON")
else ()
set (CMAKE_CROSSCOMPILING_STR "OFF")
endif ()

# Find root of install tree relative to CMAKE_INSTALL_CMAKEDIR
file (RELATIVE_PATH PROJECT_ROOT_DIR
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" "${CMAKE_INSTALL_PREFIX}")
# strip trailing slash
get_filename_component (PROJECT_ROOT_DIR "${PROJECT_ROOT_DIR}/." PATH)


configure_file (project-config.cmake.in project-config.cmake @ONLY)
configure_file (project-config-version.cmake.in
project-config-version.cmake @ONLY)
install (FILES
"${CMAKE_CURRENT_BINARY_DIR}/project-config.cmake"
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
RENAME "${PROJECT_NAME}-config.cmake")
install (FILES
"${CMAKE_CURRENT_BINARY_DIR}/project-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
RENAME "${PROJECT_NAME}-config-version.cmake")
69 changes: 69 additions & 0 deletions cmake/project-config-version.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Version checking for @PROJECT_NAME@

set (PACKAGE_VERSION "@PROJECT_VERSION@")
set (PACKAGE_VERSION_MAJOR "@PROJECT_VERSION_MAJOR@")
set (PACKAGE_VERSION_MINOR "@PROJECT_VERSION_MINOR@")
set (PACKAGE_VERSION_PATCH "@PROJECT_VERSION_PATCH@")

# These variable definitions parallel those in @PROJECT_NAME@'s
# cmake/CMakeLists.txt.
if (MSVC)
# For checking the compatibility of MSVC_TOOLSET_VERSION; see
# https://docs.microsoft.com/en-us/cpp/porting/overview-of-potential-upgrade-issues-visual-cpp
# Assume major version number is obtained by dropping the last decimal
# digit.
math (EXPR MSVC_TOOLSET_MAJOR "${MSVC_TOOLSET_VERSION}/10")
endif ()
if (CMAKE_CROSSCOMPILING)
# Ensure that all "true" (resp. "false") settings are represented by
# the same string.
set (CMAKE_CROSSCOMPILING_STR "ON")
else ()
set (CMAKE_CROSSCOMPILING_STR "OFF")
endif ()

if (NOT PACKAGE_FIND_NAME STREQUAL "@PROJECT_NAME@")
# Check package name (in particular, because of the way cmake finds
# package config files, the capitalization could easily be "wrong").
# This is necessary to ensure that the automatically generated
# variables, e.g., <package>_FOUND, are consistently spelled.
set (REASON "package = @PROJECT_NAME@, NOT ${PACKAGE_FIND_NAME}")
set (PACKAGE_VERSION_UNSUITABLE TRUE)
elseif (NOT (APPLE OR (NOT DEFINED CMAKE_SIZEOF_VOID_P) OR
CMAKE_SIZEOF_VOID_P EQUAL @CMAKE_SIZEOF_VOID_P@))
# Reject if there's a 32-bit/64-bit mismatch (not necessary with Apple
# since a multi-architecture library is built for that platform).
set (REASON "sizeof(*void) = @CMAKE_SIZEOF_VOID_P@")
set (PACKAGE_VERSION_UNSUITABLE TRUE)
elseif (MSVC AND NOT (
# toolset version must be at least as great as @PROJECT_NAME@'s
MSVC_TOOLSET_VERSION GREATER_EQUAL @MSVC_TOOLSET_VERSION@
# and major versions must match
AND MSVC_TOOLSET_MAJOR EQUAL @MSVC_TOOLSET_MAJOR@ ))
# Reject if there's a mismatch in MSVC compiler versions
set (REASON "MSVC_TOOLSET_VERSION = @MSVC_TOOLSET_VERSION@")
set (PACKAGE_VERSION_UNSUITABLE TRUE)
elseif (NOT CMAKE_CROSSCOMPILING_STR STREQUAL "@CMAKE_CROSSCOMPILING_STR@")
# Reject if there's a mismatch in ${CMAKE_CROSSCOMPILING}
set (REASON "cross-compiling = @CMAKE_CROSSCOMPILING@")
set (PACKAGE_VERSION_UNSUITABLE TRUE)
elseif (CMAKE_CROSSCOMPILING AND
NOT (CMAKE_SYSTEM_NAME STREQUAL "@CMAKE_SYSTEM_NAME@" AND
CMAKE_SYSTEM_PROCESSOR STREQUAL "@CMAKE_SYSTEM_PROCESSOR@"))
# Reject if cross-compiling and there's a mismatch in the target system
set (REASON "target = @CMAKE_SYSTEM_NAME@-@CMAKE_SYSTEM_PROCESSOR@")
set (PACKAGE_VERSION_UNSUITABLE TRUE)
elseif (PACKAGE_FIND_VERSION)
if (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
set (PACKAGE_VERSION_EXACT TRUE)
elseif (PACKAGE_FIND_VERSION VERSION_LESS PACKAGE_VERSION
AND PACKAGE_FIND_VERSION_MAJOR EQUAL PACKAGE_VERSION_MAJOR)
set (PACKAGE_VERSION_COMPATIBLE TRUE)
endif ()
endif ()

# If unsuitable, append the reason to the package version so that it's
# visible to the user.
if (PACKAGE_VERSION_UNSUITABLE)
set (PACKAGE_VERSION "${PACKAGE_VERSION} (${REASON})")
endif ()
29 changes: 29 additions & 0 deletions cmake/project-config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Configure @PROJECT_NAME@
#
# Set
# @PROJECT_NAME@_FOUND = 1
# @PROJECT_NAME@_INCLUDE_DIRS = /usr/local/include
# @PROJECT_NAME@_LIBRARIES = shapelib::shp
# @PROJECT_NAME@_LIBRARY_DIRS = /usr/local/lib
# @PROJECT_NAME@_BINARY_DIRS = /usr/local/bin
# @PROJECT_NAME@_VERSION = 1.5.0 (for example)

message (STATUS "Reading ${CMAKE_CURRENT_LIST_FILE}")
# @PROJECT_NAME@_VERSION is set by version file
message (STATUS
"@PROJECT_NAME@ configuration, version ${@PROJECT_NAME@_VERSION}")

# Tell the user project where to find our headers and libraries
get_filename_component (_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
get_filename_component (_ROOT "${_DIR}/@PROJECT_ROOT_DIR@" ABSOLUTE)
set (@PROJECT_NAME@_INCLUDE_DIRS "${_ROOT}/@CMAKE_INSTALL_INCLUDEDIR@")
set (@PROJECT_NAME@_LIBRARY_DIRS "${_ROOT}/@CMAKE_INSTALL_LIBDIR@")
set (@PROJECT_NAME@_BINARY_DIRS "${_ROOT}/@CMAKE_INSTALL_BINDIR@")

set (@PROJECT_NAME@_LIBRARIES shapelib::shp)
# Read in the exported definition of the library
include ("${_DIR}/@PROJECT_NAME@-targets.cmake")

unset (_ROOT)
unset (_DIR)

0 comments on commit 20ce540

Please sign in to comment.