File: AwsCheckHeaders.cmake

package info (click to toggle)
aws-crt-python 0.24.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 75,932 kB
  • sloc: ansic: 418,984; python: 23,626; makefile: 6,035; sh: 4,075; ruby: 208; java: 82; perl: 73; cpp: 25; xml: 11
file content (108 lines) | stat: -rw-r--r-- 4,917 bytes parent folder | download
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
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0.

# This cmake logic verifies that each of our headers is complete, in that it
# #includes any necessary dependencies, and that it builds under C++ as well.
#
# To do so, we generate a single-line C or C++ source file that includes each
# header, and link all of these stub source files into a test executable.

option(PERFORM_HEADER_CHECK "Performs compile-time checks that each header can be included independently. Requires a C++ compiler.")

if (PERFORM_HEADER_CHECK)
    enable_language(CXX)
endif()

# Call as: aws_check_headers(${target} HEADERS TO CHECK LIST)
function(aws_check_headers target)
    if (NOT PERFORM_HEADER_CHECK)
        return()
    endif()
    # parse function arguments
    set(options IS_CXX)
    cmake_parse_arguments(ARG "${options}" "" "" ${ARGN})

    aws_check_headers_internal(${target} 11 ${ARG_IS_CXX} ${ARG_UNPARSED_ARGUMENTS})
    aws_check_headers_internal(${target} 14 ${ARG_IS_CXX} ${ARG_UNPARSED_ARGUMENTS})
    aws_check_headers_internal(${target} 17 ${ARG_IS_CXX} ${ARG_UNPARSED_ARGUMENTS})
    aws_check_headers_internal(${target} 20 ${ARG_IS_CXX} ${ARG_UNPARSED_ARGUMENTS})
    aws_check_headers_internal(${target} 23 ${ARG_IS_CXX} ${ARG_UNPARSED_ARGUMENTS})
endfunction()

function(aws_check_headers_internal target std is_cxx)
    # Check that compiler supports this std
    list (FIND CMAKE_CXX_COMPILE_FEATURES "cxx_std_${std}" feature_idx)
    if (${feature_idx} LESS 0)
        return()
    endif()

    set(HEADER_CHECKER_ROOT "${CMAKE_CURRENT_BINARY_DIR}/header-checker-cxx${std}")

    # Write stub main file
    set(HEADER_CHECKER_MAIN "${HEADER_CHECKER_ROOT}/headerchecker_main.c")
    set(HEADER_CHECKER_LIB ${target}-header-check-cxx${std})
    file(WRITE ${HEADER_CHECKER_MAIN} "
        int main(int argc, char **argv) {
            (void)argc;
            (void)argv;

            return 0;
        }\n")


    add_executable(${HEADER_CHECKER_LIB} ${HEADER_CHECKER_MAIN})
    target_link_libraries(${HEADER_CHECKER_LIB} ${target})
    target_compile_definitions(${HEADER_CHECKER_LIB} PRIVATE AWS_UNSTABLE_TESTING_API=1 AWS_HEADER_CHECKER=1)

    # We want to be able to verify that the proper C++ header guards are in place, so
    # build this target as a C++ application
    set_target_properties(${HEADER_CHECKER_LIB} PROPERTIES
        LINKER_LANGUAGE CXX
        CXX_STANDARD ${std}
        CXX_STANDARD_REQUIRED 0
        C_STANDARD 99
    )

    # Ensure our headers can be included by an application with its warnings set very high.
    # Most compiler options are universal, but some are C++ only.
    set(compiler_options_all "")
    set(compiler_options_cxx_only "")
    if(MSVC)
        # MSVC complains about windows' own header files. Use /W4 instead of /Wall
        list(APPEND compiler_options_all /W4 /WX)
    else()
        list(APPEND compiler_options_all -Wall -Wextra -Wpedantic -Werror)

        if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
            # -Wuseless-cast requested by https://github.com/awslabs/aws-c-common/issues/973
            list(APPEND compiler_options_cxx_only -Wuseless-cast)
        endif()
    endif()
    target_compile_options(${HEADER_CHECKER_LIB} PRIVATE ${compiler_options_all})

    foreach(header IN LISTS ARGN)
        if (NOT ${header} MATCHES "\\.inl$")
            # create unique token for this file, e.g.:
            # "${CMAKE_CURRENT_SOURCE_DIR}/include/aws/common/byte_buf.h" -> "aws_common_byte_buf_h"
            file(RELATIVE_PATH include_path "${CMAKE_CURRENT_SOURCE_DIR}/include" ${header})
            # replace non-alphanumeric characters with underscores
            string(REGEX REPLACE "[^a-zA-Z0-9]" "_" unique_token ${include_path})
            # test compiling header from a .cpp and .c file (or just .cpp if this header IS_CXX)
            set(c_file "${HEADER_CHECKER_ROOT}/headerchecker_${unique_token}.c")
            set(cpp_file "${HEADER_CHECKER_ROOT}/headerchecker_${unique_token}.cpp")
            # include header twice to check for include-guards
            # define a unique int or compiler complains that there's nothing in the file
            file(WRITE "${cpp_file}" "#include <${include_path}>\n#include <${include_path}>\nint ${unique_token}_cpp;")
            target_sources(${HEADER_CHECKER_LIB} PUBLIC "${cpp_file}")
            if (NOT is_cxx)
                file(WRITE "${c_file}" "#include <${include_path}>\n#include <${include_path}>\nint ${unique_token}_c;\n")
                target_sources(${HEADER_CHECKER_LIB} PUBLIC "${c_file}")
            endif()

            # for .cpp file, apply C++ only compiler options
            if(compiler_options_cxx_only)
                set_source_files_properties(${cpp_file} PROPERTIES COMPILE_OPTIONS ${compiler_options_cxx_only})
            endif()
        endif()
    endforeach(header)
endfunction()