xref: /aosp_15_r20/external/toolchain-utils/compiler_wrapper/clang_flags_test.go (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1*760c253cSXin Li// Copyright 2019 The ChromiumOS Authors
2*760c253cSXin Li// Use of this source code is governed by a BSD-style license that can be
3*760c253cSXin Li// found in the LICENSE file.
4*760c253cSXin Li
5*760c253cSXin Lipackage main
6*760c253cSXin Li
7*760c253cSXin Liimport (
8*760c253cSXin Li	"errors"
9*760c253cSXin Li	"fmt"
10*760c253cSXin Li	"io"
11*760c253cSXin Li	"path/filepath"
12*760c253cSXin Li	"strings"
13*760c253cSXin Li	"testing"
14*760c253cSXin Li)
15*760c253cSXin Li
16*760c253cSXin Lifunc TestClangBasename(t *testing.T) {
17*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
18*760c253cSXin Li		var tests = []struct {
19*760c253cSXin Li			in  string
20*760c253cSXin Li			out string
21*760c253cSXin Li		}{
22*760c253cSXin Li			{"./x86_64-cros-linux-gnu-clang", ".*/clang"},
23*760c253cSXin Li			{"./x86_64-cros-linux-gnu-clang++", ".*/clang\\+\\+"},
24*760c253cSXin Li		}
25*760c253cSXin Li
26*760c253cSXin Li		for _, tt := range tests {
27*760c253cSXin Li			cmd := ctx.must(callCompiler(ctx, ctx.cfg,
28*760c253cSXin Li				ctx.newCommand(tt.in, mainCc)))
29*760c253cSXin Li			if err := verifyPath(cmd, tt.out); err != nil {
30*760c253cSXin Li				t.Error(err)
31*760c253cSXin Li			}
32*760c253cSXin Li		}
33*760c253cSXin Li	})
34*760c253cSXin Li}
35*760c253cSXin Li
36*760c253cSXin Lifunc TestClangPathGivenClangEnv(t *testing.T) {
37*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
38*760c253cSXin Li		ctx.env = []string{"CLANG=/a/b/clang"}
39*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
40*760c253cSXin Li			ctx.newCommand(clangX86_64, mainCc)))
41*760c253cSXin Li		if err := verifyPath(cmd, "/a/b/clang"); err != nil {
42*760c253cSXin Li			t.Error(err)
43*760c253cSXin Li		}
44*760c253cSXin Li	})
45*760c253cSXin Li}
46*760c253cSXin Li
47*760c253cSXin Lifunc TestAbsoluteClangPathBasedOnRootPath(t *testing.T) {
48*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
49*760c253cSXin Li		ctx.cfg.clangRootRelPath = "somepath"
50*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
51*760c253cSXin Li			ctx.newCommand(filepath.Join(ctx.tempDir, clangX86_64), mainCc)))
52*760c253cSXin Li		if err := verifyPath(cmd, filepath.Join(ctx.tempDir, "somepath/usr/bin/clang")); err != nil {
53*760c253cSXin Li			t.Error(err)
54*760c253cSXin Li		}
55*760c253cSXin Li	})
56*760c253cSXin Li}
57*760c253cSXin Li
58*760c253cSXin Lifunc TestRelativeClangPathBasedOnRootPath(t *testing.T) {
59*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
60*760c253cSXin Li		ctx.cfg.clangRootRelPath = "somepath"
61*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
62*760c253cSXin Li			ctx.newCommand(clangX86_64, mainCc)))
63*760c253cSXin Li		if err := verifyPath(cmd, "somepath/usr/bin/clang"); err != nil {
64*760c253cSXin Li			t.Error(err)
65*760c253cSXin Li		}
66*760c253cSXin Li	})
67*760c253cSXin Li}
68*760c253cSXin Li
69*760c253cSXin Lifunc TestRelativeClangPathWithDirBasedOnRootPath(t *testing.T) {
70*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
71*760c253cSXin Li		ctx.cfg.clangRootRelPath = "somepath"
72*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
73*760c253cSXin Li			ctx.newCommand("test/x86_64-cros-linux-gnu-clang", mainCc)))
74*760c253cSXin Li		if err := verifyPath(cmd, "test/somepath/usr/bin/clang"); err != nil {
75*760c253cSXin Li			t.Error(err)
76*760c253cSXin Li		}
77*760c253cSXin Li	})
78*760c253cSXin Li}
79*760c253cSXin Li
80*760c253cSXin Lifunc TestPathEnvClangPathBasedOnRootPath(t *testing.T) {
81*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
82*760c253cSXin Li		ctx.cfg.clangRootRelPath = "somepath"
83*760c253cSXin Li		ctx.env = []string{"PATH=" + filepath.Join(ctx.tempDir, "/pathenv")}
84*760c253cSXin Li		ctx.writeFile(filepath.Join(ctx.tempDir, "/pathenv/x86_64-cros-linux-gnu-clang"), "")
85*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
86*760c253cSXin Li			ctx.newCommand("x86_64-cros-linux-gnu-clang", mainCc)))
87*760c253cSXin Li		if err := verifyPath(cmd, filepath.Join(ctx.tempDir, "pathenv/somepath/usr/bin/clang")); err != nil {
88*760c253cSXin Li			t.Error(err)
89*760c253cSXin Li		}
90*760c253cSXin Li	})
91*760c253cSXin Li}
92*760c253cSXin Li
93*760c253cSXin Lifunc TestClangPathForClangHostWrapper(t *testing.T) {
94*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
95*760c253cSXin Li		ctx.cfg.isHostWrapper = true
96*760c253cSXin Li		ctx.cfg.clangRootRelPath = "somepath"
97*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
98*760c253cSXin Li			ctx.newCommand(clangX86_64, mainCc)))
99*760c253cSXin Li		if err := verifyPath(cmd, filepath.Join(ctx.tempDir, "clang")); err != nil {
100*760c253cSXin Li			t.Error(err)
101*760c253cSXin Li		}
102*760c253cSXin Li	})
103*760c253cSXin Li}
104*760c253cSXin Li
105*760c253cSXin Lifunc TestClangPathForAndroidWrapper(t *testing.T) {
106*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
107*760c253cSXin Li		ctx.cfg.isAndroidWrapper = true
108*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
109*760c253cSXin Li			ctx.newCommand("somedir/clang", mainCc)))
110*760c253cSXin Li		if err := verifyPath(cmd, "somedir/clang.real"); err != nil {
111*760c253cSXin Li			t.Error(err)
112*760c253cSXin Li		}
113*760c253cSXin Li	})
114*760c253cSXin Li}
115*760c253cSXin Li
116*760c253cSXin Lifunc TestClangPathForAndroidWrapperWithSymlinks(t *testing.T) {
117*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
118*760c253cSXin Li		ctx.cfg.isAndroidWrapper = true
119*760c253cSXin Li		ctx.writeFile("base/come_clang", "")
120*760c253cSXin Li		ctx.symlink("base/some_clang", "linked/clang")
121*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
122*760c253cSXin Li			ctx.newCommand("linked/clang", mainCc)))
123*760c253cSXin Li		if err := verifyPath(cmd, "linked/some_clang.real"); err != nil {
124*760c253cSXin Li			t.Error(err)
125*760c253cSXin Li		}
126*760c253cSXin Li	})
127*760c253cSXin Li}
128*760c253cSXin Li
129*760c253cSXin Lifunc TestUseXclangPathAndCalcResourceDirByNestedClangCall(t *testing.T) {
130*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
131*760c253cSXin Li		ctx.cfg.clangRootRelPath = "somepath"
132*760c253cSXin Li		ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
133*760c253cSXin Li			if ctx.cmdCount > 1 {
134*760c253cSXin Li				return nil
135*760c253cSXin Li			}
136*760c253cSXin Li			if err := verifyPath(cmd, "somepath/usr/bin/clang"); err != nil {
137*760c253cSXin Li				t.Error(err)
138*760c253cSXin Li			}
139*760c253cSXin Li			if err := verifyArgOrder(cmd, "--print-resource-dir"); err != nil {
140*760c253cSXin Li				t.Error(err)
141*760c253cSXin Li			}
142*760c253cSXin Li			fmt.Fprint(stdout, "someResourcePath\n")
143*760c253cSXin Li			return nil
144*760c253cSXin Li		}
145*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
146*760c253cSXin Li			ctx.newCommand(clangX86_64, "-Xclang-path=somedir", mainCc)))
147*760c253cSXin Li		if err := verifyPath(cmd, "somedir/clang"); err != nil {
148*760c253cSXin Li			t.Error(err)
149*760c253cSXin Li		}
150*760c253cSXin Li		if err := verifyArgOrder(cmd, "-resource-dir=someResourcePath",
151*760c253cSXin Li			"--gcc-toolchain=/usr", mainCc); err != nil {
152*760c253cSXin Li			t.Error(err)
153*760c253cSXin Li		}
154*760c253cSXin Li	})
155*760c253cSXin Li}
156*760c253cSXin Li
157*760c253cSXin Lifunc TestXclangPathFailIfNestedClangCallFails(t *testing.T) {
158*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
159*760c253cSXin Li		ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
160*760c253cSXin Li			fmt.Fprint(stderr, "someclangerror")
161*760c253cSXin Li			return errors.New("someerror")
162*760c253cSXin Li		}
163*760c253cSXin Li		stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg,
164*760c253cSXin Li			ctx.newCommand(clangX86_64, "-Xclang-path=somedir", mainCc)))
165*760c253cSXin Li		if err := verifyInternalError(stderr); err != nil {
166*760c253cSXin Li			t.Fatal(err)
167*760c253cSXin Li		}
168*760c253cSXin Li		if !strings.Contains(stderr, "clang") {
169*760c253cSXin Li			t.Errorf("could not find compiler path on stderr. Got: %s", stderr)
170*760c253cSXin Li		}
171*760c253cSXin Li		if !strings.Contains(stderr, "someerror") {
172*760c253cSXin Li			t.Errorf("could not find original error on stderr. Got: %s", stderr)
173*760c253cSXin Li		}
174*760c253cSXin Li		if !strings.Contains(stderr, "someclangerror") {
175*760c253cSXin Li			t.Errorf("stderr was not forwarded. Got: %s", stderr)
176*760c253cSXin Li		}
177*760c253cSXin Li	})
178*760c253cSXin Li}
179*760c253cSXin Li
180*760c253cSXin Lifunc TestConvertGccToClangFlags(t *testing.T) {
181*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
182*760c253cSXin Li		var tests = []struct {
183*760c253cSXin Li			in  string
184*760c253cSXin Li			out string
185*760c253cSXin Li		}{
186*760c253cSXin Li			{"-Wno-error=maybe-uninitialized", "-Wno-error=uninitialized"},
187*760c253cSXin Li			{"-Wno-error=cpp", "-Wno-#warnings"},
188*760c253cSXin Li			{"-Xclang-only=-abc=xyz", "-abc=xyz"},
189*760c253cSXin Li		}
190*760c253cSXin Li
191*760c253cSXin Li		for _, tt := range tests {
192*760c253cSXin Li			cmd := ctx.must(callCompiler(ctx, ctx.cfg,
193*760c253cSXin Li				ctx.newCommand(clangX86_64, tt.in, mainCc)))
194*760c253cSXin Li			if err := verifyArgCount(cmd, 0, tt.in); err != nil {
195*760c253cSXin Li				t.Error(err)
196*760c253cSXin Li			}
197*760c253cSXin Li			if err := verifyArgOrder(cmd, tt.out, mainCc); err != nil {
198*760c253cSXin Li				t.Error(err)
199*760c253cSXin Li			}
200*760c253cSXin Li		}
201*760c253cSXin Li	})
202*760c253cSXin Li}
203*760c253cSXin Li
204*760c253cSXin Lifunc TestFilterUnsupportedClangFlags(t *testing.T) {
205*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
206*760c253cSXin Li		var tests = []struct {
207*760c253cSXin Li			compiler      string
208*760c253cSXin Li			flag          string
209*760c253cSXin Li			expectedCount int
210*760c253cSXin Li		}{
211*760c253cSXin Li			{clangX86_64, "-Wstrict-aliasing=xyz", 0},
212*760c253cSXin Li			{clangX86_64, "-finline-limit=xyz", 0},
213*760c253cSXin Li			{"./armv7a-cros-linux-gnu-clang", "-ftrapv", 0},
214*760c253cSXin Li			{"./armv7a-cros-win-gnu-clang", "-ftrapv", 1},
215*760c253cSXin Li			{"./armv8a-cros-win-gnu-clang", "-ftrapv", 1},
216*760c253cSXin Li			{clangX86_64, "-ftrapv", 1},
217*760c253cSXin Li		}
218*760c253cSXin Li
219*760c253cSXin Li		for _, tt := range tests {
220*760c253cSXin Li			cmd := ctx.must(callCompiler(ctx, ctx.cfg,
221*760c253cSXin Li				ctx.newCommand(tt.compiler, tt.flag, mainCc)))
222*760c253cSXin Li			if err := verifyArgCount(cmd, tt.expectedCount, tt.flag); err != nil {
223*760c253cSXin Li				t.Error(err)
224*760c253cSXin Li			}
225*760c253cSXin Li		}
226*760c253cSXin Li	})
227*760c253cSXin Li}
228*760c253cSXin Li
229*760c253cSXin Lifunc TestClangArchFlags(t *testing.T) {
230*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
231*760c253cSXin Li		var tests = []struct {
232*760c253cSXin Li			compiler string
233*760c253cSXin Li			flags    []string
234*760c253cSXin Li		}{
235*760c253cSXin Li			{"./i686_64-cros-linux-gnu-clang", []string{mainCc, "-target", "i686_64-cros-linux-gnu"}},
236*760c253cSXin Li			{"./x86_64-cros-linux-gnu-clang", []string{mainCc, "-target", "x86_64-cros-linux-gnu"}},
237*760c253cSXin Li		}
238*760c253cSXin Li		for _, tt := range tests {
239*760c253cSXin Li			cmd := ctx.must(callCompiler(ctx, ctx.cfg,
240*760c253cSXin Li				ctx.newCommand(tt.compiler, mainCc)))
241*760c253cSXin Li			if err := verifyArgOrder(cmd, tt.flags...); err != nil {
242*760c253cSXin Li				t.Error(err)
243*760c253cSXin Li			}
244*760c253cSXin Li		}
245*760c253cSXin Li	})
246*760c253cSXin Li}
247*760c253cSXin Li
248*760c253cSXin Lifunc TestClangLinkerPathProbesBinariesOnPath(t *testing.T) {
249*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
250*760c253cSXin Li		linkerPath := filepath.Join(ctx.tempDir, "a/b/c")
251*760c253cSXin Li		ctx.writeFile(filepath.Join(linkerPath, "x86_64-cros-linux-gnu-ld.bfd"), "")
252*760c253cSXin Li		ctx.env = []string{"PATH=nonExistantPath:" + linkerPath}
253*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
254*760c253cSXin Li			ctx.newCommand("./x86_64-cros-linux-gnu-clang", mainCc)))
255*760c253cSXin Li		if err := verifyArgOrder(cmd, "-Ba/b/c"); err != nil {
256*760c253cSXin Li			t.Error(err)
257*760c253cSXin Li		}
258*760c253cSXin Li		if err := verifyArgOrder(cmd, "--prefix=a/b/c/x86_64-cros-linux-gnu-"); err != nil {
259*760c253cSXin Li			t.Error(err)
260*760c253cSXin Li		}
261*760c253cSXin Li
262*760c253cSXin Li	})
263*760c253cSXin Li}
264*760c253cSXin Li
265*760c253cSXin Lifunc TestClangLinkerPathEvaluatesSymlinksForBinariesOnPath(t *testing.T) {
266*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
267*760c253cSXin Li		realLinkerPath := filepath.Join(ctx.tempDir, "a/original/path/somelinker")
268*760c253cSXin Li		ctx.writeFile(realLinkerPath, "")
269*760c253cSXin Li		firstLinkLinkerPath := filepath.Join(ctx.tempDir, "a/first/somelinker")
270*760c253cSXin Li		ctx.symlink(realLinkerPath, firstLinkLinkerPath)
271*760c253cSXin Li		secondLinkLinkerPath := filepath.Join(ctx.tempDir, "a/second/x86_64-cros-linux-gnu-ld.bfd")
272*760c253cSXin Li		ctx.symlink(firstLinkLinkerPath, secondLinkLinkerPath)
273*760c253cSXin Li
274*760c253cSXin Li		ctx.env = []string{"PATH=nonExistantPath:" + filepath.Dir(secondLinkLinkerPath)}
275*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
276*760c253cSXin Li			ctx.newCommand("./x86_64-cros-linux-gnu-clang", mainCc)))
277*760c253cSXin Li		if err := verifyArgOrder(cmd, "-Ba/first"); err != nil {
278*760c253cSXin Li			t.Error(err)
279*760c253cSXin Li		}
280*760c253cSXin Li		if err := verifyArgOrder(cmd, "--prefix=a/first/x86_64-cros-linux-gnu-"); err != nil {
281*760c253cSXin Li			t.Error(err)
282*760c253cSXin Li		}
283*760c253cSXin Li
284*760c253cSXin Li	})
285*760c253cSXin Li}
286*760c253cSXin Li
287*760c253cSXin Lifunc TestClangFallbackLinkerPathRelativeToRootDir(t *testing.T) {
288*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
289*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
290*760c253cSXin Li			ctx.newCommand(clangX86_64, mainCc)))
291*760c253cSXin Li		if err := verifyArgOrder(cmd, "-Bbin"); err != nil {
292*760c253cSXin Li			t.Error(err)
293*760c253cSXin Li		}
294*760c253cSXin Li		if err := verifyArgOrder(cmd, "--prefix=bin/x86_64-cros-linux-gnu-"); err != nil {
295*760c253cSXin Li			t.Error(err)
296*760c253cSXin Li		}
297*760c253cSXin Li	})
298*760c253cSXin Li}
299*760c253cSXin Li
300*760c253cSXin Lifunc TestClangLinkerPathRelativeToRootDir(t *testing.T) {
301*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
302*760c253cSXin Li		ctx.cfg.clangRootRelPath = "somepath"
303*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
304*760c253cSXin Li			ctx.newCommand(clangX86_64, mainCc)))
305*760c253cSXin Li		if err := verifyArgOrder(cmd, "-Bsomepath/bin"); err != nil {
306*760c253cSXin Li			t.Error(err)
307*760c253cSXin Li		}
308*760c253cSXin Li		if err := verifyArgOrder(cmd, "--prefix=somepath/bin/x86_64-cros-linux-gnu-"); err != nil {
309*760c253cSXin Li			t.Error(err)
310*760c253cSXin Li		}
311*760c253cSXin Li	})
312*760c253cSXin Li}
313*760c253cSXin Li
314*760c253cSXin Lifunc TestFilterUnsupportedFlags(t *testing.T) {
315*760c253cSXin Li	withTestContext(t, func(ctx *testContext) {
316*760c253cSXin Li		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
317*760c253cSXin Li			ctx.newCommand(clangX86_64, "-Xcompiler", mainCc)))
318*760c253cSXin Li		if err := verifyArgCount(cmd, 0, "-Xcompiler"); err != nil {
319*760c253cSXin Li			t.Error(err)
320*760c253cSXin Li		}
321*760c253cSXin Li		cmd = ctx.must(callCompiler(ctx, ctx.cfg,
322*760c253cSXin Li			ctx.newCommand(clangX86_64, "-avoid-version", mainCc)))
323*760c253cSXin Li		if err := verifyArgCount(cmd, 0, "-avoid-version"); err != nil {
324*760c253cSXin Li			t.Error(err)
325*760c253cSXin Li		}
326*760c253cSXin Li	})
327*760c253cSXin Li}
328