aboutsummaryrefslogtreecommitdiff
path: root/tests/deps/SCsub
blob: ef7af7ac926f0d59f26ed65fdc10973339a1550f (plain) (blame)
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#!/usr/bin/env python
import os
import subprocess
from pathlib import Path

Import("env")

def generate_snitch_config_header(target, source, env):
    header = []
    header_filename = "snitch_config.hpp"

    header.append("// THIS FILE IS GENERATED. EDITS WILL BE LOST.")
    header.append("")

    header_file_path = Path(str(target[0]))

    include_gen_folder = Path(str(header_file_path.parent))
    include_gen_folder.mkdir(parents=True, exist_ok=True)

    header_guard = "SNITCH_CONFIG_HPP"
    header.append(f"#ifndef {header_guard}")
    header.append(f"#define {header_guard}")
    header.append("")
    header.append("#include <version> // for C++ feature check macros")

    for key, val in env.config_data.items():
        header +=(f'''
#if !defined({key})
#   define {key} {val}
#endif''').split("\n")

    header += ("""
#if defined(_MSC_VER)
#    if defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
#        define SNITCH_EXCEPTIONS_NOT_AVAILABLE
#    endif
#elif defined(__clang__) || defined(__GNUC__)
#    if !defined(__EXCEPTIONS)
#        define SNITCH_EXCEPTIONS_NOT_AVAILABLE
#    endif
#endif

#if defined(SNITCH_EXCEPTIONS_NOT_AVAILABLE)
#    undef SNITCH_WITH_EXCEPTIONS
#    define SNITCH_WITH_EXCEPTIONS 0
#endif

#if SNITCH_WITH_MULTITHREADING
#    define SNITCH_THREAD_LOCAL thread_local
#else
#    define SNITCH_THREAD_LOCAL
#endif

#if !defined(__cpp_lib_bit_cast)
#    undef SNITCH_CONSTEXPR_FLOAT_USE_BITCAST
#    define SNITCH_CONSTEXPR_FLOAT_USE_BITCAST 0
#endif

#if (!defined(__cpp_lib_to_chars)) || (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE <= 11) ||     \
    (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 14000) ||                                      \
    (defined(_MSC_VER) && _MSC_VER <= 1924)
#    undef SNITCH_APPEND_TO_CHARS
#    define SNITCH_APPEND_TO_CHARS 0
#endif

#if SNITCH_SHARED_LIBRARY
#    if defined(_MSC_VER)
#        if defined(SNITCH_EXPORTS)
#            define SNITCH_EXPORT __declspec(dllexport)
#        else
#            define SNITCH_EXPORT __declspec(dllimport)
#        endif
#    elif defined(__clang__) || defined(__GNUC__)
#        define SNITCH_EXPORT [[gnu::visibility("default")]]
#    else
#        define SNITCH_EXPORT
#    endif
#else
#    define SNITCH_EXPORT
#endif
    """.split("\n"))

    header.append("")
    header.append(f"#endif // {header_guard}")
    header.append("")

    with header_file_path.open("w+", encoding="utf-8") as header_file:
        header_file.write("\n".join(header))

