3
# Thomas Nagy, 2006 (ita)
9
import Action, Common, Object, Params, Runner, Scan, Utils
10
from Params import error, fatal, debug
11
from Params import set_globals, globals
13
def getSOfromLA(lafile):
15
contents = open(lafile, 'r').read()
16
match = re.search("^dlname='([^']*)'$", contents, re.M)
17
if match: return match.group(1)
20
set_globals('MOC_H', ['.hh', '.h'])
21
set_globals('UI_EXT', ['.ui'])
22
set_globals('SKEL_EXT', ['.skel'])
23
set_globals('STUB_EXT', ['.stub'])
24
set_globals('KCFGC_EXT', ['.kcfgc'])
26
kcfg_regexp = re.compile('[fF]ile\s*=\s*(.+)\s*', re.M)
27
"regexp for the kcfg scanner"
29
class kcfg_scanner(Scan.scanner):
30
"a scanner for .kcfgc files (kde xml configuration files)"
32
Scan.scanner.__init__(self)
34
def scan(self, node, env, path_lst):
35
variant = node.variant(env)
37
debug("kcfg scanner called for "+str(node), 'kcfg')
38
file = open(node.abspath(env), 'rb')
39
found = kcfg_regexp.findall(file.read())
43
fatal("no kcfg file found when scanning the .kcfgc- that's very bad")
47
node = dir.get_file(name)
48
if node: return ([node], found)
49
fatal("the kcfg file was not found - that's very bad")
52
g_kcfg_scanner = kcfg_scanner()
53
"scanner for kcfg files (kde)"
55
# kde .ui file processing
56
#uic_vardeps = ['UIC', 'UIC_FLAGS', 'UIC_ST']
57
uic_vardeps = ['UIC', 'QTPLUGINS']
59
# outputs : 1. hfile 2. cppfile
61
base = task.m_outputs[1].m_name
64
inc_kde ='#include <klocale.h>\n#include <kdialog.h>\n'
65
inc_moc ='#include "%s.moc"\n' % base
67
ui_path = task.m_inputs[0].bldpath(task.m_env)
68
h_path = task.m_outputs[0].bldpath(task.m_env)
69
cpp_path = task.m_outputs[1].bldpath(task.m_env)
71
qtplugins = task.m_env['QTPLUGINS']
72
uic_command = task.m_env['UIC']
74
comp_h = '%s -L %s -nounload -o %s %s' % (uic_command, qtplugins, h_path, ui_path)
75
comp_c = '%s -L %s -nounload -tr tr2i18n -impl %s %s >> %s' % (uic_command, qtplugins, h_path, ui_path, cpp_path)
77
ret = Runner.exec_command( comp_h )
80
dest = open( cpp_path, 'w' )
84
ret = Runner.exec_command( comp_c )
87
dest = open( cpp_path, 'a' )
94
class kde_translations(Object.genobj):
95
def __init__(self, appname):
96
Object.genobj.__init__(self, 'other')
98
self.m_appname = appname
100
for file in self.path.files():
102
base, ext = os.path.splitext(file.m_name)
103
if ext != '.po': continue
104
task = self.create_task('po', self.env, 20)
105
task.set_inputs(file)
106
task.set_outputs(file.change_ext('.gmo'))
107
self.m_tasks.append(task)
110
destfilename = self.m_appname+'.mo'
112
current = Params.g_build.m_curdirnode
113
for file in self.path.files():
114
lang, ext = os.path.splitext(file.m_name)
115
if ext != '.po': continue
117
node = self.path.find_source(lang+'.gmo')
118
orig = node.relpath_gen(current)
120
destfile = os.path.join(lang, 'LC_MESSAGES', destfilename)
121
Common.install_as('KDE_LOCALE', destfile, orig, self.env)
124
class kde_documentation(Object.genobj):
125
def __init__(self, appname, lang):
126
Object.genobj.__init__(self, 'other')
128
self.m_appname = appname
132
def add_docs(self, s):
133
self.m_docs = s+" "+self.m_docs
135
for filename in self.m_docs.split():
136
if not filename: continue
137
node = self.path.find_source(filename)
139
self.m_files.append(node)
140
(base, ext) = os.path.splitext(filename)
141
if ext == '.docbook':
142
task = self.create_task('meinproc', self.env, 20)
143
task.set_inputs(node)
144
task.set_outputs(node.change_ext('.cache.bz2'))
145
self.m_docbooks.append(task)
147
destpath = os.path.join(self.m_lang, self.m_appname)
149
current = Params.g_build.m_curdirnode
151
for task in self.m_docbooks:
152
lst.append(task.m_outputs[0].abspath(self.env))
153
for doc in self.m_files:
154
lst.append(doc.abspath(self.env))
156
Common.install_files('KDE_DOC', destpath, lst, self.env)
158
def handler_ui(self, node, base=''):
160
cppnode = node.change_ext('.cpp')
161
hnode = node.change_ext('.h')
163
uictask = self.create_task('uic', self.env, 20)
164
uictask.set_inputs(node)
165
uictask.set_outputs([hnode, cppnode])
167
moctask = self.create_task('moc', self.env)
168
moctask.set_inputs(hnode)
169
moctask.set_outputs(node.change_ext('.moc'))
171
cpptask = self.create_task('cpp', self.env)
172
cpptask.set_inputs(cppnode)
173
cpptask.set_outputs(node.change_ext('.o'))
174
cpptask.m_run_after = [moctask]
176
def handler_kcfgc(self, node, base=''):
177
tree = Params.g_build
178
if tree.needs_rescan(node, self.env):
179
hash = {'path_lst': self.dir_lst['path_lst']}
180
g_kcfg_scanner.do_scan(node, self.env, hashparams=hash)
182
variant = node.variant(self.env)
183
kcfg_node = tree.m_depends_on[variant][node][0]
184
cppnode = node.change_ext('.cpp')
186
# run with priority 2
187
task = self.create_task('kcfg', nice=2)
188
task.set_inputs([kcfg_node, node])
189
task.set_outputs([cppnode, node.change_ext('.h')])
191
cpptask = self.create_task('cpp', self.env)
192
cpptask.set_inputs(cppnode)
193
cpptask.set_outputs(node.change_ext('.o'))
195
def handler_skel_or_stub(obj, base, type):
196
if not base in obj.skel_or_stub:
197
kidltask = obj.create_task('kidl', obj.env, 20)
198
kidltask.set_inputs(obj.find(base+'.h'))
199
kidltask.set_outputs(obj.find(base+'.kidl'))
200
obj.skel_or_stub[base] = kidltask
202
# this is a cascading builder .h->.kidl->_stub.cpp->_stub.o->link
203
# instead of saying "task.run_after(othertask)" we only give priority numbers on tasks
205
# the skel or stub (dcopidl2cpp)
206
task = obj.create_task(type, obj.env, 40)
207
task.set_inputs(obj.skel_or_stub[base].m_outputs)
208
task.set_outputs(obj.find(''.join([base,'_',type,'.cpp'])))
210
# compile the resulting file (g++)
211
cpptask = obj.create_task('cpp', obj.env)
212
cpptask.set_inputs(task.m_outputs)
213
cpptask.set_outputs(obj.find(''.join([base,'_',type,'.o'])))
215
def handler_stub(self, node, base=''):
216
handler_skel_or_stub(self, base, 'stub')
218
def handler_skel(self, node, base=''):
219
handler_skel_or_stub(self, base, 'skel')
222
class kdeobj(cpp.cppobj):
223
s_default_ext = ['.cpp', '.ui', '.kcfgc', '.skel', '.stub']
224
def __init__(self, type='program'):
225
cpp.cppobj.__init__(self, type)
226
self.m_linktask = None
228
self.skel_or_stub = {}
229
self.defines_lst = {}
230
self.want_libtool = -1 # fake libtool here
232
# valid types are ['program', 'shlib', 'staticlib', 'module', 'convenience', 'other']
234
def apply_core(self):
236
if self.want_libtool and self.want_libtool>0: self.apply_libtool()
238
obj_ext = self.env[self.m_type+'_obj_ext'][0]
240
# get the list of folders to use by the scanners
241
# all our objects share the same include paths anyway
242
tree = Params.g_build
243
self.dir_lst = { 'path_lst' : self._incpaths_lst, 'defines' : self.defines_lst }
245
lst = self.source.split()
248
# attach a new method called "find" (i know, evil ;; ita)
249
self.find = self.path.find_build
252
node = self.path.find_build(filename)
255
if ext != 'skel' and ext != 'stub':
256
fatal("cannot find %s in %s" % (filename, str(self.path)))
257
base, ext = os.path.splitext(filename)
259
fun = self.get_hook(ext)
261
fun(self, node, base=base)
264
# scan for moc files to produce, create cpp tasks at the same time
266
if tree.needs_rescan(node, self.env):
267
ccroot.g_c_scanner.do_scan(node, self.env, hashparams = self.dir_lst)
272
variant = node.variant(self.env)
274
try: tmp_lst = tree.m_raw_deps[variant][node]
277
base2, ext2 = os.path.splitext(d)
278
if not ext2 == '.moc': continue
281
error("paranoia owns")
283
# process that base.moc only once
286
# find the extension - this search is done only once
287
if Params.g_options.kde_header_ext:
288
ext = Params.g_options.kde_header_ext
290
path = node.m_parent.srcpath(self.env)
291
for i in globals('MOC_H'):
293
os.stat(os.path.join(path,base2+i))
298
if not ext: fatal("no header found for %s which is a moc file" % filename)
300
# next time we will not search for the extension (look at the 'for' loop below)
301
h_node = node.change_ext(ext)
302
m_node = node.change_ext('.moc')
303
tree.m_depends_on[variant][m_node] = h_node
306
task = self.create_task('moc', self.env)
307
task.set_inputs(h_node)
308
task.set_outputs(m_node)
309
moctasks.append(task)
311
# look at the file inputs, it is set right above
312
for d in tree.m_depends_on[variant][node]:
314
if name[-4:]=='.moc':
315
task = self.create_task('moc', self.env)
316
task.set_inputs(tree.m_depends_on[variant][d])
318
moctasks.append(task)
321
# create the task for the cpp file
322
cpptask = self.create_task('cpp', self.env)
324
cpptask.m_scanner = ccroot.g_c_scanner
325
cpptask.m_scanner_params = self.dir_lst
327
cpptask.set_inputs(node)
328
cpptask.set_outputs(node.change_ext(obj_ext))
329
cpptask.m_run_after = moctasks
331
# and after the cpp objects, the remaining is the link step - in a lower priority so it runs alone
332
if self.m_type=='staticlib': linktask = self.create_task('ar_link_static', self.env, ccroot.g_prio_link)
333
else: linktask = self.create_task('cpp_link', self.env, ccroot.g_prio_link)
335
for t in self.p_compiletasks: cppoutputs.append(t.m_outputs[0])
336
linktask.set_inputs(cppoutputs)
337
linktask.set_outputs(self.path.find_build(self.get_target_name()))
339
self.m_linktask = linktask
341
if self.m_type != 'program' and self.want_libtool:
342
latask = self.create_task('fakelibtool', self.env, 200)
343
latask.set_inputs(linktask.m_outputs)
344
latask.set_outputs(self.path.find_build(self.get_target_name('.la')))
345
self.m_latask = latask
348
if self.m_type == 'module':
349
self.install_results('KDE_MODULE', '', self.m_linktask)
350
if self.want_libtool: self.install_results('KDE_MODULE', '', self.m_latask)
351
elif self.m_type == 'shlib':
355
if self.want_libtool: self.install_results(dest_var, dest_subdir, self.m_latask)
356
if sys.platform=='win32' or not self.vnum:
357
self.install_results(dest_var, dest_subdir, self.m_linktask)
359
libname = self.m_linktask.m_outputs[0].m_name
361
nums=self.vnum.split('.')
362
name3 = libname+'.'+self.vnum
363
name2 = libname+'.'+nums[0]
366
filename = self.m_linktask.m_outputs[0].relpath_gen(Params.g_build.m_curdirnode)
368
Common.install_as(dest_var, dest_subdir+'/'+name3, filename)
370
#print 'lib/'+name2, '->', name3
371
#print 'lib/'+name1, '->', name2
373
Common.symlink_as(dest_var, name3, dest_subdir+'/'+name2)
374
Common.symlink_as(dest_var, name2, dest_subdir+'/'+name1)
376
ccroot.ccroot.install(self)
378
def detect_kde(conf):
380
# Detect the qt and kde environment using kde-config mostly
382
#if env.has_key('ARGS'): return env['ARGS'].get(varname, '')
384
try: v = getattr(Params.g_options, varname)
388
def getpath(varname):
390
#if not env.has_key('ARGS'): return None
391
#v=env['ARGS'].get(varname, None)
392
if v: v=os.path.abspath(v)
395
def exec_and_read(cmd):
397
ret = p.read().strip()
401
prefix = getpath('prefix')
402
execprefix = getpath('execprefix')
403
datadir = getpath('datadir')
404
libdir = getpath('libdir')
406
kdedir = getstr('kdedir')
407
kdeincludes = getpath('kdeincludes')
408
kdelibs = getpath('kdelibs')
410
qtdir = getstr('qtdir')
411
qtincludes = getpath('qtincludes')
412
qtlibs = getpath('qtlibs')
413
libsuffix = getstr('libsuffix')
415
if (prefix=='/usr/local' or prefix=='/usr/local/') and not Params.g_options.usrlocal:
420
if libdir: libdir = libdir+libsuffix
422
## Detect the kde libraries
423
print "Checking for kde-config :",
424
str="which kde-config 2>/dev/null"
425
if kdedir: str="which %s 2>/dev/null" % (kdedir+'/bin/kde-config')
426
kde_config = exec_and_read(str)
428
p('GREEN', 'kde-config was found as '+kde_config)
430
if kdedir: p('RED','kde-config was NOT found in the folder given '+kdedir)
431
else: p('RED','kde-config was NOT found in your PATH')
432
print "Make sure kde is installed properly"
433
print "(missing package kdebase-devel?)"
435
if kdedir: env['KDEDIR']=kdedir
436
else: env['KDEDIR'] = exec_and_read('%s -prefix' % kde_config)
438
print "Checking for kde version :",
439
kde_version = exec_and_read('%s --version|grep KDE' % kde_config).split()[1]
440
if int(kde_version[0]) != 3 or int(kde_version[2]) < 2:
441
p('RED', kde_version)
442
p('RED',"Your kde version can be too old")
443
p('RED',"Please make sure kde is at least 3.2")
445
p('GREEN',kde_version)
447
## Detect the Qt library
448
print "Checking for the Qt library :",
449
if not qtdir: qtdir = os.getenv("QTDIR")
451
p('GREEN',"Qt is in "+qtdir)
454
tmplibdir = exec_and_read('%s --expandvars --install lib' % kde_config)
455
libkdeuiSO = os.path.join(tmplibdir, getSOfromLA(os.path.join(tmplibdir,'/libkdeui.la')) )
456
m = re.search('(.*)/lib/libqt.*', exec_and_read('ldd %s | grep libqt' % libkdeuiSO).split()[2])
460
p('YELLOW',"Qt was found as "+m.group(1))
462
p('RED','Qt was not found')
463
p('RED','* Make sure libqt3-dev is installed')
464
p('RED','* Set QTDIR (for example, "export QTDIR=/usr/lib/qt3")')
465
p('RED','* Try "waf -h" for more options')
467
env['QTDIR'] = qtdir.strip()
468
env['LIB_QT'] = 'qt-mt'
470
## Find the necessary programs uic and moc
471
print "Checking for uic :",
472
uic = qtdir + "/bin/uic"
473
if os.path.isfile(uic):
474
p('GREEN',"uic was found as "+uic)
476
uic = exec_and_read("which uic 2>/dev/null")
478
p('YELLOW',"uic was found as "+uic)
480
uic = exec_and_read("which uic 2>/dev/null")
482
p('YELLOW',"uic was found as "+uic)
484
p('RED','The program uic was not found')
485
p('RED','* Make sure libqt3-dev is installed')
486
p('RED','* Set QTDIR or PATH appropriately')
490
print "Checking for moc :",
491
moc = qtdir + "/bin/moc"
492
if os.path.isfile(moc):
493
p('GREEN',"moc was found as "+moc)
495
moc = exec_and_read("which moc 2>/dev/null")
497
p('YELLOW',"moc was found as "+moc)
498
elif os.path.isfile("/usr/share/qt3/bin/moc"):
499
moc = "/usr/share/qt3/bin/moc"
500
p('YELLOW',"moc was found as "+moc)
502
p('RED','The program moc was not found')
503
p('RED','* Make sure libqt3-dev is installed')
504
p('RED','* Set QTDIR or PATH appropriately')
508
## check for the qt and kde includes
509
print "Checking for the Qt includes :",
510
if qtincludes and os.path.isfile(qtincludes + "/qlayout.h"):
511
# The user told where to look for and it looks valid
512
p('GREEN',"ok "+qtincludes)
514
if os.path.isfile(qtdir + "/include/qlayout.h"):
515
# Automatic detection
516
p('GREEN',"ok "+qtdir+"/include/")
517
qtincludes = qtdir + "/include/"
518
elif os.path.isfile("/usr/include/qt3/qlayout.h"):
520
p('YELLOW','the Qt headers were found in /usr/include/qt3/')
521
qtincludes = "/usr/include/qt3"
523
p('RED','The Qt headers were not found')
524
p('RED','* Make sure libqt3-dev is installed')
525
p('RED','* Set QTDIR or PATH appropriately')
528
print "Checking for the kde includes :",
529
kdeprefix = exec_and_read('%s --prefix' % kde_config)
531
kdeincludes = kdeprefix+"/include/"
532
if os.path.isfile(kdeincludes + "/klineedit.h"):
533
p('GREEN',"ok "+kdeincludes)
535
if os.path.isfile(kdeprefix+"/include/kde/klineedit.h"):
536
# Debian, Fedora probably
537
p('YELLOW',"the kde headers were found in %s/include/kde/"%kdeprefix)
538
kdeincludes = kdeprefix + "/include/kde/"
540
p('RED',"The kde includes were NOT found")
541
p('RED',"* Make sure kdelibs-dev is installed")
542
p('RED',"* Try 'waf -h' for more options")
546
kdec_opts = {'KDE_BIN' : 'exe', 'KDE_APPS' : 'apps',
547
'KDE_DATA' : 'data', 'KDE_ICONS' : 'icon',
548
'KDE_MODULE' : 'module', 'KDE_LOCALE' : 'locale',
549
'KDE_KCFG' : 'kcfg', 'KDE_DOC' : 'html',
550
'KDE_MENU' : 'apps', 'KDE_XDG' : 'xdgdata-apps',
551
'KDE_MIME' : 'mime', 'KDE_XDGDIR' : 'xdgdata-dirs',
552
'KDE_SERV' : 'services','KDE_SERVTYPES' : 'servicetypes',
553
'CPPPATH_KDECORE': 'include' }
556
## use the user-specified prefix
557
if not execprefix: execprefix=prefix
558
if not datadir: datadir=os.path.join(prefix,'share')
559
if not libdir: libdir=os.path.join(execprefix, "lib"+libsuffix)
561
subst_vars = lambda x: x.replace('${exec_prefix}', execprefix)\
562
.replace('${datadir}', datadir)\
563
.replace('${libdir}', libdir)\
564
.replace('${prefix}', prefix)
565
debian_fix = lambda x: x.replace('/usr/share', '${datadir}')
566
env['PREFIX'] = prefix
567
env['KDE_LIB'] = libdir
568
for (var, option) in kdec_opts.items():
569
dir = exec_and_read('%s --install %s' % (kde_config, option))
570
if var == 'KDE_DOC': dir = debian_fix(dir)
571
env[var] = subst_vars(dir)
574
env['PREFIX'] = exec_and_read('%s --expandvars --prefix' % kde_config)
575
env['KDE_LIB'] = exec_and_read('%s --expandvars --install lib' % kde_config)
576
for (var, option) in kdec_opts.items():
577
dir = exec_and_read('%s --expandvars --install %s' % (kde_config, option))
580
env['QTPLUGINS']=exec_and_read('%s --expandvars --install qtplugins' % kde_config)
582
## kde libs and includes
583
env['CPPPATH_KDECORE']=kdeincludes
585
kdelibs=exec_and_read('%s --expandvars --install lib' % kde_config)
586
env['LIBPATH_KDECORE']=kdelibs
588
## qt libs and includes
589
env['CPPPATH_QT']=qtincludes
591
qtlibs=qtdir+"/lib"+libsuffix
592
env['LIBPATH_QT']=qtlibs
596
if Params.g_options.want_rpath:
597
env['RPATH_QT']=['-Wl,--rpath='+qtlibs]
598
env['RPATH_KDECORE']=['-Wl,--rpath='+kdelibs]
602
env['LIB_KDECORE'] = 'kdecore'
603
env['LIB_KIO'] = 'kio'
604
env['LIB_KMDI'] = 'kmdi'
605
env['LIB_KPARTS'] = 'kparts'
606
env['LIB_KDEPRINT'] = 'kdeprint'
607
env['LIB_KDEGAMES'] = 'kdegames'
609
env['KCONFIG_COMPILER'] = 'kconfig_compiler'
611
env['MEINPROC'] = 'meinproc'
612
env['MEINPROCFLAGS'] = '--check'
613
env['MEINPROC_ST'] = '--cache %s %s'
615
env['POCOM'] = 'msgfmt'
618
env['MOC_FLAGS'] = ''
621
env['DCOPIDL'] = 'dcopidl'
622
env['DCOPIDL2CPP'] = 'dcopidl2cpp'
624
env['module_CXXFLAGS'] = ['-fPIC', '-DPIC']
625
env['module_LINKFLAGS'] = ['-shared']
626
env['module_obj_ext'] = ['.os']
627
env['module_PREFIX'] = 'lib'
628
env['module_SUFFIX'] = '.so'
630
try: env['module_CXXFLAGS']=env['shlib_CXXFLAGS']
633
try: env['module_LINKFLAGS']=env['shlib_LINKFLAGS']
637
Action.simple_action('moc', '${MOC} ${MOC_FLAGS} ${SRC} ${MOC_ST} ${TGT}', color='BLUE')
638
Action.simple_action('meinproc', '${MEINPROC} ${MEINPROCFLAGS} --cache ${TGT} ${SRC}', color='BLUE')
639
Action.simple_action('po', '${POCOM} ${SRC} ${PO_ST} ${TGT}', color='BLUE')
640
Action.simple_action('kidl', '${DCOPIDL} ${SRC} > ${TGT} || (rm -f ${TGT} ; false)', color='BLUE')
641
Action.simple_action('skel', 'cd ${SRC[0].bld_dir(env)} && ${DCOPIDL2CPP} --c++-suffix cpp ' \
642
'--no-signals --no-stub ${SRC[0].m_name}', color='BLUE')
643
Action.simple_action('stub', 'cd ${SRC[0].bld_dir(env)} && ${DCOPIDL2CPP} --c++-suffix cpp ' \
644
'--no-signals --no-skel ${SRC[0].m_name}', color='BLUE')
645
Action.simple_action('kcfg', '${KCONFIG_COMPILER} -d${SRC[0].bld_dir(env)} ' \
646
'${SRC[0].bldpath(env)} ${SRC[1].bldpath(env)}', color='BLUE')
647
Action.Action('uic', vars=uic_vardeps, func=uic_build, color='BLUE')
649
Object.register('kde_translations', kde_translations)
650
Object.register('kde_documentation', kde_documentation)
651
Object.register('kde', kdeobj)
653
Object.hook('kde', 'UI_EXT', handler_ui)
654
Object.hook('kde', 'SKEL_EXT', handler_skel)
655
Object.hook('kde', 'STUB_EXT', handler_stub)
656
Object.hook('kde', 'KCFGC_EXT', handler_kcfgc)
660
conf.check_tool('checks')
661
conf.env['KDE_IS_FOUND'] = 0
665
conf.env['KDE_IS_FOUND'] = 1
668
def set_options(opt):
670
opt.add_option('--want-rpath', type='int', default=1, dest='want_rpath', help='set rpath to 1 or 0 [Default 1]')
674
opt.add_option('--usrlocal',
677
help='force prefix=/usr/local/',
680
opt.add_option('--header-ext',
683
help='header extension for moc files',
684
dest='kde_header_ext')
686
for i in "execprefix datadir libdir kdedir kdeincludes kdelibs qtdir qtincludes qtlibs libsuffix".split():
687
opt.add_option('--'+i, type='string', default='', dest=i)