1 # -*- Python -*- 2 3 import os 4 import platform 5 import re 6 import subprocess 7 8 9 # Configuration file for the 'lit' test runner. 10 11 # name: The name of this test suite. 12 config.name = 'Clang' 13 14 # Tweak PATH for Win32 15 if platform.system() == 'Windows': 16 # Seek sane tools in directories and set to $PATH. 17 path = getattr(config, 'lit_tools_dir', None) 18 path = lit.getToolsPath(path, 19 config.environment['PATH'], 20 ['cmp.exe', 'grep.exe', 'sed.exe']) 21 if path is not None: 22 path = os.path.pathsep.join((path, 23 config.environment['PATH'])) 24 config.environment['PATH'] = path 25 26 # testFormat: The test format to use to interpret tests. 27 # 28 # For now we require '&&' between commands, until they get globally killed and 29 # the test runner updated. 30 execute_external = (platform.system() != 'Windows' 31 or lit.getBashPath() not in [None, ""]) 32 config.test_format = lit.formats.ShTest(execute_external) 33 34 # suffixes: A list of file extensions to treat as test files. 35 config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s'] 36 37 # test_source_root: The root path where tests are located. 38 config.test_source_root = os.path.dirname(__file__) 39 40 # test_exec_root: The root path where tests should be run. 41 clang_obj_root = getattr(config, 'clang_obj_root', None) 42 if clang_obj_root is not None: 43 config.test_exec_root = os.path.join(clang_obj_root, 'test') 44 45 # Set llvm_{src,obj}_root for use by others. 46 config.llvm_src_root = getattr(config, 'llvm_src_root', None) 47 config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) 48 49 # Clear some environment variables that might affect Clang. 50 # 51 # This first set of vars are read by Clang, but shouldn't affect tests 52 # that aren't specifically looking for these features, or are required 53 # simply to run the tests at all. 54 # 55 # FIXME: Should we have a tool that enforces this? 56 57 # safe_env_vars = ('TMPDIR', 'TEMP', 'TMP', 'USERPROFILE', 'PWD', 58 # 'MACOSX_DEPLOYMENT_TARGET', 'IPHONEOS_DEPLOYMENT_TARGET', 59 # 'IOS_SIMULATOR_DEPLOYMENT_TARGET', 60 # 'VCINSTALLDIR', 'VC100COMNTOOLS', 'VC90COMNTOOLS', 61 # 'VC80COMNTOOLS') 62 possibly_dangerous_env_vars = ['COMPILER_PATH', 'RC_DEBUG_OPTIONS', 63 'CINDEXTEST_PREAMBLE_FILE', 'LIBRARY_PATH', 64 'CPATH', 'C_INCLUDE_PATH', 'CPLUS_INCLUDE_PATH', 65 'OBJC_INCLUDE_PATH', 'OBJCPLUS_INCLUDE_PATH', 66 'LIBCLANG_TIMING', 'LIBCLANG_OBJTRACKING', 67 'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX', 68 'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS', 69 'LIBCLANG_RESOURCE_USAGE', 70 'LIBCLANG_CODE_COMPLETION_LOGGING'] 71 # Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it. 72 if platform.system() != 'Windows': 73 possibly_dangerous_env_vars.append('INCLUDE') 74 for name in possibly_dangerous_env_vars: 75 if name in config.environment: 76 del config.environment[name] 77 78 # Tweak the PATH to include the tools dir and the scripts dir. 79 if clang_obj_root is not None: 80 llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) 81 if not llvm_tools_dir: 82 lit.fatal('No LLVM tools dir set!') 83 path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH'])) 84 config.environment['PATH'] = path 85 86 llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) 87 if not llvm_libs_dir: 88 lit.fatal('No LLVM libs dir set!') 89 path = os.path.pathsep.join((llvm_libs_dir, 90 config.environment.get('LD_LIBRARY_PATH',''))) 91 config.environment['LD_LIBRARY_PATH'] = path 92 93 ### 94 95 # Check that the object root is known. 96 if config.test_exec_root is None: 97 # Otherwise, we haven't loaded the site specific configuration (the user is 98 # probably trying to run on a test file directly, and either the site 99 # configuration hasn't been created by the build system, or we are in an 100 # out-of-tree build situation). 101 102 # Check for 'clang_site_config' user parameter, and use that if available. 103 site_cfg = lit.params.get('clang_site_config', None) 104 if site_cfg and os.path.exists(site_cfg): 105 lit.load_config(config, site_cfg) 106 raise SystemExit 107 108 # Try to detect the situation where we are using an out-of-tree build by 109 # looking for 'llvm-config'. 110 # 111 # FIXME: I debated (i.e., wrote and threw away) adding logic to 112 # automagically generate the lit.site.cfg if we are in some kind of fresh 113 # build situation. This means knowing how to invoke the build system though, 114 # and I decided it was too much magic. We should solve this by just having 115 # the .cfg files generated during the configuration step. 116 117 llvm_config = lit.util.which('llvm-config', config.environment['PATH']) 118 if not llvm_config: 119 lit.fatal('No site specific configuration available!') 120 121 # Get the source and object roots. 122 llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip() 123 llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip() 124 clang_src_root = os.path.join(llvm_src_root, "tools", "clang") 125 clang_obj_root = os.path.join(llvm_obj_root, "tools", "clang") 126 127 # Validate that we got a tree which points to here, using the standard 128 # tools/clang layout. 129 this_src_root = os.path.dirname(config.test_source_root) 130 if os.path.realpath(clang_src_root) != os.path.realpath(this_src_root): 131 lit.fatal('No site specific configuration available!') 132 133 # Check that the site specific configuration exists. 134 site_cfg = os.path.join(clang_obj_root, 'test', 'lit.site.cfg') 135 if not os.path.exists(site_cfg): 136 lit.fatal('No site specific configuration available! You may need to ' 137 'run "make test" in your Clang build directory.') 138 139 # Okay, that worked. Notify the user of the automagic, and reconfigure. 140 lit.note('using out-of-tree build at %r' % clang_obj_root) 141 lit.load_config(config, site_cfg) 142 raise SystemExit 143 144 ### 145 146 # Discover the 'clang' and 'clangcc' to use. 147 148 import os 149 150 def inferClang(PATH): 151 # Determine which clang to use. 152 clang = os.getenv('CLANG') 153 154 # If the user set clang in the environment, definitely use that and don't 155 # try to validate. 156 if clang: 157 return clang 158 159 # Otherwise look in the path. 160 clang = lit.util.which('clang', PATH) 161 162 if not clang: 163 lit.fatal("couldn't find 'clang' program, try setting " 164 "CLANG in your environment") 165 166 return clang 167 168 # When running under valgrind, we mangle '-vg' onto the end of the triple so we 169 # can check it with XFAIL and XTARGET. 170 if lit.useValgrind: 171 config.target_triple += '-vg' 172 173 config.clang = inferClang(config.environment['PATH']).replace('\\', '/') 174 if not lit.quiet: 175 lit.note('using clang: %r' % config.clang) 176 177 # Note that when substituting %clang_cc1 also fill in the include directory of 178 # the builtin headers. Those are part of even a freestanding environment, but 179 # Clang relies on the driver to locate them. 180 def getClangBuiltinIncludeDir(clang): 181 # FIXME: Rather than just getting the version, we should have clang print 182 # out its resource dir here in an easy to scrape form. 183 cmd = subprocess.Popen([clang, '-print-file-name=include'], 184 stdout=subprocess.PIPE) 185 if not cmd.stdout: 186 lit.fatal("Couldn't find the include dir for Clang ('%s')" % clang) 187 return cmd.stdout.read().strip() 188 189 config.substitutions.append( ('%clang_cc1', '%s -cc1 -internal-isystem %s' 190 % (config.clang, 191 getClangBuiltinIncludeDir(config.clang))) ) 192 193 config.substitutions.append( ('%clangxx', ' ' + config.clang + 194 ' -ccc-clang-cxx -ccc-cxx ')) 195 config.substitutions.append( ('%clang', ' ' + config.clang + ' ') ) 196 config.substitutions.append( ('%test_debuginfo', ' ' + config.llvm_src_root + '/utils/test_debuginfo.pl ') ) 197 198 # FIXME: Find nicer way to prohibit this. 199 config.substitutions.append( 200 (' clang ', """*** Do not use 'clang' in tests, use '%clang'. ***""") ) 201 config.substitutions.append( 202 (' clang\+\+ ', """*** Do not use 'clang++' in tests, use '%clangxx'. ***""")) 203 config.substitutions.append( 204 (' clang-cc ', 205 """*** Do not use 'clang-cc' in tests, use '%clang_cc1'. ***""") ) 206 config.substitutions.append( 207 (' clang -cc1 ', 208 """*** Do not use 'clang -cc1' in tests, use '%clang_cc1'. ***""") ) 209 config.substitutions.append( 210 (' %clang-cc1 ', 211 """*** invalid substitution, use '%clang_cc1'. ***""") ) 212 213 ### 214 215 # Set available features we allow tests to conditionalize on. 216 # 217 # As of 2011.08, crash-recovery tests still do not pass on FreeBSD. 218 if platform.system() not in ['FreeBSD']: 219 config.available_features.add('crash-recovery') 220 221 # Shell execution 222 if platform.system() not in ['Windows'] or lit.getBashPath() != '': 223 config.available_features.add('shell') 224 225 # ANSI escape sequences in non-dump terminal 226 if platform.system() not in ['Windows']: 227 config.available_features.add('ansi-escape-sequences') 228 229 # Registered Targets 230 def get_llc_props(tool): 231 set_of_targets = set() 232 enable_assertions = False 233 234 cmd = subprocess.Popen([tool, '-version'], stdout=subprocess.PIPE) 235 236 # Parse the stdout to get the list of registered targets. 237 parse_targets = False 238 for line in cmd.stdout: 239 if parse_targets: 240 m = re.match( r'(.*) - ', line) 241 if m is not None: 242 set_of_targets.add(m.group(1).strip() + '-registered-target') 243 else: 244 break 245 elif "Registered Targets:" in line: 246 parse_targets = True 247 248 if re.search(r'with assertions', line): 249 enable_assertions = True 250 251 return {"set_of_targets": set_of_targets, 252 "enable_assertions": enable_assertions} 253 254 llc_props = get_llc_props(os.path.join(llvm_tools_dir, 'llc')) 255 if len(llc_props['set_of_targets']) > 0: 256 config.available_features.update(llc_props['set_of_targets']) 257 else: 258 lit.fatal('No Targets Registered with the LLVM Tools!') 259 260 if llc_props['enable_assertions']: 261 config.available_features.add('asserts') 262 263 if lit.util.which('xmllint'): 264 config.available_features.add('xmllint') 265 266