def build_snitch(env):
    major_version = 1
    minor_version = 2
    patch_version = 5
    git_run = subprocess.run(["git", "describe", "--tags", "--abbrev=0"], text=True, cwd="snitch/", capture_output=True)
    if git_run.returncode == 0:
        tag = git_run.stdout.strip().removeprefix("v").split(".")
        major_version = tag[0]
        minor_version = tag[1]
        patch_version = tag[2]

    SHARED_BUILD = False
    HEADER_ONLY = False
    UNITY_BUILD = True

    SNITCH_VERSION = "{}.{}.{}".format(major_version, minor_version, patch_version)

    snitch_env = env.Clone()

    snitch_env.Append(
        BUILDERS={
            "GenerateSnitchConfig": snitch_env.Builder(action=generate_snitch_config_header)
        }
    )

    snitch_env.config_data = {
        "SNITCH_MAX_TEST_CASES": 5000, #"Maximum number of test cases in a test application."
        "SNITCH_MAX_NESTED_SECTIONS": 8,#"Maximum depth of nested sections in a test case."
        "SNITCH_MAX_EXPR_LENGTH": 1024, #"Maximum length of a printed expression when reporting failure."
        "SNITCH_MAX_MESSAGE_LENGTH": 1024, #"Maximum length of error or status messages."
        "SNITCH_MAX_TEST_NAME_LENGTH": 1024, #"Maximum length of a test case name."
        "SNITCH_MAX_TAG_LENGTH": 256, #"Maximum length of a test tag."
        "SNITCH_MAX_CAPTURES": 8, #"Maximum number of captured expressions in a test case."
        "SNITCH_MAX_CAPTURE_LENGTH": 256, #"Maximum length of a captured expression."
        "SNITCH_MAX_UNIQUE_TAGS": 1024, #"Maximum number of unique tags in a test application."
        "SNITCH_MAX_COMMAND_LINE_ARGS": 1024, #"Maximum number of command line arguments to a test application."
        "SNITCH_MAX_REGISTERED_REPORTERS": 8, #"Maximum number of registered reporter that can be selected from the command line."
        "SNITCH_MAX_PATH_LENGTH": 1024, #"Maximum length of a file path when writing output to file."
        "SNITCH_MAX_REPORTER_SIZE_BYTES": 128, #"Maximum size (in bytes) of a reporter object."

        "SNITCH_DEFINE_MAIN": 1, #"Define main() in snitch -- disable to provide your own main() function."
        "SNITCH_WITH_EXCEPTIONS": 0, #"Use exceptions in snitch implementation -- will be forced OFF if exceptions are not available."
        "SNITCH_WITH_MULTITHREADING": 0, #"Make the testing framework thread-safe -- disable if multithreading is not needed."
        "SNITCH_WITH_TIMINGS": 1, #"Measure the time taken by each test case -- disable to speed up tests."
        "SNITCH_WITH_SHORTHAND_MACROS": 1, #"Use short names for test macros -- disable if this causes conflicts."
        "SNITCH_CONSTEXPR_FLOAT_USE_BITCAST": 1, #"Use std::bit_cast if available to implement exact constexpr float-to-string conversion."
        "SNITCH_APPEND_TO_CHARS": 1, #"Use std::to_chars for string conversions -- disable for greater compatability with a slight performance cost."
        "SNITCH_DEFAULT_WITH_COLOR": 1, #"Enable terminal colors by default -- can also be controlled by command line interface."
        "SNITCH_DECOMPOSE_SUCCESSFUL_ASSERTIONS": 0, #"Enable expression decomposition even for successful assertions -- more expensive."
        "SNITCH_WITH_ALL_REPORTERS": 1, #"Allow all built-in reporters to be selected from the command line -- disable for faster compilation."
        "SNITCH_WITH_TEAMCITY_REPORTER": 0, #"Allow the TeamCity reporter to be selected from the command line -- enable if needed."
        "SNITCH_WITH_CATCH2_XML_REPORTER": 0, #"Allow the Catch2 XML reporter to be selected from the command line -- enable if needed."

        "SNITCH_HEADER_ONLY": 0, #"Create a single-header header-only version of snitch."
        "SNITCH_UNITY_BUILD": ("1" if UNITY_BUILD else "0"), #"Build sources as single file instead of separate files (faster full build)."
        "SNITCH_DO_TEST": 1, #"Build tests."
    }

    snitch_full_version = ""
    git_run = subprocess.run(["git", "log", "-1", "--format=%h"], text=True, cwd="snitch/", capture_output=True)
    if git_run.returncode == 0:
        snitch_full_version = git_run.stdout.strip()

    snitch_full_version = SNITCH_VERSION + (".{}".format(snitch_full_version) if snitch_full_version else "")

    snitch_env.Append(CPPDEFINES=[
        f'SNITCH_VERSION=\\"{SNITCH_VERSION}\\"',
        f'SNITCH_FULL_VERSION=\\"{snitch_full_version}\\"',
        f"SNITCH_VERSION_MAJOR={major_version}",
        f"SNITCH_VERSION_MINOR={minor_version}",
        f"SNITCH_VERSION_PATCH={patch_version}"
    ])
    snitch_env.Append(CPPDEFINES=["SNITCH_SHARED_LIBRARY=" + ("1" if not HEADER_ONLY and SHARED_BUILD else "0")])

    include_path = "snitch/include"
    source_path = "snitch/src"
    unity_source = "snitch.cpp"

    config = snitch_env.GenerateSnitchConfig(snitch_env.File(Path(include_path) / "snitch" / "snitch_config.hpp"), "SCsub")

    snitch_env.Append(CPPPATH=[[snitch_env.Dir(p) for p in [source_path, include_path]]])
    sources = snitch_env.GlobRecursive("*.cpp", [source_path], unity_source)

    if UNITY_BUILD:
        sources = [snitch_env.File(Path(source_path) / unity_source)]

    env.snitch_sources = sources

    if not HEADER_ONLY:
        library = None
        project_name = "snitch"
        library_name = "lib" + project_name + env["LIBSUFFIX"]
        if SHARED_BUILD:
            if snitch_env.get("is_msvc", False):
                pass
            else:
                snitch_env.Append(CXXFLAGS=["-fvisibility=hidden", "-fvisibility-inlines-hidden"])

            library = snitch_env.SharedLibrary(target=Path(source_path) / library_name, source=sources)
        else:
            library = snitch_env.StaticLibrary(target=Path(source_path) / library_name, source=sources)
            env.Append(LIBPATH=[snitch_env.Dir(source_path)])
            env.Prepend(LIBS=[library_name])

        Default([config, library])

        env.Append(CPPPATH=[snitch_env.Dir(include_path)])
    else:
        env.Append(CPPPATH=[[snitch_env.Dir(p) for p in [source_path, include_path]]])
        Default(config)

build_snitch(env)