trozen
trozen

Reputation: 1273

Get cmake options from program

How can I get CMake options used for building from within a program?

E.g. I would like to use this:

int main()
{
    std::cout << "Build options: " << BUILD_OPTIONS << std::endl;
}

BUILD_OPTIONS would contain a string with all options passed to cmake, like:

cmake -DOPT1 -DOPT3

with CMakeLists.txt defined as follows:

option(OPT1 "option 1" OFF)
option(OPT2 "option 2" OFF)
option(OPT3 "option 3" OFF)

The desired output of such program:

Build options: OPT1=ON OPT3=ON

(OPT2 skipped, as it is not defined explicitly and equal to default value)

Upvotes: 1

Views: 1393

Answers (5)

trozen
trozen

Reputation: 1273

It is possible to pass a list of all defines to a program in a single string using generator expressions:

target_compile_options(target PRIVATE "-DENABLED_FEATURES=\"$<JOIN:$<TARGET_PROPERTY:COMPILE_DEFINITIONS>,$<COMMA>>\"")

Using target_compile_options instead of target_compile_definitions, as the latter would cause infinite recursion.

In CMake 3.15 and newer it is possible to use REMOVE_DUPLICATES generator, if a single define may appear several times on a command line.

Upvotes: 0

trozen
trozen

Reputation: 1273

Finally I'm using the following approach, maybe someone fill find that useful. Instead of option() function I'm using custom feature_option():

include(cmake/options.cmake)

feature_option(OPT1 "option 1" OFF)
feature_option(OPT2 "option 2" OFF)
feature_option(OPT3 "option 3" OFF)

which defines the option and also stores it on a list. Then it can be passed to the compiler via ENABLED_FEATURES define:

get_feature_list(feature_list)
message(STATUS "Enabled features: ${feature_list}")
target_compile_definitions(target PUBLIC "-DENABLED_FEATURES=\"${feature_list}\"")

Those functions are defined in separate options.cmake file, so they can be used in project consiting of multiple modules:

function(feature_option option_variable help_string) # optional argument: default_value
    option(${option_variable} ${help_string} ${ARGN})
    get_property(FEATURE_VARIABLE_LIST GLOBAL PROPERTY FEATURE_VARIABLE_LIST)
    set_property(GLOBAL PROPERTY FEATURE_VARIABLE_LIST ${FEATURE_VARIABLE_LIST} ${option_variable})
endfunction()

function(get_feature_list output_variable)
    get_property(FEATURE_VARIABLE_LIST GLOBAL PROPERTY FEATURE_VARIABLE_LIST)
    foreach(option_variable ${FEATURE_VARIABLE_LIST})
        set(option_value "${${option_variable}}")
        if(${option_value})
            if(feature_list)
                set(feature_list "${feature_list},${option_variable}")
            else()
                set(feature_list "${option_variable}")
            endif()
        endif()
    endforeach()
    set(${output_variable} ${feature_list} PARENT_SCOPE)
endfunction()

Upvotes: 0

Tal Avraham
Tal Avraham

Reputation: 326

Well, if the program itself was compiled using the CMakeLists.txt file, you could write something along these lines:

option (OPT1 “option 1” OFF)
option (OPT2 “option 2” OFF)

if (OPT1)
    add_definitions (-DOPT1_ENABLED)
endif(OPT1)

if (OPT2)
    add_definitions (-DOPT2_ENABLED)
endif(OPT2)

Then in your program:

int main(void)
{
    std::cout << “Build options: “;
#ifdef OPT1_ENABLED
    std::cout << “OPT1=ON ”;
#else
    std::cout << “OPT1=OFF ”;
#endif /* OPT1 */

#ifdef OPT2_ENABLED
    std::cout << “OPT2=ON ”;
#else
    std::cout << “OPT2=OFF ”;
#endif /* OPT2 */

    std::cout << endl;
    return 0;
}

Upvotes: 0

Ľubom&#237;r Carik
Ľubom&#237;r Carik

Reputation: 407

It is possible to use configure_file command with 'cmakedefine' feaure. This is capable to generate something very similar what autotools do i.e. config.h with all enabled/disabled features. The final string may be concatenated from particular sub-string depending if CMake option defined.

Upvotes: 0

Bodo
Bodo

Reputation: 9855

I don't know if it is possible to find out if an option has been specified explicitly or not.

The proposed solution will show all option values as specified in a CMake string variable. It consists of 3 steps:

  • Combine the option values to a string in CMakeLists.txt
  • Let CMake generate a source file with placeholder substitution.
  • Compile and link your program with the generated file.

In CMakeLists.txt add e.g.

set(BUILD_OPTIONS "OPT1=${OPT1} OPT2=${OPT2} OPT3=${OPT3}")

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build_options.c.in ${CMAKE_CURRENT_BINARY_DIR}/build_options.c @ONLY)

Manually created files:

build_options.c.in

#include "build_options.h"

const char *BUILD_OPTIONS = "@BUILD_OPTIONS@";

build_options.h

#ifndef BUILD_OPTIONS_H_
#define BUILD_OPTIONS_H_

extern const char *BUILD_OPTIONS;

#endif /* BUILD_OPTIONS_H_ */

CMake will generate build_options.c

#include "build_options.h"

const char *BUILD_OPTIONS = "OPT1=ON OPT2=OFF OPT3=ON";

Upvotes: 1

Related Questions