## # vcpkg_check_features ## Check if one or more features are a part of a package installation. ## ## ## Usage ## ```cmake ## vcpkg_check_features( ## OUT_FEATURE_OPTIONS ## [FEATURES ## ## [ ] ## ...] ## [INVERTED_FEATURES ## ## [ ] ## ...] ## ) ## ``` ## `vcpkg_check_features()` accepts these parameters: ## ## * `OUT_FEATURE_OPTIONS`: ## An output variable, the function will clear the variable passed to `OUT_FEATURE_OPTIONS` ## and then set it to contain a list of option definitions (`-D=ON|OFF`). ## ## This should be set to `FEATURE_OPTIONS` by convention. ## ## * `FEATURES`: ## A list of (`FEATURE_NAME`, `OPTION_NAME`) pairs. ## For each `FEATURE_NAME` a definition is added to `OUT_FEATURE_OPTIONS` in the form of: ## ## * `-D=ON`, if a feature is specified for installation, ## * `-D=OFF`, otherwise. ## ## * `INVERTED_FEATURES`: ## A list of (`FEATURE_NAME`, `OPTION_NAME`) pairs, uses reversed logic from `FEATURES`. ## For each `FEATURE_NAME` a definition is added to `OUT_FEATURE_OPTIONS` in the form of: ## ## * `-D=OFF`, if a feature is specified for installation, ## * `-D=ON`, otherwise. ## ## ## ## Notes ## ## The `FEATURES` name parameter can be omitted if no `INVERTED_FEATURES` are used. ## ## At least one (`FEATURE_NAME`, `OPTION_NAME`) pair must be passed to the function call. ## ## Arguments passed to `FEATURES` and `INVERTED_FEATURES` are not validated to prevent duplication. ## If the same (`FEATURE_NAME`, `OPTION_NAME`) pair is passed to both lists, ## two conflicting definitions are added to `OUT_FEATURE_OPTIONS`. ## ## ## ## Examples ## ## ### Example 1: Regular features ## ## ```cmake ## $ ./vcpkg install mimalloc[asm,secure] ## ## # ports/mimalloc/portfile.cmake ## vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS ## # Keyword FEATURES is optional if INVERTED_FEATURES are not used ## asm MI_SEE_ASM ## override MI_OVERRIDE ## secure MI_SECURE ## ) ## ## vcpkg_configure_cmake( ## SOURCE_PATH ${SOURCE_PATH} ## PREFER_NINJA ## OPTIONS ## # Expands to "-DMI_SEE_ASM=ON; -DMI_OVERRIDE=OFF; -DMI_SECURE=ON" ## ${FEATURE_OPTIONS} ## ) ## ``` ## ## ### Example 2: Inverted features ## ## ```cmake ## $ ./vcpkg install cpprestsdk[websockets] ## ## # ports/cpprestsdk/portfile.cmake ## vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS ## INVERTED_FEATURES # <- Keyword INVERTED_FEATURES required ## brotli CPPREST_EXCLUDE_BROTLI ## websockets CPPREST_EXCLUDE_WEBSOCKETS ## ) ## ## vcpkg_configure_cmake( ## SOURCE_PATH ${SOURCE_PATH} ## PREFER_NINJA ## OPTIONS ## # Expands to "-DCPPREST_EXCLUDE_BROTLI=ON; -DCPPREST_EXCLUDE_WEBSOCKETS=OFF" ## ${FEATURE_OPTIONS} ## ) ## ``` ## ## ### Example 3: Set multiple options for same feature ## ## ```cmake ## $ ./vcpkg install pcl[cuda] ## ## # ports/pcl/portfile.cmake ## vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS ## cuda WITH_CUDA ## cuda BUILD_CUDA ## cuda BUILD_GPU ## ) ## ## vcpkg_configure_cmake( ## SOURCE_PATH ${SOURCE_PATH} ## PREFER_NINJA ## OPTIONS ## # Expands to "-DWITH_CUDA=ON; -DBUILD_CUDA=ON; -DBUILD_GPU=ON" ## ${FEATURE_OPTIONS} ## ) ## ``` ## ## ### Example 4: Use regular and inverted features ## ## ```cmake ## $ ./vcpkg install rocksdb[tbb] ## ## # ports/rocksdb/portfile.cmake ## vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS ## FEATURES # <- Keyword FEATURES is required because INVERTED_FEATURES are being used ## tbb WITH_TBB ## INVERTED_FEATURES ## tbb ROCKSDB_IGNORE_PACKAGE_TBB ## ) ## ## vcpkg_configure_cmake( ## SOURCE_PATH ${SOURCE_PATH} ## PREFER_NINJA ## OPTIONS ## # Expands to "-DWITH_TBB=ON; -DROCKSDB_IGNORE_PACKAGE_TBB=OFF" ## ${FEATURE_OPTIONS} ## ) ## ``` ## ## ## Examples in portfiles ## ## * [cpprestsdk](https://github.com/microsoft/vcpkg/blob/master/ports/cpprestsdk/portfile.cmake) ## * [pcl](https://github.com/microsoft/vcpkg/blob/master/ports/pcl/portfile.cmake) ## * [rocksdb](https://github.com/microsoft/vcpkg/blob/master/ports/rocksdb/portfile.cmake) ## function(vcpkg_check_features) # parse parameters such that semicolons in options arguments to COMMAND don't get erased cmake_parse_arguments(PARSE_ARGV 0 _vcf "" "OUT_FEATURE_OPTIONS" "FEATURES;INVERTED_FEATURES") if (NOT DEFINED _vcf_OUT_FEATURE_OPTIONS) message(FATAL_ERROR "OUT_FEATURE_OPTIONS must be specified.") endif() macro(_check_features _vcf_ARGUMENT _set_if _set_else) list(LENGTH ${_vcf_ARGUMENT} FEATURES_SET_LEN) math(EXPR _vcf_INCORRECT_ARGN "${FEATURES_SET_LEN} % 2") if(_vcf_INCORRECT_ARGN) message(FATAL_ERROR "Called with incorrect number of arguments.") endif() set(_vcf_IS_FEATURE_NAME_ARG ON) foreach(_vcf_ARG ${${_vcf_ARGUMENT}}) if(_vcf_IS_FEATURE_NAME_ARG) set(_vcf_FEATURE_NAME ${_vcf_ARG}) if(NOT ${_vcf_FEATURE_NAME} IN_LIST ALL_FEATURES) message(FATAL_ERROR "Unknown feature: ${_vcf_FEATURE_NAME}") endif() set(_vcf_IS_FEATURE_NAME_ARG OFF) else() set(_vcf_FEATURE_VARIABLE ${_vcf_ARG}) if(${_vcf_FEATURE_NAME} IN_LIST FEATURES) list(APPEND _vcf_FEATURE_OPTIONS "-D${_vcf_FEATURE_VARIABLE}=${_set_if}") else() list(APPEND _vcf_FEATURE_OPTIONS "-D${_vcf_FEATURE_VARIABLE}=${_set_else}") endif() set(_vcf_IS_FEATURE_NAME_ARG ON) endif() endforeach() endmacro() set(_vcf_FEATURE_OPTIONS) if (DEFINED _vcf_FEATURES OR DEFINED _vcf_INVERTED_FEATURES) _check_features(_vcf_FEATURES ON OFF) _check_features(_vcf_INVERTED_FEATURES OFF ON) else() # Skip arguments that correspond to OUT_FEATURE_OPTIONS and its value. list(SUBLIST ARGN 2 -1 _vcf_ARGN) _check_features(_vcf_ARGN ON OFF) endif() set(${_vcf_OUT_FEATURE_OPTIONS} "${_vcf_FEATURE_OPTIONS}" PARENT_SCOPE) endfunction()