summaryrefslogtreecommitdiff
path: root/tests/projects/c++/modules/test_base.lua
blob: 6116b36e6d6d882bbe7d4f5ec65d0d37cb0507f6 (plain)
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
202
203
204
205
206
207
208
209
210
211
import("lib.detect.find_tool")
import("core.base.semver")
import("core.tool.toolchain")
import("utils.ci.is_running", {alias = "ci_is_running"})

CLANG_MIN_VER = is_subhost("windows") and "19" or "17"
CLANG_CL_MIN_VER = "19"
GCC_MIN_VER = "11"
MSVC_MIN_VER = "14.29"

function _build(check_outdata)
    local flags = ""
    if ci_is_running() then
        flags = "-vD"
    end
    if check_outdata then
        local outdata
        outdata = os.iorun("xmake -r " ..  flags)
        if outdata then
            if outdata:find(check_outdata.str, 1, true) then
                raise(check_outdata.format_string .. "\n%s", outdata)
            end
        end
    else
        os.run("xmake -r " .. flags)
    end
    local outdata = os.iorun("xmake " .. flags)
    if outdata then
        if outdata:find("compiling", 1, true) or outdata:find("linking", 1, true) or outdata:find("generating", 1, true) then
            raise("Modules incremental compilation does not work\n%s", outdata)
        end
    end
end

function can_build()
    if is_subhost("windows") then
        return true
    elseif is_subhost("msys") then
        return true
    elseif is_host("linux") then
        local gcc = find_tool("gcc", {version = true})
        if gcc and gcc.version and semver.compare(gcc.version, GCC_MIN_VER) >= 0 then
            return true
        end
        local clang = find_tool("clang", {version = true})
        if clang and clang.version and semver.compare(clang.version, CLANG_MIN_VER) >= 0 then
            return true
        end
    end
end

function build_tests(toolchain_name, opt)
    assert(opt and opt.version)
    local version
    if is_subhost("windows") then
        local msvc = toolchain.load("msvc")
        if not msvc or not msvc:check() then
            wprint("msvc not found, skipping tests")
            return
        end
        local vcvars = msvc:config("vcvars")
        if not vcvars or not vcvars.VCInstallDir or not vcvars.VCToolsVersion then
            wprint("msvc not found, skipping tests")
            return
        end
        version = vcvars.VCToolsVersion
    end
    if opt.compiler then
        local cc = find_tool(opt.compiler, {version = true})
        if not cc then
            wprint(opt.compiler .. " not found, skipping tests")
            return
        end
        version = cc.version
    end

    local compiler = toolchain_name == "msvc" and "cl" or opt.compiler
    if not version or not (semver.compare(version, opt.version) >= 0) then
        local version_str = compiler ..  " >= " .. opt.version .. (version and " (found " .. version .. ")" or "") .. " "
        wprint(version_str .. "not found, skipping tests")
        return
    end

    local two_phases = (opt.two_phases == nil or opt.two_phases == true)
    local policies = "--policies=build.c++.modules.std:" .. (opt.stdmodule and "y" or "n")
    policies = policies .. ",build.c++.modules.fallbackscanner:" .. (opt.fallbackscanner and "y" or "n")
    policies = policies .. ",build.c++.modules.two_phases:" .. (two_phases and "y" or "n")

    local platform = " "
    if opt.platform then
        platform = " -p "  .. opt.platform .. " "
    end

    local runtimes = " "
    if opt.runtimes then
        runtimes = " --runtimes=" .. opt.runtimes .. " "
    end
    print("running with config: (toolchain: %s, compiler: %s, version: %s, runtimes: %s, stdmodule: %s, fallback scanner: %s, two phases: %s)",
        toolchain_name, compiler, version, opt.runtimes or "default", opt.stdmodule or false, opt.fallbackscanner or false, two_phases)

    local flags = ""
    if opt.flags then
        flags = " " .. table.concat(opt.flags, " ")
    end
    if ci_is_running() then
        flags = flags .. " -vD"
    end

    os.exec("xmake clean -a")
    os.exec("xmake f" .. platform .. "--toolchain=" .. toolchain_name .. runtimes .. "-c --yes " .. policies .. flags)
    if opt.build then
        opt.build()
    else
        _build(opt.check_outdata)
    end
    if opt.after_build then
        opt.after_build(platform, toolchain_name, runtimes, policies, flags)
    end
