This is a mirror page, please see the original page:

https://xmake.io/#/manual/helper_interfaces

Automatic detection of auxiliary interface

In addition, the version of this interface after 2.2.5 provides some built-in helper functions, which can be imported directly using includes. See the specific built-in functions: Helper functions

We can use these interfaces to detect links, c/c++ type, includes and compiler features, and write macro definitions to config.h

Among them, we provide two types of interfaces, check_xxx and configvar_check_xxx. The interfaces prefixed with configvar_ will be written into the config.h.in template file specified by add_configfiles after passing the test.

And check_xxx only defines related macros to participate in compilation, but it will not be persisted in config.h.in.

For related issues, see:

-#342
-#1715

Note: Instead of introducing these interfaces separately via includes("check_links.lua"),
for versions 2.8.5 and above, you can use the more convenient

includes("@builtin/check")

to bring in all the checking interfaces at once, but of course we can also bring in individual scripts on an as-needed basis:

includes("@builtin/check/check_links.lua")

The original introduction path, which does not distinguish whether it is a user path or not, is not easy to manage and maintain,
and is easily interfered by user configurations, so it will be gradually deprecated later.

We can check whether the specified links pass or not by trying to link.

includes("check_links.lua")

target("test")
    set_kind("binary")
    add_files("*.c")
    add_configfiles("config.h.in")
    configvar_check_links("HAS_PTHREAD", {"pthread", "m", "dl"})

config.h.in

${define HAS_PTHREAD}

config.h

#define HAS_PTHREAD 1
/* #undef HAS_PTHREAD */

Detect c/c++ type

We can also detect the existence of c/c++ types.

configvar_check_ctypes is used to detect c code types, and configvar_check_cxxtypes is used to detect c++ code types.

includes("check_ctypes.lua")

target("test")
    set_kind("binary")
    add_files("*.c")
    add_configfiles("config.h.in")
    configvar_check_ctypes("HAS_WCHAR", "wchar_t")
    configvar_check_ctypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"})

config.h.in

${define HAS_WCHAR}
${define HAS_WCHAR_AND_FLOAT}

config.h

/* #undef HAS_WCHAR */
/* #undef HAS_WCHAR_AND_FLOAT */

Detect c/c++ functions

configvar_check_cfuncs is used to detect c code functions, and configvar_check_cxxfuncs is used to detect c++ code functions.

includes("check_cfuncs.lua")

target("test")
    set_kind("binary")
    add_files("*.c")
    add_configfiles("config.h.in")
    configvar_check_cfuncs("HAS_SETJMP", "setjmp", {includes = {"signal.h", "setjmp.h"}})

config.h.in

${define HAS_SETJMP}

config.h

#define HAS_SETJMP 1
/* #undef HAS_SETJMP */

Detect c/c++ header files

configvar_check_cincludes is used to detect c code header files, and configvar_check_cxxincludes is used to detect c++ code header files.

includes("check_cincludes.lua")

target("test")
    set_kind("binary")
    add_files("*.c")
    add_configfiles("config.h.in")
    configvar_check_cincludes("HAS_STRING_H", "string.h")
    configvar_check_cincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"})

config.h.in

${define HAS_STRING_H}
${define HAS_STRING_AND_STDIO_H}

config.h

/* #undef HAS_STRING_H */
#define HAS_STRING_AND_STDIO_H 1

Detect c/c++ code snippets

configvar_check_csnippets is used to detect c code snippets, and configvar_check_cxxsnippets is used to detect c++ code snippets.

includes("check_csnippets.lua")

target("test")
    set_kind("binary")
    add_files("*.c")
    add_configfiles("config.h.in")
    configvar_check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");")

config.h.in

${define HAS_STATIC_ASSERT}

config.h

#define HAS_STATIC_ASSERT 1

After v2.5.7, check_csnippets has been improved, adding tryrun and output parameters to try to run and capture output.

includes("check_csnippets.lua")

target("test")
    set_kind("binary")
    add_files("*.c")
    add_configfiles("config.h.in")

    check_csnippets("HAS_INT_4", "return (sizeof(int) == 4)? 0: -1;", {tryrun = true})
    check_csnippets("INT_SIZE",'printf("%d", sizeof(int)); return 0;', {output = true, number = true})
    configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0: -1;", {tryrun = true})
    configvar_check_csnippets("PTR_SIZE",'printf("%d", sizeof(void*)); return 0;', {output = true, number = true})

If capture output is enabled, ${define PTR_SIZE} in config.h.in will automatically generate #define PTR_SIZE 4.

Among them, the number = true setting can be forced as a number instead of a string value, otherwise it will be defined as #define PTR_SIZE "4" by default

Detecting compiler features

includes("check_features.lua")

target("test")
    set_kind("binary")
    add_files("*.c")
    add_configfiles("config.h.in")
    configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr")
    configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"})

config.h.in

${define HAS_CONSTEXPR}
${define HAS_CONSEXPR_AND_STATIC_ASSERT}

config.h

/* #undef HAS_CONSTEXPR */
#define HAS_CONSEXPR_AND_STATIC_ASSERT 1

List of all c compiler features:

Feature name
c_static_assert
c_restrict
c_variadic_macros
c_function_prototypes

List of all c++ compiler features:

