2 # Waf utilities for easily building standard unixey packages/libraries
3 # Licensed under the GNU GPL v2 or later, see COPYING file for details.
4 # Copyright (C) 2008 Dave Robillard
5 # Copyright (C) 2008 Nedko Arnaudov
13 from TaskGen
import feature
, before
, after
18 # Only run autowaf hooks once (even if sub projects call several times)
22 # Compute dependencies globally
24 #preproc.go_absolute = True
27 @after('apply_lib_vars')
28 @before('apply_obj_vars_cc', 'apply_obj_vars_cxx')
29 def include_config_h(self
):
30 self
.env
.append_value('INC_PATHS', self
.bld
.srcnode
)
33 "Add standard autowaf options if they havn't been added yet"
37 opt
.tool_options('compiler_cc')
38 opt
.tool_options('compiler_cxx')
39 opt
.add_option('--debug', action
='store_true', default
=False, dest
='debug',
40 help="Build debuggable binaries [Default: False]")
41 opt
.add_option('--strict', action
='store_true', default
=False, dest
='strict',
42 help="Use strict compiler flags and show all warnings [Default: False]")
43 opt
.add_option('--build-docs', action
='store_true', default
=False, dest
='build_docs',
44 help="Build documentation - requires doxygen [Default: False]")
45 opt
.add_option('--bundle', action
='store_true', default
=False,
46 help="Build a self-contained bundle [Default: False]")
47 opt
.add_option('--bindir', type='string',
48 help="Executable programs [Default: PREFIX/bin]")
49 opt
.add_option('--libdir', type='string',
50 help="Libraries [Default: PREFIX/lib]")
51 opt
.add_option('--includedir', type='string',
52 help="Header files [Default: PREFIX/include]")
53 opt
.add_option('--datadir', type='string',
54 help="Shared data [Default: PREFIX/share]")
55 opt
.add_option('--mandir', type='string',
56 help="Manual pages [Default: DATADIR/man]")
57 opt
.add_option('--htmldir', type='string',
58 help="HTML documentation [Default: DATADIR/doc/PACKAGE]")
59 opt
.add_option('--lv2-user', action
='store_true', default
=False, dest
='lv2_user',
60 help="Install LV2 bundles to user-local location [Default: False]")
61 if sys
.platform
== "darwin":
62 opt
.add_option('--lv2dir', type='string',
63 help="LV2 bundles [Default: /Library/Audio/Plug-Ins/LV2]")
65 opt
.add_option('--lv2dir', type='string',
66 help="LV2 bundles [Default: LIBDIR/lv2]")
69 def check_header(conf
, name
, define
='', mandatory
=False):
70 "Check for a header iff it hasn't been checked for yet"
71 if type(conf
.env
['AUTOWAF_HEADERS']) != dict:
72 conf
.env
['AUTOWAF_HEADERS'] = {}
74 checked
= conf
.env
['AUTOWAF_HEADERS']
75 if not name
in checked
:
78 conf
.check(header_name
=name
, define_name
=define
, mandatory
=mandatory
)
80 conf
.check(header_name
=name
, mandatory
=mandatory
)
82 def check_tool(conf
, name
):
83 "Check for a tool iff it hasn't been checked for yet"
84 if type(conf
.env
['AUTOWAF_TOOLS']) != dict:
85 conf
.env
['AUTOWAF_TOOLS'] = {}
87 checked
= conf
.env
['AUTOWAF_TOOLS']
88 if not name
in checked
:
92 def check_pkg(conf
, name
, **args
):
93 "Check for a package iff it hasn't been checked for yet"
94 var_name
= 'HAVE_' + args
['uselib_store']
95 check
= not var_name
in conf
.env
96 if not check
and 'atleast_version' in args
:
97 # Re-check if version is newer than previous check
98 checked_version
= conf
.env
['VERSION_' + name
]
99 if checked_version
and checked_version
< args
['atleast_version']:
102 conf
.check_cfg(package
=name
, args
="--cflags --libs", **args
)
103 found
= bool(conf
.env
['HAVE_' + args
['uselib_store']])
105 conf
.define('HAVE_' + args
['uselib_store'], int(found
))
106 if 'atleast_version' in args
:
107 conf
.env
['VERSION_' + name
] = args
['atleast_version']
109 conf
.undefine('HAVE_' + args
['uselib_store'])
110 if args
['mandatory'] == True:
111 conf
.fatal("Required package " + name
+ " not found")
113 def chop_prefix(conf
, var
):
114 name
= conf
.env
[var
][len(conf
.env
['PREFIX']):]
115 if len(name
) > 0 and name
[0] == '/':
125 def append_cxx_flags(val
):
126 conf
.env
.append_value('CCFLAGS', val
)
127 conf
.env
.append_value('CXXFLAGS', val
)
129 check_tool(conf
, 'misc')
130 check_tool(conf
, 'compiler_cc')
131 check_tool(conf
, 'compiler_cxx')
132 conf
.env
['BUILD_DOCS'] = Options
.options
.build_docs
133 conf
.env
['DEBUG'] = Options
.options
.debug
134 conf
.env
['PREFIX'] = os
.path
.abspath(os
.path
.expanduser(os
.path
.normpath(conf
.env
['PREFIX'])))
135 if Options
.options
.bundle
:
136 conf
.env
['BUNDLE'] = True
137 conf
.define('BUNDLE', 1)
138 conf
.env
['BINDIR'] = conf
.env
['PREFIX']
139 conf
.env
['INCLUDEDIR'] = conf
.env
['PREFIX'] + '/Headers/'
140 conf
.env
['LIBDIR'] = conf
.env
['PREFIX'] + '/Libraries/'
141 conf
.env
['DATADIR'] = conf
.env
['PREFIX'] + '/Resources/'
142 conf
.env
['HTMLDIR'] = conf
.env
['PREFIX'] + '/Resources/Documentation/'
143 conf
.env
['MANDIR'] = conf
.env
['PREFIX'] + '/Resources/Man/'
144 conf
.env
['LV2DIR'] = conf
.env
['PREFIX'] + '/PlugIns/'
146 conf
.env
['BUNDLE'] = False
147 if Options
.options
.bindir
:
148 conf
.env
['BINDIR'] = Options
.options
.bindir
150 conf
.env
['BINDIR'] = conf
.env
['PREFIX'] + '/bin/'
151 if Options
.options
.includedir
:
152 conf
.env
['INCLUDEDIR'] = Options
.options
.includedir
154 conf
.env
['INCLUDEDIR'] = conf
.env
['PREFIX'] + '/include/'
155 if Options
.options
.libdir
:
156 conf
.env
['LIBDIR'] = Options
.options
.libdir
158 conf
.env
['LIBDIR'] = conf
.env
['PREFIX'] + '/lib/'
159 if Options
.options
.datadir
:
160 conf
.env
['DATADIR'] = Options
.options
.datadir
162 conf
.env
['DATADIR'] = conf
.env
['PREFIX'] + '/share/'
163 if Options
.options
.htmldir
:
164 conf
.env
['HTMLDIR'] = Options
.options
.htmldir
166 conf
.env
['HTMLDIR'] = conf
.env
['DATADIR'] + 'doc/' + Utils
.g_module
.APPNAME
+ '/'
167 if Options
.options
.mandir
:
168 conf
.env
['MANDIR'] = Options
.options
.mandir
170 conf
.env
['MANDIR'] = conf
.env
['DATADIR'] + 'man/'
171 if Options
.options
.lv2dir
:
172 conf
.env
['LV2DIR'] = Options
.options
.lv2dir
174 if Options
.options
.lv2_user
:
175 if sys
.platform
== "darwin":
176 conf
.env
['LV2DIR'] = os
.getenv('HOME') + '/Library/Audio/Plug-Ins/LV2'
178 conf
.env
['LV2DIR'] = os
.getenv('HOME') + '/.lv2'
180 if sys
.platform
== "darwin":
181 conf
.env
['LV2DIR'] = '/Library/Audio/Plug-Ins/LV2'
183 conf
.env
['LV2DIR'] = conf
.env
['LIBDIR'] + 'lv2/'
185 conf
.env
['BINDIRNAME'] = chop_prefix(conf
, 'BINDIR')
186 conf
.env
['LIBDIRNAME'] = chop_prefix(conf
, 'LIBDIR')
187 conf
.env
['DATADIRNAME'] = chop_prefix(conf
, 'DATADIR')
188 conf
.env
['LV2DIRNAME'] = chop_prefix(conf
, 'LV2DIR')
190 if Options
.options
.debug
:
191 conf
.env
['CCFLAGS'] = '-O0 -g -std=c99'
192 conf
.env
['CXXFLAGS'] = '-O0 -g -ansi'
193 if Options
.options
.strict
:
194 conf
.env
['CCFLAGS'] = '-O0 -g -std=c99 -pedantic'
195 append_cxx_flags('-Wall -Wextra -Wno-unused-parameter')
196 conf
.env
.append_value('CXXFLAGS', '-Woverloaded-virtual')
197 append_cxx_flags('-fPIC -DPIC')
200 def set_local_lib(conf
, name
, has_objects
):
201 conf
.define('HAVE_' + name
.upper(), 1)
203 if type(conf
.env
['AUTOWAF_LOCAL_LIBS']) != dict:
204 conf
.env
['AUTOWAF_LOCAL_LIBS'] = {}
205 conf
.env
['AUTOWAF_LOCAL_LIBS'][name
.lower()] = True
207 if type(conf
.env
['AUTOWAF_LOCAL_HEADERS']) != dict:
208 conf
.env
['AUTOWAF_LOCAL_HEADERS'] = {}
209 conf
.env
['AUTOWAF_LOCAL_HEADERS'][name
.lower()] = True
211 def use_lib(bld
, obj
, libs
):
212 abssrcdir
= os
.path
.abspath('.')
213 libs_list
= libs
.split()
215 in_headers
= l
.lower() in bld
.env
['AUTOWAF_LOCAL_HEADERS']
216 in_libs
= l
.lower() in bld
.env
['AUTOWAF_LOCAL_LIBS']
218 if hasattr(obj
, 'uselib_local'):
219 obj
.uselib_local
+= ' lib' + l
.lower() + ' '
221 obj
.uselib_local
= 'lib' + l
.lower() + ' '
223 if in_headers
or in_libs
:
224 inc_flag
= '-iquote ' + abssrcdir
+ '/' + l
.lower()
225 for f
in ['CCFLAGS', 'CXXFLAGS']:
226 if not inc_flag
in bld
.env
[f
]:
227 bld
.env
.prepend_value(f
, inc_flag
)
229 if hasattr(obj
, 'uselib'):
230 obj
.uselib
+= ' ' + l
235 def display_header(title
):
236 Utils
.pprint('BOLD', title
)
238 def display_msg(conf
, msg
, status
= None, color
= None):
240 if type(status
) == bool and status
or status
== "True":
242 elif type(status
) == bool and not status
or status
== "False":
244 Utils
.pprint('NORMAL', "%s :" % msg
.ljust(conf
.line_just
), sep
='')
245 Utils
.pprint(color
, status
)
247 def print_summary(conf
):
254 display_header('Global configuration')
255 display_msg(conf
, "Install prefix", conf
.env
['PREFIX'])
256 display_msg(conf
, "Debuggable build", str(conf
.env
['DEBUG']))
257 display_msg(conf
, "Build documentation", str(conf
.env
['BUILD_DOCS']))
261 def link_flags(env
, lib
):
262 return ' '.join(map(lambda x
: env
['LIB_ST'] % x
, env
['LIB_' + lib
]))
264 def compile_flags(env
, lib
):
265 return ' '.join(map(lambda x
: env
['CPPPATH_ST'] % x
, env
['CPPPATH_' + lib
]))
276 def build_pc(bld
, name
, version
, libs
):
277 '''Build a pkg-config file for a library.
278 name -- uppercase variable name (e.g. 'SOMENAME')
279 version -- version string (e.g. '1.2.3')
280 libs -- string/list of dependencies (e.g. 'LIBFOO GLIB')
283 obj
= bld
.new_task_gen('subst')
284 obj
.source
= name
.lower() + '.pc.in'
285 obj
.target
= name
.lower() + '.pc'
286 obj
.install_path
= '${PREFIX}/${LIBDIRNAME}/pkgconfig'
287 pkg_prefix
= bld
.env
['PREFIX']
288 if pkg_prefix
[-1] == '/':
289 pkg_prefix
= pkg_prefix
[:-1]
291 'prefix' : pkg_prefix
,
292 'exec_prefix' : '${prefix}',
293 'libdir' : '${exec_prefix}/lib',
294 'includedir' : '${prefix}/include',
295 name
+ '_VERSION' : version
,
296 name
+ '_VERSION_MAJOR_MINOR' : ".".join(version
.split(".")[0:2]),
298 if type(libs
) != list:
301 obj
.dict[i
+ '_LIBS'] = link_flags(bld
.env
, i
)
302 obj
.dict[i
+ '_CFLAGS'] = compile_flags(bld
.env
, i
)
304 # Doxygen API documentation
305 def build_dox(bld
, name
, version
, srcdir
, blddir
):
306 if not bld
.env
['BUILD_DOCS']:
308 obj
= bld
.new_task_gen('subst')
309 obj
.source
= 'doc/reference.doxygen.in'
310 obj
.target
= 'doc/reference.doxygen'
312 src_dir
= srcdir
+ '/' + name
.lower()
313 doc_dir
= blddir
+ '/default/' + name
.lower() + '/doc'
316 doc_dir
= blddir
+ '/default/doc'
318 name
+ '_VERSION' : version
,
319 name
+ '_SRCDIR' : os
.path
.abspath(src_dir
),
320 name
+ '_DOC_DIR' : os
.path
.abspath(doc_dir
)
322 obj
.install_path
= ''
323 out1
= bld
.new_task_gen('command-output')
324 out1
.stdout
= '/doc/doxygen.out'
325 out1
.stdin
= '/doc/reference.doxygen' # whatever..
326 out1
.command
= 'doxygen'
327 out1
.argv
= [os
.path
.abspath(doc_dir
) + '/reference.doxygen']
328 out1
.command_is_external
= True
331 # This isn't really correct (for packaging), but people asking is annoying
332 if Options
.commands
['install']:
333 try: os
.popen("/sbin/ldconfig")