2

Is it possible to do a platform check for the output of a program?

Let's say I want to compile this program:

#include <library.h>
#include <iostream>
int main() {
    std::cout << LIBRARY_MAGIC_VALUE << std::endl;
    return 0;
}

and run it (within CMake configure step) to extract the value of LIBRARY_MAGIC_VALUE.

In the How to write platform checks (moved to: here) guide it seems that this use-case is not contemplated, or specialized only to specific things (like checking the size of a type).

How can I implement such a check?

3
  • CMake 3.0 has a "execute_process" the deprecated version is "exec_program" I think. Instead of trying to cout you can do a return LIBRARY_MAGIC_VALUE and set the return variable in "execute_process" and use that value to do the check? Commented Jul 13, 2017 at 14:46
  • execute_process doesn't cover building the program right? if I add the program as a target, how do I specify that it is needed at configure step? Commented Jul 13, 2017 at 14:51
  • Correct, its more like running a secondary program to determine the values you are after. You could add it as a dependency. So VersionChecker first and then the AppUsingVersionChecker, each with its own CMakeList.txt. Commented Jul 13, 2017 at 14:54

2 Answers 2

5

You can use the CMake built-in try_run command as follows:

TRY_RUN(
    # Name of variable to store the run result (process exit status; number) in:
    test_run_result

    # Name of variable to store the compile result (TRUE or FALSE) in:
    test_compile_result

    # Binary directory:
    ${CMAKE_CURRENT_BINARY_DIR}/

    # Source file to be compiled:
    ${CMAKE_CURRENT_SOURCE_DIR}/test.cpp

    # Where to store the output produced during compilation:
    COMPILE_OUTPUT_VARIABLE test_compile_output

    # Where to store the output produced by running the compiled executable:
    RUN_OUTPUT_VARIABLE test_run_output)

This attempts to compile and run the given check in test.cpp. You still need to check whether try_run succeeded to compile and run the check, and handle the output appropriately. For example, you can do something like this:

# Did compilation succeed and process return 0 (success)?
IF("${test_compile_result}" AND ("${test_run_result}" EQUAL 0))
    # Strip whitespace (such as the trailing newline from std::endl)
    # from the produced output:
    STRING(STRIP "${test_run_output}" test_run_output)
ELSE()
    # Error on failure and print error message:
    MESSAGE(FATAL_ERROR "Failed check!")
ENDIF()
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, try_run is the way to go
4

Use try_run command for such checks:

try_run(LIBRARY_MAGIC_VAL_RUN_RESULT
    LIBRARY_MAGIC_VAL_COMPILE_RESULT
    ${CMAKE_CURRENT_BINARY_DIR}/library_magic_val
    "test_library_magic_val.c"
    RUN_OUTPUT_VARIABLE LIBRARY_MAGIC_VAL_OUTPUT)

# Do not forget to check 'LIBRARY_MAGIC_VAL_RUN_RESULT' and
# 'LIBRARY_MAGIC_VAL_COMPILE_RESULT' for successfullness.

# Variable LIBRARY_MAGIC_VAL_OUTPUT now contains output of your test program.

1 Comment

Thanks, this solved it. Also note that to specify include path one has to use the CMAKE_FLAGS keyword such as try_run(RUN_RESULT COMPILE_RESULT binary source.c CMAKE_FLAGS -DINCLUDE_DIRECTORIES=/path/to/foo RUN_OUTPUT_VARIABLE OUTVAR)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.