Package wafadmin :: Package Tools :: Module ccroot
[hide private]
[frames] | no frames]

Source Code for Module wafadmin.Tools.ccroot

  1  #!/usr/bin/env python 
  2  # encoding: utf-8 
  3  # Thomas Nagy, 2005-2008 (ita) 
  4   
  5  "base for all c/c++ programs and libraries" 
  6   
  7  import os, sys, re 
  8  import TaskGen, Utils, preproc, Logs, Build, Options 
  9  from Logs import error, debug, warn 
 10  from Utils import md5 
 11  from TaskGen import taskgen, after, before, feature 
 12  from Constants import * 
 13   
 14  import config_c # <- necessary for the configuration, do not touch 
 15   
 16  get_version_re = re.compile('\d+\.\d+(\.?\d+)*') 
17 -def get_cc_version(conf, cc, version_var):
18 v = conf.env 19 output = Utils.cmd_output('%s -dumpversion' % cc) 20 if output: 21 match = get_version_re.search(output) 22 if match: 23 v[version_var] = match.group(0) 24 conf.check_message('compiler', 'version', 1, v[version_var]) 25 return v[version_var] 26 warn('could not determine the compiler version')
27
28 -class DEBUG_LEVELS:
29 ULTRADEBUG = "ultradebug" 30 DEBUG = "debug" 31 RELEASE = "release" 32 OPTIMIZED = "optimized" 33 CUSTOM = "custom" 34 35 ALL = [ULTRADEBUG, DEBUG, RELEASE, OPTIMIZED, CUSTOM]
36
37 -def scan(self):
38 "look for .h the .cpp need" 39 debug('ccroot: _scan_preprocessor(self, node, env, path_lst)') 40 all_nodes = [] 41 all_names = [] 42 seen = [] 43 for node in self.inputs: 44 gruik = preproc.c_parser(nodepaths = self.env['INC_PATHS'], defines = self.defines) 45 gruik.start(node, self.env) 46 if Logs.verbose: 47 debug('deps: nodes found for %s: %s %s' % (str(node), str(gruik.nodes), str(gruik.names))) 48 debug('deps: deps found for %s: %s' % (str(node), str(gruik.deps))) 49 for x in gruik.nodes: 50 if id(x) in seen: continue 51 seen.append(id(x)) 52 all_nodes.append(x) 53 for x in gruik.names: 54 if not x in all_names: 55 all_names.append(x) 56 return (all_nodes, gruik.names)
57
58 -class ccroot_abstract(TaskGen.task_gen):
59 "Parent class for programs and libraries in languages c, c++ and moc (Qt)"
60 - def __init__(self, *k, **kw):
61 TaskGen.task_gen.__init__(self, *k) 62 63 # TODO m_type is obsolete 64 if len(k)>1: self.type = k[1] 65 else: self.type = '' 66 if self.type: 67 self.features.append('c' + self.type) 68 69 # includes, seen from the current directory 70 self.includes='' 71 72 self.defines = '' 73 self.rpaths = '' 74 75 self.uselib = '' 76 77 # new scheme: provide the names of the local libraries to link with 78 # the objects found will be post()-ed 79 self.uselib_local='' 80 81 # add .o files produced by another task_gen class (task generator names) 82 self.add_objects = '' 83 84 # version number for shared libraries 85 #self.vnum='1.2.3' # 86 #self.soname='.so.3' # else soname is computed from vnum 87 88 #self.program_chmod = 0755 # by default: 0755 89 90 # do not forget to set the following variables in a subclass 91 self.p_flag_vars = [] 92 self.p_type_vars = [] 93 94 #self.link = '' # optional: kind of link to apply (ar, cc, cxx, ..) 95 96 self.scanner_defines = {} 97 98 self.compiled_tasks = [] 99 self.link_task = None
100 101 # characteristics of what we want to build: cc, cpp, program, staticlib, shlib, etc 102 #self.features = ['program'] 103
104 - def clone(self, env):
105 new_obj = TaskGen.task_gen.clone(self, env) 106 variant = '_' + self.env.variant() 107 108 if self.name: new_obj.name = self.name + variant 109 else: new_obj.name = self.target + variant 110 new_obj.uselib_local = [x + variant for x in Utils.to_list(self.uselib_local) ] 111 return new_obj
112
113 -def get_target_name(self):
114 name = self.target 115 pattern = self.env[self.type+'_PATTERN'] 116 if not pattern: pattern = '%s' 117 118 # name can be src/mylib 119 k = name.rfind('/') 120 return name[0:k+1] + pattern % name[k+1:]
121
122 @taskgen 123 -def apply_verif(self):
124 if not 'objects' in self.features: 125 if not self.source: 126 raise Utils.WafError('no source files specified for %s' % self) 127 if not self.target: 128 raise Utils.WafError('no target for %s' % self)
129
130 -def install_shlib(self):
131 nums = self.vnum.split('.') 132 133 path = self.install_path 134 libname = self.outputs[0].name 135 136 name3 = libname+'.'+self.vnum 137 name2 = libname+'.'+nums[0] 138 name1 = libname 139 140 filename = self.outputs[0].abspath(self.env) 141 bld = Build.bld 142 bld.install_as(os.path.join(path, name3), filename, env=self.env) 143 bld.symlink_as(os.path.join(path, name2), name3) 144 bld.symlink_as(os.path.join(path, name1), name3)
145
146 # TODO reference the d programs, shlibs in d.py, not here 147 148 @taskgen 149 @feature('cprogram', 'dprogram') 150 @before('apply_core') 151 -def vars_target_cprogram(self):
152 self.default_install_path = '${PREFIX}/bin'
153
154 @taskgen 155 @feature('cstaticlib', 'dstaticlib') 156 @before('apply_core') 157 -def vars_target_cstaticlib(self):
158 self.default_install_path = '${PREFIX}/lib'
159
160 @taskgen 161 @feature('cshlib', 'dshlib') 162 @before('apply_core') 163 -def vars_target_cshlib(self):
164 self.default_install_path = '${PREFIX}/lib'
165
166 @taskgen 167 @feature('cprogram', 'dprogram') 168 @after('apply_objdeps') 169 -def install_target_cprogram(self):
170 if not Options.is_install: return 171 try: mode = self.program_chmod 172 except AttributeError: mode = 0755 173 self.link_task.install_path = self.install_path 174 self.link_task.chmod = mode
175
176 @taskgen 177 @feature('cstaticlib', 'dstaticlib') 178 @after('apply_objdeps') 179 -def install_target_cstaticlib(self):
180 if not Options.is_install: return 181 self.link_task.install_path = self.install_path
182
183 @taskgen 184 @feature('cshlib', 'dshlib') 185 @after('apply_objdeps') 186 -def install_target_cshlib(self):
187 if not Options.is_install: return 188 tsk = self.link_task 189 self.link_task.install_path = self.install_path 190 191 if getattr(self, 'vnum', '') and sys.platform != 'win32': 192 tsk.vnum = self.vnum 193 tsk.install = install_shlib
194
195 @taskgen 196 @after('apply_type_vars') 197 -def apply_incpaths(self):
198 "used by the scanner" 199 lst = [] 200 for lib in self.to_list(self.uselib): 201 for path in self.env['CPPPATH_' + lib]: 202 if not path in lst: 203 lst.append(path) 204 if preproc.go_absolute: 205 for path in preproc.standard_includes: 206 if not path in lst: 207 lst.append(path) 208 for path in self.to_list(self.includes): 209 if not path in lst: 210 lst.append(path) 211 if (not preproc.go_absolute) and os.path.isabs(path): 212 self.env.prepend_value('CPPPATH', path) 213 214 tree = Build.bld 215 inc_lst = [] 216 for path in lst: 217 node = None 218 if os.path.isabs(path): 219 if preproc.go_absolute: 220 node = Build.bld.root.find_dir(path) 221 else: 222 node = self.path.find_dir(path) 223 224 if node: 225 inc_lst.append(node) 226 227 self.env['INC_PATHS'] = self.env['INC_PATHS'] + inc_lst
228
229 @taskgen 230 -def apply_type_vars(self):
231 # if the type defines uselib to add, add them 232 st = self.env[self.type+'_USELIB'] 233 if st: self.uselib = self.uselib + ' ' + st 234 235 # each compiler defines variables like 'shlib_CXXFLAGS', 'shlib_LINKFLAGS', etc 236 # so when we make a cppobj of the type shlib, CXXFLAGS are modified accordingly 237 for var in self.p_type_vars: 238 compvar = '_'.join([self.type, var]) 239 #print compvar 240 value = self.env[compvar] 241 if value: self.env.append_value(var, value)
242 259
260 @taskgen 261 @after('apply_vnum') 262 -def apply_lib_vars(self):
263 env = self.env 264 265 # 1. the case of the libs defined in the project (visit ancestors first) 266 # the ancestors external libraries (uselib) will be prepended 267 uselib = self.to_list(self.uselib) 268 seen = [] 269 names = [] + self.to_list(self.uselib_local) # consume a copy of the list of names 270 while names: 271 x = names.pop(0) 272 # visit dependencies only once 273 if x in seen: 274 continue 275 276 # object does not exist ? 277 y = Build.bld.name_to_obj(x) 278 if not y: 279 raise Utils.WafError("object '%s' was not found in uselib_local (required by '%s')" % (x, self.name)) 280 281 # object has ancestors to process: add them to the end of the list 282 if y.uselib_local: 283 lst = y.to_list(y.uselib_local) 284 for u in lst: 285 if not u in seen: 286 names.append(u) 287 288 # safe to process the current object 289 y.post() 290 seen.append(x) 291 292 if 'cshlib' in y.features: 293 env.append_value('LIB', y.target) 294 elif 'cstaticlib' in y.features: 295 env.append_value('STATICLIB', y.target) 296 297 # add the link path too 298 tmp_path = y.path.bldpath(self.env) 299 if not tmp_path in env['LIBPATH']: env.prepend_value('LIBPATH', tmp_path) 300 301 # set the dependency over the link task 302 if y.link_task is not None: 303 self.link_task.set_run_after(y.link_task) 304 dep_nodes = getattr(self.link_task, 'dep_nodes', []) 305 self.link_task.dep_nodes = dep_nodes + y.link_task.outputs 306 307 # add ancestors uselib too 308 morelibs = y.to_list(y.uselib) 309 for v in morelibs: 310 if v in uselib: continue 311 uselib = [v]+uselib 312 313 # if the library task generator provides 'export_incdirs', add to the include path 314 # if no one uses this feature, it will be removed 315 if getattr(y, 'export_incdirs', None): 316 cpppath_st = self.env['CPPPATH_ST'<