1 # specialist handling of header files for Samba
3 import Build
, re
, Task
, TaskGen
, shutil
, sys
, Logs
4 from samba_utils
import *
7 def header_install_path(header
, header_path
):
8 '''find the installation path for a header, given a header_path option'''
11 if not isinstance(header_path
, list):
13 for (p1
, dir) in header_path
:
14 for p2
in TO_LIST(p1
):
15 if fnmatch
.fnmatch(header
, p2
):
17 # default to current path
21 re_header
= re
.compile('^\s*#\s*include[ \t]*"([^"]+)"', re
.I | re
.M
)
23 # a dictionary mapping source header paths to public header paths
26 def find_suggested_header(hpath
):
27 '''find a suggested header path to use'''
28 base
= os
.path
.basename(hpath
)
31 if os
.path
.basename(h
) == base
:
32 ret
.append('<%s>' % header_map
[h
])
33 ret
.append('"%s"' % h
)
36 def create_public_header(task
):
37 '''create a public header from a private one, output within the build tree'''
38 src
= task
.inputs
[0].abspath(task
.env
)
39 tgt
= task
.outputs
[0].bldpath(task
.env
)
41 if os
.path
.exists(tgt
):
44 relsrc
= os_path_relpath(src
, task
.env
.TOPDIR
)
46 infile
= open(src
, mode
='r')
47 outfile
= open(tgt
, mode
='w')
50 search_paths
= [ '', task
.env
.RELPATH
]
51 for i
in task
.env
.EXTRA_INCLUDES
:
53 search_paths
.append(i
[1:])
58 # allow some straight substitutions
59 if task
.env
.public_headers_replace
and line
.strip() in task
.env
.public_headers_replace
:
60 outfile
.write(task
.env
.public_headers_replace
[line
.strip()] + '\n')
63 # see if its an include line
64 m
= re_header
.match(line
)
69 # its an include, get the header path
71 if hpath
.startswith("bin/default/"):
74 # some are always allowed
75 if task
.env
.public_headers_skip
and hpath
in task
.env
.public_headers_skip
:
79 # work out the header this refers to
81 for s
in search_paths
:
82 p
= os
.path
.normpath(os
.path
.join(s
, hpath
))
84 outfile
.write("#include <%s>\n" % header_map
[p
])
90 if task
.env
.public_headers_allow_broken
:
91 Logs
.warn("Broken public header include '%s' in '%s'" % (hpath
, relsrc
))
95 # try to be nice to the developer by suggesting an alternative
96 suggested
= find_suggested_header(hpath
)
99 sys
.stderr
.write("%s:%u:Error: unable to resolve public header %s (maybe try one of %s)\n" % (
100 os
.path
.relpath(src
, os
.getcwd()), linenumber
, hpath
, suggested
))
101 raise Utils
.WafError("Unable to resolve header path '%s' in public header '%s' in directory %s" % (
102 hpath
, relsrc
, task
.env
.RELPATH
))
107 def PUBLIC_HEADERS(bld
, public_headers
, header_path
=None, public_headers_install
=True):
108 '''install some headers
110 header_path may either be a string that is added to the INCLUDEDIR,
111 or it can be a dictionary of wildcard patterns which map to destination
112 directories relative to INCLUDEDIR
114 bld
.SET_BUILD_GROUP('final')
115 if not bld
.env
.build_public_headers
:
116 bld
.env
.build_public_headers
= ''
118 # create the public header in the given path
120 for h
in TO_LIST(public_headers
):
121 inst_path
= header_install_path(h
, header_path
)
122 if h
.find(':') != -1:
128 inst_name
= os
.path
.basename(h
)
129 relpath1
= os_path_relpath(bld
.srcnode
.abspath(), bld
.curdir
)
130 relpath2
= os_path_relpath(bld
.curdir
, bld
.srcnode
.abspath())
131 targetdir
= os
.path
.normpath(os
.path
.join(relpath1
, bld
.env
.build_public_headers
, inst_path
))
132 if not os
.path
.exists(os
.path
.join(bld
.curdir
, targetdir
)):
133 raise Utils
.WafError("missing source directory %s for public header %s" % (targetdir
, inst_name
))
134 target
= os
.path
.join(targetdir
, inst_name
)
136 # the source path of the header, relative to the top of the source tree
137 src_path
= os
.path
.normpath(os
.path
.join(relpath2
, h_name
))
139 # the install path of the header, relative to the public include directory
140 target_path
= os
.path
.normpath(os
.path
.join(inst_path
, inst_name
))
142 header_map
[src_path
] = target_path
144 build_dir
= os
.path
.join(bld
.bldnode
.abspath(),
146 bld
.env
.build_public_headers
,
148 if not os
.path
.exists(build_dir
):
151 t
= bld
.SAMBA_GENERATOR('HEADER_%s/%s/%s' % (relpath2
, inst_path
, inst_name
),
153 rule
=create_public_header
,
156 t
.env
.RELPATH
= relpath2
157 t
.env
.TOPDIR
= bld
.srcnode
.abspath()
158 if not bld
.env
.public_headers_list
:
159 bld
.env
.public_headers_list
= []
160 bld
.env
.public_headers_list
.append(os
.path
.join(inst_path
, inst_name
))
161 if public_headers_install
:
162 bld
.INSTALL_FILES('${INCLUDEDIR}',
164 destname
=os
.path
.join(inst_path
, inst_name
), flat
=True)
165 Build
.BuildContext
.PUBLIC_HEADERS
= PUBLIC_HEADERS