Esempio n. 1
0
 def test_ensure_file_error(self):
     with named_directory() as d, working_directory(d):
         self.assertFalse(os.path.exists('test'))
         goma_link.ensure_file('test')
         self.assertTrue(os.path.exists('test'))
         self.assertRaises(OSError, goma_link.ensure_file,
                           'test/impossible')
 def test_fallback_lto(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'main.cpp', '-o',
             'main.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'foo.cpp', '-o',
             'foo.o'
         ])
         rc = goma_ld.GomaLinkUnix().main([
             'goma_ld.py', '--gomacc', 'gomacc', '--',
             self.clangxx(), '-fuse-ld=lld', '-flto=thin', 'main.o',
             'foo.o', '-o', 'main'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # lto.main directory should not be present.
         self.assertFalse(os.path.exists(os.path.join(d, 'lto.main')))
         # Check that main does not call foo.
         disasm = subprocess.check_output(['llvm-objdump', '-d', 'main'])
         main_idx = disasm.index(b' <main>:\n')
         after_main_idx = disasm.index(b'\n\n', main_idx)
         main_disasm = disasm[main_idx:after_main_idx]
         self.assertNotIn(b'foo', main_disasm)
 def test_no_gomacc(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'main.cpp', '-o',
             'main.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'foo.cpp', '-o',
             'foo.o'
         ])
         rc = GomaLinkUnixWhitelistMain().main([
             'goma_ld.py', '--no-gomacc', '-j', '16', '--',
             self.clangxx(), '-fuse-ld=lld', '-flto=thin', 'main.o',
             'foo.o', '-o', 'main'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # build.ninja file should not have gomacc invocations in it.
         with open(os.path.join(d, 'lto.main', 'build.ninja')) as f:
             buildrules = f.read()
             self.assertNotIn('gomacc ', buildrules)
             self.assertIn('build lto.main/main.o : codegen ', buildrules)
             self.assertIn('build lto.main/foo.o : codegen ', buildrules)
         # Check that main does not call foo.
         disasm = subprocess.check_output(['llvm-objdump', '-d', 'main'])
         main_idx = disasm.index(b' <main>:\n')
         after_main_idx = disasm.index(b'\n\n', main_idx)
         main_disasm = disasm[main_idx:after_main_idx]
         self.assertNotIn(b'foo', main_disasm)
 def test_debug_params(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         os.makedirs('obj')
         subprocess.check_call([
             self.clangxx(), '-c', '-g', '-gsplit-dwarf', '-flto=thin',
             'main.cpp', '-o', 'obj/main.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-g', '-gsplit-dwarf', '-flto=thin',
             'foo.cpp', '-o', 'obj/foo.o'
         ])
         with open('main.rsp', 'w') as f:
             f.write('obj/main.o\n' 'obj/foo.o\n')
         rc = GomaLinkUnixWhitelistMain().main([
             'goma_ld.py',
             self.clangxx(), '-fuse-ld=lld', '-flto=thin', '-g',
             '-gsplit-dwarf', '-Wl,--lto-O2', '-o', 'main', '@main.rsp'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # Check debug info present, refers to .dwo file, and does not
         # contain full debug info for foo.cpp.
         dbginfo = subprocess.check_output(
             ['llvm-dwarfdump', '-debug-info',
              'main']).decode('utf-8', 'backslashreplace')
         self.assertRegexpMatches(dbginfo,
                                  '\\bDW_AT_GNU_dwo_name\\b.*\\.dwo"')
         self.assertNotRegexpMatches(dbginfo,
                                     '\\bDW_AT_name\\b.*foo\\.cpp"')
Esempio n. 5
0
 def test_override_allowlist(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'main.cpp', '-o',
             'main.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'foo.cpp', '-o',
             'foo.o'
         ])
         rc = goma_ld.GomaLinkUnix().main([
             'goma_ld.py', '--generate', '--allowlist', '--',
             self.clangxx(), '-fuse-ld=lld', '-flto=thin', 'main.o',
             'foo.o', '-o', 'main'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # build.ninja file should have rules for main and foo.
         ninjafile = os.path.join(d, 'lto.main', 'build.ninja')
         self.assertTrue(os.path.exists(ninjafile))
         with open(ninjafile) as f:
             buildrules = f.read()
             self.assertIn('build lto.main/main.o.stamp : codegen ',
                           buildrules)
             self.assertIn('build lto.main/foo.o.stamp : codegen ',
                           buildrules)
Esempio n. 6
0
 def test_distributed_lto_common_objs(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         os.makedirs('obj')
         subprocess.check_call([
             self.clangcl(), '-c', '-Os', '-flto=thin', 'main.cpp',
             '-Foobj/main.obj'
         ])
         subprocess.check_call([
             self.clangcl(), '-c', '-Os', '-flto=thin', 'foo.cpp',
             '-Foobj/foo.obj'
         ])
         subprocess.check_call([
             self.clangcl(), '-c', '-Os', '-flto=thin', 'bar.cpp',
             '-Foobj/bar.obj'
         ])
         subprocess.check_call([
             'llvm-ar', 'crsT', 'obj/foobar.lib', 'obj/bar.obj',
             'obj/foo.obj'
         ])
         with open('main.rsp', 'w') as f:
             f.write('obj/main.obj\n' 'obj/foobar.lib\n')
         with open('my_goma.sh', 'w') as f:
             f.write('#! /bin/sh\n\ngomacc "$@"\n')
         os.chmod('my_goma.sh', 0o755)
         rc = goma_link.GomaLinkWindows().main([
             'goma_link.py', '--gomacc', './my_goma.sh', '--',
             self.lld_link(), '-nodefaultlib', '-entry:main',
             '-out:main.exe', '@main.rsp'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # Check codegen parameters.
         with open(os.path.join(d, 'lto.main.exe', 'build.ninja')) as f:
             buildrules = f.read()
             codegen_match = re.search('^rule codegen\\b.*?^[^ ]',
                                       buildrules, re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(codegen_match)
             codegen_text = codegen_match.group(0)
             self.assertIn('my_goma.sh', codegen_text)
             self.assertNotIn('-flto', codegen_text)
             self.assertIn(
                 'build common_objs/obj/main.obj.stamp : codegen ',
                 buildrules)
             self.assertIn('build common_objs/obj/foo.obj.stamp : codegen ',
                           buildrules)
             self.assertIn(' index = common_objs/empty.thinlto.bc',
                           buildrules)
             link_match = re.search(
                 '^build main.exe : native-link\\b.*?^[^ ]', buildrules,
                 re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(link_match)
             link_text = link_match.group(0)
             self.assertNotIn('main.exe.split.obj', link_text)
         # Check that main does not call foo.
         disasm = subprocess.check_output(
             ['llvm-objdump', '-d', 'main.exe'])
         # There are no symbols in the disassembly, but we're expecting two
         # functions, one of which calls the other.
         self.assertTrue(b'call' in disasm or b'jmp' in disasm)
Esempio n. 7
0
 def test_distributed_lto_allowlist(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         os.makedirs('obj')
         subprocess.check_call([
             self.clangcl(), '-c', '-Os', '-flto=thin', '-m32', 'main.cpp',
             '-Foobj/main.obj'
         ])
         subprocess.check_call([
             self.clangcl(), '-c', '-Os', '-flto=thin', '-m32', 'foo.cpp',
             '-Foobj/foo.obj'
         ])
         subprocess.check_call([
             self.clangcl(), '-c', '-Os', '-flto=thin', '-m32', 'bar.cpp',
             '-Foobj/bar.obj'
         ])
         subprocess.check_call([
             'llvm-ar', 'crsT', 'obj/foobar.lib', 'obj/bar.obj',
             'obj/foo.obj'
         ])
         with open('main.rsp', 'w') as f:
             f.write('obj/main.obj\n' 'obj/foobar.lib\n')
         rc = GomaLinkWindowsAllowMain().main([
             'goma_link.py', '--gomacc', 'gomacc', '--',
             self.lld_link(), '-nodefaultlib', '-entry:main',
             '-machine:X86', '-opt:lldlto=2',
             '-mllvm:-import-instr-limit=10', '-out:main.exe', '@main.rsp'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # Check codegen parameters.
         with open(os.path.join(d, 'lto.main.exe', 'build.ninja')) as f:
             buildrules = f.read()
             codegen_match = re.search('^rule codegen\\b.*?^[^ ]',
                                       buildrules, re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(codegen_match)
             codegen_text = codegen_match.group(0)
             self.assertIn('gomacc', codegen_text)
             self.assertIn('-m32', codegen_text)
             self.assertIn('-mllvm -import-instr-limit=10', codegen_text)
             self.assertNotIn('-flto', codegen_text)
             self.assertIn(
                 'build lto.main.exe/obj/main.obj.stamp : codegen ',
                 buildrules)
             self.assertIn(
                 'build lto.main.exe/obj/foo.obj.stamp : codegen ',
                 buildrules)
             link_match = re.search(
                 '^build main.exe : native-link\\b.*?^[^ ]', buildrules,
                 re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(link_match)
             link_text = link_match.group(0)
             self.assertIn('main.exe.split.obj', link_text)
         # Check that main does not call foo.
         disasm = subprocess.check_output(
             ['llvm-objdump', '-d', 'main.exe'])
         # There are no symbols in the disassembly, but we're expecting a single
         # function, with no calls or jmps.
         self.assertNotIn(b'jmp', disasm)
         self.assertNotIn(b'call', disasm)
 def test_ensure_file_existing(self):
   with named_directory() as d, working_directory(d):
     self.assertFalse(os.path.exists('foo/test'))
     goma_link.ensure_file('foo/test')
     self.assertTrue(os.path.exists('foo/test'))
     os.utime('foo/test', (0, 0))
     statresult = os.stat('foo/test')
     goma_link.ensure_file('foo/test')
     self.assertTrue(os.path.exists('foo/test'))
     newstatresult = os.stat('foo/test')
     self.assertEqual(newstatresult.st_mtime, statresult.st_mtime)
Esempio n. 9
0
 def test_generate_no_codegen(self):
     with named_directory() as d, working_directory(d):
         with open('main.o', 'wb') as f:
             f.write(b'\7fELF')
         with mock.patch('sys.stderr', new_callable=StringIO) as stderr:
             rc = GomaLinkUnixAllowMain().main([
                 'goma_ld.py', '--generate', '--',
                 self.clangxx(), 'main.o', '-o', 'main'
             ])
             self.assertEqual(rc, 5)
             self.assertIn('no ninja file generated.\n', stderr.getvalue())
Esempio n. 10
0
 def test_generate(self):
     with named_directory() as d, working_directory(d):
         with open('main.o', 'wb') as f:
             f.write(b'BC\xc0\xde')
         with mock.patch('sys.stderr', new_callable=StringIO) as stderr:
             rc = GomaLinkUnixAllowMain().main([
                 'goma_ld.py', '--generate', '--',
                 self.clangxx(), 'main.o', '-o', 'main'
             ])
             self.assertEqual(rc, 0)
             m = re.search('ninja file (.*)', stderr.getvalue())
             self.assertIsNotNone(m)
             path = shlex.split(m.group(1))[0]
             self.assertTrue(os.path.exists(path))
             content = open(path).read()
             self.assertRegex(
                 content,
                 re.compile('^build [^:]+/main\\.o\\.stamp : codegen ',
                            re.MULTILINE))
Esempio n. 11
0
 def test_distributed_lto_thin_archive_subdir(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         os.makedirs('obj')
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'main.cpp', '-o',
             'obj/main.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'foo.cpp', '-o',
             'obj/foo.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', 'bar.cpp', '-o',
             'obj/bar.o'
         ])
         subprocess.check_call([
             'llvm-ar', 'crsT', 'obj/libfoobar.a', 'obj/bar.o', 'obj/foo.o'
         ])
         rc = GomaLinkUnixAllowMain().main([
             'goma_ld.py',
             self.clangxx(), '-fuse-ld=lld', '-flto=thin', 'obj/main.o',
             'obj/libfoobar.a', '-o', 'main'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # build.ninja file should have gomacc invocations in it.
         with open(os.path.join(d, 'lto.main', 'build.ninja')) as f:
             buildrules = f.read()
             self.assertIn('gomacc ', buildrules)
             self.assertIn('build lto.main/obj/main.o.stamp : codegen ',
                           buildrules)
             self.assertIn('build lto.main/obj/foo.o.stamp : codegen ',
                           buildrules)
         # Check that main does not call foo.
         disasm = subprocess.check_output(['llvm-objdump', '-d', 'main'])
         main_idx = disasm.index(b' <main>:\n')
         after_main_idx = disasm.index(b'\n\n', main_idx)
         main_disasm = disasm[main_idx:after_main_idx]
         self.assertNotIn(b'foo', main_disasm)
Esempio n. 12
0
 def test_override_allowlist(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         os.makedirs('obj')
         subprocess.check_call([
             self.clangcl(), '-c', '-O2', '-flto=thin', 'main.cpp',
             '-Foobj/main.obj'
         ])
         subprocess.check_call([
             self.clangcl(), '-c', '-O2', '-flto=thin', 'foo.cpp',
             '-Foobj/foo.obj'
         ])
         rc = goma_link.GomaLinkWindows().main([
             'goma_link.py', '--generate', '--allowlist', '--',
             self.lld_link(), '-nodefaultlib', '-entry:main',
             '-opt:lldlto=2', '-out:main.exe', 'obj/main.obj', 'obj/foo.obj'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # Check that we have rules for main and foo, and that they are
         # not common objects.
         with open(os.path.join(d, 'lto.main.exe', 'build.ninja')) as f:
             buildrules = f.read()
             codegen_match = re.search(r'^rule codegen\b.*?^[^ ]',
                                       buildrules, re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(codegen_match)
             codegen_text = codegen_match.group(0)
             self.assertNotIn('-flto', codegen_text)
             self.assertIn(
                 'build lto.main.exe/obj/main.obj.stamp : codegen ',
                 buildrules)
             self.assertIn(
                 'build lto.main.exe/obj/foo.obj.stamp : codegen ',
                 buildrules)
             link_match = re.search(
                 r'^build main.exe : native-link\b.*?^[^ ]', buildrules,
                 re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(link_match)
Esempio n. 13
0
 def test_ensure_file_no_dir(self):
   with named_directory() as d, working_directory(d):
     self.assertFalse(os.path.exists('test'))
     goma_link.ensure_file('test')
     self.assertTrue(os.path.exists('test'))
 def test_distributed_lto_params(self):
     with named_directory() as d, working_directory(d):
         _create_inputs(d)
         os.makedirs('obj')
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', '-m32',
             '-fsplit-lto-unit', '-fwhole-program-vtables', 'main.cpp',
             '-o', 'obj/main.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', '-m32',
             '-fsplit-lto-unit', '-fwhole-program-vtables', 'foo.cpp', '-o',
             'obj/foo.o'
         ])
         subprocess.check_call([
             self.clangxx(), '-c', '-Os', '-flto=thin', '-m32',
             '-fsplit-lto-unit', '-fwhole-program-vtables', 'bar.cpp', '-o',
             'obj/bar.o'
         ])
         subprocess.check_call([
             'llvm-ar', 'crsT', 'obj/libfoobar.a', 'obj/bar.o', 'obj/foo.o'
         ])
         with open('main.rsp', 'w') as f:
             f.write('-fsplit-lto-unit\n'
                     '-fwhole-program-vtables\n'
                     'obj/main.o\n'
                     'obj/libfoobar.a\n')
         rc = GomaLinkUnixWhitelistMain().main([
             'goma_ld.py',
             self.clangxx(), '-fuse-ld=lld', '-flto=thin', '-m32',
             '-Wl,-mllvm', '-Wl,-generate-type-units', '-Wl,--lto-O2', '-o',
             'main', '-Wl,--start-group', '@main.rsp', '-Wl,--end-group'
         ])
         # Should succeed.
         self.assertEqual(rc, 0)
         # Check codegen parameters.
         with open(os.path.join(d, 'lto.main', 'build.ninja')) as f:
             buildrules = f.read()
             codegen_match = re.search('^rule codegen\\b.*?^[^ ]',
                                       buildrules, re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(codegen_match)
             codegen_text = codegen_match.group(0)
             self.assertIn('gomacc', codegen_text)
             self.assertIn('-m32', codegen_text)
             self.assertIn('-mllvm -generate-type-units', codegen_text)
             self.assertNotIn('-flto', codegen_text)
             self.assertIn('build lto.main/obj/main.o : codegen ',
                           buildrules)
             self.assertIn('build lto.main/obj/foo.o : codegen ',
                           buildrules)
             link_match = re.search('^build main : native-link\\b.*?^[^ ]',
                                    buildrules, re.MULTILINE | re.DOTALL)
             self.assertIsNotNone(link_match)
             link_text = link_match.group(0)
             self.assertIn('main.split.o', link_text)
         # Check that main does not call foo.
         disasm = subprocess.check_output(['llvm-objdump', '-d', 'main'])
         main_idx = disasm.index(b' <main>:\n')
         after_main_idx = disasm.index(b'\n\n', main_idx)
         main_disasm = disasm[main_idx:after_main_idx]
         self.assertNotIn(b'foo', main_disasm)