Feature name
cxx_variable_templates
cxx_relaxed_constexpr
cxx_aggregate_default_initializers
cxx_contextual_conversions
cxx_attribute_deprecated
cxx_decltype_auto
cxx_digit_separators
cxx_generic_lambdas
cxx_lambda_init_captures
cxx_binary_literals
cxx_return_type_deduction
cxx_decltype_incomplete_return_types
cxx_reference_qualified_functions
cxx_alignof
cxx_attributes
cxx_inheriting_constructors
cxx_thread_local
cxx_alias_templates
cxx_delegating_constructors
cxx_extended_friend_declarations
cxx_final
cxx_nonstatic_member_init
cxx_override
cxx_user_literals
cxx_constexpr
cxx_defaulted_move_initializers
cxx_enum_forward_declarations
cxx_noexcept
cxx_nullptr
cxx_range_for
cxx_unrestricted_unions
cxx_explicit_conversions
cxx_lambdas
cxx_local_type_template_args
cxx_raw_string_literals
cxx_auto_type
cxx_defaulted_functions
cxx_deleted_functions
cxx_generalized_initializers
cxx_inline_namespaces
cxx_sizeof_member
cxx_strong_enums
cxx_trailing_return_types
cxx_unicode_literals
cxx_uniform_initialization
cxx_variadic_templates
cxx_decltype
cxx_default_function_template_args
cxx_long_long_type
cxx_right_angle_brackets
cxx_rvalue_references
cxx_static_assert
cxx_extern_templates
cxx_func_identifier
cxx_variadic_macros
cxx_template_template_parameters

v2.5.9 adds c++17 feature detection:

Feature name
cxx_aggregate_bases
cxx_aligned_new
cxx_capture_star_this
cxx_constexpr
cxx_deduction_guides
cxx_enumerator_attributes
cxx_fold_expressions
cxx_guaranteed_copy_elision
cxx_hex_float
cxx_if_constexpr
cxx_inheriting_constructors
cxx_inline_variables
cxx_namespace_attributes
cxx_noexcept_function_type
cxx_nontype_template_args
cxx_nontype_template_parameter_auto
cxx_range_based_for
cxx_static_assert
cxx_structured_bindings
cxx_template_template_args
cxx_variadic_using

v2.5.9 adds c++20 feature detection:

Feature name
cxx_aggregate_paren_init
cxx_char8_t
cxx_concepts
cxx_conditional_explicit
cxx_consteval
cxx_constexpr
cxx_constexpr_dynamic_alloc
cxx_constexpr_in_decltype
cxx_constinit
cxx_deduction_guides
cxx_designated_initializers
cxx_generic_lambdas
cxx_impl_coroutine
cxx_impl_destroying_delete
cxx_impl_three_way_comparison
cxx_init_captures
cxx_modules
cxx_nontype_template_args
cxx_using_enum

After 2.5.8, support for cstd and c++ std versions are added, related issues: #1715

configvar_check_features("HAS_CXX_STD_98", "cxx_std_98")
configvar_check_features("HAS_CXX_STD_11", "cxx_std_11", {languages = "c++11"})
configvar_check_features("HAS_CXX_STD_14", "cxx_std_14", {languages = "c++14"})
configvar_check_features("HAS_CXX_STD_17", "cxx_std_17", {languages = "c++17"})
configvar_check_features("HAS_CXX_STD_20", "cxx_std_20", {languages = "c++20"})
configvar_check_features("HAS_C_STD_89", "c_std_89")
configvar_check_features("HAS_C_STD_99", "c_std_99")
configvar_check_features("HAS_C_STD_11", "c_std_11", {languages = "c11"})
configvar_check_features("HAS_C_STD_17", "c_std_17", {languages = "c17"})

Detect built-in macro definitions

There are some built-in macro definitions in the compiler, such as __GNUC__, etc. We can use the check_macros and configvar_check_macros auxiliary scripts to detect their existence.

Related issues: #1715

- Check whether the macro is defined
configvar_check_macros("HAS_GCC", "__GNUC__")
- The detection macro is not defined
configvar_check_macros("NO_GCC", "__GNUC__", {defined = false})
- Detect macro conditions
configvar_check_macros("HAS_CXX20", "__cplusplus >= 202002L", {languages = "c++20"})

Detect type size

In previous versions, type detection was possible with check_csnippets and output = true.

check_csnippets("INT_SIZE", 'printf("%d", sizeof(int)); return 0;', {output = true, number = true})

This way, however, extracts the type size information by trying to run the test code and then getting the run output.

This doesn't work for cross-compilation.

In version 2.8.5, we added the check_sizeof helper interface, which allows you to extract type size information by parsing the binary file of the test program directly.

Since there is no need to run tests, this approach not only supports cross-compilation, but also greatly improves the efficiency of testing and is much easier to use.

includes("@builtin/check")

target("test")
    set_kind("static")
    add_files("*.cpp")
    check_sizeof("LONG_SIZE", "long")
    check_sizeof("STRING_SIZE", "std::string", {includes = "string"})
$ xmake f -c
checking for LONG_SIZE ... 8
checking for STRING_SIZE ... 24

Alternatively, I can check for it in the script field with target:check_sizeof.

Detecting big-endian

After version 2.8.9, we added the check_bigendian interface to determine if the current compilation target is in bigendian mode.

includes("@builtin/check")

target("test")
    set_kind("static")
    add_files("*.cpp")
    check_bigendian("IS_BIG_ENDIAN")

If the test passes and it is currently in big endian mode, then IS_BIG_ENDIAN=1 is defined.