2 # Copyright 2014 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
12 from driver_env import env
13 import driver_test_utils
17 class TestPrecompiledHeaders(driver_test_utils.DriverTesterCommon):
19 super(TestPrecompiledHeaders, self).setUp()
20 driver_test_utils.ApplyTestEnvOverrides(env)
21 self.exit_backup = sys.exit
22 sys.exit = driver_test_utils.FakeExit
23 self.temp_dir = tempfile.mkdtemp()
26 # Reset some internal state.
27 sys.exit = self.exit_backup
28 filetype.ClearFileTypeCaches()
29 filetype.SetForcedFileType(None)
30 shutil.rmtree(self.temp_dir)
31 super(TestPrecompiledHeaders, self).tearDown()
33 def runDriver(self, driver, flags):
34 driver_tools.RunDriver(driver, flags)
35 # Reset some internal state.
36 filetype.ClearFileTypeCaches()
37 filetype.SetForcedFileType(None)
39 def getFirstTestHeader(self, suffix='.h'):
40 filename = os.path.join(self.temp_dir, 'test_foo' + suffix)
41 with open(filename, 'w') as t:
43 #ifndef _PNACL_DRIVER_TESTS_TEST_HEADER_H_
44 #define _PNACL_DRIVER_TESTS_TEST_HEADER_H_
46 void foo_cxx(int x, int y);
53 def getSecondTestHeader(self, first_header, suffix='.h'):
54 filename = os.path.join(self.temp_dir, 'test_bar' + suffix)
55 with open(filename, 'w') as t:
62 '''.format(header=first_header))
65 def getTestSource(self, header_name, suffix='.c'):
66 filename = os.path.join(self.temp_dir, 'test_source' + suffix)
67 with open(filename, 'w') as t:
68 t.write('''#include <%s>
77 #endif''' % header_name)
80 def compileAndCheck(self, driver, header, source, is_cxx):
81 source_base, _ = os.path.splitext(source)
82 out = source_base + '.ll'
83 self.runDriver(driver,
84 ['-include', header, '-S', source, '-o', out])
85 self.checkCompiledAs(out, is_cxx=is_cxx)
87 def checkCompiledAs(self, out, is_cxx):
88 with open(out, 'r') as t:
90 self.assertTrue('foo_cxx' in t.read())
92 self.assertTrue('bar_c' in t.read())
94 #---- Actual tests -----#
96 def test_one_with_xlang(self):
97 """Test compiling one PCH file with an explicit -x, but no -o"""
98 h = self.getFirstTestHeader(suffix='.h')
99 h2 = self.getSecondTestHeader(h.name, suffix='.h')
100 self.runDriver('pnacl-clang',
101 ['-x', 'c-header', '-I', self.temp_dir, h2.name])
102 s = self.getTestSource(h2.name)
103 self.compileAndCheck('pnacl-clang', h2.name, s.name, is_cxx=False)
105 def test_one_override_output(self):
106 """Test compiling one PCH file with an explicit -o <output>"""
107 h = self.getFirstTestHeader(suffix='.h')
108 h2 = self.getSecondTestHeader(h.name, suffix='.h')
109 h2_out = h2.name + 'fancy.pch'
110 self.assertFalse(os.path.exists(h2_out))
111 self.runDriver('pnacl-clang',
112 ['-x', 'c-header', '-I', self.temp_dir, h2.name,
114 self.assertTrue(os.path.exists(h2_out))
115 s = self.getTestSource(h2.name)
116 self.compileAndCheck('pnacl-clang', h2.name, s.name, is_cxx=False)
118 def test_two_with_xlang(self):
119 """Test compiling two PCH files with an explicit -x"""
120 # Specifying multiple header files without something like -c, or -S
121 # should be fine. It should not attempt to compile and link like what
122 # would happen if there were .c or .cpp files without -c, or -S.
123 h = self.getFirstTestHeader(suffix='.h')
124 h2 = self.getSecondTestHeader(h.name, suffix='.h')
125 self.runDriver('pnacl-clang',
126 ['-x', 'c-header', '-I', self.temp_dir, h.name, h2.name])
127 self.assertTrue(os.path.exists(driver_tools.DefaultPCHOutputName(h.name)))
128 self.assertTrue(os.path.exists(driver_tools.DefaultPCHOutputName(h2.name)))
129 s = self.getTestSource(h2.name)
130 self.compileAndCheck('pnacl-clang', h2.name, s.name, is_cxx=False)
132 def test_ignored_dash_mode(self):
133 """Test that compiling PCH (essentially) ignores -c, -S, but not -E"""
134 h = self.getFirstTestHeader(suffix='.h')
135 self.runDriver('pnacl-clang',
136 ['-c', '-x', 'c-header', '-I', self.temp_dir, h.name])
137 h2 = self.getSecondTestHeader(h.name, suffix='.h')
138 self.runDriver('pnacl-clang',
139 ['-S', '-x', 'c-header', '-I', self.temp_dir, h2.name])
140 s = self.getTestSource(h2.name)
141 self.compileAndCheck('pnacl-clang', h2.name, s.name, is_cxx=False)
143 def test_not_ignore_dash_E(self):
144 """Test that compiling PCH does not ignore -E"""
145 h = self.getFirstTestHeader(suffix='.h')
146 self.runDriver('pnacl-clang',
147 ['-E', '-x', 'c-header', '-I', self.temp_dir, h.name])
148 self.assertFalse(os.path.exists(driver_tools.DefaultPCHOutputName(h.name)))
150 def test_two_no_xlang(self):
151 """Test compiling two PCH files without a -x (guess from suffix/driver)"""
152 h = self.getFirstTestHeader(suffix='.h')
153 h2 = self.getSecondTestHeader(h.name, suffix='.h')
154 self.runDriver('pnacl-clang',
155 ['-I', self.temp_dir, h.name, h2.name])
156 s = self.getTestSource(h2.name)
157 self.compileAndCheck('pnacl-clang', h2.name, s.name, is_cxx=False)
159 def test_hpp_no_xlang_clangxx(self):
160 """Test what happens when using clang++ without a -x <...> / .hpp file"""
161 h = self.getFirstTestHeader(suffix='.hpp')
162 h2 = self.getSecondTestHeader(h.name, suffix='.hpp')
163 self.runDriver('pnacl-clang++',
164 ['-I', self.temp_dir, h2.name])
165 s = self.getTestSource(h2.name, suffix='.cc')
166 self.compileAndCheck('pnacl-clang++', h2.name, s.name, is_cxx=True)
168 def test_h_clangxx(self):
169 """Test what happens when using clang++ but -x c++-header and .h file"""
170 # We cannot test .h with clang++ and without a -x c++-header.
171 # clang will actually say: "warning: treating 'c-header' input as
172 # 'c++-header' when in C++ mode, this behavior is deprecated."
173 # The way the pnacl drivers intercept -x and cache filetypes also
174 # makes that difficult to distinguish between the -x c-header case and the
176 h = self.getFirstTestHeader(suffix='.h')
177 h2 = self.getSecondTestHeader(h.name, suffix='.h')
178 self.runDriver('pnacl-clang++',
179 ['-x', 'c++-header', '-I', self.temp_dir, h2.name])
180 s = self.getTestSource(h2.name, suffix='.cc')
181 self.compileAndCheck('pnacl-clang++', h2.name, s.name, is_cxx=True)
183 def test_hpp_no_xlang_clang(self):
184 """Test what happens when using clang with no -x <...> / .hpp file"""
185 h = self.getFirstTestHeader(suffix='.hpp')
186 h2 = self.getSecondTestHeader(h.name, suffix='.hpp')
187 self.runDriver('pnacl-clang',
188 ['-I', self.temp_dir, h2.name])
189 s = self.getTestSource(h2.name, suffix='.cc')
190 self.compileAndCheck('pnacl-clang', h2.name, s.name, is_cxx=True)
192 def test_mixed_headers_other(self):
193 """Test that we throw an error when trying to mix doing PCH w/ compiling"""
194 h = self.getFirstTestHeader(suffix='.hpp')
195 h2 = self.getSecondTestHeader(h.name, suffix='.hpp')
196 s = self.getTestSource(h2.name, suffix='.cc')
197 self.assertRaises(driver_test_utils.DriverExitException,
200 ['-I', self.temp_dir, h2.name, '-c', s.name])
202 def test_relocatable_header(self):
203 """Tests that the driver accepts --relocatable-header."""
204 h = self.getFirstTestHeader(suffix='.h')
205 h2 = self.getSecondTestHeader(h.name, suffix='.h')
206 driver_tools.RunDriver('pnacl-clang',
207 ['-x', 'c-header', '--relocatable-pch',
208 '-isysroot', self.temp_dir, h2.name])