1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
|
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
if (NOT BASIC_PROJECT_CONFIG_DONE)
message(FATAL_ERROR "Before including the LibraryTarget module, the BasicConfig module must be included.")
endif ()
if (TARGET_CONFIG_DONE)
message(FATAL_ERROR "Can not include LibraryTarget module when targets are already configured.")
endif ()
# check whether project type is set correctly
if (("${META_PROJECT_TYPE}" STREQUAL "plugin") OR ("${META_PROJECT_TYPE}" STREQUAL "qtplugin"))
set(META_IS_PLUGIN YES)
endif ()
if ((NOT "${META_PROJECT_TYPE}" STREQUAL "library")
AND (NOT "${META_PROJECT_TYPE}" STREQUAL "")
AND NOT META_IS_PLUGIN)
message(
FATAL_ERROR
"The LibraryTarget CMake module is intended to be used for building library projects only (and not for applications)."
)
endif ()
# add option for enabling versioned mingw-w64 libraries (disabled by default to preserve compatibility, will be the only
# naming scheme in v6)
option(VERSIONED_MINGW_LIBRARIES
"enables versioned libraries like 'libc++utilities-5.dll' instead of 'c++utilities.dll' for mingw-w64 targets" OFF)
# include packages for configure_package_config_file, write_basic_package_version_file and find_template_file
include(CMakePackageConfigHelpers)
include(TemplateFinder)
# set install destination for the CMake modules, config files and header files
set(INCLUDE_SUBDIR "${CMAKE_INSTALL_INCLUDEDIR}")
set(HEADER_INSTALL_DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
if (NAMESPACE_PREFIX OR META_CONFIG_SUFFIX)
set(INCLUDE_SUBDIR "${INCLUDE_SUBDIR}/${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}")
set(HEADER_INSTALL_DESTINATION
"${HEADER_INSTALL_DESTINATION}/${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}")
endif ()
set(CMAKE_MODULE_INSTALL_DESTINATION "${META_DATA_DIR_ABSOLUTE}/cmake/modules")
set(CMAKE_CONFIG_INSTALL_DESTINATION "${META_DATA_DIR_ABSOLUTE}/cmake")
# remove library prefix when building with mingw-w64 (just for consistency with qmake)
if (MINGW AND NOT VERSIONED_MINGW_LIBRARIES)
set(CMAKE_SHARED_LIBRARY_PREFIX "")
endif ()
# set compile definitions for static build
if (NOT BUILD_SHARED_LIBS)
list(APPEND META_PUBLIC_COMPILE_DEFINITIONS ${META_PROJECT_VARNAME_UPPER}_STATIC)
endif ()
# add global library-specific header
find_template_file("global.h" CPP_UTILITIES GLOBAL_H_TEMPLATE_FILE)
if ("${META_PROJECT_NAME}" STREQUAL "c++utilities")
set(GENERAL_GLOBAL_H_INCLUDE_PATH "\"application/global.h\"")
else ()
set(GENERAL_GLOBAL_H_INCLUDE_PATH "<c++utilities/application/global.h>")
endif ()
configure_file(
"${GLOBAL_H_TEMPLATE_FILE}" "${CMAKE_CURRENT_SOURCE_DIR}/global.h" # simply add this to source to ease inclusion
NEWLINE_STYLE UNIX # since this goes to sources ensure consistency
)
list(APPEND HEADER_FILES global.h)
# add header to check library version
set(VERSION_HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/resources/version.h")
find_template_file("version.h" CPP_UTILITIES VERSION_H_TEMPLATE_FILE)
configure_file("${VERSION_H_TEMPLATE_FILE}" "${VERSION_HEADER_FILE}" NEWLINE_STYLE UNIX)
list(APPEND SOURCE_FILES "${VERSION_HEADER_FILE}")
# determine SOVERSION
if (NOT META_SOVERSION AND NOT META_IS_PLUGIN)
if (META_VERSION_EXACT_SONAME)
set(META_SOVERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}")
else ()
set(META_SOVERSION "${META_VERSION_MAJOR}")
endif ()
endif ()
# define relevant files
set(ALL_FILES
${HEADER_FILES}
${SRC_FILES}
${GENERATED_DBUS_FILES}
${WIDGETS_FILES}
${QML_FILES}
${RES_FILES}
${WINDOWS_ICON_PATH})
if (NOT BUILTIN_TRANSLATIONS)
list(APPEND ALL_FILES ${QM_FILES})
endif ()
# determine include path used when building the project itself
if (TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE)
# use existing TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE if already defined
elseif (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include")
# use special include directory if available
set(TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
else ()
# use the project folder itself
set(TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/..")
endif ()
# configure target type for building the library
if (BUILD_SHARED_LIBS)
if (META_IS_PLUGIN)
set(META_LIBRARY_TYPE MODULE)
else ()
set(META_LIBRARY_TYPE SHARED)
endif ()
else ()
set(META_LIBRARY_TYPE STATIC)
# define QT_STATICPLUGIN when building static Qt plugins
if ("${META_PROJECT_TYPE}" STREQUAL "qtplugin")
list(APPEND META_PRIVATE_COMPILE_DEFINITIONS QT_STATICPLUGIN)
endif ()
endif ()
# add custom libraries
append_user_defined_additional_libraries()
# allow writing public compile definitions to a header file instead of just relying on CMake/pkg-config
option(USE_HEADER_FOR_PUBLIC_COMPILE_DEFINITIONS "writes public compile definitions to a header file" ON)
set(TARGET_GENERATED_INCLUDE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include")
set(TARGET_DEFINITIONS_HEADER "${TARGET_GENERATED_INCLUDE_DIRECTORY}/${META_PROJECT_NAME}-definitions.h")
if (USE_HEADER_FOR_PUBLIC_COMPILE_DEFINITIONS)
set(EXISTING_DEFS_FOR_HEADER "none")
if (EXISTS "${TARGET_DEFINITIONS_HEADER}")
file(READ "${TARGET_DEFINITIONS_HEADER}" EXISTING_DEFS_FOR_HEADER)
endif ()
set(DEFS_FOR_HEADER "")
foreach (DEF ${META_PUBLIC_COMPILE_DEFINITIONS})
if (DEF MATCHES "([A-Za-z0-9_]+)=([A-Za-z0-9_ ]+)")
set(DEF_NAME "${CMAKE_MATCH_1}")
set(DEF_VALUE " ${CMAKE_MATCH_2}")
elseif (DEF MATCHES "([A-Za-z0-9_]+)")
set(DEF_NAME "${CMAKE_MATCH_1}")
set(DEF_VALUE "")
endif ()
if (DEF_NAME)
set(DEFS_FOR_HEADER "${DEFS_FOR_HEADER}#ifndef ${DEF_NAME}\n#define ${DEF_NAME}${DEF_VALUE}\n#endif\n")
endif ()
endforeach ()
if (NOT "${DEFS_FOR_HEADER}" STREQUAL "${EXISTING_DEFS_FOR_HEADER}")
file(WRITE "${TARGET_DEFINITIONS_HEADER}" "${DEFS_FOR_HEADER}")
else ()
message(STATUS "Header \"${TARGET_DEFINITIONS_HEADER}\" for ${META_PROJECT_NAME} did not change.")
endif ()
endif ()
# add library to be created, set libs to link against, set version and C++ standard
if (META_HEADER_ONLY_LIB)
add_library(${META_TARGET_NAME} INTERFACE)
target_link_libraries(${META_TARGET_NAME} INTERFACE ${META_ADDITIONAL_LINK_FLAGS} "${PUBLIC_LIBRARIES}"
"${PRIVATE_LIBRARIES}")
target_include_directories(
${META_TARGET_NAME}
INTERFACE $<BUILD_INTERFACE:${TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE}>
$<BUILD_INTERFACE:${TARGET_GENERATED_INCLUDE_DIRECTORY}>
$<INSTALL_INTERFACE:${HEADER_INSTALL_DESTINATION}> ${PUBLIC_INCLUDE_DIRS})
target_compile_definitions(${META_TARGET_NAME} INTERFACE "${META_PUBLIC_COMPILE_DEFINITIONS}")
target_compile_options(${META_TARGET_NAME} INTERFACE "${META_PUBLIC_COMPILE_OPTIONS}" "${META_PRIVATE_COMPILE_OPTIONS}")
set_target_properties(${META_TARGET_NAME} PROPERTIES EXPORT_COMPILE_COMMANDS "${ENABLE_EXPORT_COMPILE_COMMANDS}")
else ()
add_library(${META_TARGET_NAME} ${META_LIBRARY_TYPE} ${ALL_FILES})
target_link_libraries(
${META_TARGET_NAME}
PUBLIC ${META_ADDITIONAL_LINK_FLAGS} "${PUBLIC_LIBRARIES}"
PRIVATE "${PRIVATE_LIBRARIES}")
if (META_IS_PLUGIN)
target_include_directories(
${META_TARGET_NAME} PRIVATE $<BUILD_INTERFACE:${TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE}>
$<BUILD_INTERFACE:${TARGET_GENERATED_INCLUDE_DIRECTORY}> "${PRIVATE_INCLUDE_DIRS}")
else ()
target_include_directories(
${META_TARGET_NAME}
PUBLIC $<BUILD_INTERFACE:${TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE}>
$<BUILD_INTERFACE:${TARGET_GENERATED_INCLUDE_DIRECTORY}>
$<INSTALL_INTERFACE:${HEADER_INSTALL_DESTINATION}> ${PUBLIC_INCLUDE_DIRS}
PRIVATE "${PRIVATE_INCLUDE_DIRS}")
endif ()
target_compile_definitions(
${META_TARGET_NAME}
PUBLIC "${META_PUBLIC_COMPILE_DEFINITIONS}"
PRIVATE "${META_PRIVATE_COMPILE_DEFINITIONS}")
target_compile_options(
${META_TARGET_NAME}
PUBLIC "${META_PUBLIC_COMPILE_OPTIONS}"
PRIVATE "${META_PRIVATE_COMPILE_OPTIONS}")
set_target_properties(
${META_TARGET_NAME}
PROPERTIES VERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}"
SOVERSION "${META_SOVERSION}"
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
LINK_SEARCH_START_STATIC ${STATIC_LINKAGE}
LINK_SEARCH_END_STATIC ${STATIC_LINKAGE}
AUTOGEN_TARGET_DEPENDS "${AUTOGEN_DEPS}"
QT_DEFAULT_PLUGINS "${META_QT_DEFAULT_PLUGINS}"
EXPORT_COMPILE_COMMANDS "${ENABLE_EXPORT_COMPILE_COMMANDS}")
if (NOT META_CXX_STANDARD STREQUAL "any")
set_target_properties(${META_TARGET_NAME} PROPERTIES CXX_STANDARD "${META_CXX_STANDARD}")
endif ()
if (META_PLUGIN_CATEGORY)
set_target_properties(${META_TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${META_PLUGIN_CATEGORY}")
endif ()
# incorporate the SOVERSION into the library name for mingw-w64 targets
set(TARGET_SUFFIX_FOR_PC "")
if (BUILD_SHARED_LIBS
AND NOT META_IS_PLUGIN
AND MINGW
AND VERSIONED_MINGW_LIBRARIES)
if (NOT META_DLLVERSION)
string(REPLACE "." "-" META_DLLVERSION "${META_SOVERSION}")
endif ()
set_target_properties(${META_TARGET_NAME} PROPERTIES SUFFIX "-${META_DLLVERSION}.dll")
set(TARGET_SUFFIX_FOR_PC "-${META_DLLVERSION}")
endif ()
# avoid duplicating the "lib" prefix if the target name already starts with "lib"
if (META_TARGET_NAME MATCHES "lib.*")
set_target_properties(${META_TARGET_NAME} PROPERTIES PREFIX "")
endif ()
# add target for pulling only headers because some libraries contain header-only parts which are useful on their own
if (NOT META_PLUGIN_CATEGORY)
add_library(${META_TARGET_NAME}-headers INTERFACE)
target_include_directories(
${META_TARGET_NAME}-headers
INTERFACE $<BUILD_INTERFACE:${TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE}>
$<BUILD_INTERFACE:${TARGET_GENERATED_INCLUDE_DIRECTORY}>
$<INSTALL_INTERFACE:${HEADER_INSTALL_DESTINATION}> ${PUBLIC_INCLUDE_DIRS})
target_compile_definitions(${META_TARGET_NAME}-headers INTERFACE "${META_PUBLIC_COMPILE_DEFINITIONS}")
target_compile_options(${META_TARGET_NAME}-headers INTERFACE "${META_PUBLIC_COMPILE_OPTIONS}")
endif ()
endif ()
# populate META_PUBLIC_LIB_DEPENDS
foreach (DEPENDENCY ${PUBLIC_LIBRARIES})
if (NOT "${DEPENDENCY}" IN_LIST META_PUBLIC_LIB_DEPENDS)
list(APPEND META_PUBLIC_LIB_DEPENDS ${DEPENDENCY})
endif ()
endforeach ()
# populate META_PRIVATE_LIB_DEPENDS (only required when building static libraries)
if (NOT BUILD_SHARED_LIBS)
foreach (DEPENDENCY ${PRIVATE_LIBRARIES})
if (NOT "${DEPENDENCY}" IN_LIST META_PUBLIC_LIB_DEPENDS AND NOT "${DEPENDENCY}" IN_LIST META_PRIVATE_LIB_DEPENDS)
list(APPEND META_PRIVATE_LIB_DEPENDS ${DEPENDENCY})
endif ()
endforeach ()
endif ()
# Qt Creator does not show INTERFACE_SOURCES in project tree, so create a custom target as workaround
if (META_HEADER_ONLY_LIB)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headeronly.cpp"
"// not belonging to a real target, only for header-only lib files showing up in Qt Creator")
add_library(${META_TARGET_NAME}_interface_sources_for_qtcreator EXCLUDE_FROM_ALL
"${CMAKE_CURRENT_BINARY_DIR}/headeronly.cpp" ${HEADER_FILES})
target_include_directories(
${META_TARGET_NAME}_interface_sources_for_qtcreator
INTERFACE $<BUILD_INTERFACE:${TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE}>
$<INSTALL_INTERFACE:${HEADER_INSTALL_DESTINATION}> ${PUBLIC_INCLUDE_DIRS})
target_compile_definitions(${META_TARGET_NAME}_interface_sources_for_qtcreator
INTERFACE "${META_PUBLIC_COMPILE_DEFINITIONS}")
target_compile_options(${META_TARGET_NAME}_interface_sources_for_qtcreator INTERFACE "${META_PUBLIC_COMPILE_OPTIONS}")
set_target_properties(
${META_TARGET_NAME}_interface_sources_for_qtcreator
PROPERTIES VERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}"
SOVERSION "${META_SOVERSION}"
AUTOGEN_TARGET_DEPENDS "${AUTOGEN_DEPS}")
if (NOT META_CXX_STANDARD STREQUAL "any")
set_target_properties(${META_TARGET_NAME}_interface_sources_for_qtcreator PROPERTIES CXX_STANDARD
"${META_CXX_STANDARD}")
endif ()
endif ()
# generate CMake code to configure additional arguments for required CMake-packages
set(ADDITIONAL_ARGUMENTS_FOR_REQUIRED_CMAKE_PACKAGES)
foreach (INTERFACE_REQUIRED_PACKAGE ${INTERFACE_REQUIRED_PACKAGES})
if (PACKAGE_ARGS_${INTERFACE_REQUIRED_PACKAGE})
set(ADDITIONAL_ARGUMENTS_FOR_REQUIRED_CMAKE_PACKAGES
"${ADDITIONAL_ARGUMENTS_FOR_REQUIRED_CMAKE_PACKAGES}set(${META_PROJECT_VARNAME_UPPER}_FIND_PACKAGE_ARGS_${INTERFACE_REQUIRED_PACKAGE} \"${PACKAGE_ARGS_${INTERFACE_REQUIRED_PACKAGE}}\")\n"
)
endif ()
endforeach ()
# generate CMake code to configure CMake-target to pkg-config module mapping
set(TARGET_TO_PKG_CONFIG_MODULE_NAME_MAPPING
"set(PKG_CONFIG_${META_TARGET_NAME} \"${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}\")")
foreach (INTERFACE_REQUIRED_PKG_CONFIG_MODULE ${INTERFACE_REQUIRED_PKG_CONFIG_MODULES})
string(REPLACE "::" "_" INTERFACE_REQUIRED_PKG_CONFIG_MODULE_VARNAME "${INTERFACE_REQUIRED_PKG_CONFIG_MODULE}")
set(TARGET_TO_PKG_CONFIG_MODULE_NAME_MAPPING
"${TARGET_TO_PKG_CONFIG_MODULE_NAME_MAPPING}\nset(PKG_CONFIG_${INTERFACE_REQUIRED_PKG_CONFIG_MODULE_VARNAME} \"${PKG_CONFIG_${INTERFACE_REQUIRED_PKG_CONFIG_MODULE_VARNAME}}\")"
)
endforeach ()
# add all REQUIRED_PACKAGES that are exported by the current build to INTERFACE_REQUIRED_PACKAGES
foreach (REQUIRED_PACKAGE ${REQUIRED_PACKAGES})
# note: Looks like CMake (as of version 3.24.0) adds a check for targets that are exported as part of the current build
# in "*Targets.cmake" export files as those targets are also added as "IMPORTED_LINK_DEPENDENT_LIBRARIES". For instance,
# qtforkawesome and qtquickforkawesome are built within the same project and qtforkawesome ends up as
# IMPORTED_LINK_DEPENDENT_LIBRARIES on qtquickforkawesome's export and is checked to exist.
if ("${EXPORT_${REQUIRED_PACKAGE}}")
list(APPEND INTERFACE_REQUIRED_PACKAGES "${REQUIRED_PACKAGE}")
endif ()
endforeach ()
# create the CMake package config file from template
if (INTERFACE_REQUIRED_PACKAGES)
list(REMOVE_ITEM INTERFACE_REQUIRED_PACKAGES "")
list(REMOVE_DUPLICATES INTERFACE_REQUIRED_PACKAGES)
endif ()
if (INTERFACE_REQUIRED_PKG_CONFIG_MODULES)
list(REMOVE_ITEM INTERFACE_REQUIRED_PKG_CONFIG_MODULES "")
list(REMOVE_DUPLICATES INTERFACE_REQUIRED_PKG_CONFIG_MODULES)
endif ()
set(CONFIG_TARGETS "${CMAKE_CURRENT_BINARY_DIR}/${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}Config.cmake")
if (NAMESPACE_PREFIX OR META_CONFIG_SUFFIX)
list(APPEND CONFIG_TARGETS "${CMAKE_CURRENT_BINARY_DIR}/${META_PROJECT_NAME}Config.cmake")
endif ()
find_template_file("Config.cmake" CPP_UTILITIES CONFIG_TEMPLATE_FILE)
foreach (CONFIG_TARGET ${CONFIG_TARGETS})
configure_package_config_file(
"${CONFIG_TEMPLATE_FILE}" "${CONFIG_TARGET}"
INSTALL_DESTINATION "${CMAKE_CONFIG_INSTALL_DESTINATION}"
PATH_VARS CMAKE_MODULE_INSTALL_DESTINATION CMAKE_CONFIG_INSTALL_DESTINATION HEADER_INSTALL_DESTINATION
BIN_INSTALL_DESTINATION LIB_INSTALL_DESTINATION META_DATA_DIR)
endforeach ()
list(APPEND CMAKE_CONFIG_FILES
"${CMAKE_CURRENT_BINARY_DIR}/${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}ConfigVersion.cmake")
# write the CMake version config file
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}ConfigVersion.cmake
VERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}"
COMPATIBILITY SameMajorVersion)
# compute dependencies for pkg-config file
macro (compute_dependencies_for_package_config DEPENDS OUTPUT_VAR_PKGS OUTPUT_VAR_LIBS UNSET)
if (UNSET)
unset(${OUTPUT_VAR_PKGS})
unset(${OUTPUT_VAR_LIBS})
endif ()
foreach (DEPENDENCY ${${DEPENDS}})
if ("${DEPENDENCY}" STREQUAL "general")
continue()
endif ()
# handle use of generator expressions (use BUILD_INTERFACE; ignore INSTALL_INTERFACE)
if ("${DEPENDENCY}" MATCHES "\\\$\\<BUILD_INTERFACE:(.*)\\>")
set(DEPENDENCY "${CMAKE_MATCH_1}")
elseif ("${DEPENDENCY}" MATCHES "\\\$\\<INSTALL_INTERFACE:(.*)\\>")
continue()
endif ()
# find the name of the pkg-config package for the dependency
string(REPLACE "::" "_" DEPENDENCY_VARNAME "${DEPENDENCY}")
if (PKG_CONFIG_${DEPENDENCY_VARNAME})
# add pkg-config modules for the dependency
foreach (PKG_CONFIG_MODULE ${PKG_CONFIG_${DEPENDENCY_VARNAME}})
set(${OUTPUT_VAR_PKGS} "${${OUTPUT_VAR_PKGS}} ${PKG_CONFIG_MODULE}")
endforeach ()
elseif (TARGET "${DEPENDENCY}")
# find the raw-library flags for the dependency add interface link libraries of the target
get_target_property("${DEPENDENCY_VARNAME}_TARGET_TYPE" "${DEPENDENCY}" TYPE)
get_target_property("${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES" "${DEPENDENCY}" "INTERFACE_LINK_LIBRARIES")
set(${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES_EXISTING FALSE)
set(${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES_TARGETS)
foreach (LIBRARY ${${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES})
if (TARGET ${LIBRARY})
list(APPEND ${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES_TARGETS ${LIBRARY})
set(${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES_EXISTING TRUE)
elseif (EXISTS ${LIBRARY})
set(${OUTPUT_VAR_LIBS} "${${OUTPUT_VAR_LIBS}} ${LIBRARY}")
set(${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES_EXISTING TRUE)
endif ()
endforeach ()
compute_dependencies_for_package_config("${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES_TARGETS"
"${OUTPUT_VAR_PKGS}" "${OUTPUT_VAR_LIBS}" NO)
# skip further processing if it is an interface library target
if (${DEPENDENCY_VARNAME}_INTERFACE_LINK_LIBRARIES_EXISTING OR "${${DEPENDENCY_VARNAME}_TARGET_TYPE}" STREQUAL
"INTERFACE_LIBRARY")
continue()
endif ()
# add library location of the target
set(HAS_LIBRARY_LOCATION NO)
if (DEPENDENCY IN_LIST BUNDLED_TARGETS)
# bundled targets are installed at the same location and using the same flags as the actual library so adding
# the library name itself is sufficient
set(${OUTPUT_VAR_LIBS} "${${OUTPUT_VAR_LIBS}} -l${DEPENDENCY}")
set(HAS_LIBRARY_LOCATION YES)
endif ()
if (NOT HAS_LIBRARY_LOCATION AND META_CURRENT_CONFIGURATION)
get_target_property("${DEPENDENCY_VARNAME}_IMPORTED_LOCATION_${META_CURRENT_CONFIGURATION}" "${DEPENDENCY}"
"IMPORTED_LOCATION_${META_CURRENT_CONFIGURATION}")
# check whether path points to the build directory; libraries must not be referenced using their build
# location
string(FIND "${${DEPENDENCY_VARNAME}_IMPORTED_LOCATION_${META_CURRENT_CONFIGURATION}}"
"${CMAKE_CURRENT_BINARY_DIR}" BINARY_DIR_INDEX)
if (NOT BINARY_DIR_INDEX EQUAL 0
AND EXISTS "${${DEPENDENCY_VARNAME}_IMPORTED_LOCATION_${META_CURRENT_CONFIGURATION}}")
set(${OUTPUT_VAR_LIBS}
"${${OUTPUT_VAR_LIBS}} ${${DEPENDENCY_VARNAME}_IMPORTED_LOCATION_${META_CURRENT_CONFIGURATION}}")
set(HAS_LIBRARY_LOCATION YES)
endif ()
endif ()
if (NOT HAS_LIBRARY_LOCATION)
get_target_property("${DEPENDENCY_VARNAME}_IMPORTED_LOCATION" "${DEPENDENCY}" IMPORTED_LOCATION)
# check whether path points to the build directory; libraries must not be referenced using their build
# location
string(FIND "${${DEPENDENCY_VARNAME}_IMPORTED_LOCATION}" "${CMAKE_CURRENT_BINARY_DIR}" BINARY_DIR_INDEX)
if (NOT BINARY_DIR_INDEX EQUAL 0 AND EXISTS "${${DEPENDENCY_VARNAME}_IMPORTED_LOCATION}")
set(${OUTPUT_VAR_LIBS} "${${OUTPUT_VAR_LIBS}} ${${DEPENDENCY_VARNAME}_IMPORTED_LOCATION}")
set(HAS_LIBRARY_LOCATION YES)
endif ()
endif ()
# assume the target is a 3rd party library built within the current project as a bundled dependency -> the target
# is supposed to be installed in either a standard search directory or the same directory as this library so a
# simple -l flag should be sufficient
if (NOT HAS_LIBRARY_LOCATION)
set(${OUTPUT_VAR_LIBS} "${${OUTPUT_VAR_LIBS}} -l${DEPENDENCY}")
endif ()
# add libraries required by the imported target
get_target_property("${DEPENDENCY_VARNAME}_IMPORTED_LINK_INTERFACE_LIBRARIES" "${DEPENDENCY}"
"IMPORTED_LINK_INTERFACE_LIBRARIES")
compute_dependencies_for_package_config("${DEPENDENCY_VARNAME}_IMPORTED_LINK_INTERFACE_LIBRARIES"
"${OUTPUT_VAR_PKGS}" "${OUTPUT_VAR_LIBS}" NO)
else ()
# add raw dependency
if (DEPENDENCY MATCHES ".*/.*")
set(${OUTPUT_VAR_LIBS} "${${OUTPUT_VAR_LIBS}} ${DEPENDENCY}")
else ()
set(${OUTPUT_VAR_LIBS} "${${OUTPUT_VAR_LIBS}} -l${DEPENDENCY}")
endif ()
endif ()
endforeach ()
endmacro ()
compute_dependencies_for_package_config(META_PUBLIC_LIB_DEPENDS META_PUBLIC_PC_PKGS META_PUBLIC_LIB_DEPENDS_FOR_PC YES)
compute_dependencies_for_package_config(META_PRIVATE_LIB_DEPENDS META_PRIVATE_PC_PKGS META_PRIVATE_LIB_DEPENDS_FOR_PC YES)
if (NOT META_HEADER_ONLY_LIB)
string(REGEX REPLACE "^lib" "" META_TARGET_NAME_FOR_PC "${META_TARGET_NAME}")
set(META_PUBLIC_LIB_DEPENDS_FOR_PC
" -l${META_TARGET_NAME_FOR_PC}${TARGET_SUFFIX_FOR_PC}${META_PUBLIC_LIB_DEPENDS_FOR_PC}")
endif ()
if (META_PUBLIC_LIB_DEPENDS_FOR_PC)
set(META_PUBLIC_LIB_DEPENDS_FOR_PC " -L\${libdir}${META_PUBLIC_LIB_DEPENDS_FOR_PC}")
endif ()
# compute other values for pkg-config
set(META_PROJECT_NAME_FOR_PC "${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}")
foreach (COMPILE_DEFINITION ${META_PUBLIC_COMPILE_DEFINITIONS})
set(META_COMPILE_DEFINITIONS_FOR_PC "${META_COMPILE_DEFINITIONS_FOR_PC} -D${COMPILE_DEFINITION}")
endforeach ()
# create pkg-config file from template using previously computed values
find_template_file("template.pc" CPP_UTILITIES PKGCONFIG_TEMPLATE_FILE)
configure_file("${PKGCONFIG_TEMPLATE_FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${META_PROJECT_NAME_FOR_PC}.pc" @ONLY)
set(PC_FILES "${CMAKE_CURRENT_BINARY_DIR}/${META_PROJECT_NAME_FOR_PC}.pc")
# add install targets
if (NOT META_NO_INSTALL_TARGETS AND ENABLE_INSTALL_TARGETS)
# add install target for the CMake config files
install(
FILES ${CMAKE_CONFIG_FILES}
DESTINATION "${META_DATA_DIR}/cmake"
COMPONENT cmake-config)
if (NOT TARGET install-cmake-config)
add_custom_target(install-cmake-config COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cmake-config -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif ()
# add install target for pkg-config file
if (PC_FILES)
install(
FILES ${PC_FILES}
DESTINATION "${CMAKE_INSTALL_LIBDIR}${SELECTED_LIB_SUFFIX}/pkgconfig"
COMPONENT pkg-config)
endif ()
if (NOT TARGET install-pkg-config)
add_custom_target(install-pkg-config COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=pkg-config -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif ()
# add install target for libs
if (NOT TARGET install-binary)
add_custom_target(install-binary COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=binary -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif ()
# add install target for stripped libs
if (NOT TARGET install-binary-strip)
add_custom_target(
install-binary-strip COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_DO_STRIP=1 -DCMAKE_INSTALL_COMPONENT=binary -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif ()
# determine install dir for Qt plugins
if ("${META_PROJECT_TYPE}" STREQUAL "qtplugin")
if (QT_PLUGIN_DIR)
set(LIBRARY_DESTINATION "${QT_PLUGIN_DIR}")
else ()
if (COMMAND query_qmake_variable_path)
query_qmake_variable_path(QT_INSTALL_PLUGINS)
elseif (COMMAND query_qmake_variable)
query_qmake_variable(QT_INSTALL_PLUGINS)
endif ()
if (QT_INSTALL_PLUGINS)
string(FIND "${QT_INSTALL_PLUGINS}" "${CMAKE_INSTALL_PREFIX}"
CMAKE_INSTALL_PREFIX_INDEX_IN_QT_INSTALL_PLUGINS)
if ("${CMAKE_INSTALL_PREFIX_INDEX_IN_QT_INSTALL_PLUGINS}" EQUAL 0)
set(LIBRARY_DESTINATION ${QT_INSTALL_PLUGINS})
else ()
message(
WARNING
"According to qmake the Qt plugin directory is \"${QT_INSTALL_PLUGINS}\". However, that path is not within the install prefix \"${CMAKE_INSTALL_PREFIX}\" and therefore ignored."
)
endif ()
endif ()
if (NOT LIBRARY_DESTINATION)
set(LIBRARY_DESTINATION ${CMAKE_INSTALL_LIBDIR}${SELECTED_LIB_SUFFIX}/qt/plugins)
message(
WARNING
"Unable to detect appropriate install directory for Qt plugins (assuming \"${LIBRARY_DESTINATION}\"). Set QT_PLUGIN_DIR to specify the directory to install Qt plugins to manually."
)
endif ()
endif ()
if (META_PLUGIN_CATEGORY)
set(LIBRARY_DESTINATION ${LIBRARY_DESTINATION}/${META_PLUGIN_CATEGORY})
endif ()
else ()
set(LIBRARY_DESTINATION ${CMAKE_INSTALL_LIBDIR}${SELECTED_LIB_SUFFIX})
endif ()
# add install targets and export targets
set(TARGETS_TO_EXPORT "${META_TARGET_NAME}")
foreach (BUNDLED_TARGET ${BUNDLED_TARGETS})
if (NOT ${BUNDLED_TARGET} IN_LIST LIBRARIES OR (NOT BUILD_SHARED_LIBS AND ${BUNDLED_TARGET} IN_LIST PRIVATE_LIBRARIES
))
list(APPEND TARGETS_TO_EXPORT ${BUNDLED_TARGET})
endif ()
endforeach ()
if (NOT META_HEADER_ONLY_LIB AND NOT META_PLUGIN_CATEGORY)
list(APPEND TARGETS_TO_EXPORT "${META_TARGET_NAME}-headers")
endif ()
install(
TARGETS ${TARGETS_TO_EXPORT}
EXPORT "${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}Targets"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT binary
LIBRARY DESTINATION ${LIBRARY_DESTINATION} COMPONENT binary
ARCHIVE DESTINATION ${LIBRARY_DESTINATION} COMPONENT binary)
add_dependencies(install-binary "${META_TARGET_NAME}")
add_dependencies(install-binary-strip "${META_TARGET_NAME}")
install(
EXPORT ${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}Targets
DESTINATION "${META_DATA_DIR}/cmake"
EXPORT_LINK_INTERFACE_LIBRARIES
COMPONENT cmake-config)
# allow checking for the export in subsequent sibling projects/directories
get_directory_property(HAS_PARENT_DIRECTORY PARENT_DIRECTORY)
if (HAS_PARENT_DIRECTORY)
set("EXPORT_${NAMESPACE_PREFIX}${META_PROJECT_NAME}${META_CONFIG_SUFFIX}"
ON
PARENT_SCOPE)
endif ()
# add install target for header files
if (NOT META_IS_PLUGIN)
foreach (HEADER_FILE ${HEADER_FILES} ${ADDITIONAL_HEADER_FILES})
get_filename_component(HEADER_DIR "${HEADER_FILE}" DIRECTORY)
string(FIND "${HEADER_DIR}" "${META_PROJECT_NAME}/" HEADER_DIR_PRO)
if (HEADER_DIR STREQUAL META_PROJECT_NAME)
unset(HEADER_DIR)
elseif (HEADER_DIR_PRO EQUAL 0)
string(LENGTH "${META_PROJECT_NAME}/" HEADER_DIR_BEGIN)
string(SUBSTRING "${HEADER_DIR}" "${HEADER_DIR_BEGIN}" -1 HEADER_DIR)
endif ()
install(
FILES "${HEADER_FILE}"
DESTINATION "${INCLUDE_SUBDIR}/${META_PROJECT_NAME}/${HEADER_DIR}"
COMPONENT header)
endforeach ()
install(
FILES "${VERSION_HEADER_FILE}"
DESTINATION "${INCLUDE_SUBDIR}/${META_PROJECT_NAME}"
COMPONENT header)
install(
FILES "${TARGET_DEFINITIONS_HEADER}"
DESTINATION "${INCLUDE_SUBDIR}/${META_PROJECT_NAME}"
COMPONENT header)
if (NOT TARGET install-header)
add_custom_target(install-header COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=header -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif ()
endif ()
# add install target for CMake modules
foreach (CMAKE_MODULE_FILE ${CMAKE_MODULE_FILES})
get_filename_component(CMAKE_MODULE_DIR ${CMAKE_MODULE_FILE} DIRECTORY)
install(
FILES ${CMAKE_MODULE_FILE}
DESTINATION ${META_DATA_DIR}/${CMAKE_MODULE_DIR}
COMPONENT cmake-modules)
endforeach ()
if (NOT TARGET install-cmake-modules)
add_custom_target(install-cmake-modules COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cmake-modules -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif ()
# add install target for CMake templates
foreach (CMAKE_TEMPLATE_FILE ${CMAKE_TEMPLATE_FILES})
get_filename_component(CMAKE_TEMPLATE_DIR ${CMAKE_TEMPLATE_FILE} DIRECTORY)
install(
FILES ${CMAKE_TEMPLATE_FILE}
DESTINATION ${META_DATA_DIR}/${CMAKE_TEMPLATE_DIR}
COMPONENT cmake-templates)
endforeach ()
if (NOT TARGET install-cmake-templates)
add_custom_target(install-cmake-templates COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cmake-templates -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif ()
# add install target for all the cmake stuff
if (NOT TARGET install-cmake-stuff)
add_custom_target(install-cmake-stuff)
add_dependencies(install-cmake-stuff install-cmake-config install-cmake-modules install-cmake-templates)
endif ()
# add targets to ease creating mingw-w64 packages under Arch Linux
if (MINGW)
option(ENABLE_TARGETS_FOR_MINGW_CROSS_PACKAGING
"enable targets to ease creating mingw-w64 packages under Arch Linux" OFF)
else ()
set(ENABLE_TARGETS_FOR_MINGW_CROSS_PACKAGING OFF)
endif ()
if (ENABLE_TARGETS_FOR_MINGW64_CROSS_PACKAGING)
if (NOT TARGET install-mingw-w64)
add_custom_target(install-mingw-w64)
endif ()
add_dependencies(install-mingw-w64 install-binary install-header install-cmake-stuff install-pkg-config)
if (NOT TARGET install-mingw-w64-strip)
add_custom_target(install-mingw-w64-strip)
endif ()
add_dependencies(install-mingw-w64-strip install-binary-strip install-header install-cmake-stuff install-pkg-config)
if (LOCALIZATION_TARGET)
add_dependencies(install-mingw-w64 ${LOCALIZATION_TARGET})
add_dependencies(install-mingw-w64-strip ${LOCALIZATION_TARGET})
endif ()
find_program(STRIP_BINARY_PATH strip ONLY_CMAKE_FIND_ROOT_PATH)
if (NOT CMAKE_STRIP)
set(STRIP_BINARY_PATH "${CMAKE_STRIP}")
endif ()
if (NOT STRIP_BINARY_PATH)
set(STRIP_BINARY_PATH "$ENV{STRIP}")
endif ()
if (NOT STRIP_BINARY_PATH)
message(FATAL_ERROR "Unable to find strip. Please set ${STRIP_BINARY_PATH}.")
else ()
message(STATUS "Using strip binary under \"${STRIP_BINARY_PATH}\".")
endif ()
if (NOT META_HEADER_ONLY_LIB AND NOT META_IS_PLUGIN)
if (CMAKE_GENERATOR STREQUAL "Ninja")
set(DESTDIR "\$\$\{DESTDIR\}\$\$\{DESTDIR:+/\}")
else ()
set(DESTDIR "\$\{DESTDIR\}\$\{DESTDIR:+/\}")
endif ()
add_custom_target(
install-${META_TARGET_NAME}-mingw-w64-linker-file-strip
COMMAND
"${STRIP_BINARY_PATH}" -g
"${DESTDIR}${CMAKE_INSTALL_FULL_LIBDIR}${SELECTED_LIB_SUFFIX}/$<TARGET_LINKER_FILE_NAME:${META_TARGET_NAME}>"
)
add_dependencies(install-${META_TARGET_NAME}-mingw-w64-linker-file-strip install-binary-strip)
add_dependencies(install-mingw-w64-strip install-${META_TARGET_NAME}-mingw-w64-linker-file-strip)
endif ()
endif ()
endif ()
set(TARGET_CONFIG_DONE YES)
|