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 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792
|
#################################################
# ign_find_package(<PACKAGE_NAME>
# [REQUIRED] [PRIVATE] [EXACT] [QUIET] [BUILD_ONLY] [PKGCONFIG_IGNORE]
# [COMPONENTS <components_of_PACKAGE_NAME>]
# [OPTIONAL_COMPONENTS <components_of_PACKAGE_NAME>]
# [REQUIRED_BY <components_of_project>]
# [PRIVATE_FOR <components_of_project>]
# [VERSION <ver>]
# [EXTRA_ARGS <args>]
# [PRETTY <name>]
# [PURPOSE <"explanation for this dependency">]
# [PKGCONFIG <pkgconfig_name>]
# [PKGCONFIG_LIB <lib_name>]
# [PKGCONFIG_VER_COMPARISON < > = <= >= ])
#
# This is a wrapper for the standard cmake find_package which behaves according
# to the conventions of the ignition library. In particular, we do not quit
# immediately when a required package is missing. Instead, we check all
# dependencies and provide an overview of what is missing at the end of the
# configuration process. Descriptions of the function arguments are as follows:
#
# <PACKAGE_NAME>: The name of the package as it would normally be passed to
# find_package(~). Note if your package corresponds to a
# find-module named FindABC.cmake, then <PACKAGE_NAME> must be
# ABC, with the case matching. If the find-module is named
# FindAbc.cmake, then <PACKAGE_NAME> must be Abc. This will not
# necessarily match the library's actual name, nor will it
# necessarily match the name used by pkgconfig, so there are
# additional arguments (i.e. PRETTY, PKGCONFIG) to specify
# alternative names for this package that can be used depending
# on the context.
#
# [REQUIRED]: Optional. If provided, macro will trigger an ignition build_error
# when the package cannot be found. If not provided, this macro will
# trigger an ignition build_warning when the package is not found.
# To specify that something is required by some set of components
# (rather than the core library), use REQUIRED_BY.
#
# [PRIVATE]: Optional. Use this to indicate that consumers of the project do not
# need to link against the package, but it must be present on the
# system, because our project must link against it.
#
# [EXACT]: Optional. This will pass on the EXACT option to find_package(~) and
# also add it to the call to find_dependency(~) in the
# <project>-config.cmake file.
#
# [QUIET]: Optional. If provided, it will be passed forward to cmake's
# find_package(~) command. This macro will still print its normal
# output, except there will be no warning if the package is missing,
# unless REQUIRED or REQUIRED_BY is specified.
#
# [BUILD_ONLY]: Optional. Use this to indicate that the project only needs this
# package while building, and it does not need to be available to
# the consumer of this project at all. Normally this should only
# apply to (1) a header-only library whose headers are included
# exclusively in the source files and not included in any public
# (i.e. installed) project headers, or to (2) a static library
# dependency.
#
# [PKGCONFIG_IGNORE]: Discouraged. If this option is provided, this package will
# not be added to the project's pkgconfig file in any way.
# This should only be used in very rare circumstances. Note
# that BUILD_ONLY will also prevent a pkgconfig entry from
# being produced.
#
# [COMPONENTS]: Optional. If provided, the list that follows it will be passed
# to find_package(~) to indicate which components of PACKAGE_NAME
# are considered to be dependencies of either this project
# (specified by REQUIRED) or this project's components (specified
# by REQUIRED_BY). This is effectively the same as the
# find_package( ... COMPONENTS <components>) argument.
#
# [REQUIRED_BY]: Optional. If provided, the list that follows it must indicate
# which library components require the dependency. Note that if
# REQUIRED is specified, then REQUIRED_BY does NOT need to be
# specified for any components which depend on the core library,
# because their dependence on this package will effectively be
# inherited from the core library. This will trigger a build
# warning to tell the user which component requires this
# dependency.
#
# [PRIVATE_FOR]: Optional. If provided, the list that follows it must indicate
# which library components depend on this package privately (i.e.
# the package should not be included in its list of interface
# libraries). This is only relevant for components that follow
# the REQUIRED_BY command. Note that the PRIVATE argument does
# not apply to components specified by REQUIRED_BY. This argument
# MUST be given for components whose private dependencies have
# been specified with REQUIRED_BY.
#
# [VERSION]: Optional. Follow this argument with the major[.minor[.patch[.tweak]]]
# version that you need for this package.
#
# [EXTRA_ARGS]: Optional. Additional args to pass forward to find_package(~)
#
# [PRETTY]: Optional. If provided, the string that follows will replace
# <PACKAGE_NAME> when printing messages, warnings, or errors to the
# terminal.
#
# [PURPOSE]: Optional. If provided, the string that follows will be appended to
# the build_warning or build_error that this function produces when
# the package could not be found.
#
# ==========================================================================
# The following arguments pertain to the automatic generation of your
# project's pkgconfig file. Ideally, this information should be provided
# automatically by ignition-cmake through the cmake find-module that is written
# for your dependency. However, if your package gets distributed with its own
# cmake config-file or find-module, then it might not automatically set this
# information. Therefore, we provide the ability to set it through your call to
# ign_find_package(~). These arguments can also be used to overwrite the
# pkg-config entries that get generated by the ign-cmake find-module for the
# package. Do not hesitate to ask for help if you need to use these arguments.
#
# [PKGCONFIG]: Optional. If provided, the string that follows will be used to
# specify a "required package" for pkgconfig. Note that the option
# PKGCONFIG_LIB has higher precedence than this option.
#
# [PKGCONFIG_LIB]: Optional. Use this to indicate that the package should be
# considered a "library" by pkgconfig. This is used for
# libraries which do not come with *.pc metadata, such as
# system libraries, libm, libdl, or librt. Generally you should
# leave this out, because most packages will be considered
# "modules" by pkgconfig. The string which follows this
# argument will be used as the library name, and the string
# that follows a PKGCONFIG argument will be ignored, so the
# PKGCONFIG argument can be left out when using this argument.
#
# [PKGCONFIG_VER_COMPARISON]: Optional. If provided, pkgconfig will be told how
# the available version of this package must compare
# to the specified version. Acceptable values are
# =, <, >, <=, >=. Default will be =. If no version
# is provided using VERSION, then this will be left
# out, whether or not it is provided.
#
macro(ign_find_package PACKAGE_NAME)
#------------------------------------
# Define the expected arguments
set(options REQUIRED PRIVATE EXACT QUIET BUILD_ONLY PKGCONFIG_IGNORE)
set(oneValueArgs VERSION PRETTY PURPOSE EXTRA_ARGS PKGCONFIG PKGCONFIG_LIB PKGCONFIG_VER_COMPARISON)
set(multiValueArgs REQUIRED_BY PRIVATE_FOR COMPONENTS OPTIONAL_COMPONENTS)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_find_package "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#------------------------------------
# Construct the arguments to pass to find_package
set(${PACKAGE_NAME}_find_package_args ${PACKAGE_NAME})
if(ign_find_package_VERSION)
list(APPEND ${PACKAGE_NAME}_find_package_args ${ign_find_package_VERSION})
endif()
if(ign_find_package_QUIET)
list(APPEND ${PACKAGE_NAME}_find_package_args QUIET)
endif()
if(ign_find_package_EXACT)
list(APPEND ${PACKAGE_NAME}_find_package_args EXACT)
endif()
if(ign_find_package_COMPONENTS)
list(APPEND ${PACKAGE_NAME}_find_package_args COMPONENTS ${ign_find_package_COMPONENTS})
endif()
if(ign_find_package_OPTIONAL_COMPONENTS)
list(APPEND ${PACKAGE_NAME}_find_package_args OPTIONAL_COMPONENTS ${ign_find_package_OPTIONAL_COMPONENTS})
endif()
if(ign_find_package_EXTRA_ARGS)
list(APPEND ${PACKAGE_NAME}_find_package_args ${ign_find_package_EXTRA_ARGS})
endif()
#------------------------------------
# Figure out which name to print
if(ign_find_package_PRETTY)
set(${PACKAGE_NAME}_pretty ${ign_find_package_PRETTY})
else()
set(${PACKAGE_NAME}_pretty ${PACKAGE_NAME})
endif()
#------------------------------------
# Call find_package with the provided arguments
find_package(${${PACKAGE_NAME}_find_package_args})
if(${PACKAGE_NAME}_FOUND)
message(STATUS "Looking for ${${PACKAGE_NAME}_pretty} - found\n")
else()
message(STATUS "Looking for ${${PACKAGE_NAME}_pretty} - not found\n")
#------------------------------------
# Construct the warning/error message to produce
set(${PACKAGE_NAME}_msg "Missing dependency [${${PACKAGE_NAME}_pretty}]")
if(ign_find_package_COMPONENTS)
ign_list_to_string(comp_str ign_find_package_COMPONENTS DELIM ", ")
set(${PACKAGE_NAME}_msg "${${PACKAGE_NAME}_msg} (Components: ${comp_str})")
endif()
if(DEFINED ign_find_package_PURPOSE)
set(${PACKAGE_NAME}_msg "${${PACKAGE_NAME}_msg} - ${ign_find_package_PURPOSE}")
endif()
#------------------------------------
# If the package is unavailable, tell the user.
if(ign_find_package_REQUIRED)
# If it was required by the project, we will create an error.
ign_build_error(${${PACKAGE_NAME}_msg})
elseif(ign_find_package_REQUIRED_BY)
foreach(component ${ign_find_package_REQUIRED_BY})
if(NOT SKIP_${component})
# Otherwise, if it was only required by some of the components, create
# a warning about which components will not be available, unless the
# user explicitly requested that it be skipped
ign_build_warning("Skipping component [${component}]: ${${PACKAGE_NAME}_msg}.\n ^~~~~ Set SKIP_${component}=true in cmake to suppress this warning.\n ")
# Create a variable to indicate that we need to skip the component
set(INTERNAL_SKIP_${component} true)
# Track the missing dependencies
ign_string_append(${component}_MISSING_DEPS "${${PACKAGE_NAME}_pretty}" DELIM ", ")
endif()
endforeach()
else()
if(NOT ign_find_package_QUIET)
ign_build_warning(${${PACKAGE_NAME}_msg})
endif()
endif()
endif()
#------------------------------------
# Add this package to the list of dependencies that will be inserted into the
# find-config file, unless the invoker specifies that it should not be added.
# Also, add this package or library as an entry to the pkgconfig file that we
# will produce for our project.
if( ${PACKAGE_NAME}_FOUND
AND (ign_find_package_REQUIRED OR ign_find_package_REQUIRED_BY)
AND NOT ign_find_package_BUILD_ONLY)
# Set up the arguments we want to pass to the find_dependency invokation for
# our ignition project. We always need to pass the name of the dependency.
#
# NOTE: We escape the dollar signs because we want those variable
# evaluations to be a part of the string that we produce. It is going
# to be put into a *-config.cmake file. Those variables determine
# whether the find_package(~) call will be REQUIRED and/or QUIET.
#
# TODO: When we migrate to cmake-3.9+, this can be removed because calling
# find_dependency(~) will automatically forward these properties.
set(${PACKAGE_NAME}_dependency_args "${PACKAGE_NAME}")
# If a version is provided here, we should pass that as well.
if(ign_find_package_VERSION)
ign_string_append(${PACKAGE_NAME}_dependency_args ${ign_find_package_VERSION})
endif()
# If we have specified the exact version, we should provide that as well.
if(ign_find_package_EXACT)
ign_string_append(${PACKAGE_NAME}_dependency_args EXACT)
endif()
# NOTE (MXG): 7 seems to be the number of escapes required to get
# "${ign_package_required}" and "${ign_package_quiet}" to show up correctly
# as strings in the final config-file outputs. It is unclear to me why the
# escapes get collapsed exactly three times, so it is possible that any
# changes to this script could cause a different number of escapes to be
# necessary. Please use caution when modifying this script.
ign_string_append(${PACKAGE_NAME}_dependency_args "\\\\\\\${ign_package_quiet} \\\\\\\${ign_package_required}")
# If we have specified components of the dependency, mention those.
if(ign_find_package_COMPONENTS)
ign_string_append(${PACKAGE_NAME}_dependency_args "COMPONENTS ${ign_find_package_COMPONENTS}")
endif()
# If there are any additional arguments for the find_package(~) command,
# forward them along.
if(ign_find_package_EXTRA_ARGS)
ign_string_append(${PACKAGE_NAME}_dependency_args "${ign_find_package_EXTRA_ARGS}")
endif()
# TODO: When we migrate to cmake-3.9+ bring back find_dependency(~) because
# at that point it will be able to support COMPONENTS and EXTRA_ARGS
# set(${PACKAGE_NAME}_find_dependency "find_dependency(${${PACKAGE_NAME}_dependency_args})")
set(${PACKAGE_NAME}_find_dependency "find_package(${${PACKAGE_NAME}_dependency_args})")
if(ign_find_package_REQUIRED)
# If this is REQUIRED, add it to PROJECT_CMAKE_DEPENDENCIES
ign_string_append(PROJECT_CMAKE_DEPENDENCIES "${${PACKAGE_NAME}_find_dependency}" DELIM "\n")
endif()
if(ign_find_package_REQUIRED_BY)
# Identify which components are privately requiring this package
foreach(component ${ign_find_package_PRIVATE_FOR})
set(${component}_${PACKAGE_NAME}_PRIVATE true)
endforeach()
# If this is required by some components, add it to the
# ${component}_CMAKE_DEPENDENCIES variables that are specific to those
# componenets
foreach(component ${ign_find_package_REQUIRED_BY})
if(NOT ${component}_${PACKAGE_NAME}_PRIVATE)
ign_string_append(${component}_CMAKE_DEPENDENCIES "${${PACKAGE_NAME}_find_dependency}" DELIM "\n")
endif()
endforeach()
endif()
#------------------------------------
# Add this library or project to its relevant pkgconfig entry, unless we
# have been explicitly instructed to ignore it.
if(NOT ign_find_package_PKGCONFIG_IGNORE)
# Here we will set up the pkgconfig entry for this package. Ordinarily,
# these variables should be set by the ign-cmake custom find-module for
# the package which should use ign_pkg_check_modules[_quiet] or
# ign_pkg_config_library_entry. However, that will not be performed by
# third-party dependencies that provide their own find-module or their own
# cmake config-module. Therefore, we provide the option of specifying
# pkgconfig information through the call to ign_find_package. This also
# allows callers of ign_find_package(~) to overwrite the default
# pkg-config entry that gets generated by the ign-cmake find-modules.
# If the caller has specified the arguments PKGCONFIG_LIB or PKGCONFIG,
# then we will overwrite these pkgconfig variables with the information
# provided by the caller.
if(ign_find_package_PKGCONFIG_LIB)
# Libraries must be prepended with -l
set(${PACKAGE_NAME}_PKGCONFIG_ENTRY "-l${ign_find_package_PKGCONFIG_LIB}")
set(${PACKAGE_NAME}_PKGCONFIG_TYPE PKGCONFIG_LIBS)
elseif(ign_find_package_PKGCONFIG)
# Modules (a.k.a. packages) can just be specified by their package
# name without any prefixes like -l
set(${PACKAGE_NAME}_PKGCONFIG_ENTRY "${ign_find_package_PKGCONFIG}")
set(${PACKAGE_NAME}_PKGCONFIG_TYPE PKGCONFIG_REQUIRES)
# Add the version requirements to the entry.
if(ign_find_package_VERSION)
# Use equivalency by default
set(comparison "=")
# If the caller has specified a version comparison operator, use that
# instead of equivalency.
if(ign_find_package_PKGCONFIG_VER_COMPARISON)
set(comparison ${ign_find_package_PKGCONFIG_VER_COMPARISON})
endif()
# Append the comparison and the version onto the pkgconfig entry
set(${PACKAGE_NAME}_PKGCONFIG_ENTRY "${${PACKAGE_NAME}_PKGCONFIG_ENTRY} ${comparison} ${ign_find_package_VERSION}")
endif()
endif()
if(NOT ${PACKAGE_NAME}_PKGCONFIG_ENTRY)
# The find-module has not provided a default pkg-config entry for this
# package, and the caller of ign_find_package(~) has not explicitly
# provided pkg-config information. The caller has also not specified
# PKGCONFIG_IGNORE. This means that the requirements of this package
# will be unintentionally omitted from the auto-generated
# ignition-<project>.pc file. This is probably an oversight in our build
# system scripts, so we will emit a warning about this.
message(AUTHOR_WARNING
" -- THIS MESSAGE IS INTENDED FOR IGNITION-${IGN_DESIGNATION_UPPER} AUTHORS --\n"
" (IF YOU SEE THIS, PLEASE REPORT IT)\n"
"Could not find pkg-config information for ${PACKAGE_NAME}. "
"It was not provided by the find-module for the package, nor was it "
"explicitly passed into the call to ign_find_package(~). This is "
"most likely an error in this project's use of ign-cmake.")
else()
# We have pkg-config information for this package
if(ign_find_package_REQUIRED)
if(ign_find_package_PRIVATE)
# If this is a private library or module, use the _PRIVATE suffix
set(PROJECT_${PACKAGE_NAME}_PKGCONFIG_TYPE ${${PACKAGE_NAME}_PKGCONFIG_TYPE}_PRIVATE)
else()
# Otherwise, use the plain type
set(PROJECT_${PACKAGE_NAME}_PKGCONFIG_TYPE ${${PACKAGE_NAME}_PKGCONFIG_TYPE})
endif()
# Append the entry as a string onto the project-wide variable for
# whichever requirement type we selected
ign_string_append(PROJECT_${PROJECT_${PACKAGE_NAME}_PKGCONFIG_TYPE} ${${PACKAGE_NAME}_PKGCONFIG_ENTRY})
endif()
if(ign_find_package_REQUIRED_BY)
# For each of the components that requires this package, append its
# entry as a string onto the component-specific variable for whichever
# requirement type we selected
foreach(component ${ign_find_package_REQUIRED_BY})
if(${component}_${PACKAGE_NAME}_PRIVATE)
# If this is a private library or module, use the _PRIVATE suffix
set(${component}_${PACKAGE_NAME}_PKGCONFIG_TYPE ${component}_${${PACKAGE_NAME}_PKGCONFIG_TYPE}_PRIVATE)
else()
# Otherwise, use the plain type
set(${component}_${PACKAGE_NAME}_PKGCONFIG_TYPE ${component}_${${PACKAGE_NAME}_PKGCONFIG_TYPE})
endif()
# Append the entry as a string onto the component-specific variable
# for whichever required type we selected
ign_string_append(${${component}_${PACKAGE_NAME}_PKGCONFIG_TYPE} ${${PACKAGE_NAME}_PKGCONFIG_ENTRY})
endforeach()
endif()
endif()
endif()
endif()
endmacro()
#################################################
# ign_string_append(<output_var> <value_to_append> [DELIM <delimiter>])
#
# <output_var>: The name of the string variable that should be appended to
#
# <value_to_append>: The value that should be appended to the string
#
# [DELIM]: Specify a delimiter to separate the contents with. Default value is a
# space
#
# Macro to append a value to a string
macro(ign_string_append output_var val)
#------------------------------------
# Define the expected arguments
# NOTE: options cannot be set to PARENT_SCOPE alone, so we put it explicitly
# into cmake_parse_arguments(~). We use a semicolon to concatenate it with
# this options variable, so all other options should be specified here.
set(options)
set(oneValueArgs DELIM)
set(multiValueArgs) # We are not using multiValueArgs yet
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_string_append "PARENT_SCOPE;${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ign_string_append_DELIM)
set(delim "${ign_string_append_DELIM}")
else()
set(delim " ")
endif()
if( (NOT ${output_var}) OR (${output_var} STREQUAL "") )
# If ${output_var} is blank, just set it to equal ${val}
set(${output_var} "${val}")
else()
# If ${output_var} already has a value in it, append ${val} with the
# delimiter in-between.
set(${output_var} "${${output_var}}${delim}${val}")
endif()
if(ign_string_append_PARENT_SCOPE)
set(${output_var} "${${output_var}}" PARENT_SCOPE)
endif()
endmacro()
#################################################
# Macro to turn a list into a string
macro(ign_list_to_string _output _input_list)
set(${_output})
foreach(_item ${${_input_list}})
# Append each item, and forward any extra options to ign_string_append, such
# as DELIM or PARENT_SCOPE
ign_string_append(${_output} "${_item}" ${ARGN})
endforeach(_item)
endmacro()
#################################################
# ign_get_sources_and_unittests(<lib_srcs> <tests>)
#
# Grab all the files ending in "*.cc" from either the "src/" subdirectory or the
# current subdirectory if "src/" does not exist. They will be collated into
# library source files <lib_sources_var> and unittest source files <tests_var>.
#
# These output variables can be consumed directly by ign_create_core_library(~),
# ign_add_component(~), ign_build_tests(~), and ign_build_executables(~).
function(ign_get_libsources_and_unittests lib_sources_var tests_var)
# Glob all the source files
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/src)
# Prefer files in the src/ subdirectory
file(GLOB source_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "src/*.cc")
file(GLOB test_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "src/*_TEST.cc")
else()
# If src/ doesn't exist, then use the current directory
file(GLOB source_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "*.cc")
file(GLOB test_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "*_TEST.cc")
endif()
# Sort the files alphabetically
if(source_files)
list(SORT source_files)
endif()
if(test_files)
list(SORT test_files)
endif()
# Initialize the test list
set(tests)
# Remove the unit tests from the list of source files
foreach(test_file ${test_files})
# Remove from the source_files list.
list(REMOVE_ITEM source_files ${test_file})
# Append to the list of tests.
list(APPEND tests ${test_file})
endforeach()
# Return the lists that have been created.
set(${lib_sources_var} ${source_files} PARENT_SCOPE)
set(${tests_var} ${tests} PARENT_SCOPE)
endfunction()
#################################################
# ign_get_sources(<sources>)
#
# From the current directory, grab all the source files and place them into
# <sources>. Remove their paths to make them suitable for passing into
# ign_add_[library/tests].
function(ign_get_sources sources_var)
# GLOB all the source files
file(GLOB source_files "*.cc")
list(SORT source_files)
# Initialize this list
set(sources)
foreach(source_file ${source_files})
# Remove the path from the source file and append it the list of soures
get_filename_component(source ${source_file} NAME)
list(APPEND sources ${source})
endforeach()
# Return the list that has been created
set(${sources_var} ${sources} PARENT_SCOPE)
endfunction()
#################################################
# ign_install_all_headers(
# [EXCLUDE_FILES <excluded_headers>]
# [EXCLUDE_DIRS <dirs>]
# [GENERATED_HEADERS <headers>]
# [COMPONENT] <component>)
#
# From the current directory, install all header files, including files from all
# subdirectories (recursively). You can optionally specify directories or files
# to exclude from installation (the names must be provided relative to the current
# source directory).
#
# This will accept all files ending in *.h and *.hh. You may append an
# additional suffix (like .old or .backup) to prevent a file from being included.
#
# GENERATED_HEADERS should be generated headers which should be included by
# ${IGN_DESIGNATION}.hh. This will only add them to the header, it will not
# generate or install them.
#
# This will also run configure_file on ign_auto_headers.hh.in and config.hh.in
# and install them. This will NOT install any other files or directories that
# appear in the ${CMAKE_CURRENT_BINARY_DIR}.
#
# If the COMPONENT option is specified, this will skip over configuring a
# config.hh file since it would be redundant with the core library.
#
function(ign_install_all_headers)
#------------------------------------
# Define the expected arguments
set(options)
set(oneValueArgs COMPONENT) # We are not using oneValueArgs yet
set(multiValueArgs EXCLUDE_FILES EXCLUDE_DIRS GENERATED_HEADERS)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_install_all_headers "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
#------------------------------------
# Build the list of directories
file(GLOB_RECURSE all_files LIST_DIRECTORIES TRUE RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*")
list(SORT all_files)
set(directories)
foreach(f ${all_files})
# Check if this file is a directory
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${f})
# Check if it is in the list of excluded directories
list(FIND ign_install_all_headers_EXCLUDE_DIRS ${f} f_index)
set(append_file TRUE)
foreach(subdir ${ign_install_all_headers_EXCLUDE_DIRS})
# Check if ${f} contains ${subdir} as a substring
string(FIND ${f} ${subdir} pos)
# If ${subdir} is a substring of ${f} at the very first position, then
# we should not include anything from this directory. This makes sure
# that if a user specifies "EXCLUDE_DIRS foo" we will also exclude
# the directories "foo/bar/..." and so on. We will not, however, exclude
# a directory named "bar/foo/".
if(${pos} EQUAL 0)
set(append_file FALSE)
break()
endif()
endforeach()
if(append_file)
list(APPEND directories ${f})
endif()
endif()
endforeach()
# Append the current directory to the list
list(APPEND directories ".")
#------------------------------------
# Install all the non-excluded header directories along with all of their
# non-excluded headers
foreach(dir ${directories})
# GLOB all the header files in dir
file(GLOB headers RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/*.h" "${dir}/*.hh" "${dir}/*.hpp")
list(SORT headers)
# Remove the excluded headers
if(headers)
foreach(exclude ${ign_install_all_headers_EXCLUDE_FILES})
list(REMOVE_ITEM headers ${exclude})
endforeach()
endif()
# Add each header, prefixed by its directory, to the auto headers variable
foreach(header ${headers})
set(ign_headers "${ign_headers}#include <${PROJECT_INCLUDE_DIR}/${header}>\n")
endforeach()
if("." STREQUAL ${dir})
set(destination "${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR}")
else()
set(destination "${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR}/${dir}")
endif()
install(
FILES ${headers}
DESTINATION ${destination}
COMPONENT headers)
endforeach()
# Add generated headers to the list of includes
foreach(header ${ign_install_all_headers_GENERATED_HEADERS})
set(ign_headers "${ign_headers}#include <${PROJECT_INCLUDE_DIR}/${header}>\n")
endforeach()
if(ign_install_all_headers_COMPONENT)
set(component_name ${ign_install_all_headers_COMPONENT})
# Define the install directory for the component meta header
set(meta_header_install_dir ${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR}/${component_name})
# Define the input/output of the configuration for the component "master" header
set(master_header_in ${IGNITION_CMAKE_DIR}/ign_auto_headers.hh.in)
set(master_header_out ${CMAKE_CURRENT_BINARY_DIR}/${component_name}.hh)
else()
# Define the install directory for the core master meta header
set(meta_header_install_dir ${IGN_INCLUDE_INSTALL_DIR_FULL}/${PROJECT_INCLUDE_DIR})
# Define the input/output of the configuration for the core "master" header
set(master_header_in ${IGNITION_CMAKE_DIR}/ign_auto_headers.hh.in)
set(master_header_out ${CMAKE_CURRENT_BINARY_DIR}/../${IGN_DESIGNATION}.hh)
endif()
# Generate the "master" header that includes all of the headers
configure_file(${master_header_in} ${master_header_out})
# Install the "master" header
install(
FILES ${master_header_out}
DESTINATION ${meta_header_install_dir}/..
COMPONENT headers)
# Define the input/output of the configuration for the "config" header
set(config_header_in ${CMAKE_CURRENT_SOURCE_DIR}/config.hh.in)
set(config_header_out ${CMAKE_CURRENT_BINARY_DIR}/config.hh)
if(NOT ign_install_all_headers_COMPONENT)
# Produce an error if the config file is missing
#
# TODO: Maybe we should have a generic config.hh.in file that we fall back
# on if the project does not have one for itself?
if(NOT EXISTS ${config_header_in})
message(FATAL_ERROR
"Developer error: You are missing the file [${config_header_in}]! "
"Did you forget to move it from your project's cmake directory while "
"migrating to the use of ignition-cmake?")
endif()
# Generate the "config" header that describes our project configuration
configure_file(${config_header_in} ${config_header_out})
# Install the "config" header
install(
FILES ${config_header_out}
DESTINATION ${meta_header_install_dir}
COMPONENT headers)
endif()
endfunction()
#################################################
# ign_build_error macro
macro(ign_build_error)
foreach(str ${ARGN})
set(msg "\t${str}")
list(APPEND build_errors ${msg})
endforeach()
endmacro(ign_build_error)
#################################################
# ign_build_warning macro
macro(ign_build_warning)
foreach(str ${ARGN})
list(APPEND build_warnings "${str}")
endforeach(str ${ARGN})
endmacro(ign_build_warning)
#################################################
macro(ign_add_library lib_target_name)
message(FATAL_ERROR
"ign_add_library(<target_name> <sources>) is deprecated. Instead, use "
"ign_create_core_library(SOURCES <sources>). It will determine the library "
"target name automatically from the project name. To add a component "
"library, use ign_add_component(~). Be sure to pass the CXX_STANDARD "
"argument to these functions in order to set the C++ standard that they "
"require.")
ign_create_core_library(SOURCES ${ARGN})
endmacro()
#################################################
# _ign_check_known_cxx_standards(<11|14|17>)
#
# Creates a fatal error if the variable passed in does not represent a supported
# version of the C++ standard.
#
# NOTE: This function is meant for internal ign-cmake use
#
function(_ign_check_known_cxx_standards standard)
list(FIND IGN_KNOWN_CXX_STANDARDS ${standard} known)
if(${known} EQUAL -1)
message(FATAL_ERROR
"You have specified an unsupported standard: ${standard}. "
"Accepted values are: ${IGN_KNOWN_CXX_STANDARDS}.")
endif()
endfunction()
#################################################
# _ign_handle_cxx_standard(<function_prefix>
# <target_name>
# <pkgconfig_cflags_variable>)
#
# Handles the C++ standard argument for ign_create_core_library(~) and
# ign_add_component(~).
#
# NOTE: This is only meant for internal ign-cmake use.
#
macro(_ign_handle_cxx_standard prefix target pkgconfig_cflags)
if(${prefix}_CXX_STANDARD)
_ign_check_known_cxx_standards(${${prefix}_CXX_STANDARD})
endif()
if(${prefix}_PRIVATE_CXX_STANDARD)
_ign_check_known_cxx_standards(${${prefix}_PRIVATE_CXX_STANDARD})
endif()
if(${prefix}_INTERFACE_CXX_STANDARD)
_ign_check_known_cxx_standards(${${prefix}_INTERFACE_CXX_STANDARD})
endif()
if(${prefix}_CXX_STANDARD
AND (${prefix}_PRIVATE_CXX_STANDARD
OR ${prefix}_INTERFACE_CXX_STANDARD))
message(FATAL_ERROR
"If CXX_STANDARD has been specified, then you are not allowed to specify "
"PRIVATE_CXX_STANDARD or INTERFACE_CXX_STANDARD. Please choose to either "
"specify CXX_STANDARD alone, or else specify some combination of "
"PRIVATE_CXX_STANDARD and INTERFACE_CXX_STANDARD")
endif()
if(${prefix}_CXX_STANDARD)
set(${prefix}_INTERFACE_CXX_STANDARD ${${prefix}_CXX_STANDARD})
set(${prefix}_PRIVATE_CXX_STANDARD ${${prefix}_CXX_STANDARD})
endif()
if(${prefix}_INTERFACE_CXX_STANDARD)
target_compile_features(${target} INTERFACE ${IGN_CXX_${${prefix}_INTERFACE_CXX_STANDARD}_FEATURES})
ign_string_append(${pkgconfig_cflags} "-std=c++${${prefix}_INTERFACE_CXX_STANDARD}")
endif()
if(${prefix}_PRIVATE_CXX_STANDARD)
target_compile_features(${target} PRIVATE ${IGN_CXX_${${prefix}_PRIVATE_CXX_STANDARD}_FEATURES})
endif()
endmacro()
#################################################
# ign_create_core_library(SOURCES <sources>
# [CXX_STANDARD <11|14|17>]
# [PRIVATE_CXX_STANDARD <11|14|17>]
# [INTERFACE_CXX_STANDARD <11|14|17>]
# [GET_TARGET_NAME <output_var>]
# [LEGACY_PROJECT_PREFIX <prefix>])
#
# This function will produce the "core" library for your project. There is no
# need to specify a name for the library, because that will be determined by
# your project information.
#
# SOURCES: Required. Specify the source files that will be used to generate the
# library.
#
# [GET_TARGET_NAME]: Optional. The variable that follows this argument will be
# set to the library target name that gets produced by this
# function. The target name will always be
# ${PROJECT_LIBRARY_TARGET_NAME}.
#
# [LEGACY_PROJECT_PREFIX]: Optional. The variable that follows this argument will be
# used as a prefix for the legacy cmake config variables
# <prefix>_LIBRARIES and <prefix>_INCLUDE_DIRS.
#
# If you need a specific C++ standard, you must also specify it in this
# function in order to ensure that your library's target properties get set
# correctly. The following is a breakdown of your choices:
#
# [CXX_STANDARD]: This library must compile using the specified standard, and so
# must any libraries which link to it.
#
# [PRIVATE_CXX_STANDARD]: This library must compile using the specified standard,
# but libraries which link to it do not need to.
#
# [INTERFACE_CXX_STANDARD]: Any libraries which link to this library must compile
# with the specified standard.
#
# Most often, you will want to use CXX_STANDARD, but there may be cases in which
# you want a finer degree of control. If your library must compile with a
# different standard than what is required by dependent libraries, then you can
# specify both PRIVATE_CXX_STANDARD and INTERFACE_CXX_STANDARD without any
# conflict. However, both of those arguments conflict with CXX_STANDARD, so you
# are not allowed to use either of them if you use the CXX_STANDARD argument.
#
function(ign_create_core_library)
#------------------------------------
# Define the expected arguments
set(options INTERFACE)
set(oneValueArgs INCLUDE_SUBDIR LEGACY_PROJECT_PREFIX CXX_STANDARD PRIVATE_CXX_STANDARD INTERFACE_CXX_STANDARD GET_TARGET_NAME)
set(multiValueArgs SOURCES)
#------------------------------------
# Parse the arguments
cmake_parse_arguments(ign_create_core_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ign_create_core_library_SOURCES)
set(sources ${ign_create_core_library_SOURCES})
elseif(NOT ign_create_core_library_INTERFACE)
message(FATAL_ERROR "You must specify SOURCES for ign_create_core_library(~)!")
endif()
if(ign_create_core_library_INTERFACE)
set(interface_option INTERFACE)
set(property_type INTERFACE)
else()
set(interface_option) # Intentionally blank
set(property_type PUBLIC)
endif()
#------------------------------------
# Create the target for the core library, and configure it to be installed
_ign_add_library_or_component(
LIB_NAME ${PROJECT_LIBRARY_TARGET_NAME}
INCLUDE_DIR "${PROJECT_INCLUDE_DIR}"
EXPORT_BASE IGNITION_${IGN_DESIGNATION_UPPER}
SOURCES ${sources}
${interface_option})
# These generator expressions are necessary for multi-configuration generators
# such as MSVC on Windows. They also ensure that our target exports its
# headers correctly
target_include_directories(${PROJECT_LIBRARY_TARGET_NAME}
${property_type}
# This is the publicly installed headers directory.
"$<INSTALL_INTERFACE:${IGN_INCLUDE_INSTALL_DIR_FULL}>"
# This is the in-build version of the core library headers directory.
# Generated headers for the core library get placed here.
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>"
# Generated headers for the core library might also get placed here.
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/core/include>")
# We explicitly create these directories to avoid false-flag compiler warnings
file(MAKE_DIRECTORY
"${PROJECT_BINARY_DIR}/include"
"${PROJECT_BINARY_DIR}/core/include")
if(EXISTS "${PROJECT_SOURCE_DIR}/include")
target_include_directories(${PROJECT_LIBRARY_TARGET_NAME}
${property_type}
# This is the build directory version of the headers. When exporting the
# target, this will not be included, because it is tied to the build
# interface instead of the install interface.
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>")
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/core/include")
target_include_directories(${PROJECT_LIBRARY_TARGET_NAME}
${property_type}
# This is the include directories for projects that put the core library
# contents into its own subdirectory.
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/core/include>")
endif()
#------------------------------------
# Adjust variables if a specific C++ standard was requested
_ign_handle_cxx_standard(ign_create_core_library
${PROJECT_LIBRARY_TARGET_NAME} PROJECT_PKGCONFIG_CFLAGS)
#------------------------------------
# Handle cmake and pkgconfig packaging
if(ign_create_core_library_INTERFACE)
set(project_pkgconfig_core_lib) # Intentionally blank
else()
set(project_pkgconfig_core_lib "-l${PROJECT_NAME_LOWER}")
endif()
# Export and install the core library's cmake target and package information
_ign_create_cmake_package(LEGACY_PROJECT_PREFIX ${ign_create_core_library_LEGACY_PROJECT_PREFIX})
# Generate and install the core library's pkgconfig information
_ign_create_pkgconfig()
#------------------------------------
# Pass back the target name if they ask for it.
if(ign_create_core_library_GET_TARGET_NAME)
set(${ign_create_core_library_GET_TARGET_NAME} ${PROJECT_LIBRARY_TARGET_NAME} PARENT_SCOPE)
endif()
endfunction()
#################################################
# ign_add_component(<component>
# SOURCES <sources> | INTERFACE
# [DEPENDS_ON_COMPONENTS <components...>]
# [INCLUDE_SUBDIR <subdirectory_name>]
# [GET_TARGET_NAME <output_var>]
# [INDEPENDENT_FROM_PROJECT_LIB]
# [PRIVATELY_DEPENDS_ON_PROJECT_LIB]
# [INTERFACE_DEPENDS_ON_PROJECT_LIB]
# [CXX_STANDARD <11|14|17>]
# [PRIVATE_CXX_STANDARD <11|14|17>]
# [INTERFACE_CXX_STANDARD <11|14|17>])
#
# This function will produce a "component" library for your project. This is the
# recommended way to produce plugins or library modules.
#
# <component>: Required. Name of the component. The final name of this library
# and its target will be ignition-<project><major_ver>-<component>
#
# SOURCES: Required (unless INTERFACE is specified). Specify the source files
# that will be used to generate the library.
#
# INTERFACE: Indicate that this is an INTERFACE library which does not require
# any source files. This is required if SOURCES is not specified.
#
# [DEPENDS_ON_COMPONENTS]: Specify a list of other components of this package
# that this component depends on. This argument should
# be considered mandatory whenever there are
# inter-component dependencies in an ignition package.
#
# [INCLUDE_SUBDIR]: Optional. If specified, the public include headers for this
# component will go into "ignition/<project>/<subdirectory_name>/".
# If not specified, they will go into "ignition/<project>/<component>/"
#
# [GET_TARGET_NAME]: Optional. The variable that follows this argument will be
# set to the library target name that gets produced by this
# function. The target name will always be
# ${PROJECT_LIBRARY_TARGET_NAME}-<component>.
#
# [INDEPENDENT_FROM_PROJECT_LIB]:
# Optional. Specify this if you do NOT want this component to automatically
# be linked to the core library of this project. The default behavior is to
# be publically linked.
#
# [PRIVATELY_DEPENDS_ON_PROJECT_LIB]:
# Optional. Specify this if this component privately depends on the core
# library of this project (i.e. users of this component do not need to
# interface with the core library). The default behavior is to be publicly
# linked.
#
# [INTERFACE_DEPENDS_ON_PROJECT_LIB]:
# Optional. Specify this if the component's interface depends on the core
# library of this project (i.e. users of this component need to interface
# with the core library), but the component itself does not need to link to
# the core library.
#
# See the documentation of ign_create_core_library(~) for more information about
# specifying the C++ standard. If your component publicly depends on the core
# library, then you probably do not need to specify the standard, because it
# will get inherited from the core library.
function(ign_add_component component_name)
#------------------------------------
# Define the expected arguments
set(options INTERFACE INDEPENDENT_FROM_PROJECT_LIB PRIVATELY_DEPENDS_ON_PROJECT_LIB INTERFACE_DEPENDS_ON_PROJECT_LIB)
set(oneValueArgs INCLUDE_SUBDIR GET_TARGET_NAME)
set(multiValueArgs SOURCES DEPENDS_ON_COMPONENTS)
#------------------------------------
# Parse the arguments
cmake_parse_arguments(ign_add_component "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(POLICY CMP0079)
cmake_policy(SET CMP0079 NEW)
endif()
if(ign_add_component_SOURCES)
set(sources ${ign_add_component_SOURCES})
elseif(NOT ign_add_component_INTERFACE)
message(FATAL_ERROR "You must specify SOURCES for ign_add_component(~)!")
endif()
if(ign_add_component_INCLUDE_SUBDIR)
set(include_subdir ${ign_add_component_INCLUDE_SUBDIR})
else()
set(include_subdir ${component_name})
endif()
if(ign_add_component_INTERFACE)
set(interface_option INTERFACE)
set(property_type INTERFACE)
else()
set(interface_option) # Intentionally blank
set(property_type PUBLIC)
endif()
# Set the name of the component's target
set(component_target_name ${PROJECT_LIBRARY_TARGET_NAME}-${component_name})
# Pass the component's target name back to the caller if requested
if(ign_add_component_GET_TARGET_NAME)
set(${ign_add_component_GET_TARGET_NAME} ${component_target_name} PARENT_SCOPE)
endif()
# Create an upper case version of the component name, to be used as an export
# base name.
string(TOUPPER ${component_name} component_name_upper)
# hyphen is not supported as macro name, replace it by underscore
string(REPLACE "-" "_" component_name_upper ${component_name_upper})
#------------------------------------
# Create the target for this component, and configure it to be installed
_ign_add_library_or_component(
LIB_NAME ${component_target_name}
INCLUDE_DIR "${PROJECT_INCLUDE_DIR}/${include_subdir}"
EXPORT_BASE IGNITION_${IGN_DESIGNATION_UPPER}_${component_name_upper}
SOURCES ${sources}
${interface_option})
if(ign_add_component_INDEPENDENT_FROM_PROJECT_LIB OR
ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB)
# If we are not linking this component to the core library, then we need to
# add these include directories to this component library directly. This is
# not needed if we link to the core library, because that will pull in these
# include directories automatically.
target_include_directories(${component_target_name}
${property_type}
# This is the publicly installed ignition/math headers directory.
"$<INSTALL_INTERFACE:${IGN_INCLUDE_INSTALL_DIR_FULL}>"
# This is the in-build version of the core library's headers directory.
# Generated headers for this component might get placed here, even if
# the component is independent of the core library.
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>")
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/include")
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/${component_name}/include")
target_include_directories(${component_target_name}
${property_type}
# This is the in-source version of the component-specific headers
# directory. When exporting the target, this will not be included,
# because it is tied to the build interface instead of the install
# interface.
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/${component_name}/include>")
endif()
target_include_directories(${component_target_name}
${property_type}
# This is the in-build version of the component-specific headers
# directory. Generated headers for this component might end up here.
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/${component_name}/include>")
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/${component_name}/include")
#------------------------------------
# Adjust variables if a specific C++ standard was requested
_ign_handle_cxx_standard(ign_add_component
${component_target_name} ${component_name}_PKGCONFIG_CFLAGS)
#------------------------------------
# Adjust the packaging variables based on how this component depends (or not)
# on the core library.
if(ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB)
target_link_libraries(${component_target_name}
PRIVATE ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(ign_add_component_INTERFACE_DEPENDS_ON_PROJECT_LIB)
target_link_libraries(${component_target_name}
INTERFACE ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(NOT ign_add_component_INDEPENDENT_FROM_PROJECT_LIB AND
NOT ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB AND
NOT ign_add_component_INTERFACE_DEPENDS_ON_PROJECT_LIB)
target_link_libraries(${component_target_name}
${property_type} ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(NOT ign_add_component_INDEPENDENT_FROM_PROJECT_LIB)
# Add the core library as a cmake dependency for this component
# NOTE: It seems we need to triple-escape "${ign_package_required}" and
# "${ign_package_quiet}" here.
ign_string_append(${component_name}_CMAKE_DEPENDENCIES
"if(NOT ${PKG_NAME}_CONFIG_INCLUDED)\n find_package(${PKG_NAME} ${PROJECT_VERSION_FULL_NO_SUFFIX} EXACT \\\${ign_package_quiet} \\\${ign_package_required})\nendif()" DELIM "\n")
# Choose what type of pkgconfig entry the core library belongs to
set(lib_pkgconfig_type ${component_name}_PKGCONFIG_REQUIRES)
if(ign_add_component_PRIVATELY_DEPENDS_ON_PROJECT_LIB
AND NOT ign_add_component_INTERFACE_DEPENDS_ON_PROJECT_LIB)
set(lib_pkgconfig_type ${lib_pkgconfig_type}_PRIVATE)
endif()
ign_string_append(${lib_pkgconfig_type} "${PKG_NAME} = ${PROJECT_VERSION_FULL_NO_SUFFIX}")
endif()
if(ign_add_component_DEPENDS_ON_COMPONENTS)
ign_string_append(${component_name}_CMAKE_DEPENDENCIES
"find_package(${PKG_NAME} ${PROJECT_VERSION_FULL_NO_SUFFIX} EXACT \\\${ign_package_quiet} \\\${ign_package_required} COMPONENTS ${ign_add_component_DEPENDS_ON_COMPONENTS})" DELIM "\n")
endif()
#------------------------------------
# Set variables that are needed by cmake/ignition-component-config.cmake.in
set(component_pkg_name ${component_target_name})
if(ign_add_component_INTERFACE)
set(component_pkgconfig_lib)
else()
set(component_pkgconfig_lib "-l${component_pkg_name}")
endif()
set(component_cmake_dependencies ${${component_name}_CMAKE_DEPENDENCIES})
# This next set is redundant, but it serves as a reminder that this input
# variable is used in config files
set(component_name ${component_name})
# ... and by cmake/pkgconfig/ignition-component.pc.in
set(component_pkgconfig_requires ${${component_name}_PKGCONFIG_REQUIRES})
set(component_pkgconfig_requires_private ${${component_name}_PKGCONFIG_REQUIRES_PRIVATE})
set(component_pkgconfig_lib_deps ${${component_name}_PKGCONFIG_LIBS})
set(component_pkgconfig_lib_deps_private ${${component_name}_PKGCONFIG_LIBS_PRIVATE})
set(component_pkgconfig_cflags ${${component_name}_PKGCONFIG_CFLAGS})
# Export and install the cmake target and package information
_ign_create_cmake_package(COMPONENT ${component_name})
# Generate and install the pkgconfig information for this component
_ign_create_pkgconfig(COMPONENT ${component_name})
#------------------------------------
# Add this component to the "all" target
target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME}-all INTERFACE ${lib_name})
get_property(all_known_components TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS)
if(NOT all_known_components)
set_property(TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS "${component_target_name}")
else()
set_property(TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS "${all_known_components};${component_target_name}")
endif()
endfunction()
#################################################
function(ign_create_all_target)
add_library(${PROJECT_LIBRARY_TARGET_NAME}-all INTERFACE)
install(
TARGETS ${PROJECT_LIBRARY_TARGET_NAME}-all
EXPORT ${PROJECT_LIBRARY_TARGET_NAME}-all
LIBRARY DESTINATION ${IGN_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${IGN_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${IGN_BIN_INSTALL_DIR}
COMPONENT libraries)
endfunction()
#################################################
function(ign_export_target_all)
# find_all_pkg_components is used as a variable in ignition-all-config.cmake.in
set(find_all_pkg_components "")
get_property(all_known_components TARGET ${PROJECT_LIBRARY_TARGET_NAME}-all
PROPERTY INTERFACE_IGN_ALL_KNOWN_COMPONENTS)
if(all_known_components)
foreach(component ${all_known_components})
ign_string_append(find_all_pkg_components "find_dependency(${component} ${PROJECT_VERSION_FULL_NO_SUFFIX} EXACT)" DELIM "\n")
endforeach()
endif()
_ign_create_cmake_package(ALL)
endfunction()
#################################################
# Used internally by _ign_add_library_or_component to report argument errors
macro(_ign_add_library_or_component_arg_error missing_arg)
message(FATAL_ERROR "ignition-cmake developer error: Must specify "
"${missing_arg} to _ign_add_library_or_component!")
endmacro()
#################################################
# This is only meant for internal use by ignition-cmake. If you are a consumer
# of ignition-cmake, please use ign_create_core_library(~) or
# ign_add_component(~) instead of this.
#
# _ign_add_library_or_component(LIB_NAME <lib_name>
# INCLUDE_DIR <dir_name>
# EXPORT_BASE <export_base>
# SOURCES <sources>)
#
macro(_ign_add_library_or_component)
# NOTE: The following local variables are used in the Export.hh.in file, so if
# you change their names here, you must also change their names there:
# - include_dir
# - export_base
# - lib_name
#------------------------------------
# Define the expected arguments
set(options INTERFACE)
set(oneValueArgs LIB_NAME INCLUDE_DIR EXPORT_BASE)
set(multiValueArgs SOURCES)
#------------------------------------
# Parse the arguments
cmake_parse_arguments(_ign_add_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(_ign_add_library_LIB_NAME)
set(lib_name ${_ign_add_library_LIB_NAME})
else()
_ign_add_library_or_component_arg_error(LIB_NAME)
endif()
if(NOT _ign_add_library_INTERFACE)
if(_ign_add_library_SOURCES)
set(sources ${_ign_add_library_SOURCES})
else()
_ign_add_library_or_component_arg_error(SOURCES)
endif()
else()
set(sources)
endif()
if(_ign_add_library_INCLUDE_DIR)
set(include_dir ${_ign_add_library_INCLUDE_DIR})
else()
_ign_add_library_or_component_arg_error(INCLUDE_DIR)
endif()
if(_ign_add_library_EXPORT_BASE)
set(export_base ${_ign_add_library_EXPORT_BASE})
else()
_ign_add_library_or_component_arg_error(EXPORT_BASE)
endif()
# check that export_base has no invalid symbols
string(REPLACE "-" "_" export_base_replaced ${export_base})
if(NOT ${export_base} STREQUAL ${export_base_replaced})
message(FATAL_ERROR
"export_base has a hyphen which is not"
"supported by macros used for visibility")
endif()
#------------------------------------
# Create the library target
message(STATUS "Configuring library: ${lib_name}")
if(_ign_add_library_INTERFACE)
add_library(${lib_name} INTERFACE)
else()
add_library(${lib_name} ${sources})
endif()
#------------------------------------
# Add fPIC if we are supposed to
if(IGN_ADD_fPIC_TO_LIBRARIES AND NOT _ign_add_library_INTERFACE)
target_compile_options(${lib_name} PRIVATE -fPIC)
endif()
if(NOT _ign_add_library_INTERFACE)
#------------------------------------
# Generate export macro headers
# Note: INTERFACE libraries do not need the export header
set(binary_include_dir
"${CMAKE_BINARY_DIR}/include/${include_dir}")
set(implementation_file_name "${binary_include_dir}/detail/Export.hh")
include(GenerateExportHeader)
# This macro will generate a header called detail/Export.hh which implements
# some C-macros that are useful for exporting our libraries. The
# implementation header does not provide any commentary or explanation for its
# macros, so we tuck it away in the detail/ subdirectory, and then provide a
# public-facing header that provides commentary for the macros.
generate_export_header(${lib_name}
BASE_NAME ${export_base}
EXPORT_FILE_NAME ${implementation_file_name}
EXPORT_MACRO_NAME DETAIL_${export_base}_VISIBLE
NO_EXPORT_MACRO_NAME DETAIL_${export_base}_HIDDEN
DEPRECATED_MACRO_NAME IGN_DEPRECATED_ALL_VERSIONS)
set(install_include_dir
"${IGN_INCLUDE_INSTALL_DIR_FULL}/${include_dir}")
# Configure the installation of the automatically generated file.
install(
FILES "${implementation_file_name}"
DESTINATION "${install_include_dir}/detail"
COMPONENT headers)
# Configure the public-facing header for exporting and deprecating. This
# header provides commentary for the macros so that developers can know their
# purpose.
configure_file(
"${IGNITION_CMAKE_DIR}/Export.hh.in"
"${binary_include_dir}/Export.hh")
# Configure the installation of the public-facing header.
install(
FILES "${binary_include_dir}/Export.hh"
DESTINATION "${install_include_dir}"
COMPONENT headers)
set_target_properties(
${lib_name}
PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
VERSION ${PROJECT_VERSION_FULL})
endif()
#------------------------------------
# Configure the installation of the target
install(
TARGETS ${lib_name}
EXPORT ${lib_name}
LIBRARY DESTINATION ${IGN_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${IGN_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${IGN_BIN_INSTALL_DIR}
COMPONENT libraries)
endmacro()
#################################################
macro(ign_add_executable _name)
add_executable(${_name} ${ARGN})
target_link_libraries(${_name} ${general_libraries})
endmacro()
#################################################
# ign_target_interface_include_directories(<target> [include_targets])
#
# Add the INTERFACE_INCLUDE_DIRECTORIES of [include_targets] to the public
# INCLUDE_DIRECTORIES of <target>. This allows us to propagate the include
# directories of <target> along to any other libraries that depend on it.
#
# You MUST pass in targets to include, not directory names. We must not use
# explicit directory names here if we want our package to be relocatable.
function(ign_target_interface_include_directories name)
foreach(include_target ${ARGN})
target_include_directories(
${name} PUBLIC
$<TARGET_PROPERTY:${include_target},INTERFACE_INCLUDE_DIRECTORIES>)
endforeach()
endfunction()
#################################################
macro(ign_install_includes _subdir)
install(FILES ${ARGN}
DESTINATION ${IGN_INCLUDE_INSTALL_DIR}/${_subdir} COMPONENT headers)
endmacro()
#################################################
macro(ign_install_library)
message(FATAL_ERROR
"ign_install_library is deprecated. "
"Please remove it from your cmake script!")
endmacro()
#################################################
macro(ign_install_executable _name )
set_target_properties(${_name} PROPERTIES VERSION ${PROJECT_VERSION_FULL})
install (TARGETS ${_name} DESTINATION ${IGN_BIN_INSTALL_DIR})
manpage(${_name} 1)
endmacro()
#################################################
# Macro to setup supported compiler warnings
# Based on work of Florent Lamiraux, Thomas Moulard, JRL, CNRS/AIST.
macro(ign_filter_valid_compiler_options var)
include(CheckCXXCompilerFlag)
# Store the current setting for CMAKE_REQUIRED_QUIET
set(original_cmake_required_quiet ${CMAKE_REQUIRED_QUIET})
# Make these tests quiet so they don't pollute the cmake output
set(CMAKE_REQUIRED_QUIET true)
foreach(flag ${ARGN})
CHECK_CXX_COMPILER_FLAG(${flag} result${flag})
if(result${flag})
set(${var} "${${var}} ${flag}")
endif()
endforeach()
# Restore the old setting for CMAKE_REQUIRED_QUIET
set(CMAKE_REQUIRED_QUIET ${original_cmake_required_quiet})
endmacro()
#################################################
# ign_build_executables(SOURCES <sources>
# [PREFIX <prefix>]
# [LIB_DEPS <library_dependencies>]
# [INCLUDE_DIRS <include_dependencies>]
# [EXEC_LIST <output_var>]
# [EXCLUDE_PROJECT_LIB])
#
# Build executables for an ignition project. Arguments are as follows:
#
# SOURCES: Required. The names (without a path) of the source files for your
# executables.
#
# PREFIX: Optional. This will append <prefix> onto each executable name.
#
# LIB_DEPS: Optional. Additional library dependencies that every executable
# should link to, not including the library build by this project (it
# will be linked automatically, unless you pass in the
# EXCLUDE_PROJECT_LIB option).
#
# INCLUDE_DIRS: Optional. Additional include directories that should be visible
# to all of these executables.
#
# EXEC_LIST: Optional. Provide a variable which will be given the list of the
# names of the executables generated by this macro. These will also
# be the names of the targets.
#
# EXCLUDE_PROJECT_LIB: Pass this argument if you do not want your executables to
# link to your project's core library. On Windows, this
# will also skip the step of copying the runtime library
# into your executable's directory.
#
macro(ign_build_executables)
#------------------------------------
# Define the expected arguments
set(options EXCLUDE_PROJECT_LIB)
set(oneValueArgs PREFIX EXEC_LIST)
set(multiValueArgs SOURCES LIB_DEPS INCLUDE_DIRS)
if(ign_build_executables_EXEC_LIST)
set(${ign_build_executables_EXEC_LIST} "")
endif()
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_build_executables "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
foreach(exec_file ${ign_build_executables_SOURCES})
get_filename_component(BINARY_NAME ${exec_file} NAME_WE)
set(BINARY_NAME ${ign_build_executables_PREFIX}${BINARY_NAME})
add_executable(${BINARY_NAME} ${exec_file})
if(ign_build_executables_EXEC_LIST)
list(APPEND ${ign_build_executables_EXEC_LIST} ${BINARY_NAME})
endif()
if(NOT ign_build_executables_EXCLUDE_PROJECT_LIB)
target_link_libraries(${BINARY_NAME} ${PROJECT_LIBRARY_TARGET_NAME})
endif()
if(ign_build_executables_LIB_DEPS)
target_link_libraries(${BINARY_NAME} ${ign_build_executables_LIB_DEPS})
endif()
target_include_directories(${BINARY_NAME}
PRIVATE
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
${ign_build_executables_INCLUDE_DIRS})
endforeach()
endmacro()
#################################################
# ign_build_tests(TYPE <test_type>
# SOURCES <sources>
# [LIB_DEPS <library_dependencies>]
# [INCLUDE_DIRS <include_dependencies>]
# [TEST_LIST <output_var>])
#
# Build tests for an ignition project. Arguments are as follows:
#
# TYPE: Required. Preferably UNIT, INTEGRATION, PERFORMANCE, or REGRESSION.
#
# SOURCES: Required. The names (without the path) of the source files for your
# tests. Each file will turn into a test.
#
# LIB_DEPS: Optional. Additional library dependencies that every test should
# link to, not including the library built by this project (it will be
# linked automatically). gtest and gtest_main will also be linked.
#
# INCLUDE_DIRS: Optional. Additional include directories that should be visible
# to all the tests of this type.
#
# TEST_LIST: Optional. Provide a variable which will be given the list of the
# names of the tests generated by this macro. These will also be the
# names of the targets.
#
# EXCLUDE_PROJECT_LIB: Pass this argument if you do not want your tests to
# link to your project's core library. On Windows, this
# will also skip the step of copying the runtime library
# into your executable's directory.
#
macro(ign_build_tests)
#------------------------------------
# Define the expected arguments
set(options SOURCE EXCLUDE_PROJECT_LIB) # NOTE: DO NOT USE "SOURCE", we're adding it here to catch typos
set(oneValueArgs TYPE TEST_LIST)
set(multiValueArgs SOURCES LIB_DEPS INCLUDE_DIRS)
#------------------------------------
# Parse the arguments
_ign_cmake_parse_arguments(ign_build_tests "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT ign_build_tests_TYPE)
# If you have encountered this error, you are probably migrating to the
# new ignition-cmake system. Be sure to also provide a SOURCES argument
# when calling ign_build_tests.
message(FATAL_ERROR "Developer error: You must specify a TYPE for your tests!")
endif()
if(ign_build_tests_SOURCE)
# We have encountered cases where someone accidentally passes a SOURCE
# argument instead of a SOURCES argument into ign_build_tests, and the macro
# didn't report any problem with it. Adding this warning should make it more
# clear when that particular typo occurs.
message(AUTHOR_WARNING
"Your script has specified SOURCE for ign_build_tests, which is not an "
"option. Did you mean to specify SOURCES (note the plural)?")
endif()
set(TEST_TYPE ${ign_build_tests_TYPE})
if(BUILD_TESTING)
if(NOT DEFINED ign_build_tests_SOURCES)
message(STATUS "No tests have been specified for ${TEST_TYPE}")
else()
list(LENGTH ign_build_tests_SOURCES num_tests)
message(STATUS "Adding ${num_tests} ${TEST_TYPE} tests")
endif()
if(NOT ign_build_tests_EXCLUDE_PROJECT_LIB)
ign_build_executables(
PREFIX "${TEST_TYPE}_"
SOURCES ${ign_build_tests_SOURCES}
LIB_DEPS gtest gtest_main ${ign_build_tests_LIB_DEPS}
INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/test/gtest/include ${ign_build_tests_INCLUDE_DIRS}
EXEC_LIST test_list)
else()
ign_build_executables(
PREFIX "${TEST_TYPE}_"
SOURCES ${ign_build_tests_SOURCES}
LIB_DEPS gtest gtest_main ${ign_build_tests_LIB_DEPS}
INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/test/gtest/include ${ign_build_tests_INCLUDE_DIRS}
EXEC_LIST test_list
EXCLUDE_PROJECT_LIB)
endif()
if(ign_build_tests_TEST_LIST)
set(${ign_build_tests_TEST_LIST} ${test_list})
endif()
# Find the Python interpreter for running the
# check_test_ran.py script
include(IgnPython)
# Build all the tests
foreach(target_name ${test_list})
if(USE_LOW_MEMORY_TESTS)
target_compile_options(${target_name} PRIVATE -DUSE_LOW_MEMORY_TESTS=1)
endif()
add_test(NAME ${target_name} COMMAND
${target_name} --gtest_output=xml:${CMAKE_BINARY_DIR}/test_results/${target_name}.xml)
if(UNIX)
# gtest requies pthread when compiled on a Unix machine
target_link_libraries(${target_name} pthread)
endif()
target_compile_definitions(${target_name} PRIVATE
"TESTING_PROJECT_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\"")
if(PYTHONINTERP_FOUND)
# Check that the test produced a result and create a failure if it didn't.
# Guards against crashed and timed out tests.
add_test(check_${target_name} ${PYTHON_EXECUTABLE} ${IGNITION_CMAKE_TOOLS_DIR}/check_test_ran.py
${CMAKE_BINARY_DIR}/test_results/${target_name}.xml)
endif()
endforeach()
else()
message(STATUS "Testing is disabled -- skipping ${TEST_TYPE} tests")
endif()
endmacro()
#################################################
# ign_set_target_public_cxx_standard(<11|14|17>)
#
# NOTE: This was a temporary workaround for an earlier prerelease and is
# deprecated as of the "Components" pull request.
#
macro(ign_set_project_public_cxx_standard standard)
message(FATAL_ERROR
"The ign_set_project_public_cxx_standard(~) macro is deprecated. "
"Instead, use the CXX_STANDARD argument of ign_create_core_library(~).")
_ign_check_known_cxx_standards(${standard})
target_compile_features(${PROJECT_LIBRARY_TARGET_NAME} PUBLIC ${IGN_CXX_${standard}_FEATURES})
# Note: We have to reconfigure the pkg-config information for the core library
# because this macro can only be called after ign_create_core_library(~). This
# is somewhat wasteful, so we should strongly prefer to use the CXX_STANDARD
# argument of ign_create_core_library(~).
ign_string_append(PROJECT_PKGCONFIG_CFLAGS "-std=c++${standard}")
_ign_create_pkgconfig()
endmacro()
#################################################
# _ign_cmake_parse_arguments(<prefix> <options> <oneValueArgs> <multiValueArgs> [ARGN])
#
# Set <prefix> to match the prefix that is given to cmake_parse_arguments(~).
# This should also match the name of the function or macro that called it.
#
# NOTE: This should only be used by functions inside of ign-cmake specifically.
# Other ignition projects should not use this macro.
#
macro(_ign_cmake_parse_arguments prefix options oneValueArgs multiValueArgs)
cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(${prefix}_UNPARSED_ARGUMENTS)
# The user passed in some arguments that we don't currently recognize. We'll
# emit a warning so they can check whether they're using the correct version
# of ign-cmake.
message(AUTHOR_WARNING
"\nThe build script has specified some unrecognized arguments for ${prefix}(~):\n"
"${${prefix}_UNPARSED_ARGUMENTS}\n"
"Either the script has a typo, or it is using an unexpected version of ign-cmake. "
"The version of ign-cmake currently being used is ${ignition-cmake${IGNITION_CMAKE_VERSION_MAJOR}_VERSION}\n")
endif()
endmacro()
|