1 # Samba automatic dependency handling and project rules
3 import Build
, os
, re
, Environment
4 from samba_utils
import *
5 from samba_autoconf
import *
8 def ADD_GLOBAL_DEPENDENCY(ctx
, dep
):
9 '''add a dependency for all binaries and libraries'''
10 if not 'GLOBAL_DEPENDENCIES' in ctx
.env
:
11 ctx
.env
.GLOBAL_DEPENDENCIES
= []
12 ctx
.env
.GLOBAL_DEPENDENCIES
.append(dep
)
15 def TARGET_ALIAS(bld
, target
, alias
):
16 '''define an alias for a target name'''
17 cache
= LOCAL_CACHE(bld
, 'TARGET_ALIAS')
19 print("Target alias %s already set to %s : newalias %s" % (alias
, cache
[alias
], target
))
22 Build
.BuildContext
.TARGET_ALIAS
= TARGET_ALIAS
26 def SET_SYSLIB_DEPS(conf
, target
, deps
):
27 '''setup some implied dependencies for a SYSLIB'''
28 cache
= LOCAL_CACHE(conf
, 'SYSLIB_DEPS')
32 def EXPAND_ALIAS(bld
, target
):
33 '''expand a target name via an alias'''
34 aliases
= LOCAL_CACHE(bld
, 'TARGET_ALIAS')
36 return aliases
[target
]
38 Build
.BuildContext
.EXPAND_ALIAS
= EXPAND_ALIAS
41 def expand_subsystem_deps(bld
):
42 '''expand the reverse dependencies resulting from subsystem
43 attributes of modules'''
44 subsystems
= LOCAL_CACHE(bld
, 'INIT_FUNCTIONS')
45 aliases
= LOCAL_CACHE(bld
, 'TARGET_ALIAS')
46 targets
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
51 bld
.ASSERT(s
in targets
, "Subsystem target %s not declared" % s
)
53 if type == 'DISABLED' or type == 'EMPTY':
56 t
= bld
.name_to_obj(s
, bld
.env
)
57 bld
.ASSERT(t
is not None, "Subsystem target %s not found" % s
)
58 for d
in subsystems
[s
]:
59 type = targets
[d
['TARGET']]
60 if type != 'DISABLED' and type != 'EMPTY':
61 t
.samba_deps_extended
.append(d
['TARGET'])
62 t2
= bld
.name_to_obj(d
['TARGET'], bld
.env
)
63 t2
.samba_includes_extended
.extend(t
.samba_includes_extended
)
64 t2
.samba_deps_extended
.extend(t
.samba_deps_extended
)
65 t
.samba_deps_extended
= unique_list(t
.samba_deps_extended
)
69 def build_dependencies(self
):
70 '''This builds the dependency list for a target. It runs after all the targets are declared
72 The reason this is not just done in the SAMBA_*() rules is that we have no way of knowing
73 the full dependency list for a target until we have all of the targets declared.
76 if self
.samba_type
in ['LIBRARY', 'BINARY', 'PYTHON']:
77 self
.uselib
= list(self
.final_syslibs
)
78 self
.uselib_local
= list(self
.final_libs
)
79 self
.add_objects
= list(self
.final_objects
)
81 # extra link flags from pkg_config
82 libs
= self
.final_syslibs
.copy()
84 (ccflags
, ldflags
) = library_flags(self
, list(libs
))
85 new_ldflags
= getattr(self
, 'ldflags', [])
86 new_ldflags
.extend(ldflags
)
87 self
.ldflags
= new_ldflags
89 debug('deps: computed dependencies for target %s: uselib=%s uselib_local=%s add_objects=%s',
90 self
.sname
, self
.uselib
, self
.uselib_local
, self
.add_objects
)
92 if self
.samba_type
in ['SUBSYSTEM']:
93 # this is needed for the ccflags of libs that come from pkg_config
94 self
.uselib
= list(self
.direct_syslibs
)
96 if getattr(self
, 'uselib', None):
99 up_list
.append(l
.upper())
100 self
.uselib
= up_list
103 def build_includes(self
):
104 '''This builds the right set of includes for a target.
106 One tricky part of this is that the includes= attribute for a
107 target needs to use paths which are relative to that targets
108 declaration directory (which we can get at via t.path).
110 The way this works is the includes list gets added as
111 samba_includes in the main build task declaration. Then this
112 function runs after all of the tasks are declared, and it
113 processes the samba_includes attribute to produce a includes=
117 if getattr(self
, 'samba_includes', None) is None:
122 inc_deps
= includes_objects(bld
, self
, set(), {})
126 # maybe add local includes
127 if getattr(self
, 'local_include', True) == True and getattr(self
, 'local_include_first', True):
130 includes
.extend(self
.samba_includes_extended
)
132 if 'EXTRA_INCLUDES' in bld
.env
:
133 includes
.extend(bld
.env
['EXTRA_INCLUDES'])
141 t
= bld
.name_to_obj(d
, bld
.env
)
142 bld
.ASSERT(t
is not None, "Unable to find dependency %s for %s" % (d
, self
.sname
))
143 inclist
= getattr(t
, 'samba_includes_extended', [])
144 if getattr(t
, 'local_include', True) == True:
148 tpath
= t
.samba_abspath
150 npath
= tpath
+ '/' + inc
151 if not npath
in inc_set
:
152 inc_abs
.append(npath
)
155 mypath
= self
.path
.abspath(bld
.env
)
157 relpath
= os_path_relpath(inc
, mypath
)
158 includes
.append(relpath
)
160 if getattr(self
, 'local_include', True) == True and not getattr(self
, 'local_include_first', True):
163 # now transform the includes list to be relative to the top directory
164 # which is represented by '#' in waf. This allows waf to cache the
165 # includes lists more efficiently
169 # some are already top based
170 includes_top
.append(i
)
172 absinc
= os
.path
.join(self
.path
.abspath(), i
)
173 relinc
= os_path_relpath(absinc
, self
.bld
.srcnode
.abspath())
174 includes_top
.append('#' + relinc
)
176 self
.includes
= unique_list(includes_top
)
177 debug('deps: includes for target %s: includes=%s',
178 self
.sname
, self
.includes
)
183 def add_init_functions(self
):
184 '''This builds the right set of init functions'''
188 subsystems
= LOCAL_CACHE(bld
, 'INIT_FUNCTIONS')
190 # cope with the separated object lists from BINARY and LIBRARY targets
192 if sname
.endswith('.objlist'):
196 if sname
in subsystems
:
197 modules
.append(sname
)
199 m
= getattr(self
, 'samba_modules', None)
201 modules
.extend(TO_LIST(m
))
203 m
= getattr(self
, 'samba_subsystem', None)
210 sentinal
= getattr(self
, 'init_function_sentinal', 'NULL')
212 targets
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
214 cflags
= getattr(self
, 'samba_cflags', [])[:]
216 bld
.ASSERT(m
in subsystems
,
217 "No init_function defined for module '%s' in target '%s'" % (m
, self
.sname
))
219 for d
in subsystems
[m
]:
220 if targets
[d
['TARGET']] != 'DISABLED':
221 init_fn_list
.append(d
['INIT_FUNCTION'])
222 if init_fn_list
== []:
223 cflags
.append('-DSTATIC_%s_MODULES=%s' % (m
, sentinal
))
225 cflags
.append('-DSTATIC_%s_MODULES=%s' % (m
, ','.join(init_fn_list
) + ',' + sentinal
))
226 self
.ccflags
= cflags
230 def check_duplicate_sources(bld
, tgt_list
):
231 '''see if we are compiling the same source file into multiple
232 subsystem targets for the same library or binary'''
234 debug('deps: checking for duplicate sources')
236 targets
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
242 obj_sources
= getattr(t
, 'source', '')
243 tpath
= os_path_relpath(t
.path
.abspath(bld
.env
), t
.env
['BUILD_DIRECTORY'] + '/default')
244 obj_sources
= bld
.SUBDIR(tpath
, obj_sources
)
245 t
.samba_source_set
= set(TO_LIST(obj_sources
))
248 if not targets
[t
.sname
] in [ 'LIBRARY', 'BINARY', 'PYTHON' ]:
252 for obj
in t
.add_objects
:
253 t2
= t
.bld
.name_to_obj(obj
, bld
.env
)
254 source_set
= getattr(t2
, 'samba_source_set', set())
255 sources
.append( { 'dep':obj
, 'src':source_set
} )
258 if s
['dep'] == s2
['dep']: continue
259 common
= s
['src'].intersection(s2
['src'])
260 if common
.difference(seen
):
261 print("Target %s has duplicate source files in %s and %s : %s" % (t
.sname
,
264 seen
= seen
.union(common
)
269 def check_orpaned_targets(bld
, tgt_list
):
270 '''check if any build targets are orphaned'''
272 target_dict
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
274 debug('deps: checking for orphaned targets')
277 if getattr(t
, 'samba_used', False) == True:
279 type = target_dict
[t
.sname
]
280 if not type in ['BINARY', 'LIBRARY', 'MODULE', 'ET', 'PYTHON']:
281 if re
.search('^PIDL_', t
.sname
) is None:
282 print "Target %s of type %s is unused by any other target" % (t
.sname
, type)
285 def show_final_deps(bld
, tgt_list
):
286 '''show the final dependencies for all targets'''
288 targets
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
291 if not targets
[t
.sname
] in ['LIBRARY', 'BINARY', 'PYTHON']:
293 debug('deps: final dependencies for target %s: uselib=%s uselib_local=%s add_objects=%s',
294 t
.sname
, t
.uselib
, t
.uselib_local
, t
.add_objects
)
297 def add_samba_attributes(bld
, tgt_list
):
298 '''ensure a target has a the required samba attributes'''
300 targets
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
307 t
.samba_type
= targets
[t
.sname
]
308 t
.samba_abspath
= t
.path
.abspath(bld
.env
)
309 t
.samba_deps_extended
= t
.samba_deps
[:]
310 t
.samba_includes_extended
= TO_LIST(t
.samba_includes
)[:]
311 t
.ccflags
= getattr(t
, 'samba_cflags', '')
314 def build_direct_deps(bld
, tgt_list
):
315 '''build the direct_objects and direct_libs sets for each target'''
317 targets
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
318 syslib_deps
= LOCAL_CACHE(bld
, 'SYSLIB_DEPS')
319 global_deps
= bld
.env
.GLOBAL_DEPENDENCIES
322 t
.direct_objects
= set()
323 t
.direct_libs
= set()
324 t
.direct_syslibs
= set()
325 deps
= t
.samba_deps_extended
326 deps
.extend(global_deps
)
328 d
= EXPAND_ALIAS(bld
, d
)
329 if d
== t
.sname
: continue
331 print "Unknown dependency %s in %s" % (d
, t
.sname
)
333 if targets
[d
] in [ 'EMPTY', 'DISABLED' ]:
335 if targets
[d
] == 'SYSLIB':
336 t
.direct_syslibs
.add(d
)
338 for implied
in TO_LIST(syslib_deps
[d
]):
339 t
.direct_libs
.add(implied
)
341 t2
= bld
.name_to_obj(d
, bld
.env
)
343 print "no task %s type %s" % (d
, targets
[d
])
344 if t2
.samba_type
in [ 'LIBRARY', 'MODULE' ]:
346 elif t2
.samba_type
in [ 'SUBSYSTEM', 'ASN1', 'PYTHON' ]:
347 t
.direct_objects
.add(d
)
348 debug('deps: built direct dependencies')
351 def dependency_loop(loops
, t
, target
):
352 '''add a dependency loop to the loops dictionary'''
353 if t
.sname
== target
:
355 if not target
in loops
:
356 loops
[target
] = set()
357 if not t
.sname
in loops
[target
]:
358 loops
[target
].add(t
.sname
)
361 def indirect_libs(bld
, t
, chain
, loops
):
362 '''recursively calculate the indirect library dependencies for a target
364 An indirect library is a library that results from a dependency on
368 ret
= getattr(t
, 'indirect_libs', None)
373 for obj
in t
.direct_objects
:
375 dependency_loop(loops
, t
, obj
)
378 t2
= bld
.name_to_obj(obj
, bld
.env
)
379 r2
= indirect_libs(bld
, t2
, chain
, loops
)
381 ret
= ret
.union(t2
.direct_libs
)
384 for obj
in indirect_objects(bld
, t
, set(), loops
):
386 dependency_loop(loops
, t
, obj
)
389 t2
= bld
.name_to_obj(obj
, bld
.env
)
390 r2
= indirect_libs(bld
, t2
, chain
, loops
)
392 ret
= ret
.union(t2
.direct_libs
)
395 t
.indirect_libs
= ret
400 def indirect_objects(bld
, t
, chain
, loops
):
401 '''recursively calculate the indirect object dependencies for a target
403 indirect objects are the set of objects from expanding the
404 subsystem dependencies
407 ret
= getattr(t
, 'indirect_objects', None)
408 if ret
is not None: return ret
411 for lib
in t
.direct_objects
:
413 dependency_loop(loops
, t
, lib
)
416 t2
= bld
.name_to_obj(lib
, bld
.env
)
417 r2
= indirect_objects(bld
, t2
, chain
, loops
)
419 ret
= ret
.union(t2
.direct_objects
)
422 t
.indirect_objects
= ret
426 def extended_objects(bld
, t
, chain
):
427 '''recursively calculate the extended object dependencies for a target
429 extended objects are the union of:
432 - direct and indirect objects of all direct and indirect libraries
435 ret
= getattr(t
, 'extended_objects', None)
436 if ret
is not None: return ret
439 ret
= ret
.union(t
.direct_objects
)
440 ret
= ret
.union(t
.indirect_objects
)
442 for lib
in t
.direct_libs
:
445 t2
= bld
.name_to_obj(lib
, bld
.env
)
447 r2
= extended_objects(bld
, t2
, chain
)
449 ret
= ret
.union(t2
.direct_objects
)
450 ret
= ret
.union(t2
.indirect_objects
)
453 t
.extended_objects
= ret
457 def includes_objects(bld
, t
, chain
, inc_loops
):
458 '''recursively calculate the includes object dependencies for a target
460 includes dependencies come from either library or object dependencies
462 ret
= getattr(t
, 'includes_objects', None)
466 ret
= t
.direct_objects
.copy()
467 ret
= ret
.union(t
.direct_libs
)
469 for obj
in t
.direct_objects
:
471 dependency_loop(inc_loops
, t
, obj
)
474 t2
= bld
.name_to_obj(obj
, bld
.env
)
475 r2
= includes_objects(bld
, t2
, chain
, inc_loops
)
477 ret
= ret
.union(t2
.direct_objects
)
480 for lib
in t
.direct_libs
:
482 dependency_loop(inc_loops
, t
, lib
)
485 t2
= bld
.name_to_obj(lib
, bld
.env
)
486 r2
= includes_objects(bld
, t2
, chain
, inc_loops
)
488 ret
= ret
.union(t2
.direct_objects
)
491 t
.includes_objects
= ret
495 def break_dependency_loops(bld
, tgt_list
):
496 '''find and break dependency loops'''
500 # build up the list of loops
502 indirect_objects(bld
, t
, set(), loops
)
503 indirect_libs(bld
, t
, set(), loops
)
504 includes_objects(bld
, t
, set(), inc_loops
)
509 for attr
in ['direct_objects', 'indirect_objects', 'direct_libs', 'indirect_libs']:
510 objs
= getattr(t
, attr
, set())
511 setattr(t
, attr
, objs
.difference(loops
[t
.sname
]))
514 debug('deps: Found dependency loops for target %s : %s', loop
, loops
[loop
])
516 # expand the loops mapping by one level
517 for loop
in loops
.copy():
518 for tgt
in loops
[loop
]:
520 loops
[loop
] = loops
[loop
].union(loops
[tgt
])
522 # expand indirect subsystem and library loops
523 for loop
in loops
.copy():
524 t
= bld
.name_to_obj(loop
, bld
.env
)
525 if t
.samba_type
in ['SUBSYSTEM']:
526 loops
[loop
] = loops
[loop
].union(t
.indirect_objects
)
527 loops
[loop
] = loops
[loop
].union(t
.direct_objects
)
528 if t
.samba_type
in ['LIBRARY','PYTHON']:
529 loops
[loop
] = loops
[loop
].union(t
.indirect_libs
)
530 loops
[loop
] = loops
[loop
].union(t
.direct_libs
)
531 if loop
in loops
[loop
]:
532 loops
[loop
].remove(loop
)
534 # add in the replacement dependencies
537 for attr
in ['direct_objects', 'indirect_objects', 'direct_libs', 'indirect_libs']:
538 objs
= getattr(t
, attr
, set())
540 diff
= loops
[loop
].difference(objs
)
544 debug('deps: Expanded target %s of type %s from loop %s by %s', t
.sname
, t
.samba_type
, loop
, diff
)
545 objs
= objs
.union(diff
)
546 if t
.sname
== 'ldb_password_hash':
547 debug('deps: setting %s %s to %s', t
.sname
, attr
, objs
)
548 setattr(t
, attr
, objs
)
550 def calculate_final_deps(bld
, tgt_list
, loops
):
551 '''calculate the final library and object dependencies'''
553 # start with the maximum possible list
554 t
.final_libs
= t
.direct_libs
.union(indirect_libs(bld
, t
, set(), loops
))
555 t
.final_objects
= t
.direct_objects
.union(indirect_objects(bld
, t
, set(), loops
))
558 # don't depend on ourselves
559 if t
.sname
in t
.final_libs
:
560 t
.final_libs
.remove(t
.sname
)
561 if t
.sname
in t
.final_objects
:
562 t
.final_objects
.remove(t
.sname
)
564 # find any library loops
566 if t
.samba_type
in ['LIBRARY', 'PYTHON']:
567 for l
in t
.final_libs
.copy():
568 t2
= bld
.name_to_obj(l
, bld
.env
)
569 if t
.sname
in t2
.final_libs
:
570 # we could break this in either direction. If one of the libraries
571 # has a version number, and will this be distributed publicly, then
572 # we should make it the lower level library in the DAG
573 debug('deps: removing library loop %s from %s', t
.sname
, t2
.sname
)
574 dependency_loop(loops
, t
, t2
.sname
)
575 t2
.final_libs
.remove(t
.sname
)
577 for type in ['BINARY']:
579 if t
.samba_type
!= type: continue
580 # if we will indirectly link to a target then we don't need it
581 new
= t
.final_objects
.copy()
582 for l
in t
.final_libs
:
583 t2
= bld
.name_to_obj(l
, bld
.env
)
584 t2_obj
= extended_objects(bld
, t2
, set())
585 dup
= new
.intersection(t2_obj
)
587 debug('deps: removing dups from %s of type %s: %s also in %s %s',
588 t
.sname
, t
.samba_type
, dup
, t2
.samba_type
, l
)
589 new
= new
.difference(dup
)
591 t
.final_objects
= new
594 debug('deps: Found dependency loops for target %s : %s', loop
, loops
[loop
])
596 # we now need to make corrections for any library loops we broke up
597 # any target that depended on the target of the loop and doesn't
598 # depend on the source of the loop needs to get the loop source added
599 for type in ['BINARY','PYTHON','LIBRARY']:
601 if t
.samba_type
!= type: continue
603 if loop
in t
.final_libs
:
604 diff
= loops
[loop
].difference(t
.final_libs
)
608 debug('deps: Expanded target %s by loop %s libraries %s', t
.sname
, loop
, diff
)
609 t
.final_libs
= t
.final_libs
.union(diff
)
611 # add in any syslib dependencies
613 if not t
.samba_type
in ['BINARY','PYTHON','LIBRARY']:
616 for d
in t
.final_objects
:
617 t2
= bld
.name_to_obj(d
, bld
.env
)
618 syslibs
= syslibs
.union(t2
.direct_syslibs
)
619 # this adds the indirect syslibs as well, which may not be needed
620 # depending on the linker flags
621 for d
in t
.final_libs
:
622 t2
= bld
.name_to_obj(d
, bld
.env
)
623 syslibs
= syslibs
.union(t2
.direct_syslibs
)
624 t
.final_syslibs
= syslibs
626 debug('deps: removed duplicate dependencies')
630 ######################################################################
631 # this provides a way to save our dependency calculations between runs
633 savedeps_inputs
= ['samba_deps', 'samba_includes', 'local_include', 'local_include_first', 'samba_cflags', 'source']
634 savedeps_outputs
= ['uselib', 'uselib_local', 'add_objects', 'includes', 'ccflags']
635 savedeps_outenv
= ['INC_PATHS']
636 savedeps_caches
= ['GLOBAL_DEPENDENCIES', 'TARGET_ALIAS', 'TARGET_TYPE', 'INIT_FUNCTIONS', 'SYSLIB_DEPS']
637 savedeps_files
= ['buildtools/wafsamba/samba_deps.py']
639 def save_samba_deps(bld
, tgt_list
):
640 '''save the dependency calculations between builds, to make
641 further builds faster'''
642 denv
= Environment
.Environment()
644 denv
.version
= savedeps_version
645 denv
.savedeps_inputs
= savedeps_inputs
646 denv
.savedeps_outputs
= savedeps_outputs
653 for f
in savedeps_files
:
654 denv
.files
[f
] = os
.stat(os
.path
.join(bld
.srcnode
.abspath(), f
)).st_mtime
656 for c
in savedeps_caches
:
657 denv
.caches
[c
] = LOCAL_CACHE(bld
, c
)
660 # save all the input attributes for each target
662 for attr
in savedeps_inputs
:
663 v
= getattr(t
, attr
, None)
667 denv
.input[t
.sname
] = tdeps
669 # save all the output attributes for each target
671 for attr
in savedeps_outputs
:
672 v
= getattr(t
, attr
, None)
676 denv
.output
[t
.sname
] = tdeps
679 for attr
in savedeps_outenv
:
681 tdeps
[attr
] = t
.env
[attr
]
683 denv
.outenv
[t
.sname
] = tdeps
685 depsfile
= os
.path
.join(bld
.bdir
, "sambadeps")
689 def load_samba_deps(bld
, tgt_list
):
690 '''load a previous set of build dependencies if possible'''
691 depsfile
= os
.path
.join(bld
.bdir
, "sambadeps")
692 denv
= Environment
.Environment()
694 debug('deps: checking saved dependencies')
696 if (denv
.version
!= savedeps_version
or
697 denv
.savedeps_inputs
!= savedeps_inputs
or
698 denv
.savedeps_outputs
!= savedeps_outputs
):
703 # check if critical files have changed
704 for f
in savedeps_files
:
705 if f
not in denv
.files
:
707 if denv
.files
[f
] != os
.stat(os
.path
.join(bld
.srcnode
.abspath(), f
)).st_mtime
:
710 # check if caches are the same
711 for c
in savedeps_caches
:
712 if c
not in denv
.caches
or denv
.caches
[c
] != LOCAL_CACHE(bld
, c
):
715 # check inputs are the same
718 for attr
in savedeps_inputs
:
719 v
= getattr(t
, attr
, None)
722 if t
.sname
in denv
.input:
723 olddeps
= denv
.input[t
.sname
]
727 #print '%s: \ntdeps=%s \nodeps=%s' % (t.sname, tdeps, olddeps)
730 # put outputs in place
732 if not t
.sname
in denv
.output
: continue
733 tdeps
= denv
.output
[t
.sname
]
735 setattr(t
, a
, tdeps
[a
])
737 # put output env vars in place
739 if not t
.sname
in denv
.outenv
: continue
740 tdeps
= denv
.outenv
[t
.sname
]
744 debug('deps: loaded saved dependencies')
748 def check_project_rules(bld
):
749 '''check the project rules - ensuring the targets are sane'''
751 targets
= LOCAL_CACHE(bld
, 'TARGET_TYPE')
755 # build a list of task generators we are interested in
759 if not type in ['SUBSYSTEM', 'MODULE', 'BINARY', 'LIBRARY', 'ASN1', 'PYTHON']:
761 t
= bld
.name_to_obj(tgt
, bld
.env
)
763 print "Target %s of type %s has no task generator" % (tgt
, type)
767 add_samba_attributes(bld
, tgt_list
)
769 if load_samba_deps(bld
, tgt_list
):
772 print "Checking project rules ..."
774 debug('deps: project rules checking started')
776 expand_subsystem_deps(bld
)
777 build_direct_deps(bld
, tgt_list
)
778 break_dependency_loops(bld
, tgt_list
)
779 calculate_final_deps(bld
, tgt_list
, loops
)
781 # run the various attribute generators
782 for f
in [ build_dependencies
, build_includes
, add_init_functions
]:
783 debug('deps: project rules checking %s', f
)
784 for t
in tgt_list
: f(t
)
786 debug('deps: project rules stage1 completed')
788 #check_orpaned_targets(bld, tgt_list)
790 if not check_duplicate_sources(bld
, tgt_list
):
791 print "Duplicate sources present - aborting"
794 show_final_deps(bld
, tgt_list
)
796 debug('deps: project rules checking completed - %u targets checked',
799 save_samba_deps(bld
, tgt_list
)
801 print "Project rules pass"
804 def CHECK_PROJECT_RULES(bld
):
805 '''enable checking of project targets for sanity'''
806 if bld
.env
.added_project_rules
:
808 bld
.env
.added_project_rules
= True
809 bld
.add_pre_fun(check_project_rules
)
810 Build
.BuildContext
.CHECK_PROJECT_RULES
= CHECK_PROJECT_RULES