end

function run_tests(clang_options, gcc_options, msvc_options)
    local clang_libcpp_options
    if clang_options then
        clang_libcpp_options = table.clone(clang_options)
        clang_libcpp_options.runtimes = "c++_shared"
    end
    if is_subhost("windows") then
        if clang_options then
            build_tests("llvm", clang_options)
            build_tests("clang", clang_options)
            build_tests("clang", table.join(clang_options, {two_phases = false}))
            if not clang_options.disable_clang_cl then
                local clang_cl_options = table.clone(clang_options)
                clang_cl_options.compiler = "clang-cl"
                clang_cl_options.version = CLANG_CL_MIN_VER
                build_tests("clang-cl", clang_cl_options)
                build_tests("clang-cl", table.join(clang_options, {two_phases = false}))
            end
            if clang_options.stdmodule then
                wprint("std modules tests skipped for Windows clang libc++ as it's not currently supported officially")
            else
                build_tests("llvm", clang_libcpp_options)
                build_tests("clang", clang_libcpp_options)
                build_tests("clang", table.join(clang_libcpp_options, {two_phases = false}))
            end
        end
        if msvc_options then
            build_tests("msvc", msvc_options)
            build_tests("msvc", table.join(msvc_options, {two_phases = false}))
        end
    elseif is_subhost("macosx") then
        if clang_options then
            -- macOS doesn't ship clang-scan-deps currently
            if is_subhost("macosx") then
                -- check if normal clang is avalaible
                local regular_clang_available = false

                local outdata = os.iorun("clang --version")
                if outdata then
                    regular_clang_available = true
                    if outdata:find("Apple") then
                        regular_clang_available = false
                    end
                end
                if not regular_clang_available then
                    wprint("Appleclang isn't shipped with clang-scan-deps, disabling modules tests")
                    return
                end
            end
            build_tests("llvm", clang_options)
            build_tests("clang", clang_options)
            build_tests("clang", table.join(clang_options, {two_phases = false}))
        end
    elseif is_subhost("msys") then
        if clang_options then
            clang_options.platform = "mingw"
            clang_libcpp_options.platform = "mingw"
            build_tests("llvm", clang_options)
            build_tests("clang", clang_options)
            build_tests("clang", table.join(clang_options, {two_phases = false}))
            build_tests("llvm", clang_libcpp_options)
            build_tests("clang", clang_libcpp_options)
            build_tests("clang", table.join(clang_libcpp_options, {two_phases = false}))
        end
        if gcc_options then
            gcc_options.platform = "mingw"
            build_tests("gcc", gcc_options)
            build_tests("gcc", table.join(gcc_options, {two_phases = false}))
        end
    elseif is_host("linux") then
        if clang_options then
            build_tests("llvm", clang_options)
            build_tests("clang", clang_options)
            build_tests("clang", table.join(clang_options, {two_phases = false}))
            build_tests("llvm", clang_libcpp_options)
            build_tests("clang", clang_libcpp_options)
            build_tests("clang", table.join(clang_libcpp_options, {two_phases = false}))
        end
        if gcc_options then
            build_tests("gcc", gcc_options)
            build_tests("gcc", table.join(gcc_options, {two_phases = false}))
        end
    end
end

function main(_)
    local clang_options = {compiler = "clang", version = CLANG_MIN_VER}
    local gcc_options = {compiler = "gcc", version = GCC_MIN_VER}
    local msvc_options = {version = MSVC_MIN_VER}
    run_tests(clang_options, gcc_options, msvc_options)
end