By default, Bugzilla does not search the list of RESOLVED bugs.
You can force it to do so by putting the upper-case word ALL in front of your search query, e.g.: ALL tdelibs
We recommend searching for bugs this way, as you may discover that your bug has already been resolved and fixed in a later release. View | Details | Raw Unified | Return to bug 1790
Collapse All | Expand All

(-)b/app_templates/kcontrol_module/setup.py (-2 / +2 lines)
Lines 15-23 Link Here
15
#                                                                         #
15
#                                                                         #
16
###########################################################################
16
###########################################################################
17
17
18
import kdedistutils
18
import tdedistutils
19
19
20
kdedistutils.setup(name="kcontrol_module",
20
tdedistutils.setup(name="kcontrol_module",
21
    version="0.1.0",
21
    version="0.1.0",
22
    author="AUTHOR",
22
    author="AUTHOR",
23
    author_email="YOUR@EMAIL.com",
23
    author_email="YOUR@EMAIL.com",
(-)b/app_templates/kdeapp/setup.py (-2 / +2 lines)
Lines 15-23 Link Here
15
#                                                                         #
15
#                                                                         #
16
###########################################################################
16
###########################################################################
17
17
18
import kdedistutils
18
import tdedistutils
19
19
20
kdedistutils.setup(name="kdeapp",
20
tdedistutils.setup(name="kdeapp",
21
    version="0.1.0",
21
    version="0.1.0",
22
    author="AUTHOR",
22
    author="AUTHOR",
23
    author_email="YOUR@EMAIL.com",
23
    author_email="YOUR@EMAIL.com",
(-)b/app_templates/kdeutility/setup.py (-2 / +2 lines)
Lines 15-23 Link Here
15
#                                                                         #
15
#                                                                         #
16
###########################################################################
16
###########################################################################
17
17
18
import kdedistutils
18
import tdedistutils
19
19
20
kdedistutils.setup(name="kdeutility",
20
tdedistutils.setup(name="kdeutility",
21
    version="0.1.0",
21
    version="0.1.0",
22
    author="AUTHOR",
22
    author="AUTHOR",
23
    author_email="YOUR@EMAIL.com",
23
    author_email="YOUR@EMAIL.com",
(-)b/app_templates/tdeioslave/setup.py (-2 / +2 lines)
Lines 15-23 Link Here
15
#                                                                         #
15
#                                                                         #
16
###########################################################################
16
###########################################################################
17
17
18
import kdedistutils
18
import tdedistutils
19
19
20
kdedistutils.setup(name="tdeioslave",
20
tdedistutils.setup(name="tdeioslave",
21
    version="0.1.0",
21
    version="0.1.0",
22
    author="AUTHOR",
22
    author="AUTHOR",
23
    author_email="YOUR@EMAIL.com",
23
    author_email="YOUR@EMAIL.com",
(-)b/doc/en/index.docbook (-4 / +4 lines)
Lines 125-144 Link Here
125
Distutils is based around writing a <filename>setup.py</filename> file which
125
Distutils is based around writing a <filename>setup.py</filename> file which
126
then uses the distutils package
126
then uses the distutils package
127
To use the KDE extensions, the first thing you need to do in your <filename>setup.py
127
To use the KDE extensions, the first thing you need to do in your <filename>setup.py
128
</filename> file is include the <symbol>kdedistutils</symbol> package.
128
</filename> file is include the <symbol>tdedistutils</symbol> package.
129
<programlisting>
129
<programlisting>
130
#!/usr/bin/env python
130
#!/usr/bin/env python
131
# Setup.py file for MyKDEApplication
131
# Setup.py file for MyKDEApplication
132
132
133
import kdedistutils
133
import tdedistutils
134
</programlisting>
134
</programlisting>
135
135
136
You need to call the <symbol>setup()</symbol> function from <symbol>kdedistutils</symbol>
136
You need to call the <symbol>setup()</symbol> function from <symbol>tdedistutils</symbol>
137
with all of the configuration information about your application, much like the standard
137
with all of the configuration information about your application, much like the standard
138
<symbol>setup()</symbol> from <symbol>distutils</symbol>.
138
<symbol>setup()</symbol> from <symbol>distutils</symbol>.
139
139
140
<programlisting>
140
<programlisting>
141
kdedistutils.setup(name="pytdeextensions",
141
tdedistutils.setup(name="pytdeextensions",
142
    version="0.1.0",
142
    version="0.1.0",
143
    author="Simon Edwards",
143
    author="Simon Edwards",
144
    author_email="simon@simonzone.com",
144
    author_email="simon@simonzone.com",
(-)b/setup.py (-13 / +13 lines)
Lines 23-32 Link Here
23
import glob
23
import glob
24
sys.path.insert(0,"src") # We need this for the import statement below.
24
sys.path.insert(0,"src") # We need this for the import statement below.
25
25
26
import kdedistutils
26
import tdedistutils
27
27
28
def main():
28
def main():
29
    kdedistutils.setup(name="pytdeextensions",
29
    tdedistutils.setup(name="pytdeextensions",
30
        version="0.4.0",
30
        version="0.4.0",
31
        author="Simon Edwards",
31
        author="Simon Edwards",
32
        author_email="simon@simonzone.com",
32
        author_email="simon@simonzone.com",
Lines 35-41 Link Here
35
        min_qt_version = "3.0.0",
35
        min_qt_version = "3.0.0",
36
        license = "LGPL",
36
        license = "LGPL",
37
        package_dir = {'': 'src'},
37
        package_dir = {'': 'src'},
38
        py_modules = ["kdedistutils","qtuicompiler","qtdesigner","kdedesigner"],
38
        py_modules = ["tdedistutils","qtuicompiler","qtdesigner","kdedesigner"],
39
        application_data = ["app_templates","AUTHORS","ChangeLog","COPYING","INSTALL","NEWS"],
39
        application_data = ["app_templates","AUTHORS","ChangeLog","COPYING","INSTALL","NEWS"],
40
        docbooks = [ ('doc/en','en') ],
40
        docbooks = [ ('doc/en','en') ],
41
        cmdclass = {
41
        cmdclass = {
Lines 46-63 Link Here
46
        )
46
        )
47
47
48
###########################################################################
48
###########################################################################
49
class InstallPyKDEExtensions(kdedistutils.InstallKDE):
49
class InstallPyKDEExtensions(tdedistutils.InstallKDE):
50
    sub_commands = kdedistutils.InstallKDE.sub_commands[:]
50
    sub_commands = tdedistutils.InstallKDE.sub_commands[:]
51
    sub_commands.append( ('install_libpythonize',None) )
51
    sub_commands.append( ('install_libpythonize',None) )
52
    
52
    
53
    user_options = kdedistutils.InstallKDE.user_options
53
    user_options = tdedistutils.InstallKDE.user_options
54
    user_options.append( ('install-clib=', None, "installation directory for shared libraries") )
54
    user_options.append( ('install-clib=', None, "installation directory for shared libraries") )
55
    user_options.append( ('install-cheaders=', None, "installation directory for C header files") )
55
    user_options.append( ('install-cheaders=', None, "installation directory for C header files") )
56
            
56
            
57
    def initialize_options(self):
57
    def initialize_options(self):
58
        self.install_clib = None
58
        self.install_clib = None
59
        self.install_cheaders = None
59
        self.install_cheaders = None
60
        kdedistutils.InstallKDE.initialize_options(self)
60
        tdedistutils.InstallKDE.initialize_options(self)
61
61
62
    def finalize_options(self):
62
    def finalize_options(self):
63
        if self.install_clib is None:
63
        if self.install_clib is None:
Lines 65-71 Link Here
65
                self.install_clib = os.path.join(self.prefix,'lib')
65
                self.install_clib = os.path.join(self.prefix,'lib')
66
            else:
66
            else:
67
                self.announce("Detecting KDE library directory...")
67
                self.announce("Detecting KDE library directory...")
68
                self.install_clib = kdedistutils.ask_kde_config('--install lib --expandvars').strip()
68
                self.install_clib = tdedistutils.ask_kde_config('--install lib --expandvars').strip()
69
                self.announce("  ...KDE library directory is %s" % self.install_clib)
69
                self.announce("  ...KDE library directory is %s" % self.install_clib)
70
                
70
                
71
        if self.install_cheaders is None:
71
        if self.install_cheaders is None:
Lines 73-82 Link Here
73
                self.install_cheaders = os.path.join(self.prefix,'include')
73
                self.install_cheaders = os.path.join(self.prefix,'include')
74
            else:
74
            else:
75
                self.announce("Detecting KDE headers directory...")
75
                self.announce("Detecting KDE headers directory...")
76
                self.install_cheaders = os.path.normpath(os.path.join(kdedistutils.ask_kde_config('--install lib --expandvars').strip(),"../include"))
76
                self.install_cheaders = os.path.normpath(os.path.join(tdedistutils.ask_kde_config('--install lib --expandvars').strip(),"../include"))
77
                self.announce("  ...KDE library headers is %s" % self.install_cheaders)
77
                self.announce("  ...KDE library headers is %s" % self.install_cheaders)
78
78
79
        kdedistutils.InstallKDE.finalize_options(self)
79
        tdedistutils.InstallKDE.finalize_options(self)
80
80
81
        if self.root is not None:
81
        if self.root is not None:
82
            self.change_roots('clib','cheaders')
82
            self.change_roots('clib','cheaders')
Lines 126-137 Link Here
126
                
126
                
127
            # Find the C library (libgcc, libgcc_s or some other variation).
127
            # Find the C library (libgcc, libgcc_s or some other variation).
128
            if self.clib is None:
128
            if self.clib is None:
129
                canidatepaths = ["/usr/"+kdedistutils.get_libdir_name(), "/usr/local/"+kdedistutils.get_libdir_name(), "/usr/lib" ]
129
                canidatepaths = ["/usr/"+tdedistutils.get_libdir_name(), "/usr/local/"+tdedistutils.get_libdir_name(), "/usr/lib" ]
130
                self.clib = kdedistutils.FindFileInPaths("libgcc*.so",canidatepaths)
130
                self.clib = tdedistutils.FindFileInPaths("libgcc*.so",canidatepaths)
131
                if self.clib!=None:
131
                if self.clib!=None:
132
                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
132
                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
133
                else:
133
                else:
134
                    self.clib = kdedistutils.FindFileInPaths("libgcc*.a",canidatepaths)
134
                    self.clib = tdedistutils.FindFileInPaths("libgcc*.a",canidatepaths)
135
                    if self.clib!=None:
135
                    if self.clib!=None:
136
                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0]
136
                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0]
137
            if self.clib is None:
137
            if self.clib is None:
(-)b/src/kdedistutils.py (-2279 lines)
Lines 1-2279 Link Here
1
#!/usr/bin/python
2
###########################################################################
3
# kdedistutils - description                                              #
4
# ------------------------------                                          #
5
# begin     : Thu Apr 21 2005                                             #
6
# copyright : (C) 2005 by Simon Edwards                                   #
7
# email     : simon@simonzone.com                                         #
8
#                                                                         #
9
###########################################################################
10
#                                                                         #
11
#   This program is free software; you can redistribute it and/or modify  #
12
#   it under the terms of the GNU Library General Public License as       #
13
#   published by the Free Software Foundation; either version 2 of the    #
14
#   License, or (at your option) any later version.                       #
15
#                                                                         #
16
###########################################################################
17
18
import distutils.core
19
from distutils.core import Extension
20
from distutils.cmd import Command
21
from distutils.dist import Distribution
22
from distutils.command.build import build
23
from distutils.command.install import install
24
from distutils.command.install_scripts import install_scripts
25
from distutils.command.install_data import install_data
26
from distutils.command.install_lib import install_lib
27
from distutils.util import change_root, convert_path
28
from distutils.spawn import find_executable,spawn
29
from distutils import sysconfig 
30
from distutils import log
31
from distutils import file_util
32
from distutils import dir_util
33
from distutils.util import byte_compile
34
import qtuicompiler
35
import stat
36
import os,os.path,imp,glob
37
import sys
38
from types import StringType
39
40
INSTALL_LIST = 'install_log.txt'
41
42
# Trinity-specific paths
43
tqt_modules = []
44
from distutils.sysconfig import get_python_lib
45
for m_path in sys.path:
46
    if os.path.exists(os.path.join(m_path, 'sip4_tqt')):
47
        m_sip_dir = os.path.join(m_path, 'sip4_tqt')
48
        tqt_modules.insert(0, m_sip_dir)
49
    if os.path.exists(os.path.join(m_path, 'python_tqt')):
50
        m_pyqt_dir = os.path.join(m_path, 'python_tqt')
51
        tqt_modules.insert(0, m_pyqt_dir)
52
for m_path in tqt_modules:
53
    sys.path.insert(0, m_path)
54
55
56
###########################################################################
57
def setup(**arg_dict):
58
59
    if 'cmdclass' not in arg_dict:
60
        arg_dict['cmdclass'] = {}
61
62
    cmdclass = arg_dict['cmdclass']
63
    
64
    arg_dict.setdefault('data_files',[])
65
    
66
    kdecmdclass = {'install' : InstallKDE,
67
        'install_executable_links' : InstallExecutableLinks,
68
        'install_application_data' : InstallApplicationDataAndLinks,
69
        'build_messages' : BuildI18NMessages,
70
        'install_messages' : InstallI18NMessages,
71
        'update_messages' : UpdateI18NMessages,
72
        'checkpyqt' : CheckPyQt,
73
        'checkpytde' : CheckPyTDE,
74
        'uninstall' : Uninstall,
75
        'build' : BuildKDE,
76
        'build_kcm' : BuildKControlModule,
77
        'install_kcm' : InstallKControlModule,
78
        'build_html' : BuildDocbookHTML,
79
        'install_html' : InstallDocbookHTML,
80
        'install_lib' : InstallLibWithRoot,
81
        'build_tdeioslave' : BuildTdeioslave,
82
        'install_tdeioslave' : InstallTdeioslave}
83
84
    for key in kdecmdclass.iterkeys():
85
        cmdclass.setdefault(key,kdecmdclass[key])
86
87
    arg_dict.setdefault('distclass',KDEDistribution)
88
89
    apply(distutils.core.setup,[],arg_dict)
90
91
###########################################################################
92
class KDEDistribution(Distribution):
93
    def __init__(self,attrs=None):
94
        self.min_kde_version = None
95
        self.min_qt_version = None
96
        self.kcontrol_modules = None
97
        self.tdeioslaves = None
98
        self.executable_links = None
99
        self.docbooks = None
100
        self.application_data = None
101
        self.i18n = None
102
        Distribution.__init__(self,attrs)
103
104
###########################################################################
105
def has_kcms(self):
106
    if self.distribution.kcontrol_modules is None:
107
        return 0
108
    return  len(self.distribution.kcontrol_modules)!=0
109
110
def has_docbook_html(self):
111
    if self.distribution.docbooks is None:
112
        return 0
113
    return  len(self.distribution.docbooks)!=0
114
115
def has_messages(self):
116
    if self.distribution.i18n is None:
117
        return 0
118
    return  len(self.distribution.i18n)!=0
119
120
def has_application_data(self):
121
    if self.distribution.application_data is None:
122
        return 0
123
    return  len(self.distribution.application_data)!=0
124
125
def has_tdeioslaves(self):
126
    if self.distribution.tdeioslaves is None:
127
        return 0
128
    return  len(self.distribution.tdeioslaves)!=0
129
130
###########################################################################
131
# Our slightly extended build command. This also does kcontrol modules.
132
class BuildKDE(build):
133
134
    user_options = build.user_options[:]
135
    user_options.append( ('msgfmt-exe=',None,'Path to the msgfmt executable') )
136
    user_options.append( ('meinproc-exe=',None,'Path to the meinproc executable') )
137
138
    sub_commands = build.sub_commands[:]
139
    sub_commands.append( ('build_kcm',has_kcms) )
140
    sub_commands.append( ('build_tdeioslave',has_tdeioslaves) )
141
    sub_commands.append( ('build_html',has_docbook_html) )
142
    sub_commands.append( ('build_messages',has_messages) )
143
    
144
    def __init__(self,dist):
145
        build.__init__(self,dist)
146
        self.has_kcms = has_kcms
147
        self.has_tdeioslaves = has_tdeioslaves
148
        self.has_docbook_html = has_docbook_html
149
        self.has_messages = has_messages
150
151
    def initialize_options(self):
152
        self.msgfmt_exe = None
153
        self.meinproc_exe = None
154
        build.initialize_options(self)
155
        
156
    def finalize_options(self):
157
        build.finalize_options(self)
158
        
159
        if self.msgfmt_exe is None:
160
            # Find msgfmt
161
            canidatepaths = []
162
            canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() )
163
            self.msgfmt_exe = FindExeOnPath('msgfmt',canidatepaths)
164
            if self.msgfmt_exe is None:
165
                raise SystemExit, "Unable to find 'msgfmt', needed to build i18n messages."
166
        
167
        if self.meinproc_exe is None:
168
            # Find meinproc
169
            canidatepaths = []
170
            canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() )
171
            self.meinproc_exe = FindExeOnPath('meinproc',canidatepaths)
172
            if self.meinproc_exe is None:
173
                raise SystemExit, "Unable to find 'meinproc', needed to generate Docbook HTML documentation."
174
175
###########################################################################
176
def has_executable_links(self):
177
    if self.distribution.executable_links is None:
178
        return 0
179
    return  len(self.distribution.executable_links)!=0
180
181
###########################################################################
182
class InstallKDE(install):
183
    user_options = install.user_options[:]
184
    user_options.append( ('kde-prefix=',None,"TDE installation prefix") )
185
    user_options.append( ('install-messages=',None,"installation directory for i18n message files") )
186
    user_options.append( ('install-html=',None,"installation directory for Docbook HTML files") )
187
    user_options.append( ('install-cmd=',None,"Command to use to install the files") )
188
    user_options.append( ('install-xdg-apps=',None,"directory for XDG app files") )
189
    user_options.append( ('install-kcm=',None,"directory for kcm library files") )
190
    user_options.append( ('install-tdeioslave',None,"directory for tdeioslave library files") )
191
    user_options.append( ('install-protocol',None,"directory for tdeioslave protocol files") )
192
    
193
    sub_commands = install.sub_commands[:]
194
    sub_commands.insert(0, ('checkpytde',None) )
195
    sub_commands.insert(0, ('checkpyqt',None) )
196
    sub_commands.append( ('install_executable_links',has_executable_links) )
197
    sub_commands.append( ('install_messages',has_messages) )
198
    sub_commands.append( ('install_html',has_docbook_html) )
199
    sub_commands.append( ('install_kcm',has_kcms) )
200
    sub_commands.append( ('install_tdeioslave',has_tdeioslaves) )
201
    sub_commands.append( ('install_application_data',has_application_data) )
202
        
203
    def initialize_options(self):
204
        self.kde_prefix = None
205
        self.install_messages = None
206
        self.install_html = None
207
        self.install_cmd = None
208
        self.install_xdg_apps = None
209
        self.install_kcm = None
210
        self.install_tdeioslave = None
211
        self.install_protocol = None
212
        self.install_application_data = None
213
        install.initialize_options(self)
214
        
215
    def finalize_options(self):
216
        # If no install prefix was provided, then we try to detect the KDE install prefix.
217
        self.user_supplied_kde_prefix = True
218
        
219
        if self.install_scripts is None:
220
            if self.kde_prefix is not None:
221
                self.install_scripts = os.path.join(self.kde_prefix,'bin')
222
            else:
223
                self.announce("Detecting TDE 'bin' directory...")
224
                self.install_scripts = ask_kde_config('--install exe --expandvars').strip()
225
                self.announce("   ...TDE 'bin' directory is %s" % self.install_scripts)
226
            
227
        if self.install_application_data is None:
228
            if self.kde_prefix is not None:
229
                self.install_application_data = os.path.join(self.kde_prefix,'share/apps',self.distribution.metadata.name)
230
            else:
231
                self.announce("Detecting TDE application directory...")
232
                kdeappdir = ask_kde_config('--install data --expandvars').strip()
233
                self.announce("  ...TDE application directory is %s" % self.install_application_data)
234
                self.install_application_data = os.path.join(kdeappdir,self.distribution.metadata.name)
235
236
        if self.install_messages is None:
237
            if self.kde_prefix is not None:
238
                self.install_messages = os.path.join(self.kde_prefix,'share/locale')
239
            else:
240
                self.announce("Detecting TDE messages directory...")
241
                self.install_messages = ask_kde_config('--install locale --expandvars').strip()
242
                self.announce("  ...TDE messages directory is %s" % self.install_messages)
243
244
        if self.install_html is None:
245
            if self.kde_prefix is not None:
246
                self.install_html = os.path.join(self.kde_prefix,'share/doc/tde/HTML')
247
            else:
248
                self.announce("Detecting TDE HTML directory...")
249
                self.install_html = ask_kde_config('--install html --expandvars').strip()
250
                self.announce("  ...TDE HTML directory is %s" % self.install_html)
251
252
        if self.kde_prefix is None:
253
            self.announce("Detecting TDE install prefix...")
254
            self.kde_prefix = ask_kde_config('--prefix').strip()
255
            self.announce("  ...TDE install prefix is %s" % self.kde_prefix)
256
            self.user_supplied_kde_prefix = False
257
            
258
        if self.install_cmd is None:
259
            self.announce("Detecting 'install' command...")
260
            # Ok, time to find the install command.
261
            self.install_cmd = find_executable('install')
262
            if self.install_cmd is None:
263
                raise SystemExit, "Unable to find the 'install' command, needed to install libraries."
264
            self.announce("  ...'install' command is %s" % self.install_cmd)
265
        
266
        if self.install_xdg_apps is None:
267
            self.announce("Detecting XDG apps directory...")
268
            self.install_xdg_apps = ask_kde_config('--install xdgdata-apps --expandvars').strip()
269
            self.announce("  ...XDG apps directory is %s" % self.install_xdg_apps)
270
271
        if self.install_kcm is None:
272
            self.announce("Detecting kcm library  directory...")
273
            self.install_kcm = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'trinity')
274
            self.announce("  ...kcm library directory is %s" % self.install_kcm)
275
    
276
        if self.install_tdeioslave is None:
277
            self.announce("Detecting tdeioslave library  directory...")
278
            self.install_tdeioslave = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'trinity')
279
            self.announce("  ...tdeioslave library directory is %s" % self.install_tdeioslave)
280
    
281
        if self.install_protocol is None:
282
            self.announce("Detecting tdeioslave protocol directory...")
283
            self.install_protocol = ask_kde_config('--install services --expandvars').strip()
284
            self.announce("  ...tdeioslave protocol directory is %s" % self.install_protocol)
285
    
286
        install.finalize_options(self)
287
        
288
        if self.root is not None:
289
            self.change_roots('application_data','html','messages','xdg_apps','kcm')
290
        
291
    def get_command_name(self):
292
        return 'install'
293
        
294
    def run(self):
295
        global INSTALL_LIST
296
        install.run(self)
297
        
298
        # Write out the uninstall list.
299
        fhandle = open(INSTALL_LIST,'w')
300
        for item in self.get_outputs():
301
            fhandle.write(item)
302
            fhandle.write('\n')
303
        fhandle.close()
304
305
###########################################################################
306
class InstallApplicationDataAndLinks(install_data):
307
    def get_command_name(self):
308
        return 'install_application_data'
309
        
310
    def initialize_options(self):
311
        install_data.initialize_options(self)
312
313
        self.data_files = self.distribution.application_data
314
        
315
    def finalize_options(self):
316
        self.set_undefined_options('install',
317
                                   ('install_application_data', 'install_dir'),
318
                                   ('root', 'root'),
319
                                   ('force', 'force'),
320
                                  )
321
        
322
    def run(self):
323
        self.outfiles.extend(self.mkpath(self.install_dir))
324
        for f in self.data_files:
325
            if type(f) is StringType:
326
                # it's a simple file, so copy it
327
                f = convert_path(f)
328
                if self.warn_dir:
329
                    self.warn("setup script did not provide a directory for "
330
                              "'%s' -- installing right in '%s'" %
331
                              (f, self.install_dir))
332
                if os.path.isfile(f):
333
                    (out, _) = self.copy_file(f, self.install_dir)
334
                    self.outfiles.append(out)
335
                elif os.path.isdir(f):
336
                    out = self.copy_tree(f,os.path.join(self.install_dir,f))
337
                    self.outfiles.extend(out)
338
                else:
339
                    self.warn("Setup script can't find file or directory %s needed for installation." % f)
340
            else:
341
                # it's a tuple with path to install to and a list of files
342
                dir = convert_path(f[0])
343
                if not os.path.isabs(dir):
344
                    dir = change_root(self.install_dir, dir)
345
                elif self.root:
346
                    dir = change_root(self.root, dir)
347
                self.outfiles.extend(self.mkpath(dir))
348
349
                if f[1] == []:
350
                    # If there are no files listed, the user must be
351
                    # trying to create an empty directory, so add the
352
                    # directory to the list of output files.
353
                    self.outfiles.append(dir)
354
                else:
355
                    # Copy files, adding them to the list of output files.
356
                    for data in f[1]:
357
                        data = convert_path(data)
358
                        if os.path.islink(data):
359
                            # Transplant the link to the new location without changing
360
                            # where it points to. (ie it is _not_ relocated).
361
                            dest = os.path.join(dir, os.path.basename(data))
362
                            if os.path.exists(dest):
363
                                os.remove(dest)
364
                            os.symlink(os.readlink(data),dest)
365
                            log.info("moving link %s -> %s" % (data,dest) )
366
                            #os.chmod(dest, os.stat(data)[stat.ST_MODE])
367
                        elif os.path.isdir(data):
368
                            out = self.copy_tree(data,dir)
369
                            self.outfiles.extend(out)
370
                        else:
371
                            (out, _) = self.copy_file(data, dir)
372
                            self.outfiles.append(out)
373
        
374
        # Compile the .ui files
375
        install_cmd = self.get_finalized_command('install')
376
        prefix = self.install_dir
377
        if prefix[-1] != os.sep:
378
            prefix = prefix + os.sep
379
        self.outfiles.extend(compile_qtdesigner(self.outfiles, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run))
380
        
381
        # Byte compile the .py files
382
        from distutils.util import byte_compile
383
        byte_compile(self.outfiles, optimize=0, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run)
384
385
        # Add the .pyc files to the list of outfiles.
386
        self.outfiles.extend( [item+'c' for item in self.outfiles if item.endswith('.py')] )
387
388
    def mkpath(self, name, mode=0777):
389
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
390
    
391
###########################################################################
392
class InstallExecutableLinks(Command):
393
    description = "Install symlinks"
394
395
    user_options = []
396
397
    def initialize_options(self):
398
        self.outfiles = []
399
400
    def finalize_options(self):
401
        pass
402
        
403
    def get_command_name(self):
404
        return 'install_executable_links'
405
        
406
    def run(self):
407
        # FIXME add cmd options?
408
        install_script_cmd = self.get_finalized_command('install_scripts')
409
        install_data_cmd = self.get_finalized_command('install_application_data')
410
        
411
        destination_dir = install_data_cmd.install_dir
412
        
413
        if not os.path.exists(install_script_cmd.install_dir):
414
            self.outfiles.extend(self.mkpath(install_script_cmd.install_dir))
415
        
416
        if self.distribution.executable_links is not None:
417
            for link in self.distribution.executable_links:
418
                symname = os.path.join(install_script_cmd.install_dir,link[0])
419
                target = os.path.join(destination_dir,link[1])
420
                log.info("symlinking %s -> %s", symname, target)
421
                if not self.dry_run:
422
                    if os.path.islink(symname):
423
                        os.remove(symname)
424
                    os.symlink(target,symname)
425
                self.outfiles.append(symname)
426
427
    def get_outputs(self):
428
        return self.outfiles or []
429
        
430
    def mkpath(self, name, mode=0777):
431
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
432
        
433
###########################################################################
434
# Fix the --root option for the install_lib command.
435
class InstallLibWithRoot(install_lib):
436
    user_options = install_lib.user_options[:]
437
    user_options.append( ('root=',None,"install everything relative to this alternate root directory") )
438
        
439
    def initialize_options(self):
440
        install_lib.initialize_options(self)
441
        self.root = None
442
        
443
    def finalize_options(self):
444
        own_install_dir = self.install_dir is not None
445
        
446
        install_lib.finalize_options(self)
447
        self.set_undefined_options('install', ('root', 'root'))
448
        
449
        if self.root is not None and own_install_dir:
450
            self.install_dir = change_root(self.root, self.install_dir)
451
        
452
###########################################################################
453
class Uninstall(Command):
454
    description = "Remove all installed files"
455
456
    user_options = []
457
458
    def initialize_options(self):
459
        pass
460
461
    def finalize_options(self):
462
        pass
463
        
464
    def get_command_name(self):
465
        return 'uninstall'
466
467
    def run(self):
468
        global INSTALL_LIST
469
        
470
        if not os.path.isfile(INSTALL_LIST):
471
            self.announce("Unable to uninstall, can't find the file list %s." % INSTALL_LIST)
472
            return
473
            
474
        # Suck in the file list.
475
        fhandle = open(INSTALL_LIST,'r')
476
        file_list = fhandle.readlines()
477
        fhandle.close()
478
        
479
        # Remove the files first.
480
        for item in file_list:
481
            item = item.strip()
482
            if os.path.isfile(item) or os.path.islink(item):
483
                self.announce("removing '%s'" % item)
484
                if not self.dry_run:
485
                    try:
486
                        os.remove(item)
487
                    except OSError, details:
488
                        self.warn("Could not remove file: %s" % details)
489
            elif not os.path.isdir(item):
490
                self.announce("skipping removal of '%s' (does not exist)" % item)
491
492
        # Remove the directories.
493
        file_list.sort()
494
        file_list.reverse()
495
        # Starting with the longest paths first.
496
        for item in file_list:
497
            item = item.strip()
498
            if os.path.isdir(item):
499
                self.announce("removing '%s'" % item)
500
                if not self.dry_run:
501
                    try:
502
                        os.rmdir(item)
503
                    except OSError, details:
504
                        self.warn("Could not remove directory: %s" % details)
505
506
###########################################################################
507
class BuildKControlModule(Command):
508
    description = "Build KControl extensions"
509
510
    user_options = [('no-kcontrol',None,"Don't build kcontrol extensions"),
511
                    ('build-dir=','b', "build directory (where to install from)"),
512
                    ('python-dir=',None,'Directory containing the Python installation'),
513
                    ('python-inc-dir=',None,'Directory containing C Header files for Python'),
514
                    ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'),
515
                    ('kde-lib-dir=',None,'Directory containing library files for KDE'),
516
                    ('kde-kcm-lib-dir=',None,'Directory for KDE kcm library files'),
517
                    ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'),
518
                    ('qt-lib-dir=',None,'Directory containing library files for Qt'),
519
                    ('sip-dir=',None,'Directory containing the sip library files'),
520
                    ('clib=',None,'gcc library and path'),
521
                    ('pyqt-dir=',None,'PyQt module directory'),
522
                    ('pytde-dir=',None,'PyTDE module directory'),
523
                    ('data-dir=',None,'installation directory for data (script) files')]
524
    
525
    def initialize_options(self):
526
        self.no_kcontrol = 0
527
        self.build_dir = None
528
        self.python_inc_dir = None
529
        self.python_dir = None
530
        self.kde_inc_dir = None
531
        self.kde_lib_dir = None
532
        self.kde_kcm_lib_dir = None
533
        self.qt_inc_dir = None
534
        self.qt_lib_dir = None
535
        self.sip_dir = None
536
        self.clib = None
537
        self.pyqt_dir = None
538
        self.pytde_dir = None
539
        self.data_dir = None
540
        
541
    def finalize_options(self):
542
        if self.no_kcontrol==0:
543
            self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir'))
544
        
545
            install = self.get_finalized_command('install')
546
            self.install_prefix = ask_kde_config('--prefix').strip()
547
    
548
            # KDE inc dir: find it!
549
            if self.kde_inc_dir is None:
550
                canidatepaths = []
551
                tdedir = os.getenv("TDEDIR")
552
                if tdedir!=None:
553
                    canidatepaths.append(os.path.join(tdedir,"include"))
554
                canidatepaths.append(os.path.join(install.prefix,"include"))
555
                canidatepaths.append(os.path.join(self.install_prefix,'include'))
556
                canidatepaths.append(os.path.join(self.install_prefix,'include','tde'))
557
                self.kde_inc_dir = FindFileInPaths('tdeapplication.h',canidatepaths)
558
            if self.kde_inc_dir is None:
559
                raise SystemExit, "Failed to find the KDE header file directory."
560
            if FindFileInPaths('tdeapplication.h',[self.kde_inc_dir]) is None:
561
                raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir
562
            self.announce("Using %s for KDE header files" % self.kde_inc_dir)
563
    
564
            # KDE lib dir
565
            if self.kde_lib_dir is None:
566
                self.kde_lib_dir = os.path.join(self.install_prefix,"lib")
567
            self.announce("Using %s for KDE library files" % self.kde_lib_dir)
568
    
569
            # KDE KCM lib dir
570
            if self.kde_kcm_lib_dir is None:
571
                self.kde_kcm_lib_dir = os.path.join(self.kde_lib_dir,"trinity")
572
            if FindFileInPaths('*kcm*.so',[self.kde_kcm_lib_dir]) is None:
573
                raise SystemExit, "Failed to find KDE KCM files in: %s" % self.kde_kcm_lib_dir
574
            self.announce("Using %s for KDE KCM library files" % self.kde_kcm_lib_dir)
575
            
576
            # Qt inc dir
577
            if self.qt_inc_dir is None:
578
                canidatepaths = []
579
                qtinc = os.getenv("QTINC")
580
                if qtinc != None:
581
                    canidatepaths.append(qtinc)
582
                qtdir = os.getenv("QTDIR")
583
                if qtdir != None:
584
                    canidatepaths.append(os.path.join(qtdir,"include"))
585
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/include"))
586
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
587
                canidatepaths.append(os.path.join(install.prefix,"include"))
588
                canidatepaths.append("/opt/tqt3/include")
589
                canidatepaths.append("/opt/qt/include")
590
                canidatepaths.append("/opt/qt/lib/include")
591
                canidatepaths.append("/opt/qt3/lib/include")
592
		canidatepaths.append("/usr/include/tqt3")
593
		canidatepaths.append("/usr/include/qt3")
594
                self.qt_inc_dir = FindFileInPaths('ntqstring.h',canidatepaths)
595
            if self.qt_inc_dir is None:
596
                self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths)
597
            if self.qt_inc_dir is None:
598
                raise SystemExit,"Failed to find the Qt header file directory"
599
            if FindFileInPaths('ntqstring.h',[self.qt_inc_dir]) is None:
600
                if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None:
601
                    raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir
602
            self.announce("Using %s for Qt header files" % self.qt_inc_dir)
603
    
604
            # Qt lib dir
605
            if self.qt_lib_dir is None:
606
                canidatepaths = []
607
                qtlib = os.getenv("TQTLIB")
608
                if qtlib != None:
609
                    canidatepaths.append(qtlib)
610
                qtdir = os.getenv("TQTDIR")
611
                if qtdir != None:
612
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
613
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
614
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
615
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
616
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
617
                canidatepaths.append("/opt/tqt/"+get_libdir_name())
618
                canidatepaths.append("/opt/tqt/lib/"+get_libdir_name())
619
                canidatepaths.append("/opt/tqt3/lib/"+get_libdir_name())
620
                self.qt_lib_dir = FindFileInPaths('libtqt*',canidatepaths)
621
            if self.qt_lib_dir is None:
622
                canidatepaths = []
623
                qtlib = os.getenv("QTLIB")
624
                if qtlib != None:
625
                    canidatepaths.append(qtlib)
626
                qtdir = os.getenv("QTDIR")
627
                if qtdir != None:
628
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
629
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
630
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
631
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
632
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
633
                canidatepaths.append("/opt/qt/"+get_libdir_name())
634
                canidatepaths.append("/opt/qt/lib/"+get_libdir_name())
635
                canidatepaths.append("/opt/qt3/lib/"+get_libdir_name())
636
                self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths)
637
            if self.qt_lib_dir is None:
638
                raise SystemExit, "Failed to find Qt library files"
639
            self.announce("Using %s for Qt library files" % self.qt_lib_dir)
640
                    
641
            # Python dir
642
            if self.python_dir is None:
643
                self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[0]
644
            self.announce("Using %s for the python directory" % self.python_dir)
645
            
646
            # Python include dir.
647
            if self.python_inc_dir is None:
648
                # Find the Python include directory.
649
                self.python_inc_dir = sysconfig.get_config_var("INCLUDEPY")
650
            self.announce("Using %s for Python header files" % self.python_inc_dir)
651
    
652
            # PyQt dir
653
            if self.pyqt_dir is None:
654
                self.pyqt_dir = m_pyqt_dir
655
            if self.pyqt_dir is None:
656
                self.pyqt_dir = os.path.join(sysconfig.get_python_lib(), 'python_tqt')
657
            if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None):
658
                raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir
659
            self.announce("Using %s for PyQt modules" % self.pyqt_dir)
660
    
661
            # PyTDE dir
662
            if self.pytde_dir is None:
663
                self.pytde_dir = sysconfig.get_python_lib()
664
            if (FindFileInPaths("libtdecorecmodule*",[self.pytde_dir]) is None) and (FindFileInPaths("tdecore*",[self.pytde_dir]) is None):
665
                raise SystemExit, "Failed to find the PyTDE directory: %s" % self.pytde_dir
666
            self.announce("Using %s for PyTDE modules" % self.pytde_dir)
667
            
668
            # Sip dir
669
            if self.sip_dir is None:
670
                self.sip_dir = m_sip_dir
671
            if self.sip_dir is None:
672
                self.sip_dir = os.path.join(sysconfig.get_python_lib(), 'sip4_tqt')
673
            if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None):
674
                raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir
675
            self.announce("Using %s for libsip files" % self.sip_dir)
676
                
677
            # Find the C library (libgcc, libgcc_s or some other variation).
678
            if self.clib is None:
679
                canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name(), "/usr/lib" ]
680
                self.clib = FindFileInPaths("libgcc*.so",canidatepaths)
681
                if self.clib!=None:
682
                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
683
                else:
684
                    self.clib = FindFileInPaths("libgcc*.a",canidatepaths)
685
                    if self.clib!=None:
686
                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0]
687
            if self.clib is None:
688
                raise SystemExit, "kdedistutils.py (1): Failed to find a suitable libgcc library"
689
            self.announce("Using %s for clib" % self.clib)
690
    
691
            # Make a list of places to look for python .so modules
692
            self.python_sub_dirs = sysconfig.get_config_var("LIBSUBDIRS").split()
693
            base = sysconfig.get_config_var("LIBP")
694
            self.python_sub_dirs = [ os.path.join(base,item) for item in self.python_sub_dirs ]
695
            self.python_sub_dirs.append(base)
696
697
    def get_command_name(self):
698
        return 'build_kcm'
699
700
    def run(self):
701
        if self.no_kcontrol:
702
            self.announce("Skipping KControl modules")
703
            return
704
    
705
        if not os.path.isdir(self.build_dir):
706
            os.mkdir(self.build_dir)
707
        
708
        for moduletuple in self.distribution.kcontrol_modules:
709
            self.announce("Building KControl module from desktop file %s." % moduletuple[0])
710
            
711
            # Read the desktop file
712
            factoryfunction = None
713
            libraryname = None
714
            cmodulecategory = None
715
            try:
716
                fhandle = open(moduletuple[0],'r')
717
                for line in fhandle.readlines():
718
                    parts = line.strip().split('=')
719
                    try:
720
                        if parts[0]=="X-TDE-Library":
721
                            libraryname = parts[1]
722
                        elif parts[0]=="Exec":
723
                            shellcmd = parts[1].split()
724
                            modulepath = shellcmd[-1]
725
                            if '/' in modulepath:
726
                                cmodulecategory = os.path.dirname(modulepath)
727
                            else:
728
                                cmodulecategory = ""
729
                        elif parts[0]=="X-TDE-FactoryName":
730
                            factoryfunction = 'create_'+parts[1]
731
                    except IndexError:
732
                        pass
733
                fhandle.close()
734
            except IOError:
735
                raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0]
736
                
737
            # Sanity check.
738
            if factoryfunction is None:
739
                raise SystemExit, "Failed to find factory name (Was there a X-TDE-FactoryName entry in the desktop file?)"
740
            if libraryname is None:
741
                raise SystemExit, "Failed to find library name (Was there a X-TDE-Library entry in the desktop file?)"
742
            if cmodulecategory is None:
743
                raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)"
744
            
745
            modulename = os.path.basename(moduletuple[1])
746
            if modulename.endswith('.py'):
747
                modulename = modulename[:-3]
748
            desktopfilename = moduletuple[0]
749
            
750
            stub_cpp_name = 'kcm_'+libraryname+'.cpp'
751
            stub_so_name = 'kcm_'+libraryname+'.so'
752
            stub_la_name = 'kcm_'+libraryname+'.la'
753
            python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1])
754
            
755
            # Build the 'stub' code.
756
            cppcode = self.cpptemplate % {"moduledir": self.data_dir,
757
                                            "extramodule": os.getenv("EXTRA_MODULE_DIR"),
758
                                            "modulename": modulename,
759
                                            "factoryfunction": factoryfunction,
760
                                            "python_version": python_version}
761
            
762
            # Put it on disk.
763
            cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name)
764
            try:
765
                fhandle = open(cppfile,'w')
766
                fhandle.write(cppcode)
767
                fhandle.close()
768
            except IOError:
769
                raise SystemExit, "Could not write the C++ stub: %s" % cppfile
770
                
771
            # Compile the stub library.
772
            cmdlist = ['libtool']
773
774
            # Couldn't get it to pass without this ...
775
            cmdlist.append("--mode=compile")
776
            cmdlist.append("--tag=CXX")
777
            
778
            # Find the compiler flags and options
779
            # CXX is empty on some Systems, let's do it 'the hard way'.
780
            # FIXME :: get CXX from make.conf for Gentoo.
781
            if len(sysconfig.get_config_var("CXX").split()) >= 2:
782
                cmdlist.extend(sysconfig.get_config_var("CXX").split())
783
            else:
784
                cmdlist.extend(['g++', '-pthread'])
785
786
            #cmdlist.extend(sysconfig.get_config_var("CXX").split())
787
            
788
            # cc_flags
789
            cmdlist.append("-c")
790
            cmdlist.append("-g")
791
            
792
            # The 4 is randomly chosen!
793
            # FIXME :: get CFLAGS from make.conf for Gentoo.
794
            if len(sysconfig.get_config_var("CFLAGS").split()) >=4:
795
                cmdlist.extend(sysconfig.get_config_var("CFLAGS").split())
796
            else:
797
                # On Gentoo systems, CFLAGS are not in the environment.
798
                raw = os.popen('emerge info 2> /dev/null|grep CFLAGS')
799
                lines = raw.readlines()
800
                if len(lines):
801
                    cflags = lines[0].split('"')[1].split()
802
                    print "Got CFLAGS from emerge info."
803
                    cmdlist.extend(cflags)
804
                else:
805
                    # Still no CFLAGS found, use these ...
806
                    cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes'])
807
                
808
            #sysconfig.get_config_var("CFLAGS").split()
809
            # includes
810
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
811
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
812
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEPY"))
813
            cmdlist.append("-I" + self.python_inc_dir)
814
            cmdlist.append("-I" + self.kde_inc_dir)
815
            cmdlist.append("-I" + self.kde_inc_dir + "/tde")
816
            cmdlist.append("-I" + self.qt_inc_dir)
817
            cmdlist.append("-I/usr/include/tqt")
818
            cmdlist.append("-I.")
819
            # input
820
            cmdlist.append(cppfile)
821
            # output
822
            outputfile = os.path.join(self.build_dir,libraryname+'.lo')
823
            cmdlist.append("-o")
824
            cmdlist.append(outputfile)
825
            spawn(cmdlist) # Execute!!!
826
            print
827
            
828
            # Link the resulting object file to create a shared library.
829
            cmdlist = ['libtool']
830
            cmdlist.append("--mode=link")
831
            cmdlist.append("--tag=LD")
832
            
833
            # Grab the linker command name
834
            cmdlist.append(sysconfig.get_config_var("LDSHARED").split()[0])
835
            # link_flags
836
            cmdlist.append("-module")
837
            cmdlist.append("-avoid-version")
838
            cmdlist.append("-shared")
839
            cmdlist.append("-export-dynamic")
840
            # object
841
            cmdlist.append(outputfile)
842
            cmdlist.append("-rpath"); cmdlist.append(self.kde_kcm_lib_dir)
843
            cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name))
844
            # Link libs
845
            linklist = []
846
            linklist.append("-lpython%s" % python_version)
847
            linklist.extend(sysconfig.get_config_var("LIBS").split())
848
            
849
            # FIXME I doubt half of these libraries need to be here.
850
            linklist.append(self.sip_dir+"/sip.so")
851
            # PyQt libs
852
            linklist.append(self.pyqt_dir+"/qt.so")
853
            # PyTDE libs
854
            linklist.append(self.pytde_dir+"/tdecore.so")
855
            linklist.append(self.pytde_dir+"/tdeui.so")
856
            
857
#            linklist.append("-L"+self.sip_dir); linklist.append("-lsip")
858
#            # PyQt libs
859
#            linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule")
860
#            # PyTDE libs
861
#            linklist.append("-L"+self.pytde_dir); linklist.append("-ltdecorecmodule"); linklist.append("-ltdeuicmodule")
862
            
863
            linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/trinity/lib"); linklist.append("-ltdecore"); linklist.append("-lpythonize")
864
            linklist.append("-L"+self.qt_lib_dir); linklist.append("-ltqt-mt")
865
            linklist.append("-lm")
866
            linklist.append("-lc")
867
            linklist.append(self.clib)
868
869
            linklist.append("-R"); linklist.append(self.python_dir)
870
            linklist.append("-R"); linklist.append(self.qt_lib_dir)
871
            linklist.append("-R"); linklist.append(self.sip_dir)
872
            linklist.append("-R"); linklist.append(self.pyqt_dir)
873
            linklist.append("-R"); linklist.append(self.pytde_dir)
874
            linklist.append("-R"); linklist.append(self.kde_lib_dir)
875
876
            cmdlist.extend(linklist)
877
            spawn(cmdlist) # Execute!!
878
            print
879
            
880
    cpptemplate = r"""
881
/*
882
 * pykcm_launcher.cpp
883
 * 
884
 * Launch Control Centre modules written in Python using an embedded Python
885
 * interpreter.
886
 * Based on David Boddie's PyTDE-components.
887
 */
888
889
// pythonize.h must be included first.
890
#include <pythonize.h>
891
#include <tdecmodule.h>
892
#include <tdeglobal.h>
893
#include <tdelocale.h>
894
#include <klibloader.h>
895
#include <kstandarddirs.h>
896
#include <ksimpleconfig.h>
897
#include <tqstring.h>
898
#include <sip.h>
899
900
#define MODULE_DIR "%(moduledir)s"
901
#define EXTRA_MODULE_DIR "%(extramodule)s"
902
#define MODULE_NAME "%(modulename)s"
903
#define FACTORY "%(factoryfunction)s"
904
#define CPP_FACTORY %(factoryfunction)s
905
#define LIB_PYTHON "libpython%(python_version)s.so"
906
#define debug 1
907
908
static TDECModule *report_error(char *msg) {
909
    if (debug) printf ("error: %%s\n", msg);
910
    return NULL;
911
}
912
913
static TDECModule* return_instance( TQWidget *parent, const char *name ) {
914
    TDECModule* tdecmodule;
915
    PyObject *pyTDECModuleTuple; 
916
    PyObject *pyTDECModule;
917
    Pythonize *pyize;  // Pythonize object to manage the Python interpreter.
918
    int isErr;
919
    
920
    // Try to determine what py script we're loading. Note that "name"
921
    // typically appears to be NULL.
922
    TQString script(MODULE_NAME);
923
924
    // Reload libpython, but this time tell the runtime linker to make the
925
    // symbols global and available for later loaded libraries/module.
926
    KLibLoader::self()->globalLibrary(LIB_PYTHON);
927
    
928
    // Start the interpreter.
929
    pyize = initialize();
930
    if (!pyize) {
931
        return report_error ("***Failed to start interpreter\n");
932
    }
933
    
934
    // Add the path to the python script to the interpreter search path.
935
    TQString path = TQString(MODULE_DIR);
936
    if(path == TQString::null) {
937
        return report_error ("***Failed to locate script path");
938
    }
939
    if(!pyize->appendToSysPath (path.latin1 ())) {
940
        return report_error ("***Failed to set sys.path\n");
941
    }
942
943
    // Add the extra path to the python script to the interpreter search path.
944
    TQString extrapath = TQString(EXTRA_MODULE_DIR);
945
    if(!pyize->appendToSysPath (extrapath.latin1 ())) {
946
      return report_error ("***Failed to set extra sys.path\n");
947
    }
948
    
949
    // Load the Python script.
950
    PyObject *pyModule = pyize->importModule ((char *)script.latin1 ());
951
    if(!pyModule) {
952
        PyErr_Print();
953
        return report_error ("***failed to import module\n");
954
    }
955
956
    // Inject a helper function
957
    TQString bridge = TQString("from sip4_tqt import sip\n"
958
                            "from python_tqt import qt\n"
959
                            "def kcontrol_bridge_" FACTORY "(parent,name):\n"
960
                             "    if parent!=0:\n"
961
#if SIP_VERSION >= 0x040200
962
                             "        wparent = sip.wrapinstance(parent,qt.TQWidget)\n"
963
#else                             
964
                             "        wparent = sip.wrapinstance(parent,'TQWidget')\n"
965
#endif
966
                             "    else:\n"
967
                             "        wparent = None\n"
968
                             "    inst = " FACTORY "(wparent, name)\n"
969
                             "    return (inst,sip.unwrapinstance(inst))\n");
970
    PyRun_String(bridge.latin1(),Py_file_input,PyModule_GetDict(pyModule),PyModule_GetDict(pyModule));
971
972
    // Get the Python module's factory function.
973
    PyObject *kcmFactory = pyize->getNewObjectRef(pyModule, "kcontrol_bridge_" FACTORY);
974
    if(!kcmFactory) {
975
        return report_error ("***failed to find module factory\n");
976
    }
977
    
978
    // Call the factory function. Set up the args.
979
    PyObject *pyParent = PyLong_FromVoidPtr(parent);
980
    PyObject *pyName = PyString_FromString(MODULE_NAME);
981
        // Using NN here is effect gives our references to the arguement away.
982
    PyObject *args = Py_BuildValue ("NN", pyParent, pyName);
983
    if(pyName && pyParent && args) {
984
        // run the factory function
985
        pyTDECModuleTuple = pyize->runFunction(kcmFactory, args);
986
        if(!pyTDECModuleTuple) {
987
            PyErr_Print();
988
            return report_error ("*** runFunction failure\n;");
989
        }
990
    } else {
991
        return report_error ("***failed to create args\n");
992
    }
993
    // cleanup a bit
994
    pyize->decref(args);
995
    pyize->decref(kcmFactory);
996
997
    // Stop this from getting garbage collected.
998
    Py_INCREF(PyTuple_GET_ITEM(pyTDECModuleTuple,0));
999
    
1000
    // convert the TDECModule PyObject to a real C++ TDECModule *.
1001
    isErr = 0;
1002
    pyTDECModule = PyTuple_GET_ITEM(pyTDECModuleTuple,1);
1003
    tdecmodule = (TDECModule *)PyLong_AsVoidPtr(pyTDECModule);
1004
    if(!tdecmodule) {
1005
        return report_error ("***failed sip conversion to C++ pointer\n");
1006
    }
1007
    pyize->decref(pyTDECModuleTuple);
1008
    
1009
    // PyTDE can't run the module without this - Pythonize
1010
    // grabs the lock at initialization and we have to give
1011
    // it back before exiting. At this point, we no longer need
1012
    // it.
1013
    //pyize->releaseLock ();
1014
1015
    // take care of any translation info
1016
    TDEGlobal::locale()->insertCatalogue(script);
1017
1018
    // Return the pointer to our new TDECModule
1019
    return tdecmodule;
1020
}
1021
1022
extern "C" {
1023
    // Factory function that kcontrol will call.
1024
    TDECModule* CPP_FACTORY(TQWidget *parent, const char *name) {
1025
        return return_instance(parent, name);
1026
    }
1027
}
1028
"""
1029
1030
###########################################################################
1031
class InstallKControlModule(Command):
1032
    description = "Install Kcontrol module files"
1033
    
1034
    user_options = [
1035
        ('install-dir=', 'd', "base directory for installing kcontrol module files"),
1036
        ('install-cmd=', None, "Command to use to install the files"),
1037
        ('xdg-apps-dir=',None,"directory for XDG app files"),
1038
        ('build-dir=','b', "build directory (where to install from)"),
1039
        ('root=', None, "install everything relative to this alternate root directory"),
1040
        ('force', 'f', "force installation (overwrite existing files)"),
1041
        ('skip-build', None, "skip the build steps"),
1042
        ]
1043
    boolean_options = ['force', 'skip-build']
1044
    
1045
    def initialize_options(self):
1046
        self.build_dir = None
1047
        self.install_dir = None
1048
        self.install_cmd = None
1049
        self.xdg_apps_dir = None
1050
        self.outfiles = []
1051
        self.root = None
1052
        self.force = 0
1053
        self.warn_dir = 1
1054
        self.skip_build = None
1055
1056
    def finalize_options(self):
1057
        own_install_dir = self.install_dir is not None
1058
        own_xdg_apps_dir = self.xdg_apps_dir is not None
1059
        
1060
        self.set_undefined_options('install',
1061
                                    ('build_base', 'build_dir'),
1062
                                    ('install_kcm', 'install_dir'),
1063
                                    ('install_xdg_apps','xdg_apps_dir'),
1064
                                    ('root', 'root'),
1065
                                    ('force', 'force'),
1066
                                    ('skip_build', 'skip_build'),
1067
                                    ('install_cmd', 'install_cmd')
1068
                                    )
1069
1070
        if own_install_dir and self.root is not None:
1071
            self.install_dir = change_root(self.root,self.installdir)
1072
        if own_xdg_apps_dir and self.root is not None:
1073
            self.xdg_apps_dir = change_root(self.root,self.xdg_apps_dir)
1074
            
1075
    def get_command_name(self):
1076
        return 'install_kcm'
1077
        
1078
    def run(self):
1079
        if not self.skip_build:
1080
            self.run_command('build_kcm')
1081
    
1082
        self.announce("Installing Kcontrol module files...")
1083
1084
        for moduletuple in self.distribution.kcontrol_modules:
1085
            self.announce("Building KControl module from desktop file %s." % moduletuple[0])
1086
            
1087
            # Read the desktop file
1088
            libraryname = None
1089
            cmodulecategory = None
1090
            try:
1091
                fhandle = open(moduletuple[0],'r')
1092
                for line in fhandle.readlines():
1093
                    parts = line.strip().split('=')
1094
                    try:
1095
                        if parts[0]=="X-TDE-Library":
1096
                            libraryname = parts[1]
1097
                        elif parts[0]=="Exec":
1098
                            shellcmd = parts[1].split()
1099
                            modulepath = shellcmd[-1]
1100
                            if '/' in modulepath:
1101
                                cmodulecategory = os.path.dirname(modulepath)
1102
                            else:
1103
                                cmodulecategory = ""
1104
                    except IndexError:
1105
                        pass
1106
                fhandle.close()
1107
            except IOError:
1108
                raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0]
1109
                
1110
            if libraryname is None:
1111
                raise SystemExit, "Failed to find library name (Was there a X-TDE-Library entry in the desktop file?)"
1112
            if cmodulecategory is None:
1113
                raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)"
1114
                
1115
            desktopfilename = moduletuple[0]
1116
            self.outfiles.extend(self.mkpath(self.xdg_apps_dir))
1117
            desktopfile_dest = os.path.join(self.xdg_apps_dir,os.path.basename(desktopfilename))
1118
            self.copy_file(desktopfilename, desktopfile_dest)
1119
            
1120
            stub_la_name = 'kcm_'+libraryname+'.la'
1121
    
1122
            self.outfiles.extend(self.mkpath(self.install_dir))
1123
            
1124
            # Install the library.
1125
            cmdlist = ['libtool']
1126
            cmdlist.append("--mode=install")
1127
            cmdlist.append(self.install_cmd)
1128
            cmdlist.append("-c")
1129
            cmdlist.append(os.path.join(self.build_dir,stub_la_name))
1130
            cmdlist.append(os.path.join(self.install_dir,stub_la_name))
1131
            spawn(cmdlist) # Execute!!
1132
            print
1133
1134
            self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs','kcm_'+libraryname+'*'))]
1135
            self.outfiles.append(desktopfile_dest)
1136
            
1137
        self.announce("Done installing Kcontrol module files.")
1138
        
1139
    def get_outputs(self):
1140
        return self.outfiles or []
1141
1142
    def mkpath(self, name, mode=0777):
1143
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
1144
1145
###########################################################################
1146
class BuildDocbookHTML(Command):
1147
    description = "Build Docbook HTML documentation"
1148
1149
    user_options = [('meinproc-exe=',None,"Path to the meinproc executable")]
1150
    
1151
    def initialize_options(self):
1152
        self.html_prefix = None
1153
        self.meinproc_exe = None
1154
        
1155
    def finalize_options(self):
1156
        self.set_undefined_options('build', ('meinproc_exe', 'meinproc_exe') )
1157
        
1158
    def get_command_name(self):
1159
        return 'build_docbook'
1160
1161
    def run(self):
1162
        for docbook_tuple in self.distribution.docbooks:
1163
            input_dir = docbook_tuple[0]
1164
            language_code = docbook_tuple[1]
1165
            
1166
            self.announce("Building Docbook documentation from directory %s." % input_dir)
1167
            
1168
            indexdoc_file_name = os.path.join(input_dir,'index.docbook')
1169
            if not os.path.exists(indexdoc_file_name):
1170
                raise SystemExit, "File %s is missing." % indexdoc_file_name
1171
            
1172
            cwd = os.getcwd()
1173
            os.chdir(input_dir)
1174
            try:
1175
                spawn([self.meinproc_exe,"--check","--cache",'index.cache.bz2', 'index.docbook'])
1176
                spawn([self.meinproc_exe, 'index.docbook'])
1177
            finally:
1178
                os.chdir(cwd)
1179
            
1180
###########################################################################
1181
class InstallDocbookHTML(Command):
1182
    description = "Install Docbook HTML files"
1183
    
1184
    user_options = [
1185
        ('install-dir=', 'd',"base directory for installing docbook HTML files"),
1186
        ('root=', None, "install everything relative to this alternate root directory"),
1187
        ('force', 'f', "force installation (overwrite existing files)"),
1188
        ('skip-build', None, "skip the build steps"),
1189
        ]
1190
    boolean_options = ['force', 'skip-build']
1191
    
1192
    def initialize_options(self):
1193
        self.install_dir = None
1194
        self.outfiles = []
1195
        self.root = None
1196
        self.force = 0
1197
        self.warn_dir = 1
1198
        self.skip_build = None
1199
1200
    def finalize_options(self):
1201
        own_install_dir = self.install_dir is not None
1202
        
1203
        self.set_undefined_options('install',
1204
                                   ('install_html', 'install_dir'),
1205
                                   ('root', 'root'),
1206
                                   ('force', 'force'),
1207
                                   ('skip_build', 'skip_build'),
1208
                                  )
1209
1210
        if own_install_dir and self.root is not None:
1211
            self.install_dir = change_root(self.root,self.installdir)
1212
        
1213
    def get_command_name(self):
1214
        return 'install_html'
1215
        
1216
    def run(self):
1217
        if not self.skip_build:
1218
            self.run_command('build_html')
1219
    
1220
        self.announce("Installing HTML files...")
1221
        counter = 0
1222
        for docbook_tuple in self.distribution.docbooks:
1223
            input_dir = docbook_tuple[0]
1224
            language_code = docbook_tuple[1]
1225
            
1226
            self.announce("Install Docbook documentation from directory %s." % input_dir)
1227
            source_file = os.path.join(input_dir,'index.cache.bz2')
1228
            if not os.path.exists(source_file):
1229
                raise SystemExit, "File %s is missing." % source_file
1230
            
1231
            dest_path = os.path.join(self.install_dir, language_code, self.distribution.metadata.name)
1232
            self.outfiles.extend(self.mkpath(dest_path))
1233
            dest_file = os.path.join(dest_path,'index.cache.bz2')
1234
            
1235
            self.copy_file(source_file, dest_file)
1236
            self.outfiles.append(dest_file)
1237
            counter += 1
1238
            
1239
            # Also install any lose HTML files.
1240
            for source_file in glob.glob(os.path.join(input_dir,'*.html')):
1241
                htmlfile = os.path.basename(source_file)
1242
                dest_file = os.path.join(dest_path,htmlfile)
1243
                self.copy_file(source_file, dest_file)
1244
                self.outfiles.append(dest_file)
1245
                counter += 1
1246
            
1247
            if len(docbook_tuple)==3:
1248
                extra_files = docbook_tuple[2]
1249
                for file in extra_files:
1250
                    source_file = os.path.join(input_dir,file)
1251
                    dest_file = os.path.join(self.install_dir, language_code, self.distribution.metadata.name,file)
1252
                    self.copy_file(source_file, dest_file)
1253
                    self.outfiles.append(dest_file)
1254
                    counter += 1
1255
        
1256
        self.announce("Done installing %i HTML files." % counter)
1257
        
1258
    def get_outputs(self):
1259
        return self.outfiles or []
1260
1261
    def mkpath(self, name, mode=0777):
1262
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
1263
1264
###########################################################################
1265
class UpdateI18NMessages(Command):
1266
    description = "Extract and update messages for translation"
1267
1268
    user_options = [('xgettext-exe=',None,'Full path to the xgetext executable'),\
1269
                    ('kde-pot=',None,'Location of the the KDE pot file'),\
1270
                    ('msgmerge-exe=',None,'Full path to the msgmerge executable')]
1271
1272
    def initialize_options(self):
1273
        self.xgettext_exe = None
1274
        self.msgmerge_exe = None
1275
        self.kde_pot = None
1276
        
1277
    def finalize_options(self):
1278
        if self.xgettext_exe is None:
1279
            install = self.get_finalized_command('install')
1280
        
1281
            canidate_paths = []
1282
            if install.user_supplied_kde_prefix:
1283
                canidate_paths.append(os.path.join(install.kde_prefix,'bin'))
1284
                
1285
            self.announce("Detecting xgettext...")
1286
            canidate_paths.append(ask_kde_config('--install exe --expandvars').strip())
1287
            self.xgettext_exe = FindExeOnPath('xgettext',canidate_paths)
1288
            if self.xgettext_exe is None:
1289
                raise SystemExit, "Unable to find 'xgettext'."
1290
            self.announce("  ...xgettext found at %s" % self.xgettext_exe)
1291
            
1292
        if self.msgmerge_exe is None:
1293
            install = self.get_finalized_command('install')
1294
        
1295
            canidate_paths = []
1296
            if install.user_supplied_kde_prefix:
1297
                canidate_paths.append(os.path.join(install.kde_prefix,'bin'))
1298
                
1299
            self.announce("Detecting msgmerge...")
1300
            canidate_paths.append(ask_kde_config('--install exe --expandvars').strip())
1301
            self.msgmerge_exe = FindExeOnPath('msgmerge',canidate_paths)
1302
            if self.msgmerge_exe is None:
1303
                raise SystemExit, "Unable to find 'xgettext'."
1304
            self.announce("  ...msgmerge found at %s" % self.msgmerge_exe)
1305
        
1306
        if self.kde_pot is None:
1307
            self.announce("Detecting kde.pot...")
1308
            canidatepaths = []
1309
            tdedir = os.getenv("TDEDIR")
1310
            if tdedir!=None:
1311
                canidatepaths.append(os.path.join(tdedir,"include"))
1312
            install = self.get_finalized_command('install')
1313
            canidatepaths.append(os.path.join(install.kde_prefix,"include"))
1314
            canidatepaths.append('/opt/trinity/include')
1315
            canidatepaths.append('/opt/kde/include')
1316
            kde_pot_dir = FindFileInPaths('kde.pot',canidatepaths)
1317
            
1318
            if kde_pot_dir is None:
1319
                raise SystemExit, "Failed to find the kde.pot file."
1320
                
1321
            self.kde_pot = os.path.join(kde_pot_dir,'kde.pot')
1322
            self.announce("   ...kde.pot found at %s" % self.kde_pot)
1323
1324
    def get_command_name(self):
1325
        return 'update_messages'
1326
1327
    def run(self):
1328
        if self.distribution.i18n is None: return
1329
        
1330
        self.announce("Extracting and merging i18n messages...")
1331
        po_dir = self.distribution.i18n[0]
1332
        
1333
        # FIXME : .rc and .ui files
1334
        input_files = []
1335
        
1336
        # Compile any UI files
1337
        for dir in self.distribution.i18n[1]:
1338
            for file in glob.glob(os.path.join(dir,'*.ui')):
1339
                qtuicompiler.UpdateUI(file,kde=True)
1340
        
1341
        # Fetch all of the python files.
1342
        for dir in self.distribution.i18n[1]:
1343
            input_files.extend(glob.glob(os.path.join(dir,'*.py')))
1344
        
1345
        target_pot = os.path.join(po_dir,self.distribution.metadata.name+".pot")
1346
        
1347
        cmd = [self.xgettext_exe, '-o', target_pot, '-ki18n', '-ktr2i18n', \
1348
                '-kI18N_NOOP', '-ktranslate', '-kaliasLocale','-x',self.kde_pot]
1349
        cmd.extend(input_files)
1350
        spawn(cmd)
1351
1352
        for po_file in glob.glob(os.path.join(po_dir,'*.po')):
1353
            temp_po = po_file + '.temp'
1354
            cmd = [self.msgmerge_exe,'-q','-o',temp_po,po_file,target_pot]
1355
            spawn(cmd)
1356
            os.rename(temp_po,po_file)
1357
        
1358
        self.announce("Finished with i18n messages.")
1359
        
1360
###########################################################################
1361
class BuildI18NMessages(Command):
1362
    description = "Build i18n messages"
1363
1364
    user_options = [('msgfmt-exe=',None,'Path to the msgfmt executable')]
1365
1366
    def initialize_options(self):
1367
        self.msgfmt_exe = None
1368
        
1369
    def finalize_options(self):
1370
        self.set_undefined_options('build', ('msgfmt_exe', 'msgfmt_exe'))
1371
1372
    def get_command_name(self):
1373
        return 'build_messages'
1374
1375
    def run(self):
1376
        if self.distribution.i18n is None: return
1377
        
1378
        self.announce("Building i18n messages...")
1379
        po_dir = self.distribution.i18n[0]
1380
        
1381
        i = 0
1382
        for po_file in [file for file in os.listdir(po_dir) if file.endswith('.po')]:
1383
            source = os.path.join(po_dir,po_file)
1384
            target = source[:-3]+'.gmo'
1385
            cmd = [self.msgfmt_exe,'-o',target, source]
1386
            spawn(cmd)
1387
            i += 1
1388
        self.announce("Done building %i i18n messages." % i)
1389
1390
###########################################################################
1391
class InstallI18NMessages(Command):
1392
    description = "Install messages"
1393
1394
    user_options = [
1395
        ('install-dir=', 'd',"base directory for installing message files (default: installation base dir)"),
1396
        ('root=', None, "install everything relative to this alternate root directory"),
1397
        ('force', 'f', "force installation (overwrite existing files)"),
1398
        ('skip-build', None, "skip the build steps"),
1399
        ]
1400
        
1401
    boolean_options = ['force', 'skip-build']
1402
    
1403
    def initialize_options(self):
1404
        self.install_dir = None
1405
        self.outfiles = []
1406
        self.root = None
1407
        self.force = 0
1408
        self.warn_dir = 1
1409
        self.skip_build = None
1410
1411
    def finalize_options(self):
1412
        own_install_dir = self.install_dir is not None
1413
        
1414
        self.set_undefined_options('install',
1415
                                   ('install_messages', 'install_dir'),
1416
                                   ('root', 'root'),
1417
                                   ('force', 'force'),
1418
                                   ('skip_build', 'skip_build'),
1419
                                  )
1420
1421
        if own_install_dir and self.root is not None:
1422
            self.install_dir = change_root(self.root,self.installdir)
1423
                          
1424
    def get_command_name(self):
1425
        return 'install_messages'
1426
        
1427
    def run(self):
1428
        if not self.skip_build:
1429
            self.run_command('build_messages')
1430
    
1431
        self.announce("Installing i18n messages...")
1432
        po_dir = self.distribution.i18n[0]
1433
        
1434
        counter = 0
1435
        for po_file in os.listdir(po_dir):
1436
            if po_file.endswith('.po'):
1437
                source_file = os.path.join(po_dir,po_file[:-3]) + '.gmo'
1438
                
1439
                # Setup installation of the translation file.
1440
                dest_path = os.path.join(self.install_dir, po_file[:-3],'LC_MESSAGES')
1441
                self.outfiles.extend(self.mkpath(dest_path))
1442
                dest_file = os.path.join(dest_path, self.distribution.metadata.name+'.mo')
1443
                
1444
                self.copy_file(source_file, dest_file)
1445
                self.outfiles.append(dest_file)
1446
                counter += 1
1447
        self.announce("Done installing %i i18n messages." % counter)
1448
1449
    def get_outputs(self):
1450
        return self.outfiles
1451
1452
    def mkpath(self, name, mode=0777):
1453
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
1454
1455
 
1456
###########################################################################
1457
class BuildTdeioslave(Command):
1458
    description = "Build Tdeioslaves"
1459
1460
    user_options = [('no-tdeioslave',None,"Don't build tdeioslaves"),
1461
                    ('build-dir=','b', "build directory (where to install from)"),
1462
                    ('python-dir=',None,'Directory containing the Python installation'),
1463
                    ('python-inc-dir=',None,'Directory containing C Header files for Python'),
1464
                    ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'),
1465
                    ('kde-lib-dir=',None,'Directory containing library files for KDE'),
1466
                    ('kde-tdeioslave-lib-dir=',None,'Directory for KDE tdeioslave library files'),
1467
                    ('kde-protocol-dir=',None,'Directory for KDE tdeioslave protocol files'),
1468
                    ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'),
1469
                    ('qt-lib-dir=',None,'Directory containing library files for Qt'),
1470
                    ('sip-dir=','/usr/lib/pyshared/python*','Directory containing the sip library files'),
1471
                    ('clib=',None,'gcc library and path'),
1472
                    ('pyqt-dir=','/usr/lib/pyshared/python*','PyQt module directory'),
1473
                    ('pytde-dir=',None,'PyTDE module directory'),
1474
                    ('data-dir=',None,'installation directory for data (script) files')]
1475
    
1476
    def initialize_options(self):
1477
        self.no_tdeioslave = 0
1478
        self.build_dir = None
1479
        self.python_inc_dir = None
1480
        self.python_dir = None
1481
        self.kde_inc_dir = None
1482
        self.kde_lib_dir = None
1483
        self.kde_tdeioslave_lib_dir = None
1484
        self.kde_protocol_dir = None
1485
        self.qt_inc_dir = None
1486
        self.qt_lib_dir = None
1487
        self.sip_dir = None
1488
        self.clib = None
1489
        self.pyqt_dir = None
1490
        self.pytde_dir = None
1491
        self.data_dir = None
1492
        
1493
    def finalize_options(self):
1494
        if self.no_tdeioslave==0:
1495
            self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir'))
1496
        
1497
            install = self.get_finalized_command('install')
1498
            self.install_prefix = ask_kde_config('--prefix').strip()
1499
    
1500
            # KDE inc dir: find it!
1501
            if self.kde_inc_dir is None:
1502
                canidatepaths = []
1503
                tdedir = os.getenv("TDEDIR")
1504
                if tdedir!=None:
1505
                    canidatepaths.append(os.path.join(tdedir,"include"))
1506
                canidatepaths.append(os.path.join(install.prefix,"include"))
1507
                canidatepaths.append(os.path.join(self.install_prefix,'include'))
1508
                canidatepaths.append(os.path.join(self.install_prefix,'include','tde'))
1509
                self.kde_inc_dir = FindFileInPaths('tdeapplication.h',canidatepaths)
1510
            if self.kde_inc_dir is None:
1511
                raise SystemExit, "Failed to find the KDE header file directory."
1512
            if FindFileInPaths('tdeapplication.h',[self.kde_inc_dir]) is None:
1513
                raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir
1514
            self.announce("Using %s for KDE header files" % self.kde_inc_dir)
1515
    
1516
            # KDE lib dir
1517
            if self.kde_lib_dir is None:
1518
                self.kde_lib_dir = os.path.join(self.install_prefix,"lib")
1519
            self.announce("Using %s for KDE library files" % self.kde_lib_dir)
1520
    
1521
            # KDE tdeioslave lib dir
1522
            if self.kde_tdeioslave_lib_dir is None:
1523
                self.kde_tdeioslave_lib_dir = os.path.join(self.kde_lib_dir,"trinity")
1524
            if FindFileInPaths('tdeio_*.so',[self.kde_tdeioslave_lib_dir]) is None:
1525
                raise SystemExit, "Failed to find KDE Tdeioslave library files in: %s" % self.kde_tdeioslave_lib_dir
1526
            self.announce("Using %s for KDE Tdeioslave library files" % self.kde_tdeioslave_lib_dir)
1527
            
1528
            # Qt inc dir
1529
            if self.qt_inc_dir is None:
1530
                canidatepaths = []
1531
                qtinc = os.getenv("QTINC")
1532
                if qtinc != None:
1533
                    canidatepaths.append(qtinc)
1534
                qtdir = os.getenv("QTDIR")
1535
                if qtdir != None:
1536
                    canidatepaths.append(os.path.join(qtdir,"include"))
1537
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/include"))
1538
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
1539
                canidatepaths.append(os.path.join(install.prefix,"include"))
1540
                canidatepaths.append("/opt/tqt3/include")
1541
                canidatepaths.append("/opt/qt/include")
1542
                canidatepaths.append("/opt/qt/lib/include")
1543
                canidatepaths.append("/opt/qt3/lib/include")
1544
                self.qt_inc_dir = FindFileInPaths('ntqstring.h',canidatepaths)
1545
            if self.qt_inc_dir is None:
1546
                self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths)
1547
            if self.qt_inc_dir is None:
1548
                raise SystemExit,"Failed to find the Qt header file directory"
1549
            if FindFileInPaths('ntqstring.h',[self.qt_inc_dir]) is None:
1550
                if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None:
1551
                    raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir
1552
            self.announce("Using %s for Qt header files" % self.qt_inc_dir)
1553
    
1554
            # Qt lib dir
1555
            if self.qt_lib_dir is None:
1556
                canidatepaths = []
1557
                qtlib = os.getenv("TQTLIB")
1558
                if qtlib != None:
1559
                    canidatepaths.append(qtlib)
1560
                qtdir = os.getenv("TQTDIR")
1561
                if qtdir != None:
1562
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
1563
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
1564
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
1565
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
1566
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
1567
                canidatepaths.append("/opt/tqt/"+get_libdir_name())
1568
                canidatepaths.append("/opt/tqt/lib/"+get_libdir_name())
1569
                canidatepaths.append("/opt/tqt3/lib/"+get_libdir_name())
1570
                self.qt_lib_dir = FindFileInPaths('libtqt*',canidatepaths)
1571
            if self.qt_lib_dir is None:
1572
                canidatepaths = []
1573
                qtlib = os.getenv("QTLIB")
1574
                if qtlib != None:
1575
                    canidatepaths.append(qtlib)
1576
                qtdir = os.getenv("QTDIR")
1577
                if qtdir != None:
1578
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
1579
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
1580
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
1581
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
1582
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
1583
                canidatepaths.append("/opt/qt/"+get_libdir_name())
1584
                canidatepaths.append("/opt/qt/lib/"+get_libdir_name())
1585
                canidatepaths.append("/opt/qt3/lib/"+get_libdir_name())
1586
                self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths)
1587
            if self.qt_lib_dir is None:
1588
                raise SystemExit, "Failed to find Qt library files"
1589
            self.announce("Using %s for Qt library files" % self.qt_lib_dir)
1590
                    
1591
            # Python dir
1592
            if self.python_dir is None:
1593
                self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[0]
1594
            self.announce("Using %s for the python directory" % self.python_dir)
1595
            
1596
            # Python include dir.
1597
            if self.python_inc_dir is None:
1598
                # Find the Python include directory.
1599
                self.python_inc_dir = sysconfig.get_config_var("INCLUDEPY")
1600
            self.announce("Using %s for Python header files" % self.python_inc_dir)
1601
    
1602
            # PyQt dir
1603
            if self.pyqt_dir is None:
1604
                self.pyqt_dir = m_pyqt_dir
1605
            if self.pyqt_dir is None:
1606
                self.pyqt_dir = os.path.join(sysconfig.get_python_lib(), 'python_tqt')
1607
            if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None):
1608
                raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir
1609
            self.announce("Using %s for PyQt modules" % self.pyqt_dir)
1610
    
1611
            # PyTDE dir
1612
            if self.pytde_dir is None:
1613
                self.pytde_dir = sysconfig.get_python_lib()
1614
            if (FindFileInPaths("libtdecorecmodule*",[self.pytde_dir]) is None) and (FindFileInPaths("tdecore*",[self.pytde_dir]) is None):
1615
                raise SystemExit, "Failed to find the PyTDE directory: %s" % self.pytde_dir
1616
            self.announce("Using %s for PyTDE modules" % self.pytde_dir)
1617
            
1618
            # Sip dir
1619
            if self.sip_dir is None:
1620
                self.sip_dir = m_sip_dir
1621
            if self.sip_dir is None:
1622
                self.sip_dir = os.path.join(sysconfig.get_python_lib(), 'sip4_tqt')
1623
            if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None):
1624
                raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir
1625
            self.announce("Using %s for libsip files" % self.sip_dir)
1626
                
1627
            # Find the C library (libgcc, libgcc_s or some other variation).
1628
            if self.clib is None:
1629
                canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name() ]
1630
                self.clib = FindFileInPaths("libgcc*.so",canidatepaths)
1631
                if self.clib!=None:
1632
                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
1633
                else:
1634
                    self.clib = FindFileInPaths("libgcc*.a",canidatepaths)
1635
                    if self.clib!=None:
1636
                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0]
1637
            if self.clib is None:
1638
                raise SystemExit, "kdedistutils.py (2): Failed to find a suitable libgcc library"
1639
            self.announce("Using %s for clib" % self.clib)
1640
    
1641
            # Make a list of places to look for python .so modules
1642
            self.python_sub_dirs = sysconfig.get_config_var("LIBSUBDIRS").split()
1643
            base = sysconfig.get_config_var("LIBP")
1644
            self.python_sub_dirs = [ os.path.join(base,item) for item in self.python_sub_dirs ]
1645
            self.python_sub_dirs.append(base)
1646
1647
    def get_command_name(self):
1648
        return 'build_tdeioslave'
1649
1650
    def run(self):
1651
        if self.no_tdeioslave:
1652
            self.announce("Skipping TDEIO Slaves")
1653
            return
1654
    
1655
        if not os.path.isdir(self.build_dir):
1656
            os.mkdir(self.build_dir)
1657
        
1658
        for moduletuple in self.distribution.tdeioslaves:
1659
            self.announce("Building TDEIO Slave from protocol file %s." % moduletuple[0])
1660
            
1661
            protocolfilename = moduletuple[0]
1662
            
1663
            # Read the protocol file
1664
            libraryname = None
1665
            try:
1666
                fhandle = open(protocolfilename,'r')
1667
                for line in fhandle.readlines():
1668
                    parts = line.strip().split('=')
1669
                    try:
1670
                        if parts[0]=="exec":
1671
                            libraryname = parts[1]
1672
                    except IndexError:
1673
                        pass
1674
                fhandle.close()
1675
            except IOError:
1676
                raise SystemExit, "Failed to find tdeioslave protocol file: %s" % moduletuple[0]
1677
                
1678
            # Sanity check.
1679
            if libraryname is None:
1680
                raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)"
1681
            
1682
            modulename = os.path.basename(moduletuple[1])
1683
            if modulename.endswith('.py'):
1684
                modulename = modulename[:-3]
1685
            
1686
            stub_cpp_name = libraryname+'.cpp'
1687
            stub_so_name = libraryname+'.so'
1688
            stub_la_name = libraryname+'.la'
1689
            python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1])
1690
            
1691
            # Build the 'stub' code.
1692
            cppcode = self.cpptemplate % {"moduledir": self.data_dir,
1693
                                            "modulename": modulename,
1694
                                            "python_version": python_version}
1695
            
1696
            # Put it on disk.
1697
            cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name)
1698
            try:
1699
                fhandle = open(cppfile,'w')
1700
                fhandle.write(cppcode)
1701
                fhandle.close()
1702
            except IOError:
1703
                raise SystemExit, "Could not write the C++ stub: %s" % cppfile
1704
                
1705
            # Compile the stub library.
1706
            cmdlist = ['libtool']
1707
1708
            # Couldn't get it to pass without this ...
1709
            cmdlist.append("--mode=compile")
1710
            cmdlist.append("--tag=CXX")
1711
            
1712
            # Find the compiler flags and options
1713
            # CXX is empty on some Systems, let's do it 'the hard way'.
1714
            # FIXME :: get CXX from make.conf for Gentoo.
1715
            if len(sysconfig.get_config_var("CXX").split()) >= 2:
1716
                cmdlist.extend(sysconfig.get_config_var("CXX").split())
1717
            else:
1718
                cmdlist.extend(['g++', '-pthread'])
1719
1720
            #cmdlist.extend(sysconfig.get_config_var("CXX").split())
1721
            
1722
            # cc_flags
1723
            cmdlist.append("-c")
1724
            cmdlist.append("-g")
1725
            
1726
            # The 4 is randomly chosen!
1727
            # FIXME :: get CFLAGS from make.conf for Gentoo.
1728
            if len(sysconfig.get_config_var("CFLAGS").split()) >=4:
1729
                cmdlist.extend(sysconfig.get_config_var("CFLAGS").split())
1730
            else:
1731
                # On Gentoo systems, CFLAGS are not in the environment.
1732
                raw = os.popen('emerge info 2> /dev/null|grep CFLAGS')
1733
                lines = raw.readlines()
1734
                if len(lines):
1735
                    cflags = lines[0].split('"')[1].split()
1736
                    print "Got CFLAGS from emerge info."
1737
                    cmdlist.extend(cflags)
1738
                else:
1739
                    # Still no CFLAGS found, use these ...
1740
                    cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes'])
1741
                
1742
            #sysconfig.get_config_var("CFLAGS").split()
1743
            # includes
1744
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
1745
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
1746
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEPY"))
1747
            cmdlist.append("-I" + self.python_inc_dir)
1748
            cmdlist.append("-I" + self.kde_inc_dir)
1749
            cmdlist.append("-I" + self.kde_inc_dir + "/tde")
1750
            cmdlist.append("-I" + self.qt_inc_dir)
1751
            cmdlist.append("-I/usr/include/tqt")
1752
            cmdlist.append("-I.")
1753
            # input
1754
            cmdlist.append(cppfile)
1755
            # output
1756
            outputfile = os.path.join(self.build_dir,libraryname+'.lo')
1757
            cmdlist.append("-o")
1758
            cmdlist.append(outputfile)
1759
            spawn(cmdlist) # Execute!!!
1760
            print
1761
            
1762
            # Link the resulting object file to create a shared library.
1763
            cmdlist = ['libtool']
1764
            cmdlist.append("--mode=link")
1765
            cmdlist.append("--tag=LD")
1766
            
1767
            # Grab the linker command name
1768
            cmdlist.append(sysconfig.get_config_var("LDSHARED").split()[0])
1769
            # link_flags
1770
            cmdlist.append("-module")
1771
            cmdlist.append("-avoid-version")
1772
            cmdlist.append("-shared")
1773
            cmdlist.append("-export-dynamic")
1774
            # object
1775
            cmdlist.append(outputfile)
1776
            cmdlist.append("-rpath"); cmdlist.append(self.kde_tdeioslave_lib_dir)
1777
            cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name))
1778
            # Link libs
1779
            linklist = []
1780
            linklist.append("-lpython%s" % python_version)
1781
            linklist.extend(sysconfig.get_config_var("LIBS").split())
1782
            
1783
            # FIXME I doubt half of these libraries need to be here.
1784
            linklist.append(self.sip_dir+"/sip.so")
1785
            # PyQt libs
1786
            linklist.append(self.pyqt_dir+"/qt.so")
1787
            # PyTDE libs
1788
            linklist.append(self.pytde_dir+"/tdecore.so")
1789
            
1790
#            linklist.append("-L"+self.sip_dir); linklist.append("-lsip")
1791
#            # PyQt libs
1792
#            linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule")
1793
#            # PyTDE libs
1794
#            linklist.append("-L"+self.pytde_dir); linklist.append("-ltdecorecmodule"); linklist.append("-ltdeuicmodule")
1795
            
1796
            linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/trinity/lib"); linklist.append("-ltdecore"); linklist.append("-lpythonize")
1797
            linklist.append("-L"+self.qt_lib_dir); linklist.append("-lqt-mt")
1798
            linklist.append("-lm")
1799
            linklist.append("-lc")
1800
            linklist.append(self.clib)
1801
1802
            linklist.append("-R"); linklist.append(self.python_dir)
1803
            linklist.append("-R"); linklist.append(self.qt_lib_dir)
1804
            linklist.append("-R"); linklist.append(self.sip_dir)
1805
            linklist.append("-R"); linklist.append(self.pyqt_dir)
1806
            linklist.append("-R"); linklist.append(self.pytde_dir)
1807
            linklist.append("-R"); linklist.append(self.kde_lib_dir)
1808
1809
            cmdlist.extend(linklist)
1810
            spawn(cmdlist) # Execute!!
1811
            print
1812
            
1813
    cpptemplate = r"""
1814
/*
1815
 * Launch Control Centre modules written in Python using an embedded Python
1816
 * interpreter.
1817
 * Based on David Boddie's PyTDE-components.
1818
 */
1819
1820
#include <stdio.h>
1821
#include <Python.h>
1822
#include <kinstance.h>
1823
#define MODULE_DIR "%(moduledir)s"
1824
#define MODULE_NAME "%(modulename)s"
1825
#define FACTORY "SlaveFactory"
1826
1827
const char modname[] = MODULE_NAME;
1828
#define MAIN_METHOD "dispatchLoop"
1829
1830
FILE *d = NULL;
1831
1832
PyObject* call_function(PyObject *callable, PyObject *args) {
1833
    PyObject *result, *pArgs;
1834
    
1835
    if (callable == NULL) {
1836
        printf(MODULE_NAME " tdeioslave error: callable == NULL in call_function\n");
1837
        return NULL;
1838
    }
1839
    
1840
    if (PyCallable_Check(callable)) {
1841
        if(args == NULL) {
1842
            pArgs = PyTuple_New(0);
1843
        } else {
1844
            pArgs = args;
1845
        }
1846
        result = PyObject_CallObject(callable, pArgs);
1847
        
1848
        /* If the arguments were created is this function then decrease
1849
           their reference count. */
1850
        if(args == NULL) {
1851
            Py_XDECREF(pArgs);
1852
            /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
1853
        }
1854
        
1855
        if(result == NULL) {
1856
            PyErr_Print();
1857
            PyErr_Clear();
1858
        }
1859
    }
1860
   
1861
    return result;
1862
}
1863
1864
extern "C" {
1865
    int kdemain( int argc, char **argv) {
1866
        PyObject *pModule, *pName, *pDict;
1867
        TDEInstance slave(MODULE_NAME);
1868
        
1869
        Py_SetProgramName(argv[0]);
1870
        Py_Initialize();
1871
        //PyEval_InitThreads();
1872
        PySys_SetArgv(1, argv);
1873
        
1874
        PyRun_SimpleString("import sys\n");
1875
        PyRun_SimpleString("sys.path.append('"MODULE_DIR"')\n");
1876
        
1877
        pName = PyString_FromString(modname);
1878
        pModule = PyImport_Import(pName);
1879
        
1880
        Py_XDECREF(pName);
1881
        
1882
        if(pModule == NULL) {
1883
            printf(MODULE_NAME " tdeioslave error: pModule == NULL\n");
1884
            return 1;
1885
        } else {
1886
            PyObject *pClass, *pMethod, *pArgs, *pArg1, *pArg2, *pInstance;
1887
            int i;
1888
            
1889
            pDict = PyModule_GetDict(pModule);
1890
            /* pDict is a borrowed reference */
1891
            
1892
            pClass = PyDict_GetItemString(pDict, FACTORY);
1893
            
1894
            if(pClass == NULL) {
1895
                printf(MODULE_NAME " tdeioslave error: pClass == NULL\n");
1896
                return 1;
1897
            } else {
1898
                pArgs = PyTuple_New(2);
1899
                
1900
                pArg1 = PyString_FromString(argv[2]);
1901
                pArg2 = PyString_FromString(argv[3]);
1902
                
1903
                PyTuple_SetItem(pArgs, 0, pArg1);
1904
                PyTuple_SetItem(pArgs, 1, pArg2);
1905
                
1906
                call_function(pClass, pArgs);
1907
                
1908
                /* Some time later... */
1909
                Py_XDECREF(pClass);
1910
                Py_XDECREF(pArgs);
1911
            }
1912
            
1913
            Py_XDECREF(pModule);
1914
        }
1915
        
1916
        Py_Finalize();
1917
        return 0;
1918
    }
1919
}
1920
"""
1921
###########################################################################
1922
class InstallTdeioslave(Command):
1923
    description = "Install Tdeioslave files"
1924
    
1925
    user_options = [
1926
        ('install-dir=', 'd', "base directory for installing tdeioslave module files"),
1927
        ('install-cmd=', None, "Command to use to install the files"),
1928
        ('install-protocol-dir=',None,"directory for tdeioslave protocol files"),
1929
        ('build-dir=','b', "build directory (where to install from)"),
1930
        ('root=', None, "install everything relative to this alternate root directory"),
1931
        ('force', 'f', "force installation (overwrite existing files)"),
1932
        ('skip-build', None, "skip the build steps"),
1933
        ]
1934
    boolean_options = ['force', 'skip-build']
1935
    
1936
    def initialize_options(self):
1937
        self.build_dir = None
1938
        self.install_dir = None
1939
        self.install_cmd = None
1940
        self.install_protocol_dir = None
1941
        self.outfiles = []
1942
        self.root = None
1943
        self.force = 0
1944
        self.warn_dir = 1
1945
        self.skip_build = None
1946
1947
    def finalize_options(self):
1948
        own_install_dir = self.install_dir is not None
1949
        own_install_protocol_dir = self.install_protocol_dir is not None
1950
        
1951
        self.set_undefined_options('install',
1952
                                    ('build_base', 'build_dir'),
1953
                                    ('install_tdeioslave', 'install_dir'),
1954
                                    ('root', 'root'),
1955
                                    ('force', 'force'),
1956
                                    ('skip_build', 'skip_build'),
1957
                                    ('install_cmd', 'install_cmd'),
1958
                                    ('install_protocol','install_protocol_dir')
1959
                                    )
1960
1961
        if own_install_dir and self.root is not None:
1962
            self.install_dir = change_root(self.root,self.installdir)
1963
        
1964
        if own_install_protocol_dir and self.root is not None:
1965
            self.install_protocol_dir = change_root(self.root,self.install_protocol_dir)
1966
        
1967
    def get_command_name(self):
1968
        return 'install_tdeioslave'
1969
        
1970
    def run(self):
1971
        if not self.skip_build:
1972
            self.run_command('build_tdeioslave')
1973
    
1974
        self.announce("Installing Tdeioslave files...")
1975
1976
        for moduletuple in self.distribution.tdeioslaves:
1977
            self.announce("Building Tdeioslave module from protocol file %s." % moduletuple[0])
1978
            
1979
            protocolfilename = moduletuple[0]
1980
            
1981
            # Read the protocol file
1982
            libraryname = None
1983
            try:
1984
                fhandle = open(protocolfilename,'r')
1985
                for line in fhandle.readlines():
1986
                    parts = line.strip().split('=')
1987
                    try:
1988
                        if parts[0]=="exec":
1989
                            libraryname = parts[1]
1990
                    except IndexError:
1991
                        pass
1992
                fhandle.close()
1993
            except IOError:
1994
                raise SystemExit, "Failed to find tdeioslave protocol file: %s" % moduletuple[0]
1995
                
1996
            if libraryname is None:
1997
                raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)"
1998
                
1999
            self.outfiles.extend(self.mkpath(self.install_protocol_dir))
2000
            protocolfile_dest = os.path.join(self.install_protocol_dir,os.path.basename(protocolfilename))
2001
            self.copy_file(protocolfilename, protocolfile_dest)
2002
            
2003
            stub_la_name = libraryname+'.la'
2004
    
2005
            self.outfiles.extend(self.mkpath(self.install_dir))
2006
            
2007
            # Install the library.
2008
            cmdlist = ['libtool']
2009
            cmdlist.append("--mode=install")
2010
            cmdlist.append(self.install_cmd)
2011
            cmdlist.append("-c")
2012
            cmdlist.append(os.path.join(self.build_dir,stub_la_name))
2013
            cmdlist.append(os.path.join(self.install_dir,stub_la_name))
2014
            spawn(cmdlist) # Execute!!
2015
            print
2016
2017
            self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs',libraryname+'*'))]
2018
            self.outfiles.append(protocolfile_dest)
2019
            
2020
        self.announce("Done installing Tdeioslave files.")
2021
        
2022
    def get_outputs(self):
2023
        return self.outfiles or []
2024
2025
    def mkpath(self, name, mode=0777):
2026
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
2027
 
2028
###########################################################################
2029
class CheckPyQt(Command):
2030
    description = "Checks for the presence of a working PyQt installation"
2031
2032
    user_options = []
2033
        
2034
    def initialize_options(self):
2035
        pass
2036
        
2037
    def finalize_options(self):
2038
        self.min_qt_version = self.distribution.min_qt_version
2039
        
2040
    def run(self):
2041
        if self.min_qt_version!=None:
2042
            qtver,kdever = get_qt_kde_versions()
2043
            if compare_versions(self.min_qt_version,qtver)==1:
2044
                raise SystemExit, "Your Qt version is too old. Version %s or higher is required, found %s." % (self.min_qt_version,qtver)
2045
            self.announce("Found Qt version %s." % qtver)
2046
        try:
2047
            self.announce("Checking for a working PyQt...")
2048
            import qt
2049
            self.announce("  ...PyQt is working")
2050
        except:
2051
            raise SystemExit, "Couldn't import Qt! Please make sure that PyQt is installed and working."
2052
2053
    def get_outputs(self): return []
2054
2055
###########################################################################
2056
class CheckPyTDE(Command):
2057
    description = "Checks for the presence of a working PyTDE installation"
2058
2059
    user_options = []
2060
        
2061
    def initialize_options(self):
2062
        pass
2063
        
2064
    def finalize_options(self):
2065
        self.min_kde_version = self.distribution.min_kde_version
2066
        
2067
    def run(self):
2068
        if self.min_kde_version!=None:
2069
            qtver,kdever = get_qt_kde_versions()
2070
            if compare_versions(self.min_kde_version,kdever)==1:
2071
                raise SystemExit, "Your KDE version is too old. Version %s or higher is required, found %s." % (self.min_kde_version,kdever)
2072
            self.announce("Found KDE version %s." % kdever)
2073
        self.announce("Checking for a working PyTDE...")
2074
        
2075
        # Try to import modules one by one. 
2076
        for k_module in ('dcop', 'tdecore', 'tdeui', 'tdeio', 'tdefile', 'tdeparts', 'tdehtml', 'tdespell'):
2077
            self.announce(k_module)
2078
            try:
2079
                exec('import ' + k_module)
2080
            except:
2081
                raise SystemExit, "Error: Couldn't find module '" + k_module + "'. \n" + \
2082
                    "Couldn't import KDE! Please make sure that PyTDE is installed and working.\n" + \
2083
                    "PyTDE is available here: http://www.trinitydesktop.org"
2084
        self.announce("  ...PyTDE is working")
2085
        
2086
    def get_outputs(self): return []
2087
    
2088
###########################################################################
2089
def FindFileInPaths2(globpattern,canidatepaths):
2090
    if canidatepaths is None or len(canidatepaths)==0:
2091
        return (None,None)
2092
    
2093
    # Look for the globpattern on the path.
2094
    for path in canidatepaths:
2095
        if path!=None:
2096
            files = glob.glob(os.path.join(path, globpattern))
2097
            if len(files)!=0:
2098
                return (path,os.path.basename(files[0]))
2099
    
2100
    # Continue searching with a breadth first search.
2101
    dirs = []
2102
    for path in canidatepaths:
2103
        # Examine any directories on this path.
2104
        dirlist = glob.glob(os.path.join(path, "*"))
2105
        for item in dirlist:
2106
            if os.path.isdir(item):
2107
                # Examine each subdirectory.
2108
                dirs.append(item)
2109
    # Examine all subdirectories.
2110
    return FindFileInPaths2(globpattern, dirs)
2111
2112
###########################################################################
2113
def FindFileInPaths(globpattern,canidatepaths):
2114
    x,y = FindFileInPaths2(globpattern,canidatepaths)
2115
    return x
2116
    
2117
###########################################################################
2118
# FIXME replace this with spawn.find_executable().
2119
def FindExeOnPath(exe_name,high_prio_dirs=None,low_prio_dirs=None):
2120
    candiate_paths = []
2121
    
2122
    if high_prio_dirs is not None:
2123
        candiate_paths.extend(high_prio_dirs)
2124
        
2125
    path_var = os.getenv("PATH")
2126
    candiate_paths.extend(path_var.split(':'))
2127
    
2128
    if low_prio_dirs is not None:
2129
        candiate_paths.extend(low_prio_dirs)
2130
    
2131
    for dir in candiate_paths:
2132
        if dir is not None:
2133
            candiate = os.path.join(dir,exe_name)
2134
            if os.path.isfile(candiate):
2135
                if os.access(candiate,os.X_OK):
2136
                    return candiate
2137
    return None
2138
    
2139
###########################################################################
2140
2141
def ask_kde_config(question):
2142
    # Look for the tde-config program
2143
    kdeconfig = find_executable("tde-config", os.environ['PATH'] + os.pathsep + \
2144
        os.pathsep.join(['/bin','/usr/bin','/opt/trinity/bin','/opt/kde/bin','/usr/local/bin']))
2145
    if kdeconfig!=None:
2146
        # Ask the tde-config program for the 
2147
        fhandle = os.popen(kdeconfig+' ' + question,'r')
2148
        result = fhandle.read()
2149
        fhandle.close()
2150
        return result
2151
    else:
2152
        return None
2153
2154
###########################################################################
2155
# Convert for example, "3.1.1a" => [3,1,1,'a']
2156
#
2157
def split_version_name(name):
2158
    result = []
2159
    accu = ''
2160
    type = 0
2161
    for c in name:
2162
        if type==0:
2163
            if c.isdigit():
2164
                type = 1
2165
            else:
2166
                type = 2
2167
            accu += c
2168
        elif c=='.':
2169
            if type==1:
2170
                result.append(int(accu))
2171
            else:
2172
                result.append(accu)
2173
            accu = ''
2174
            type = 0
2175
        elif type==1:
2176
            # Digits
2177
            if c.isdigit():
2178
                accu += c
2179
            else:
2180
                result.append(int(accu))
2181
                type = 2
2182
                accu = c
2183
        else:
2184
            if c.isdigit():
2185
                result.append(accu)
2186
                type = 1
2187
                accu = c
2188
            else:
2189
                accu += c
2190
    if accu!='':
2191
        result.append(accu)
2192
    return result
2193
2194
###########################################################################
2195
#
2196
# Returns:
2197
# -1 if a < b
2198
# 0 if a and b are equal
2199
# 1 if a > b
2200
def compare_versions(a,b):
2201
    aparts = split_version_name(a)
2202
    bparts = split_version_name(b)
2203
    if len(aparts)>len(bparts):
2204
        compmax = len(aparts)
2205
    else:
2206
        compmax = len(bparts)
2207
    i = 0
2208
    for i in range(compmax):
2209
        abit = 0
2210
        if i<len(aparts):
2211
            abit = aparts[i]
2212
        bit = 0
2213
        if i<len(bparts):
2214
            bbit = bparts[i]
2215
        if isinstance(abit,str) and not isinstance(bbit,str):
2216
            return 1
2217
        elif not isinstance(abit,str) and isinstance(bbit,str):
2218
            return -1
2219
        else:
2220
            if abit>bbit:
2221
                return 1
2222
            elif abit<bbit:
2223
                return -1
2224
    return 0
2225
2226
###########################################################################
2227
def get_qt_kde_versions():
2228
    versioninfo = ask_kde_config('--version')
2229
    qtver = None
2230
    kdever = None
2231
    if versioninfo!=None:
2232
        for line in versioninfo.splitlines():
2233
            if line.startswith("Qt: "):
2234
                qtver = line[4:]
2235
            elif line.startswith("TDE: "):
2236
                kdever = line[5:]
2237
    return qtver,kdever
2238
2239
###########################################################################
2240
def compile_qtdesigner(ui_files,
2241
                  force=0,
2242
                  prefix=None, base_dir=None,
2243
                  verbose=1, dry_run=0):
2244
    """Compile a collection of QT Designer UI files to .py
2245
    
2246
    If 'dry_run' is true, doesn't actually do anything that would
2247
    affect the filesystem.
2248
    """
2249
    generated_files = []
2250
    for file in ui_files:
2251
        if not file.endswith(".ui"):
2252
            continue
2253
2254
        # Terminology from the py_compile module:
2255
        #   cfile - byte-compiled file
2256
        #   dfile - purported source filename (same as 'file' by default)
2257
        if base_dir:
2258
            file = os.path.join(base_dir ,file)
2259
            
2260
        pyfile = file[:-3] + '.py'
2261
        uifile = file
2262
2263
        pyfile_base = os.path.basename(pyfile)
2264
        if force or newer(uifile, pyfile):
2265
            log.info("compiling Qt-Designer UI %s to %s", file, pyfile_base)
2266
            if not dry_run:
2267
                qtuicompiler.CompileUI(uifile, pyfile)
2268
            generated_files.append(pyfile)    
2269
        else:
2270
            log.debug("skipping Qt-Designer compilation of %s to %s",
2271
                      file, pyfile_base)
2272
    return generated_files
2273
2274
###########################################################################
2275
def get_libdir_name():
2276
    if os.uname()[4] in ['x86_64','mips64','ppc64','sparc64','s390x']:
2277
        return 'lib64'
2278
    else:
2279
        return 'lib'
(-)b/src/tdedistutils.py (+2279 lines)
Line 0 Link Here
1
#!/usr/bin/python
2
###########################################################################
3
# tdedistutils - description                                              #
4
# ------------------------------                                          #
5
# begin     : Thu Apr 21 2005                                             #
6
# copyright : (C) 2005 by Simon Edwards                                   #
7
# email     : simon@simonzone.com                                         #
8
#                                                                         #
9
###########################################################################
10
#                                                                         #
11
#   This program is free software; you can redistribute it and/or modify  #
12
#   it under the terms of the GNU Library General Public License as       #
13
#   published by the Free Software Foundation; either version 2 of the    #
14
#   License, or (at your option) any later version.                       #
15
#                                                                         #
16
###########################################################################
17
18
import distutils.core
19
from distutils.core import Extension
20
from distutils.cmd import Command
21
from distutils.dist import Distribution
22
from distutils.command.build import build
23
from distutils.command.install import install
24
from distutils.command.install_scripts import install_scripts
25
from distutils.command.install_data import install_data
26
from distutils.command.install_lib import install_lib
27
from distutils.util import change_root, convert_path
28
from distutils.spawn import find_executable,spawn
29
from distutils import sysconfig
30
from distutils import log
31
from distutils import file_util
32
from distutils import dir_util
33
from distutils.util import byte_compile
34
import qtuicompiler
35
import stat
36
import os,os.path,imp,glob
37
import sys
38
from types import StringType
39
40
INSTALL_LIST = 'install_log.txt'
41
42
# Trinity-specific paths
43
tqt_modules = []
44
from distutils.sysconfig import get_python_lib
45
for m_path in sys.path:
46
    if os.path.exists(os.path.join(m_path, 'sip4_tqt')):
47
        m_sip_dir = os.path.join(m_path, 'sip4_tqt')
48
        tqt_modules.insert(0, m_sip_dir)
49
    if os.path.exists(os.path.join(m_path, 'python_tqt')):
50
        m_pyqt_dir = os.path.join(m_path, 'python_tqt')
51
        tqt_modules.insert(0, m_pyqt_dir)
52
for m_path in tqt_modules:
53
    sys.path.insert(0, m_path)
54
55
56
###########################################################################
57
def setup(**arg_dict):
58
59
    if 'cmdclass' not in arg_dict:
60
        arg_dict['cmdclass'] = {}
61
62
    cmdclass = arg_dict['cmdclass']
63
64
    arg_dict.setdefault('data_files',[])
65
66
    kdecmdclass = {'install' : InstallKDE,
67
        'install_executable_links' : InstallExecutableLinks,
68
        'install_application_data' : InstallApplicationDataAndLinks,
69
        'build_messages' : BuildI18NMessages,
70
        'install_messages' : InstallI18NMessages,
71
        'update_messages' : UpdateI18NMessages,
72
        'checkpyqt' : CheckPyQt,
73
        'checkpytde' : CheckPyTDE,
74
        'uninstall' : Uninstall,
75
        'build' : BuildKDE,
76
        'build_kcm' : BuildKControlModule,
77
        'install_kcm' : InstallKControlModule,
78
        'build_html' : BuildDocbookHTML,
79
        'install_html' : InstallDocbookHTML,
80
        'install_lib' : InstallLibWithRoot,
81
        'build_tdeioslave' : BuildTdeioslave,
82
        'install_tdeioslave' : InstallTdeioslave}
83
84
    for key in kdecmdclass.iterkeys():
85
        cmdclass.setdefault(key,kdecmdclass[key])
86
87
    arg_dict.setdefault('distclass',KDEDistribution)
88
89
    apply(distutils.core.setup,[],arg_dict)
90
91
###########################################################################
92
class KDEDistribution(Distribution):
93
    def __init__(self,attrs=None):
94
        self.min_kde_version = None
95
        self.min_qt_version = None
96
        self.kcontrol_modules = None
97
        self.tdeioslaves = None
98
        self.executable_links = None
99
        self.docbooks = None
100
        self.application_data = None
101
        self.i18n = None
102
        Distribution.__init__(self,attrs)
103
104
###########################################################################
105
def has_kcms(self):
106
    if self.distribution.kcontrol_modules is None:
107
        return 0
108
    return  len(self.distribution.kcontrol_modules)!=0
109
110
def has_docbook_html(self):
111
    if self.distribution.docbooks is None:
112
        return 0
113
    return  len(self.distribution.docbooks)!=0
114
115
def has_messages(self):
116
    if self.distribution.i18n is None:
117
        return 0
118
    return  len(self.distribution.i18n)!=0
119
120
def has_application_data(self):
121
    if self.distribution.application_data is None:
122
        return 0
123
    return  len(self.distribution.application_data)!=0
124
125
def has_tdeioslaves(self):
126
    if self.distribution.tdeioslaves is None:
127
        return 0
128
    return  len(self.distribution.tdeioslaves)!=0
129
130
###########################################################################
131
# Our slightly extended build command. This also does kcontrol modules.
132
class BuildKDE(build):
133
134
    user_options = build.user_options[:]
135
    user_options.append( ('msgfmt-exe=',None,'Path to the msgfmt executable') )
136
    user_options.append( ('meinproc-exe=',None,'Path to the meinproc executable') )
137
138
    sub_commands = build.sub_commands[:]
139
    sub_commands.append( ('build_kcm',has_kcms) )
140
    sub_commands.append( ('build_tdeioslave',has_tdeioslaves) )
141
    sub_commands.append( ('build_html',has_docbook_html) )
142
    sub_commands.append( ('build_messages',has_messages) )
143
144
    def __init__(self,dist):
145
        build.__init__(self,dist)
146
        self.has_kcms = has_kcms
147
        self.has_tdeioslaves = has_tdeioslaves
148
        self.has_docbook_html = has_docbook_html
149
        self.has_messages = has_messages
150
151
    def initialize_options(self):
152
        self.msgfmt_exe = None
153
        self.meinproc_exe = None
154
        build.initialize_options(self)
155
156
    def finalize_options(self):
157
        build.finalize_options(self)
158
159
        if self.msgfmt_exe is None:
160
            # Find msgfmt
161
            canidatepaths = []
162
            canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() )
163
            self.msgfmt_exe = FindExeOnPath('msgfmt',canidatepaths)
164
            if self.msgfmt_exe is None:
165
                raise SystemExit, "Unable to find 'msgfmt', needed to build i18n messages."
166
167
        if self.meinproc_exe is None:
168
            # Find meinproc
169
            canidatepaths = []
170
            canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() )
171
            self.meinproc_exe = FindExeOnPath('meinproc',canidatepaths)
172
            if self.meinproc_exe is None:
173
                raise SystemExit, "Unable to find 'meinproc', needed to generate Docbook HTML documentation."
174
175
###########################################################################
176
def has_executable_links(self):
177
    if self.distribution.executable_links is None:
178
        return 0
179
    return  len(self.distribution.executable_links)!=0
180
181
###########################################################################
182
class InstallKDE(install):
183
    user_options = install.user_options[:]
184
    user_options.append( ('kde-prefix=',None,"TDE installation prefix") )
185
    user_options.append( ('install-messages=',None,"installation directory for i18n message files") )
186
    user_options.append( ('install-html=',None,"installation directory for Docbook HTML files") )
187
    user_options.append( ('install-cmd=',None,"Command to use to install the files") )
188
    user_options.append( ('install-xdg-apps=',None,"directory for XDG app files") )
189
    user_options.append( ('install-kcm=',None,"directory for kcm library files") )
190
    user_options.append( ('install-tdeioslave',None,"directory for tdeioslave library files") )
191
    user_options.append( ('install-protocol',None,"directory for tdeioslave protocol files") )
192
193
    sub_commands = install.sub_commands[:]
194
    sub_commands.insert(0, ('checkpytde',None) )
195
    sub_commands.insert(0, ('checkpyqt',None) )
196
    sub_commands.append( ('install_executable_links',has_executable_links) )
197
    sub_commands.append( ('install_messages',has_messages) )
198
    sub_commands.append( ('install_html',has_docbook_html) )
199
    sub_commands.append( ('install_kcm',has_kcms) )
200
    sub_commands.append( ('install_tdeioslave',has_tdeioslaves) )
201
    sub_commands.append( ('install_application_data',has_application_data) )
202
203
    def initialize_options(self):
204
        self.kde_prefix = None
205
        self.install_messages = None
206
        self.install_html = None
207
        self.install_cmd = None
208
        self.install_xdg_apps = None
209
        self.install_kcm = None
210
        self.install_tdeioslave = None
211
        self.install_protocol = None
212
        self.install_application_data = None
213
        install.initialize_options(self)
214
215
    def finalize_options(self):
216
        # If no install prefix was provided, then we try to detect the KDE install prefix.
217
        self.user_supplied_kde_prefix = True
218
219
        if self.install_scripts is None:
220
            if self.kde_prefix is not None:
221
                self.install_scripts = os.path.join(self.kde_prefix,'bin')
222
            else:
223
                self.announce("Detecting TDE 'bin' directory...")
224
                self.install_scripts = ask_kde_config('--install exe --expandvars').strip()
225
                self.announce("   ...TDE 'bin' directory is %s" % self.install_scripts)
226
227
        if self.install_application_data is None:
228
            if self.kde_prefix is not None:
229
                self.install_application_data = os.path.join(self.kde_prefix,'share/apps',self.distribution.metadata.name)
230
            else:
231
                self.announce("Detecting TDE application directory...")
232
                kdeappdir = ask_kde_config('--install data --expandvars').strip()
233
                self.announce("  ...TDE application directory is %s" % self.install_application_data)
234
                self.install_application_data = os.path.join(kdeappdir,self.distribution.metadata.name)
235
236
        if self.install_messages is None:
237
            if self.kde_prefix is not None:
238
                self.install_messages = os.path.join(self.kde_prefix,'share/locale')
239
            else:
240
                self.announce("Detecting TDE messages directory...")
241
                self.install_messages = ask_kde_config('--install locale --expandvars').strip()
242
                self.announce("  ...TDE messages directory is %s" % self.install_messages)
243
244
        if self.install_html is None:
245
            if self.kde_prefix is not None:
246
                self.install_html = os.path.join(self.kde_prefix,'share/doc/tde/HTML')
247
            else:
248
                self.announce("Detecting TDE HTML directory...")
249
                self.install_html = ask_kde_config('--install html --expandvars').strip()
250
                self.announce("  ...TDE HTML directory is %s" % self.install_html)
251
252
        if self.kde_prefix is None:
253
            self.announce("Detecting TDE install prefix...")
254
            self.kde_prefix = ask_kde_config('--prefix').strip()
255
            self.announce("  ...TDE install prefix is %s" % self.kde_prefix)
256
            self.user_supplied_kde_prefix = False
257
258
        if self.install_cmd is None:
259
            self.announce("Detecting 'install' command...")
260
            # Ok, time to find the install command.
261
            self.install_cmd = find_executable('install')
262
            if self.install_cmd is None:
263
                raise SystemExit, "Unable to find the 'install' command, needed to install libraries."
264
            self.announce("  ...'install' command is %s" % self.install_cmd)
265
266
        if self.install_xdg_apps is None:
267
            self.announce("Detecting XDG apps directory...")
268
            self.install_xdg_apps = ask_kde_config('--install xdgdata-apps --expandvars').strip()
269
            self.announce("  ...XDG apps directory is %s" % self.install_xdg_apps)
270
271
        if self.install_kcm is None:
272
            self.announce("Detecting kcm library  directory...")
273
            self.install_kcm = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'trinity')
274
            self.announce("  ...kcm library directory is %s" % self.install_kcm)
275
276
        if self.install_tdeioslave is None:
277
            self.announce("Detecting tdeioslave library  directory...")
278
            self.install_tdeioslave = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'trinity')
279
            self.announce("  ...tdeioslave library directory is %s" % self.install_tdeioslave)
280
281
        if self.install_protocol is None:
282
            self.announce("Detecting tdeioslave protocol directory...")
283
            self.install_protocol = ask_kde_config('--install services --expandvars').strip()
284
            self.announce("  ...tdeioslave protocol directory is %s" % self.install_protocol)
285
286
        install.finalize_options(self)
287
288
        if self.root is not None:
289
            self.change_roots('application_data','html','messages','xdg_apps','kcm')
290
291
    def get_command_name(self):
292
        return 'install'
293
294
    def run(self):
295
        global INSTALL_LIST
296
        install.run(self)
297
298
        # Write out the uninstall list.
299
        fhandle = open(INSTALL_LIST,'w')
300
        for item in self.get_outputs():
301
            fhandle.write(item)
302
            fhandle.write('\n')
303
        fhandle.close()
304
305
###########################################################################
306
class InstallApplicationDataAndLinks(install_data):
307
    def get_command_name(self):
308
        return 'install_application_data'
309
310
    def initialize_options(self):
311
        install_data.initialize_options(self)
312
313
        self.data_files = self.distribution.application_data
314
315
    def finalize_options(self):
316
        self.set_undefined_options('install',
317
                                   ('install_application_data', 'install_dir'),
318
                                   ('root', 'root'),
319
                                   ('force', 'force'),
320
                                  )
321
322
    def run(self):
323
        self.outfiles.extend(self.mkpath(self.install_dir))
324
        for f in self.data_files:
325
            if type(f) is StringType:
326
                # it's a simple file, so copy it
327
                f = convert_path(f)
328
                if self.warn_dir:
329
                    self.warn("setup script did not provide a directory for "
330
                              "'%s' -- installing right in '%s'" %
331
                              (f, self.install_dir))
332
                if os.path.isfile(f):
333
                    (out, _) = self.copy_file(f, self.install_dir)
334
                    self.outfiles.append(out)
335
                elif os.path.isdir(f):
336
                    out = self.copy_tree(f,os.path.join(self.install_dir,f))
337
                    self.outfiles.extend(out)
338
                else:
339
                    self.warn("Setup script can't find file or directory %s needed for installation." % f)
340
            else:
341
                # it's a tuple with path to install to and a list of files
342
                dir = convert_path(f[0])
343
                if not os.path.isabs(dir):
344
                    dir = change_root(self.install_dir, dir)
345
                elif self.root:
346
                    dir = change_root(self.root, dir)
347
                self.outfiles.extend(self.mkpath(dir))
348
349
                if f[1] == []:
350
                    # If there are no files listed, the user must be
351
                    # trying to create an empty directory, so add the
352
                    # directory to the list of output files.
353
                    self.outfiles.append(dir)
354
                else:
355
                    # Copy files, adding them to the list of output files.
356
                    for data in f[1]:
357
                        data = convert_path(data)
358
                        if os.path.islink(data):
359
                            # Transplant the link to the new location without changing
360
                            # where it points to. (ie it is _not_ relocated).
361
                            dest = os.path.join(dir, os.path.basename(data))
362
                            if os.path.exists(dest):
363
                                os.remove(dest)
364
                            os.symlink(os.readlink(data),dest)
365
                            log.info("moving link %s -> %s" % (data,dest) )
366
                            #os.chmod(dest, os.stat(data)[stat.ST_MODE])
367
                        elif os.path.isdir(data):
368
                            out = self.copy_tree(data,dir)
369
                            self.outfiles.extend(out)
370
                        else:
371
                            (out, _) = self.copy_file(data, dir)
372
                            self.outfiles.append(out)
373
374
        # Compile the .ui files
375
        install_cmd = self.get_finalized_command('install')
376
        prefix = self.install_dir
377
        if prefix[-1] != os.sep:
378
            prefix = prefix + os.sep
379
        self.outfiles.extend(compile_qtdesigner(self.outfiles, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run))
380
381
        # Byte compile the .py files
382
        from distutils.util import byte_compile
383
        byte_compile(self.outfiles, optimize=0, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run)
384
385
        # Add the .pyc files to the list of outfiles.
386
        self.outfiles.extend( [item+'c' for item in self.outfiles if item.endswith('.py')] )
387
388
    def mkpath(self, name, mode=0777):
389
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
390
391
###########################################################################
392
class InstallExecutableLinks(Command):
393
    description = "Install symlinks"
394
395
    user_options = []
396
397
    def initialize_options(self):
398
        self.outfiles = []
399
400
    def finalize_options(self):
401
        pass
402
403
    def get_command_name(self):
404
        return 'install_executable_links'
405
406
    def run(self):
407
        # FIXME add cmd options?
408
        install_script_cmd = self.get_finalized_command('install_scripts')
409
        install_data_cmd = self.get_finalized_command('install_application_data')
410
411
        destination_dir = install_data_cmd.install_dir
412
413
        if not os.path.exists(install_script_cmd.install_dir):
414
            self.outfiles.extend(self.mkpath(install_script_cmd.install_dir))
415
416
        if self.distribution.executable_links is not None:
417
            for link in self.distribution.executable_links:
418
                symname = os.path.join(install_script_cmd.install_dir,link[0])
419
                target = os.path.join(destination_dir,link[1])
420
                log.info("symlinking %s -> %s", symname, target)
421
                if not self.dry_run:
422
                    if os.path.islink(symname):
423
                        os.remove(symname)
424
                    os.symlink(target,symname)
425
                self.outfiles.append(symname)
426
427
    def get_outputs(self):
428
        return self.outfiles or []
429
430
    def mkpath(self, name, mode=0777):
431
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
432
433
###########################################################################
434
# Fix the --root option for the install_lib command.
435
class InstallLibWithRoot(install_lib):
436
    user_options = install_lib.user_options[:]
437
    user_options.append( ('root=',None,"install everything relative to this alternate root directory") )
438
439
    def initialize_options(self):
440
        install_lib.initialize_options(self)
441
        self.root = None
442
443
    def finalize_options(self):
444
        own_install_dir = self.install_dir is not None
445
446
        install_lib.finalize_options(self)
447
        self.set_undefined_options('install', ('root', 'root'))
448
449
        if self.root is not None and own_install_dir:
450
            self.install_dir = change_root(self.root, self.install_dir)
451
452
###########################################################################
453
class Uninstall(Command):
454
    description = "Remove all installed files"
455
456
    user_options = []
457
458
    def initialize_options(self):
459
        pass
460
461
    def finalize_options(self):
462
        pass
463
464
    def get_command_name(self):
465
        return 'uninstall'
466
467
    def run(self):
468
        global INSTALL_LIST
469
470
        if not os.path.isfile(INSTALL_LIST):
471
            self.announce("Unable to uninstall, can't find the file list %s." % INSTALL_LIST)
472
            return
473
474
        # Suck in the file list.
475
        fhandle = open(INSTALL_LIST,'r')
476
        file_list = fhandle.readlines()
477
        fhandle.close()
478
479
        # Remove the files first.
480
        for item in file_list:
481
            item = item.strip()
482
            if os.path.isfile(item) or os.path.islink(item):
483
                self.announce("removing '%s'" % item)
484
                if not self.dry_run:
485
                    try:
486
                        os.remove(item)
487
                    except OSError, details:
488
                        self.warn("Could not remove file: %s" % details)
489
            elif not os.path.isdir(item):
490
                self.announce("skipping removal of '%s' (does not exist)" % item)
491
492
        # Remove the directories.
493
        file_list.sort()
494
        file_list.reverse()
495
        # Starting with the longest paths first.
496
        for item in file_list:
497
            item = item.strip()
498
            if os.path.isdir(item):
499
                self.announce("removing '%s'" % item)
500
                if not self.dry_run:
501
                    try:
502
                        os.rmdir(item)
503
                    except OSError, details:
504
                        self.warn("Could not remove directory: %s" % details)
505
506
###########################################################################
507
class BuildKControlModule(Command):
508
    description = "Build KControl extensions"
509
510
    user_options = [('no-kcontrol',None,"Don't build kcontrol extensions"),
511
                    ('build-dir=','b', "build directory (where to install from)"),
512
                    ('python-dir=',None,'Directory containing the Python installation'),
513
                    ('python-inc-dir=',None,'Directory containing C Header files for Python'),
514
                    ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'),
515
                    ('kde-lib-dir=',None,'Directory containing library files for KDE'),
516
                    ('kde-kcm-lib-dir=',None,'Directory for KDE kcm library files'),
517
                    ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'),
518
                    ('qt-lib-dir=',None,'Directory containing library files for Qt'),
519
                    ('sip-dir=',None,'Directory containing the sip library files'),
520
                    ('clib=',None,'gcc library and path'),
521
                    ('pyqt-dir=',None,'PyQt module directory'),
522
                    ('pytde-dir=',None,'PyTDE module directory'),
523
                    ('data-dir=',None,'installation directory for data (script) files')]
524
525
    def initialize_options(self):
526
        self.no_kcontrol = 0
527
        self.build_dir = None
528
        self.python_inc_dir = None
529
        self.python_dir = None
530
        self.kde_inc_dir = None
531
        self.kde_lib_dir = None
532
        self.kde_kcm_lib_dir = None
533
        self.qt_inc_dir = None
534
        self.qt_lib_dir = None
535
        self.sip_dir = None
536
        self.clib = None
537
        self.pyqt_dir = None
538
        self.pytde_dir = None
539
        self.data_dir = None
540
541
    def finalize_options(self):
542
        if self.no_kcontrol==0:
543
            self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir'))
544
545
            install = self.get_finalized_command('install')
546
            self.install_prefix = ask_kde_config('--prefix').strip()
547
548
            # KDE inc dir: find it!
549
            if self.kde_inc_dir is None:
550
                canidatepaths = []
551
                tdedir = os.getenv("TDEDIR")
552
                if tdedir!=None:
553
                    canidatepaths.append(os.path.join(tdedir,"include"))
554
                canidatepaths.append(os.path.join(install.prefix,"include"))
555
                canidatepaths.append(os.path.join(self.install_prefix,'include'))
556
                canidatepaths.append(os.path.join(self.install_prefix,'include','tde'))
557
                self.kde_inc_dir = FindFileInPaths('tdeapplication.h',canidatepaths)
558
            if self.kde_inc_dir is None:
559
                raise SystemExit, "Failed to find the KDE header file directory."
560
            if FindFileInPaths('tdeapplication.h',[self.kde_inc_dir]) is None:
561
                raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir
562
            self.announce("Using %s for KDE header files" % self.kde_inc_dir)
563
564
            # KDE lib dir
565
            if self.kde_lib_dir is None:
566
                self.kde_lib_dir = os.path.join(self.install_prefix,"lib")
567
            self.announce("Using %s for KDE library files" % self.kde_lib_dir)
568
569
            # KDE KCM lib dir
570
            if self.kde_kcm_lib_dir is None:
571
                self.kde_kcm_lib_dir = os.path.join(self.kde_lib_dir,"trinity")
572
            if FindFileInPaths('*kcm*.so',[self.kde_kcm_lib_dir]) is None:
573
                raise SystemExit, "Failed to find KDE KCM files in: %s" % self.kde_kcm_lib_dir
574
            self.announce("Using %s for KDE KCM library files" % self.kde_kcm_lib_dir)
575
576
            # Qt inc dir
577
            if self.qt_inc_dir is None:
578
                canidatepaths = []
579
                qtinc = os.getenv("QTINC")
580
                if qtinc != None:
581
                    canidatepaths.append(qtinc)
582
                qtdir = os.getenv("QTDIR")
583
                if qtdir != None:
584
                    canidatepaths.append(os.path.join(qtdir,"include"))
585
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/include"))
586
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
587
                canidatepaths.append(os.path.join(install.prefix,"include"))
588
                canidatepaths.append("/opt/tqt3/include")
589
                canidatepaths.append("/opt/qt/include")
590
                canidatepaths.append("/opt/qt/lib/include")
591
                canidatepaths.append("/opt/qt3/lib/include")
592
		canidatepaths.append("/usr/include/tqt3")
593
		canidatepaths.append("/usr/include/qt3")
594
                self.qt_inc_dir = FindFileInPaths('ntqstring.h',canidatepaths)
595
            if self.qt_inc_dir is None:
596
                self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths)
597
            if self.qt_inc_dir is None:
598
                raise SystemExit,"Failed to find the Qt header file directory"
599
            if FindFileInPaths('ntqstring.h',[self.qt_inc_dir]) is None:
600
                if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None:
601
                    raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir
602
            self.announce("Using %s for Qt header files" % self.qt_inc_dir)
603
604
            # Qt lib dir
605
            if self.qt_lib_dir is None:
606
                canidatepaths = []
607
                qtlib = os.getenv("TQTLIB")
608
                if qtlib != None:
609
                    canidatepaths.append(qtlib)
610
                qtdir = os.getenv("TQTDIR")
611
                if qtdir != None:
612
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
613
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
614
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
615
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
616
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
617
                canidatepaths.append("/opt/tqt/"+get_libdir_name())
618
                canidatepaths.append("/opt/tqt/lib/"+get_libdir_name())
619
                canidatepaths.append("/opt/tqt3/lib/"+get_libdir_name())
620
                self.qt_lib_dir = FindFileInPaths('libtqt*',canidatepaths)
621
            if self.qt_lib_dir is None:
622
                canidatepaths = []
623
                qtlib = os.getenv("QTLIB")
624
                if qtlib != None:
625
                    canidatepaths.append(qtlib)
626
                qtdir = os.getenv("QTDIR")
627
                if qtdir != None:
628
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
629
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
630
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
631
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
632
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
633
                canidatepaths.append("/opt/qt/"+get_libdir_name())
634
                canidatepaths.append("/opt/qt/lib/"+get_libdir_name())
635
                canidatepaths.append("/opt/qt3/lib/"+get_libdir_name())
636
                self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths)
637
            if self.qt_lib_dir is None:
638
                raise SystemExit, "Failed to find Qt library files"
639
            self.announce("Using %s for Qt library files" % self.qt_lib_dir)
640
641
            # Python dir
642
            if self.python_dir is None:
643
                self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[0]
644
            self.announce("Using %s for the python directory" % self.python_dir)
645
646
            # Python include dir.
647
            if self.python_inc_dir is None:
648
                # Find the Python include directory.
649
                self.python_inc_dir = sysconfig.get_config_var("INCLUDEPY")
650
            self.announce("Using %s for Python header files" % self.python_inc_dir)
651
652
            # PyQt dir
653
            if self.pyqt_dir is None:
654
                self.pyqt_dir = m_pyqt_dir
655
            if self.pyqt_dir is None:
656
                self.pyqt_dir = os.path.join(sysconfig.get_python_lib(), 'python_tqt')
657
            if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None):
658
                raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir
659
            self.announce("Using %s for PyQt modules" % self.pyqt_dir)
660
661
            # PyTDE dir
662
            if self.pytde_dir is None:
663
                self.pytde_dir = sysconfig.get_python_lib()
664
            if (FindFileInPaths("libtdecorecmodule*",[self.pytde_dir]) is None) and (FindFileInPaths("tdecore*",[self.pytde_dir]) is None):
665
                raise SystemExit, "Failed to find the PyTDE directory: %s" % self.pytde_dir
666
            self.announce("Using %s for PyTDE modules" % self.pytde_dir)
667
668
            # Sip dir
669
            if self.sip_dir is None:
670
                self.sip_dir = m_sip_dir
671
            if self.sip_dir is None:
672
                self.sip_dir = os.path.join(sysconfig.get_python_lib(), 'sip4_tqt')
673
            if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None):
674
                raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir
675
            self.announce("Using %s for libsip files" % self.sip_dir)
676
677
            # Find the C library (libgcc, libgcc_s or some other variation).
678
            if self.clib is None:
679
                canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name(), "/usr/lib" ]
680
                self.clib = FindFileInPaths("libgcc*.so",canidatepaths)
681
                if self.clib!=None:
682
                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
683
                else:
684
                    self.clib = FindFileInPaths("libgcc*.a",canidatepaths)
685
                    if self.clib!=None:
686
                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0]
687
            if self.clib is None:
688
                raise SystemExit, "tdedistutils.py (1): Failed to find a suitable libgcc library"
689
            self.announce("Using %s for clib" % self.clib)
690
691
            # Make a list of places to look for python .so modules
692
            self.python_sub_dirs = sysconfig.get_config_var("LIBSUBDIRS").split()
693
            base = sysconfig.get_config_var("LIBP")
694
            self.python_sub_dirs = [ os.path.join(base,item) for item in self.python_sub_dirs ]
695
            self.python_sub_dirs.append(base)
696
697
    def get_command_name(self):
698
        return 'build_kcm'
699
700
    def run(self):
701
        if self.no_kcontrol:
702
            self.announce("Skipping KControl modules")
703
            return
704
705
        if not os.path.isdir(self.build_dir):
706
            os.mkdir(self.build_dir)
707
708
        for moduletuple in self.distribution.kcontrol_modules:
709
            self.announce("Building KControl module from desktop file %s." % moduletuple[0])
710
711
            # Read the desktop file
712
            factoryfunction = None
713
            libraryname = None
714
            cmodulecategory = None
715
            try:
716
                fhandle = open(moduletuple[0],'r')
717
                for line in fhandle.readlines():
718
                    parts = line.strip().split('=')
719
                    try:
720
                        if parts[0]=="X-TDE-Library":
721
                            libraryname = parts[1]
722
                        elif parts[0]=="Exec":
723
                            shellcmd = parts[1].split()
724
                            modulepath = shellcmd[-1]
725
                            if '/' in modulepath:
726
                                cmodulecategory = os.path.dirname(modulepath)
727
                            else:
728
                                cmodulecategory = ""
729
                        elif parts[0]=="X-TDE-FactoryName":
730
                            factoryfunction = 'create_'+parts[1]
731
                    except IndexError:
732
                        pass
733
                fhandle.close()
734
            except IOError:
735
                raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0]
736
737
            # Sanity check.
738
            if factoryfunction is None:
739
                raise SystemExit, "Failed to find factory name (Was there a X-TDE-FactoryName entry in the desktop file?)"
740
            if libraryname is None:
741
                raise SystemExit, "Failed to find library name (Was there a X-TDE-Library entry in the desktop file?)"
742
            if cmodulecategory is None:
743
                raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)"
744
745
            modulename = os.path.basename(moduletuple[1])
746
            if modulename.endswith('.py'):
747
                modulename = modulename[:-3]
748
            desktopfilename = moduletuple[0]
749
750
            stub_cpp_name = 'kcm_'+libraryname+'.cpp'
751
            stub_so_name = 'kcm_'+libraryname+'.so'
752
            stub_la_name = 'kcm_'+libraryname+'.la'
753
            python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1])
754
755
            # Build the 'stub' code.
756
            cppcode = self.cpptemplate % {"moduledir": self.data_dir,
757
                                            "extramodule": os.getenv("EXTRA_MODULE_DIR"),
758
                                            "modulename": modulename,
759
                                            "factoryfunction": factoryfunction,
760
                                            "python_version": python_version}
761
762
            # Put it on disk.
763
            cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name)
764
            try:
765
                fhandle = open(cppfile,'w')
766
                fhandle.write(cppcode)
767
                fhandle.close()
768
            except IOError:
769
                raise SystemExit, "Could not write the C++ stub: %s" % cppfile
770
771
            # Compile the stub library.
772
            cmdlist = ['libtool']
773
774
            # Couldn't get it to pass without this ...
775
            cmdlist.append("--mode=compile")
776
            cmdlist.append("--tag=CXX")
777
778
            # Find the compiler flags and options
779
            # CXX is empty on some Systems, let's do it 'the hard way'.
780
            # FIXME :: get CXX from make.conf for Gentoo.
781
            if len(sysconfig.get_config_var("CXX").split()) >= 2:
782
                cmdlist.extend(sysconfig.get_config_var("CXX").split())
783
            else:
784
                cmdlist.extend(['g++', '-pthread'])
785
786
            #cmdlist.extend(sysconfig.get_config_var("CXX").split())
787
788
            # cc_flags
789
            cmdlist.append("-c")
790
            cmdlist.append("-g")
791
792
            # The 4 is randomly chosen!
793
            # FIXME :: get CFLAGS from make.conf for Gentoo.
794
            if len(sysconfig.get_config_var("CFLAGS").split()) >=4:
795
                cmdlist.extend(sysconfig.get_config_var("CFLAGS").split())
796
            else:
797
                # On Gentoo systems, CFLAGS are not in the environment.
798
                raw = os.popen('emerge info 2> /dev/null|grep CFLAGS')
799
                lines = raw.readlines()
800
                if len(lines):
801
                    cflags = lines[0].split('"')[1].split()
802
                    print "Got CFLAGS from emerge info."
803
                    cmdlist.extend(cflags)
804
                else:
805
                    # Still no CFLAGS found, use these ...
806
                    cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes'])
807
808
            #sysconfig.get_config_var("CFLAGS").split()
809
            # includes
810
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
811
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
812
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEPY"))
813
            cmdlist.append("-I" + self.python_inc_dir)
814
            cmdlist.append("-I" + self.kde_inc_dir)
815
            cmdlist.append("-I" + self.kde_inc_dir + "/tde")
816
            cmdlist.append("-I" + self.qt_inc_dir)
817
            cmdlist.append("-I/usr/include/tqt")
818
            cmdlist.append("-I.")
819
            # input
820
            cmdlist.append(cppfile)
821
            # output
822
            outputfile = os.path.join(self.build_dir,libraryname+'.lo')
823
            cmdlist.append("-o")
824
            cmdlist.append(outputfile)
825
            spawn(cmdlist) # Execute!!!
826
            print
827
828
            # Link the resulting object file to create a shared library.
829
            cmdlist = ['libtool']
830
            cmdlist.append("--mode=link")
831
            cmdlist.append("--tag=LD")
832
833
            # Grab the linker command name
834
            cmdlist.append(sysconfig.get_config_var("LDSHARED").split()[0])
835
            # link_flags
836
            cmdlist.append("-module")
837
            cmdlist.append("-avoid-version")
838
            cmdlist.append("-shared")
839
            cmdlist.append("-export-dynamic")
840
            # object
841
            cmdlist.append(outputfile)
842
            cmdlist.append("-rpath"); cmdlist.append(self.kde_kcm_lib_dir)
843
            cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name))
844
            # Link libs
845
            linklist = []
846
            linklist.append("-lpython%s" % python_version)
847
            linklist.extend(sysconfig.get_config_var("LIBS").split())
848
849
            # FIXME I doubt half of these libraries need to be here.
850
            linklist.append(self.sip_dir+"/sip.so")
851
            # PyQt libs
852
            linklist.append(self.pyqt_dir+"/qt.so")
853
            # PyTDE libs
854
            linklist.append(self.pytde_dir+"/tdecore.so")
855
            linklist.append(self.pytde_dir+"/tdeui.so")
856
857
#            linklist.append("-L"+self.sip_dir); linklist.append("-lsip")
858
#            # PyQt libs
859
#            linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule")
860
#            # PyTDE libs
861
#            linklist.append("-L"+self.pytde_dir); linklist.append("-ltdecorecmodule"); linklist.append("-ltdeuicmodule")
862
863
            linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/trinity/lib"); linklist.append("-ltdecore"); linklist.append("-lpythonize")
864
            linklist.append("-L"+self.qt_lib_dir); linklist.append("-ltqt-mt")
865
            linklist.append("-lm")
866
            linklist.append("-lc")
867
            linklist.append(self.clib)
868
869
            linklist.append("-R"); linklist.append(self.python_dir)
870
            linklist.append("-R"); linklist.append(self.qt_lib_dir)
871
            linklist.append("-R"); linklist.append(self.sip_dir)
872
            linklist.append("-R"); linklist.append(self.pyqt_dir)
873
            linklist.append("-R"); linklist.append(self.pytde_dir)
874
            linklist.append("-R"); linklist.append(self.kde_lib_dir)
875
876
            cmdlist.extend(linklist)
877
            spawn(cmdlist) # Execute!!
878
            print
879
880
    cpptemplate = r"""
881
/*
882
 * pykcm_launcher.cpp
883
 *
884
 * Launch Control Centre modules written in Python using an embedded Python
885
 * interpreter.
886
 * Based on David Boddie's PyTDE-components.
887
 */
888
889
// pythonize.h must be included first.
890
#include <pythonize.h>
891
#include <tdecmodule.h>
892
#include <tdeglobal.h>
893
#include <tdelocale.h>
894
#include <klibloader.h>
895
#include <kstandarddirs.h>
896
#include <ksimpleconfig.h>
897
#include <tqstring.h>
898
#include <sip.h>
899
900
#define MODULE_DIR "%(moduledir)s"
901
#define EXTRA_MODULE_DIR "%(extramodule)s"
902
#define MODULE_NAME "%(modulename)s"
903
#define FACTORY "%(factoryfunction)s"
904
#define CPP_FACTORY %(factoryfunction)s
905
#define LIB_PYTHON "libpython%(python_version)s.so"
906
#define debug 1
907
908
static TDECModule *report_error(char *msg) {
909
    if (debug) printf ("error: %%s\n", msg);
910
    return NULL;
911
}
912
913
static TDECModule* return_instance( TQWidget *parent, const char *name ) {
914
    TDECModule* tdecmodule;
915
    PyObject *pyTDECModuleTuple;
916
    PyObject *pyTDECModule;
917
    Pythonize *pyize;  // Pythonize object to manage the Python interpreter.
918
    int isErr;
919
920
    // Try to determine what py script we're loading. Note that "name"
921
    // typically appears to be NULL.
922
    TQString script(MODULE_NAME);
923
924
    // Reload libpython, but this time tell the runtime linker to make the
925
    // symbols global and available for later loaded libraries/module.
926
    KLibLoader::self()->globalLibrary(LIB_PYTHON);
927
928
    // Start the interpreter.
929
    pyize = initialize();
930
    if (!pyize) {
931
        return report_error ("***Failed to start interpreter\n");
932
    }
933
934
    // Add the path to the python script to the interpreter search path.
935
    TQString path = TQString(MODULE_DIR);
936
    if(path == TQString::null) {
937
        return report_error ("***Failed to locate script path");
938
    }
939
    if(!pyize->appendToSysPath (path.latin1 ())) {
940
        return report_error ("***Failed to set sys.path\n");
941
    }
942
943
    // Add the extra path to the python script to the interpreter search path.
944
    TQString extrapath = TQString(EXTRA_MODULE_DIR);
945
    if(!pyize->appendToSysPath (extrapath.latin1 ())) {
946
      return report_error ("***Failed to set extra sys.path\n");
947
    }
948
949
    // Load the Python script.
950
    PyObject *pyModule = pyize->importModule ((char *)script.latin1 ());
951
    if(!pyModule) {
952
        PyErr_Print();
953
        return report_error ("***failed to import module\n");
954
    }
955
956
    // Inject a helper function
957
    TQString bridge = TQString("from sip4_tqt import sip\n"
958
                            "from python_tqt import qt\n"
959
                            "def kcontrol_bridge_" FACTORY "(parent,name):\n"
960
                             "    if parent!=0:\n"
961
#if SIP_VERSION >= 0x040200
962
                             "        wparent = sip.wrapinstance(parent,qt.TQWidget)\n"
963
#else
964
                             "        wparent = sip.wrapinstance(parent,'TQWidget')\n"
965
#endif
966
                             "    else:\n"
967
                             "        wparent = None\n"
968
                             "    inst = " FACTORY "(wparent, name)\n"
969
                             "    return (inst,sip.unwrapinstance(inst))\n");
970
    PyRun_String(bridge.latin1(),Py_file_input,PyModule_GetDict(pyModule),PyModule_GetDict(pyModule));
971
972
    // Get the Python module's factory function.
973
    PyObject *kcmFactory = pyize->getNewObjectRef(pyModule, "kcontrol_bridge_" FACTORY);
974
    if(!kcmFactory) {
975
        return report_error ("***failed to find module factory\n");
976
    }
977
978
    // Call the factory function. Set up the args.
979
    PyObject *pyParent = PyLong_FromVoidPtr(parent);
980
    PyObject *pyName = PyString_FromString(MODULE_NAME);
981
        // Using NN here is effect gives our references to the arguement away.
982
    PyObject *args = Py_BuildValue ("NN", pyParent, pyName);
983
    if(pyName && pyParent && args) {
984
        // run the factory function
985
        pyTDECModuleTuple = pyize->runFunction(kcmFactory, args);
986
        if(!pyTDECModuleTuple) {
987
            PyErr_Print();
988
            return report_error ("*** runFunction failure\n;");
989
        }
990
    } else {
991
        return report_error ("***failed to create args\n");
992
    }
993
    // cleanup a bit
994
    pyize->decref(args);
995
    pyize->decref(kcmFactory);
996
997
    // Stop this from getting garbage collected.
998
    Py_INCREF(PyTuple_GET_ITEM(pyTDECModuleTuple,0));
999
1000
    // convert the TDECModule PyObject to a real C++ TDECModule *.
1001
    isErr = 0;
1002
    pyTDECModule = PyTuple_GET_ITEM(pyTDECModuleTuple,1);
1003
    tdecmodule = (TDECModule *)PyLong_AsVoidPtr(pyTDECModule);
1004
    if(!tdecmodule) {
1005
        return report_error ("***failed sip conversion to C++ pointer\n");
1006
    }
1007
    pyize->decref(pyTDECModuleTuple);
1008
1009
    // PyTDE can't run the module without this - Pythonize
1010
    // grabs the lock at initialization and we have to give
1011
    // it back before exiting. At this point, we no longer need
1012
    // it.
1013
    //pyize->releaseLock ();
1014
1015
    // take care of any translation info
1016
    TDEGlobal::locale()->insertCatalogue(script);
1017
1018
    // Return the pointer to our new TDECModule
1019
    return tdecmodule;
1020
}
1021
1022
extern "C" {
1023
    // Factory function that kcontrol will call.
1024
    TDECModule* CPP_FACTORY(TQWidget *parent, const char *name) {
1025
        return return_instance(parent, name);
1026
    }
1027
}
1028
"""
1029
1030
###########################################################################
1031
class InstallKControlModule(Command):
1032
    description = "Install Kcontrol module files"
1033
1034
    user_options = [
1035
        ('install-dir=', 'd', "base directory for installing kcontrol module files"),
1036
        ('install-cmd=', None, "Command to use to install the files"),
1037
        ('xdg-apps-dir=',None,"directory for XDG app files"),
1038
        ('build-dir=','b', "build directory (where to install from)"),
1039
        ('root=', None, "install everything relative to this alternate root directory"),
1040
        ('force', 'f', "force installation (overwrite existing files)"),
1041
        ('skip-build', None, "skip the build steps"),
1042
        ]
1043
    boolean_options = ['force', 'skip-build']
1044
1045
    def initialize_options(self):
1046
        self.build_dir = None
1047
        self.install_dir = None
1048
        self.install_cmd = None
1049
        self.xdg_apps_dir = None
1050
        self.outfiles = []
1051
        self.root = None
1052
        self.force = 0
1053
        self.warn_dir = 1
1054
        self.skip_build = None
1055
1056
    def finalize_options(self):
1057
        own_install_dir = self.install_dir is not None
1058
        own_xdg_apps_dir = self.xdg_apps_dir is not None
1059
1060
        self.set_undefined_options('install',
1061
                                    ('build_base', 'build_dir'),
1062
                                    ('install_kcm', 'install_dir'),
1063
                                    ('install_xdg_apps','xdg_apps_dir'),
1064
                                    ('root', 'root'),
1065
                                    ('force', 'force'),
1066
                                    ('skip_build', 'skip_build'),
1067
                                    ('install_cmd', 'install_cmd')
1068
                                    )
1069
1070
        if own_install_dir and self.root is not None:
1071
            self.install_dir = change_root(self.root,self.installdir)
1072
        if own_xdg_apps_dir and self.root is not None:
1073
            self.xdg_apps_dir = change_root(self.root,self.xdg_apps_dir)
1074
1075
    def get_command_name(self):
1076
        return 'install_kcm'
1077
1078
    def run(self):
1079
        if not self.skip_build:
1080
            self.run_command('build_kcm')
1081
1082
        self.announce("Installing Kcontrol module files...")
1083
1084
        for moduletuple in self.distribution.kcontrol_modules:
1085
            self.announce("Building KControl module from desktop file %s." % moduletuple[0])
1086
1087
            # Read the desktop file
1088
            libraryname = None
1089
            cmodulecategory = None
1090
            try:
1091
                fhandle = open(moduletuple[0],'r')
1092
                for line in fhandle.readlines():
1093
                    parts = line.strip().split('=')
1094
                    try:
1095
                        if parts[0]=="X-TDE-Library":
1096
                            libraryname = parts[1]
1097
                        elif parts[0]=="Exec":
1098
                            shellcmd = parts[1].split()
1099
                            modulepath = shellcmd[-1]
1100
                            if '/' in modulepath:
1101
                                cmodulecategory = os.path.dirname(modulepath)
1102
                            else:
1103
                                cmodulecategory = ""
1104
                    except IndexError:
1105
                        pass
1106
                fhandle.close()
1107
            except IOError:
1108
                raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0]
1109
1110
            if libraryname is None:
1111
                raise SystemExit, "Failed to find library name (Was there a X-TDE-Library entry in the desktop file?)"
1112
            if cmodulecategory is None:
1113
                raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)"
1114
1115
            desktopfilename = moduletuple[0]
1116
            self.outfiles.extend(self.mkpath(self.xdg_apps_dir))
1117
            desktopfile_dest = os.path.join(self.xdg_apps_dir,os.path.basename(desktopfilename))
1118
            self.copy_file(desktopfilename, desktopfile_dest)
1119
1120
            stub_la_name = 'kcm_'+libraryname+'.la'
1121
1122
            self.outfiles.extend(self.mkpath(self.install_dir))
1123
1124
            # Install the library.
1125
            cmdlist = ['libtool']
1126
            cmdlist.append("--mode=install")
1127
            cmdlist.append(self.install_cmd)
1128
            cmdlist.append("-c")
1129
            cmdlist.append(os.path.join(self.build_dir,stub_la_name))
1130
            cmdlist.append(os.path.join(self.install_dir,stub_la_name))
1131
            spawn(cmdlist) # Execute!!
1132
            print
1133
1134
            self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs','kcm_'+libraryname+'*'))]
1135
            self.outfiles.append(desktopfile_dest)
1136
1137
        self.announce("Done installing Kcontrol module files.")
1138
1139
    def get_outputs(self):
1140
        return self.outfiles or []
1141
1142
    def mkpath(self, name, mode=0777):
1143
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
1144
1145
###########################################################################
1146
class BuildDocbookHTML(Command):
1147
    description = "Build Docbook HTML documentation"
1148
1149
    user_options = [('meinproc-exe=',None,"Path to the meinproc executable")]
1150
1151
    def initialize_options(self):
1152
        self.html_prefix = None
1153
        self.meinproc_exe = None
1154
1155
    def finalize_options(self):
1156
        self.set_undefined_options('build', ('meinproc_exe', 'meinproc_exe') )
1157
1158
    def get_command_name(self):
1159
        return 'build_docbook'
1160
1161
    def run(self):
1162
        for docbook_tuple in self.distribution.docbooks:
1163
            input_dir = docbook_tuple[0]
1164
            language_code = docbook_tuple[1]
1165
1166
            self.announce("Building Docbook documentation from directory %s." % input_dir)
1167
1168
            indexdoc_file_name = os.path.join(input_dir,'index.docbook')
1169
            if not os.path.exists(indexdoc_file_name):
1170
                raise SystemExit, "File %s is missing." % indexdoc_file_name
1171
1172
            cwd = os.getcwd()
1173
            os.chdir(input_dir)
1174
            try:
1175
                spawn([self.meinproc_exe,"--check","--cache",'index.cache.bz2', 'index.docbook'])
1176
                spawn([self.meinproc_exe, 'index.docbook'])
1177
            finally:
1178
                os.chdir(cwd)
1179
1180
###########################################################################
1181
class InstallDocbookHTML(Command):
1182
    description = "Install Docbook HTML files"
1183
1184
    user_options = [
1185
        ('install-dir=', 'd',"base directory for installing docbook HTML files"),
1186
        ('root=', None, "install everything relative to this alternate root directory"),
1187
        ('force', 'f', "force installation (overwrite existing files)"),
1188
        ('skip-build', None, "skip the build steps"),
1189
        ]
1190
    boolean_options = ['force', 'skip-build']
1191
1192
    def initialize_options(self):
1193
        self.install_dir = None
1194
        self.outfiles = []
1195
        self.root = None
1196
        self.force = 0
1197
        self.warn_dir = 1
1198
        self.skip_build = None
1199
1200
    def finalize_options(self):
1201
        own_install_dir = self.install_dir is not None
1202
1203
        self.set_undefined_options('install',
1204
                                   ('install_html', 'install_dir'),
1205
                                   ('root', 'root'),
1206
                                   ('force', 'force'),
1207
                                   ('skip_build', 'skip_build'),
1208
                                  )
1209
1210
        if own_install_dir and self.root is not None:
1211
            self.install_dir = change_root(self.root,self.installdir)
1212
1213
    def get_command_name(self):
1214
        return 'install_html'
1215
1216
    def run(self):
1217
        if not self.skip_build:
1218
            self.run_command('build_html')
1219
1220
        self.announce("Installing HTML files...")
1221
        counter = 0
1222
        for docbook_tuple in self.distribution.docbooks:
1223
            input_dir = docbook_tuple[0]
1224
            language_code = docbook_tuple[1]
1225
1226
            self.announce("Install Docbook documentation from directory %s." % input_dir)
1227
            source_file = os.path.join(input_dir,'index.cache.bz2')
1228
            if not os.path.exists(source_file):
1229
                raise SystemExit, "File %s is missing." % source_file
1230
1231
            dest_path = os.path.join(self.install_dir, language_code, self.distribution.metadata.name)
1232
            self.outfiles.extend(self.mkpath(dest_path))
1233
            dest_file = os.path.join(dest_path,'index.cache.bz2')
1234
1235
            self.copy_file(source_file, dest_file)
1236
            self.outfiles.append(dest_file)
1237
            counter += 1
1238
1239
            # Also install any lose HTML files.
1240
            for source_file in glob.glob(os.path.join(input_dir,'*.html')):
1241
                htmlfile = os.path.basename(source_file)
1242
                dest_file = os.path.join(dest_path,htmlfile)
1243
                self.copy_file(source_file, dest_file)
1244
                self.outfiles.append(dest_file)
1245
                counter += 1
1246
1247
            if len(docbook_tuple)==3:
1248
                extra_files = docbook_tuple[2]
1249
                for file in extra_files:
1250
                    source_file = os.path.join(input_dir,file)
1251
                    dest_file = os.path.join(self.install_dir, language_code, self.distribution.metadata.name,file)
1252
                    self.copy_file(source_file, dest_file)
1253
                    self.outfiles.append(dest_file)
1254
                    counter += 1
1255
1256
        self.announce("Done installing %i HTML files." % counter)
1257
1258
    def get_outputs(self):
1259
        return self.outfiles or []
1260
1261
    def mkpath(self, name, mode=0777):
1262
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
1263
1264
###########################################################################
1265
class UpdateI18NMessages(Command):
1266
    description = "Extract and update messages for translation"
1267
1268
    user_options = [('xgettext-exe=',None,'Full path to the xgetext executable'),\
1269
                    ('kde-pot=',None,'Location of the the KDE pot file'),\
1270
                    ('msgmerge-exe=',None,'Full path to the msgmerge executable')]
1271
1272
    def initialize_options(self):
1273
        self.xgettext_exe = None
1274
        self.msgmerge_exe = None
1275
        self.kde_pot = None
1276
1277
    def finalize_options(self):
1278
        if self.xgettext_exe is None:
1279
            install = self.get_finalized_command('install')
1280
1281
            canidate_paths = []
1282
            if install.user_supplied_kde_prefix:
1283
                canidate_paths.append(os.path.join(install.kde_prefix,'bin'))
1284
1285
            self.announce("Detecting xgettext...")
1286
            canidate_paths.append(ask_kde_config('--install exe --expandvars').strip())
1287
            self.xgettext_exe = FindExeOnPath('xgettext',canidate_paths)
1288
            if self.xgettext_exe is None:
1289
                raise SystemExit, "Unable to find 'xgettext'."
1290
            self.announce("  ...xgettext found at %s" % self.xgettext_exe)
1291
1292
        if self.msgmerge_exe is None:
1293
            install = self.get_finalized_command('install')
1294
1295
            canidate_paths = []
1296
            if install.user_supplied_kde_prefix:
1297
                canidate_paths.append(os.path.join(install.kde_prefix,'bin'))
1298
1299
            self.announce("Detecting msgmerge...")
1300
            canidate_paths.append(ask_kde_config('--install exe --expandvars').strip())
1301
            self.msgmerge_exe = FindExeOnPath('msgmerge',canidate_paths)
1302
            if self.msgmerge_exe is None:
1303
                raise SystemExit, "Unable to find 'xgettext'."
1304
            self.announce("  ...msgmerge found at %s" % self.msgmerge_exe)
1305
1306
        if self.kde_pot is None:
1307
            self.announce("Detecting kde.pot...")
1308
            canidatepaths = []
1309
            tdedir = os.getenv("TDEDIR")
1310
            if tdedir!=None:
1311
                canidatepaths.append(os.path.join(tdedir,"include"))
1312
            install = self.get_finalized_command('install')
1313
            canidatepaths.append(os.path.join(install.kde_prefix,"include"))
1314
            canidatepaths.append('/opt/trinity/include')
1315
            canidatepaths.append('/opt/kde/include')
1316
            kde_pot_dir = FindFileInPaths('kde.pot',canidatepaths)
1317
1318
            if kde_pot_dir is None:
1319
                raise SystemExit, "Failed to find the kde.pot file."
1320
1321
            self.kde_pot = os.path.join(kde_pot_dir,'kde.pot')
1322
            self.announce("   ...kde.pot found at %s" % self.kde_pot)
1323
1324
    def get_command_name(self):
1325
        return 'update_messages'
1326
1327
    def run(self):
1328
        if self.distribution.i18n is None: return
1329
1330
        self.announce("Extracting and merging i18n messages...")
1331
        po_dir = self.distribution.i18n[0]
1332
1333
        # FIXME : .rc and .ui files
1334
        input_files = []
1335
1336
        # Compile any UI files
1337
        for dir in self.distribution.i18n[1]:
1338
            for file in glob.glob(os.path.join(dir,'*.ui')):
1339
                qtuicompiler.UpdateUI(file,kde=True)
1340
1341
        # Fetch all of the python files.
1342
        for dir in self.distribution.i18n[1]:
1343
            input_files.extend(glob.glob(os.path.join(dir,'*.py')))
1344
1345
        target_pot = os.path.join(po_dir,self.distribution.metadata.name+".pot")
1346
1347
        cmd = [self.xgettext_exe, '-o', target_pot, '-ki18n', '-ktr2i18n', \
1348
                '-kI18N_NOOP', '-ktranslate', '-kaliasLocale','-x',self.kde_pot]
1349
        cmd.extend(input_files)
1350
        spawn(cmd)
1351
1352
        for po_file in glob.glob(os.path.join(po_dir,'*.po')):
1353
            temp_po = po_file + '.temp'
1354
            cmd = [self.msgmerge_exe,'-q','-o',temp_po,po_file,target_pot]
1355
            spawn(cmd)
1356
            os.rename(temp_po,po_file)
1357
1358
        self.announce("Finished with i18n messages.")
1359
1360
###########################################################################
1361
class BuildI18NMessages(Command):
1362
    description = "Build i18n messages"
1363
1364
    user_options = [('msgfmt-exe=',None,'Path to the msgfmt executable')]
1365
1366
    def initialize_options(self):
1367
        self.msgfmt_exe = None
1368
1369
    def finalize_options(self):
1370
        self.set_undefined_options('build', ('msgfmt_exe', 'msgfmt_exe'))
1371
1372
    def get_command_name(self):
1373
        return 'build_messages'
1374
1375
    def run(self):
1376
        if self.distribution.i18n is None: return
1377
1378
        self.announce("Building i18n messages...")
1379
        po_dir = self.distribution.i18n[0]
1380
1381
        i = 0
1382
        for po_file in [file for file in os.listdir(po_dir) if file.endswith('.po')]:
1383
            source = os.path.join(po_dir,po_file)
1384
            target = source[:-3]+'.gmo'
1385
            cmd = [self.msgfmt_exe,'-o',target, source]
1386
            spawn(cmd)
1387
            i += 1
1388
        self.announce("Done building %i i18n messages." % i)
1389
1390
###########################################################################
1391
class InstallI18NMessages(Command):
1392
    description = "Install messages"
1393
1394
    user_options = [
1395
        ('install-dir=', 'd',"base directory for installing message files (default: installation base dir)"),
1396
        ('root=', None, "install everything relative to this alternate root directory"),
1397
        ('force', 'f', "force installation (overwrite existing files)"),
1398
        ('skip-build', None, "skip the build steps"),
1399
        ]
1400
1401
    boolean_options = ['force', 'skip-build']
1402
1403
    def initialize_options(self):
1404
        self.install_dir = None
1405
        self.outfiles = []
1406
        self.root = None
1407
        self.force = 0
1408
        self.warn_dir = 1
1409
        self.skip_build = None
1410
1411
    def finalize_options(self):
1412
        own_install_dir = self.install_dir is not None
1413
1414
        self.set_undefined_options('install',
1415
                                   ('install_messages', 'install_dir'),
1416
                                   ('root', 'root'),
1417
                                   ('force', 'force'),
1418
                                   ('skip_build', 'skip_build'),
1419
                                  )
1420
1421
        if own_install_dir and self.root is not None:
1422
            self.install_dir = change_root(self.root,self.installdir)
1423
1424
    def get_command_name(self):
1425
        return 'install_messages'
1426
1427
    def run(self):
1428
        if not self.skip_build:
1429
            self.run_command('build_messages')
1430
1431
        self.announce("Installing i18n messages...")
1432
        po_dir = self.distribution.i18n[0]
1433
1434
        counter = 0
1435
        for po_file in os.listdir(po_dir):
1436
            if po_file.endswith('.po'):
1437
                source_file = os.path.join(po_dir,po_file[:-3]) + '.gmo'
1438
1439
                # Setup installation of the translation file.
1440
                dest_path = os.path.join(self.install_dir, po_file[:-3],'LC_MESSAGES')
1441
                self.outfiles.extend(self.mkpath(dest_path))
1442
                dest_file = os.path.join(dest_path, self.distribution.metadata.name+'.mo')
1443
1444
                self.copy_file(source_file, dest_file)
1445
                self.outfiles.append(dest_file)
1446
                counter += 1
1447
        self.announce("Done installing %i i18n messages." % counter)
1448
1449
    def get_outputs(self):
1450
        return self.outfiles
1451
1452
    def mkpath(self, name, mode=0777):
1453
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
1454
1455
1456
###########################################################################
1457
class BuildTdeioslave(Command):
1458
    description = "Build Tdeioslaves"
1459
1460
    user_options = [('no-tdeioslave',None,"Don't build tdeioslaves"),
1461
                    ('build-dir=','b', "build directory (where to install from)"),
1462
                    ('python-dir=',None,'Directory containing the Python installation'),
1463
                    ('python-inc-dir=',None,'Directory containing C Header files for Python'),
1464
                    ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'),
1465
                    ('kde-lib-dir=',None,'Directory containing library files for KDE'),
1466
                    ('kde-tdeioslave-lib-dir=',None,'Directory for KDE tdeioslave library files'),
1467
                    ('kde-protocol-dir=',None,'Directory for KDE tdeioslave protocol files'),
1468
                    ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'),
1469
                    ('qt-lib-dir=',None,'Directory containing library files for Qt'),
1470
                    ('sip-dir=','/usr/lib/pyshared/python*','Directory containing the sip library files'),
1471
                    ('clib=',None,'gcc library and path'),
1472
                    ('pyqt-dir=','/usr/lib/pyshared/python*','PyQt module directory'),
1473
                    ('pytde-dir=',None,'PyTDE module directory'),
1474
                    ('data-dir=',None,'installation directory for data (script) files')]
1475
1476
    def initialize_options(self):
1477
        self.no_tdeioslave = 0
1478
        self.build_dir = None
1479
        self.python_inc_dir = None
1480
        self.python_dir = None
1481
        self.kde_inc_dir = None
1482
        self.kde_lib_dir = None
1483
        self.kde_tdeioslave_lib_dir = None
1484
        self.kde_protocol_dir = None
1485
        self.qt_inc_dir = None
1486
        self.qt_lib_dir = None
1487
        self.sip_dir = None
1488
        self.clib = None
1489
        self.pyqt_dir = None
1490
        self.pytde_dir = None
1491
        self.data_dir = None
1492
1493
    def finalize_options(self):
1494
        if self.no_tdeioslave==0:
1495
            self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir'))
1496
1497
            install = self.get_finalized_command('install')
1498
            self.install_prefix = ask_kde_config('--prefix').strip()
1499
1500
            # KDE inc dir: find it!
1501
            if self.kde_inc_dir is None:
1502
                canidatepaths = []
1503
                tdedir = os.getenv("TDEDIR")
1504
                if tdedir!=None:
1505
                    canidatepaths.append(os.path.join(tdedir,"include"))
1506
                canidatepaths.append(os.path.join(install.prefix,"include"))
1507
                canidatepaths.append(os.path.join(self.install_prefix,'include'))
1508
                canidatepaths.append(os.path.join(self.install_prefix,'include','tde'))
1509
                self.kde_inc_dir = FindFileInPaths('tdeapplication.h',canidatepaths)
1510
            if self.kde_inc_dir is None:
1511
                raise SystemExit, "Failed to find the KDE header file directory."
1512
            if FindFileInPaths('tdeapplication.h',[self.kde_inc_dir]) is None:
1513
                raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir
1514
            self.announce("Using %s for KDE header files" % self.kde_inc_dir)
1515
1516
            # KDE lib dir
1517
            if self.kde_lib_dir is None:
1518
                self.kde_lib_dir = os.path.join(self.install_prefix,"lib")
1519
            self.announce("Using %s for KDE library files" % self.kde_lib_dir)
1520
1521
            # KDE tdeioslave lib dir
1522
            if self.kde_tdeioslave_lib_dir is None:
1523
                self.kde_tdeioslave_lib_dir = os.path.join(self.kde_lib_dir,"trinity")
1524
            if FindFileInPaths('tdeio_*.so',[self.kde_tdeioslave_lib_dir]) is None:
1525
                raise SystemExit, "Failed to find KDE Tdeioslave library files in: %s" % self.kde_tdeioslave_lib_dir
1526
            self.announce("Using %s for KDE Tdeioslave library files" % self.kde_tdeioslave_lib_dir)
1527
1528
            # Qt inc dir
1529
            if self.qt_inc_dir is None:
1530
                canidatepaths = []
1531
                qtinc = os.getenv("QTINC")
1532
                if qtinc != None:
1533
                    canidatepaths.append(qtinc)
1534
                qtdir = os.getenv("QTDIR")
1535
                if qtdir != None:
1536
                    canidatepaths.append(os.path.join(qtdir,"include"))
1537
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/include"))
1538
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
1539
                canidatepaths.append(os.path.join(install.prefix,"include"))
1540
                canidatepaths.append("/opt/tqt3/include")
1541
                canidatepaths.append("/opt/qt/include")
1542
                canidatepaths.append("/opt/qt/lib/include")
1543
                canidatepaths.append("/opt/qt3/lib/include")
1544
                self.qt_inc_dir = FindFileInPaths('ntqstring.h',canidatepaths)
1545
            if self.qt_inc_dir is None:
1546
                self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths)
1547
            if self.qt_inc_dir is None:
1548
                raise SystemExit,"Failed to find the Qt header file directory"
1549
            if FindFileInPaths('ntqstring.h',[self.qt_inc_dir]) is None:
1550
                if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None:
1551
                    raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir
1552
            self.announce("Using %s for Qt header files" % self.qt_inc_dir)
1553
1554
            # Qt lib dir
1555
            if self.qt_lib_dir is None:
1556
                canidatepaths = []
1557
                qtlib = os.getenv("TQTLIB")
1558
                if qtlib != None:
1559
                    canidatepaths.append(qtlib)
1560
                qtdir = os.getenv("TQTDIR")
1561
                if qtdir != None:
1562
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
1563
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
1564
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
1565
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
1566
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
1567
                canidatepaths.append("/opt/tqt/"+get_libdir_name())
1568
                canidatepaths.append("/opt/tqt/lib/"+get_libdir_name())
1569
                canidatepaths.append("/opt/tqt3/lib/"+get_libdir_name())
1570
                self.qt_lib_dir = FindFileInPaths('libtqt*',canidatepaths)
1571
            if self.qt_lib_dir is None:
1572
                canidatepaths = []
1573
                qtlib = os.getenv("QTLIB")
1574
                if qtlib != None:
1575
                    canidatepaths.append(qtlib)
1576
                qtdir = os.getenv("QTDIR")
1577
                if qtdir != None:
1578
                    canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
1579
                canidatepaths.append(os.path.join(install.prefix,"lib/tqt3/"+get_libdir_name()))
1580
                canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
1581
                canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
1582
                canidatepaths.append("/opt/tqt3/"+get_libdir_name())
1583
                canidatepaths.append("/opt/qt/"+get_libdir_name())
1584
                canidatepaths.append("/opt/qt/lib/"+get_libdir_name())
1585
                canidatepaths.append("/opt/qt3/lib/"+get_libdir_name())
1586
                self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths)
1587
            if self.qt_lib_dir is None:
1588
                raise SystemExit, "Failed to find Qt library files"
1589
            self.announce("Using %s for Qt library files" % self.qt_lib_dir)
1590
1591
            # Python dir
1592
            if self.python_dir is None:
1593
                self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[0]
1594
            self.announce("Using %s for the python directory" % self.python_dir)
1595
1596
            # Python include dir.
1597
            if self.python_inc_dir is None:
1598
                # Find the Python include directory.
1599
                self.python_inc_dir = sysconfig.get_config_var("INCLUDEPY")
1600
            self.announce("Using %s for Python header files" % self.python_inc_dir)
1601
1602
            # PyQt dir
1603
            if self.pyqt_dir is None:
1604
                self.pyqt_dir = m_pyqt_dir
1605
            if self.pyqt_dir is None:
1606
                self.pyqt_dir = os.path.join(sysconfig.get_python_lib(), 'python_tqt')
1607
            if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None):
1608
                raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir
1609
            self.announce("Using %s for PyQt modules" % self.pyqt_dir)
1610
1611
            # PyTDE dir
1612
            if self.pytde_dir is None:
1613
                self.pytde_dir = sysconfig.get_python_lib()
1614
            if (FindFileInPaths("libtdecorecmodule*",[self.pytde_dir]) is None) and (FindFileInPaths("tdecore*",[self.pytde_dir]) is None):
1615
                raise SystemExit, "Failed to find the PyTDE directory: %s" % self.pytde_dir
1616
            self.announce("Using %s for PyTDE modules" % self.pytde_dir)
1617
1618
            # Sip dir
1619
            if self.sip_dir is None:
1620
                self.sip_dir = m_sip_dir
1621
            if self.sip_dir is None:
1622
                self.sip_dir = os.path.join(sysconfig.get_python_lib(), 'sip4_tqt')
1623
            if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None):
1624
                raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir
1625
            self.announce("Using %s for libsip files" % self.sip_dir)
1626
1627
            # Find the C library (libgcc, libgcc_s or some other variation).
1628
            if self.clib is None:
1629
                canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name() ]
1630
                self.clib = FindFileInPaths("libgcc*.so",canidatepaths)
1631
                if self.clib!=None:
1632
                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
1633
                else:
1634
                    self.clib = FindFileInPaths("libgcc*.a",canidatepaths)
1635
                    if self.clib!=None:
1636
                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0]
1637
            if self.clib is None:
1638
                raise SystemExit, "tdedistutils.py (2): Failed to find a suitable libgcc library"
1639
            self.announce("Using %s for clib" % self.clib)
1640
1641
            # Make a list of places to look for python .so modules
1642
            self.python_sub_dirs = sysconfig.get_config_var("LIBSUBDIRS").split()
1643
            base = sysconfig.get_config_var("LIBP")
1644
            self.python_sub_dirs = [ os.path.join(base,item) for item in self.python_sub_dirs ]
1645
            self.python_sub_dirs.append(base)
1646
1647
    def get_command_name(self):
1648
        return 'build_tdeioslave'
1649
1650
    def run(self):
1651
        if self.no_tdeioslave:
1652
            self.announce("Skipping TDEIO Slaves")
1653
            return
1654
1655
        if not os.path.isdir(self.build_dir):
1656
            os.mkdir(self.build_dir)
1657
1658
        for moduletuple in self.distribution.tdeioslaves:
1659
            self.announce("Building TDEIO Slave from protocol file %s." % moduletuple[0])
1660
1661
            protocolfilename = moduletuple[0]
1662
1663
            # Read the protocol file
1664
            libraryname = None
1665
            try:
1666
                fhandle = open(protocolfilename,'r')
1667
                for line in fhandle.readlines():
1668
                    parts = line.strip().split('=')
1669
                    try:
1670
                        if parts[0]=="exec":
1671
                            libraryname = parts[1]
1672
                    except IndexError:
1673
                        pass
1674
                fhandle.close()
1675
            except IOError:
1676
                raise SystemExit, "Failed to find tdeioslave protocol file: %s" % moduletuple[0]
1677
1678
            # Sanity check.
1679
            if libraryname is None:
1680
                raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)"
1681
1682
            modulename = os.path.basename(moduletuple[1])
1683
            if modulename.endswith('.py'):
1684
                modulename = modulename[:-3]
1685
1686
            stub_cpp_name = libraryname+'.cpp'
1687
            stub_so_name = libraryname+'.so'
1688
            stub_la_name = libraryname+'.la'
1689
            python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1])
1690
1691
            # Build the 'stub' code.
1692
            cppcode = self.cpptemplate % {"moduledir": self.data_dir,
1693
                                            "modulename": modulename,
1694
                                            "python_version": python_version}
1695
1696
            # Put it on disk.
1697
            cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name)
1698
            try:
1699
                fhandle = open(cppfile,'w')
1700
                fhandle.write(cppcode)
1701
                fhandle.close()
1702
            except IOError:
1703
                raise SystemExit, "Could not write the C++ stub: %s" % cppfile
1704
1705
            # Compile the stub library.
1706
            cmdlist = ['libtool']
1707
1708
            # Couldn't get it to pass without this ...
1709
            cmdlist.append("--mode=compile")
1710
            cmdlist.append("--tag=CXX")
1711
1712
            # Find the compiler flags and options
1713
            # CXX is empty on some Systems, let's do it 'the hard way'.
1714
            # FIXME :: get CXX from make.conf for Gentoo.
1715
            if len(sysconfig.get_config_var("CXX").split()) >= 2:
1716
                cmdlist.extend(sysconfig.get_config_var("CXX").split())
1717
            else:
1718
                cmdlist.extend(['g++', '-pthread'])
1719
1720
            #cmdlist.extend(sysconfig.get_config_var("CXX").split())
1721
1722
            # cc_flags
1723
            cmdlist.append("-c")
1724
            cmdlist.append("-g")
1725
1726
            # The 4 is randomly chosen!
1727
            # FIXME :: get CFLAGS from make.conf for Gentoo.
1728
            if len(sysconfig.get_config_var("CFLAGS").split()) >=4:
1729
                cmdlist.extend(sysconfig.get_config_var("CFLAGS").split())
1730
            else:
1731
                # On Gentoo systems, CFLAGS are not in the environment.
1732
                raw = os.popen('emerge info 2> /dev/null|grep CFLAGS')
1733
                lines = raw.readlines()
1734
                if len(lines):
1735
                    cflags = lines[0].split('"')[1].split()
1736
                    print "Got CFLAGS from emerge info."
1737
                    cmdlist.extend(cflags)
1738
                else:
1739
                    # Still no CFLAGS found, use these ...
1740
                    cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes'])
1741
1742
            #sysconfig.get_config_var("CFLAGS").split()
1743
            # includes
1744
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
1745
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
1746
            cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEPY"))
1747
            cmdlist.append("-I" + self.python_inc_dir)
1748
            cmdlist.append("-I" + self.kde_inc_dir)
1749
            cmdlist.append("-I" + self.kde_inc_dir + "/tde")
1750
            cmdlist.append("-I" + self.qt_inc_dir)
1751
            cmdlist.append("-I/usr/include/tqt")
1752
            cmdlist.append("-I.")
1753
            # input
1754
            cmdlist.append(cppfile)
1755
            # output
1756
            outputfile = os.path.join(self.build_dir,libraryname+'.lo')
1757
            cmdlist.append("-o")
1758
            cmdlist.append(outputfile)
1759
            spawn(cmdlist) # Execute!!!
1760
            print
1761
1762
            # Link the resulting object file to create a shared library.
1763
            cmdlist = ['libtool']
1764
            cmdlist.append("--mode=link")
1765
            cmdlist.append("--tag=LD")
1766
1767
            # Grab the linker command name
1768
            cmdlist.append(sysconfig.get_config_var("LDSHARED").split()[0])
1769
            # link_flags
1770
            cmdlist.append("-module")
1771
            cmdlist.append("-avoid-version")
1772
            cmdlist.append("-shared")
1773
            cmdlist.append("-export-dynamic")
1774
            # object
1775
            cmdlist.append(outputfile)
1776
            cmdlist.append("-rpath"); cmdlist.append(self.kde_tdeioslave_lib_dir)
1777
            cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name))
1778
            # Link libs
1779
            linklist = []
1780
            linklist.append("-lpython%s" % python_version)
1781
            linklist.extend(sysconfig.get_config_var("LIBS").split())
1782
1783
            # FIXME I doubt half of these libraries need to be here.
1784
            linklist.append(self.sip_dir+"/sip.so")
1785
            # PyQt libs
1786
            linklist.append(self.pyqt_dir+"/qt.so")
1787
            # PyTDE libs
1788
            linklist.append(self.pytde_dir+"/tdecore.so")
1789
1790
#            linklist.append("-L"+self.sip_dir); linklist.append("-lsip")
1791
#            # PyQt libs
1792
#            linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule")
1793
#            # PyTDE libs
1794
#            linklist.append("-L"+self.pytde_dir); linklist.append("-ltdecorecmodule"); linklist.append("-ltdeuicmodule")
1795
1796
            linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/trinity/lib"); linklist.append("-ltdecore"); linklist.append("-lpythonize")
1797
            linklist.append("-L"+self.qt_lib_dir); linklist.append("-lqt-mt")
1798
            linklist.append("-lm")
1799
            linklist.append("-lc")
1800
            linklist.append(self.clib)
1801
1802
            linklist.append("-R"); linklist.append(self.python_dir)
1803
            linklist.append("-R"); linklist.append(self.qt_lib_dir)
1804
            linklist.append("-R"); linklist.append(self.sip_dir)
1805
            linklist.append("-R"); linklist.append(self.pyqt_dir)
1806
            linklist.append("-R"); linklist.append(self.pytde_dir)
1807
            linklist.append("-R"); linklist.append(self.kde_lib_dir)
1808
1809
            cmdlist.extend(linklist)
1810
            spawn(cmdlist) # Execute!!
1811
            print
1812
1813
    cpptemplate = r"""
1814
/*
1815
 * Launch Control Centre modules written in Python using an embedded Python
1816
 * interpreter.
1817
 * Based on David Boddie's PyTDE-components.
1818
 */
1819
1820
#include <stdio.h>
1821
#include <Python.h>
1822
#include <kinstance.h>
1823
#define MODULE_DIR "%(moduledir)s"
1824
#define MODULE_NAME "%(modulename)s"
1825
#define FACTORY "SlaveFactory"
1826
1827
const char modname[] = MODULE_NAME;
1828
#define MAIN_METHOD "dispatchLoop"
1829
1830
FILE *d = NULL;
1831
1832
PyObject* call_function(PyObject *callable, PyObject *args) {
1833
    PyObject *result, *pArgs;
1834
1835
    if (callable == NULL) {
1836
        printf(MODULE_NAME " tdeioslave error: callable == NULL in call_function\n");
1837
        return NULL;
1838
    }
1839
1840
    if (PyCallable_Check(callable)) {
1841
        if(args == NULL) {
1842
            pArgs = PyTuple_New(0);
1843
        } else {
1844
            pArgs = args;
1845
        }
1846
        result = PyObject_CallObject(callable, pArgs);
1847
1848
        /* If the arguments were created is this function then decrease
1849
           their reference count. */
1850
        if(args == NULL) {
1851
            Py_XDECREF(pArgs);
1852
            /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
1853
        }
1854
1855
        if(result == NULL) {
1856
            PyErr_Print();
1857
            PyErr_Clear();
1858
        }
1859
    }
1860
1861
    return result;
1862
}
1863
1864
extern "C" {
1865
    int kdemain( int argc, char **argv) {
1866
        PyObject *pModule, *pName, *pDict;
1867
        TDEInstance slave(MODULE_NAME);
1868
1869
        Py_SetProgramName(argv[0]);
1870
        Py_Initialize();
1871
        //PyEval_InitThreads();
1872
        PySys_SetArgv(1, argv);
1873
1874
        PyRun_SimpleString("import sys\n");
1875
        PyRun_SimpleString("sys.path.append('"MODULE_DIR"')\n");
1876
1877
        pName = PyString_FromString(modname);
1878
        pModule = PyImport_Import(pName);
1879
1880
        Py_XDECREF(pName);
1881
1882
        if(pModule == NULL) {
1883
            printf(MODULE_NAME " tdeioslave error: pModule == NULL\n");
1884
            return 1;
1885
        } else {
1886
            PyObject *pClass, *pMethod, *pArgs, *pArg1, *pArg2, *pInstance;
1887
            int i;
1888
1889
            pDict = PyModule_GetDict(pModule);
1890
            /* pDict is a borrowed reference */
1891
1892
            pClass = PyDict_GetItemString(pDict, FACTORY);
1893
1894
            if(pClass == NULL) {
1895
                printf(MODULE_NAME " tdeioslave error: pClass == NULL\n");
1896
                return 1;
1897
            } else {
1898
                pArgs = PyTuple_New(2);
1899
1900
                pArg1 = PyString_FromString(argv[2]);
1901
                pArg2 = PyString_FromString(argv[3]);
1902
1903
                PyTuple_SetItem(pArgs, 0, pArg1);
1904
                PyTuple_SetItem(pArgs, 1, pArg2);
1905
1906
                call_function(pClass, pArgs);
1907
1908
                /* Some time later... */
1909
                Py_XDECREF(pClass);
1910
                Py_XDECREF(pArgs);
1911
            }
1912
1913
            Py_XDECREF(pModule);
1914
        }
1915
1916
        Py_Finalize();
1917
        return 0;
1918
    }
1919
}
1920
"""
1921
###########################################################################
1922
class InstallTdeioslave(Command):
1923
    description = "Install Tdeioslave files"
1924
1925
    user_options = [
1926
        ('install-dir=', 'd', "base directory for installing tdeioslave module files"),
1927
        ('install-cmd=', None, "Command to use to install the files"),
1928
        ('install-protocol-dir=',None,"directory for tdeioslave protocol files"),
1929
        ('build-dir=','b', "build directory (where to install from)"),
1930
        ('root=', None, "install everything relative to this alternate root directory"),
1931
        ('force', 'f', "force installation (overwrite existing files)"),
1932
        ('skip-build', None, "skip the build steps"),
1933
        ]
1934
    boolean_options = ['force', 'skip-build']
1935
1936
    def initialize_options(self):
1937
        self.build_dir = None
1938
        self.install_dir = None
1939
        self.install_cmd = None
1940
        self.install_protocol_dir = None
1941
        self.outfiles = []
1942
        self.root = None
1943
        self.force = 0
1944
        self.warn_dir = 1
1945
        self.skip_build = None
1946
1947
    def finalize_options(self):
1948
        own_install_dir = self.install_dir is not None
1949
        own_install_protocol_dir = self.install_protocol_dir is not None
1950
1951
        self.set_undefined_options('install',
1952
                                    ('build_base', 'build_dir'),
1953
                                    ('install_tdeioslave', 'install_dir'),
1954
                                    ('root', 'root'),
1955
                                    ('force', 'force'),
1956
                                    ('skip_build', 'skip_build'),
1957
                                    ('install_cmd', 'install_cmd'),
1958
                                    ('install_protocol','install_protocol_dir')
1959
                                    )
1960
1961
        if own_install_dir and self.root is not None:
1962
            self.install_dir = change_root(self.root,self.installdir)
1963
1964
        if own_install_protocol_dir and self.root is not None:
1965
            self.install_protocol_dir = change_root(self.root,self.install_protocol_dir)
1966
1967
    def get_command_name(self):
1968
        return 'install_tdeioslave'
1969
1970
    def run(self):
1971
        if not self.skip_build:
1972
            self.run_command('build_tdeioslave')
1973
1974
        self.announce("Installing Tdeioslave files...")
1975
1976
        for moduletuple in self.distribution.tdeioslaves:
1977
            self.announce("Building Tdeioslave module from protocol file %s." % moduletuple[0])
1978
1979
            protocolfilename = moduletuple[0]
1980
1981
            # Read the protocol file
1982
            libraryname = None
1983
            try:
1984
                fhandle = open(protocolfilename,'r')
1985
                for line in fhandle.readlines():
1986
                    parts = line.strip().split('=')
1987
                    try:
1988
                        if parts[0]=="exec":
1989
                            libraryname = parts[1]
1990
                    except IndexError:
1991
                        pass
1992
                fhandle.close()
1993
            except IOError:
1994
                raise SystemExit, "Failed to find tdeioslave protocol file: %s" % moduletuple[0]
1995
1996
            if libraryname is None:
1997
                raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)"
1998
1999
            self.outfiles.extend(self.mkpath(self.install_protocol_dir))
2000
            protocolfile_dest = os.path.join(self.install_protocol_dir,os.path.basename(protocolfilename))
2001
            self.copy_file(protocolfilename, protocolfile_dest)
2002
2003
            stub_la_name = libraryname+'.la'
2004
2005
            self.outfiles.extend(self.mkpath(self.install_dir))
2006
2007
            # Install the library.
2008
            cmdlist = ['libtool']
2009
            cmdlist.append("--mode=install")
2010
            cmdlist.append(self.install_cmd)
2011
            cmdlist.append("-c")
2012
            cmdlist.append(os.path.join(self.build_dir,stub_la_name))
2013
            cmdlist.append(os.path.join(self.install_dir,stub_la_name))
2014
            spawn(cmdlist) # Execute!!
2015
            print
2016
2017
            self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs',libraryname+'*'))]
2018
            self.outfiles.append(protocolfile_dest)
2019
2020
        self.announce("Done installing Tdeioslave files.")
2021
2022
    def get_outputs(self):
2023
        return self.outfiles or []
2024
2025
    def mkpath(self, name, mode=0777):
2026
        return dir_util.mkpath(name, mode, dry_run=self.dry_run)
2027
2028
###########################################################################
2029
class CheckPyQt(Command):
2030
    description = "Checks for the presence of a working PyQt installation"
2031
2032
    user_options = []
2033
2034
    def initialize_options(self):
2035
        pass
2036
2037
    def finalize_options(self):
2038
        self.min_qt_version = self.distribution.min_qt_version
2039
2040
    def run(self):
2041
        if self.min_qt_version!=None:
2042
            qtver,kdever = get_qt_kde_versions()
2043
            if compare_versions(self.min_qt_version,qtver)==1:
2044
                raise SystemExit, "Your Qt version is too old. Version %s or higher is required, found %s." % (self.min_qt_version,qtver)
2045
            self.announce("Found Qt version %s." % qtver)
2046
        try:
2047
            self.announce("Checking for a working PyQt...")
2048
            import qt
2049
            self.announce("  ...PyQt is working")
2050
        except:
2051
            raise SystemExit, "Couldn't import Qt! Please make sure that PyQt is installed and working."
2052
2053
    def get_outputs(self): return []
2054
2055
###########################################################################
2056
class CheckPyTDE(Command):
2057
    description = "Checks for the presence of a working PyTDE installation"
2058
2059
    user_options = []
2060
2061
    def initialize_options(self):
2062
        pass
2063
2064
    def finalize_options(self):
2065
        self.min_kde_version = self.distribution.min_kde_version
2066
2067
    def run(self):
2068
        if self.min_kde_version!=None:
2069
            qtver,kdever = get_qt_kde_versions()
2070
            if compare_versions(self.min_kde_version,kdever)==1:
2071
                raise SystemExit, "Your KDE version is too old. Version %s or higher is required, found %s." % (self.min_kde_version,kdever)
2072
            self.announce("Found KDE version %s." % kdever)
2073
        self.announce("Checking for a working PyTDE...")
2074
2075
        # Try to import modules one by one.
2076
        for k_module in ('dcop', 'tdecore', 'tdeui', 'tdeio', 'tdefile', 'tdeparts', 'tdehtml', 'tdespell'):
2077
            self.announce(k_module)
2078
            try:
2079
                exec('import ' + k_module)
2080
            except:
2081
                raise SystemExit, "Error: Couldn't find module '" + k_module + "'. \n" + \
2082
                    "Couldn't import KDE! Please make sure that PyTDE is installed and working.\n" + \
2083
                    "PyTDE is available here: http://www.trinitydesktop.org"
2084
        self.announce("  ...PyTDE is working")
2085
2086
    def get_outputs(self): return []
2087
2088
###########################################################################
2089
def FindFileInPaths2(globpattern,canidatepaths):
2090
    if canidatepaths is None or len(canidatepaths)==0:
2091
        return (None,None)
2092
2093
    # Look for the globpattern on the path.
2094
    for path in canidatepaths:
2095
        if path!=None:
2096
            files = glob.glob(os.path.join(path, globpattern))
2097
            if len(files)!=0:
2098
                return (path,os.path.basename(files[0]))
2099
2100
    # Continue searching with a breadth first search.
2101
    dirs = []
2102
    for path in canidatepaths:
2103
        # Examine any directories on this path.
2104
        dirlist = glob.glob(os.path.join(path, "*"))
2105
        for item in dirlist:
2106
            if os.path.isdir(item):
2107
                # Examine each subdirectory.
2108
                dirs.append(item)
2109
    # Examine all subdirectories.
2110
    return FindFileInPaths2(globpattern, dirs)
2111
2112
###########################################################################
2113
def FindFileInPaths(globpattern,canidatepaths):
2114
    x,y = FindFileInPaths2(globpattern,canidatepaths)
2115
    return x
2116
2117
###########################################################################
2118
# FIXME replace this with spawn.find_executable().
2119
def FindExeOnPath(exe_name,high_prio_dirs=None,low_prio_dirs=None):
2120
    candiate_paths = []
2121
2122
    if high_prio_dirs is not None:
2123
        candiate_paths.extend(high_prio_dirs)
2124
2125
    path_var = os.getenv("PATH")
2126
    candiate_paths.extend(path_var.split(':'))
2127
2128
    if low_prio_dirs is not None:
2129
        candiate_paths.extend(low_prio_dirs)
2130
2131
    for dir in candiate_paths:
2132
        if dir is not None:
2133
            candiate = os.path.join(dir,exe_name)
2134
            if os.path.isfile(candiate):
2135
                if os.access(candiate,os.X_OK):
2136
                    return candiate
2137
    return None
2138
2139
###########################################################################
2140
2141
def ask_kde_config(question):
2142
    # Look for the tde-config program
2143
    kdeconfig = find_executable("tde-config", os.environ['PATH'] + os.pathsep + \
2144
        os.pathsep.join(['/bin','/usr/bin','/opt/trinity/bin','/opt/kde/bin','/usr/local/bin']))
2145
    if kdeconfig!=None:
2146
        # Ask the tde-config program for the
2147
        fhandle = os.popen(kdeconfig+' ' + question,'r')
2148
        result = fhandle.read()
2149
        fhandle.close()
2150
        return result
2151
    else:
2152
        return None
2153
2154
###########################################################################
2155
# Convert for example, "3.1.1a" => [3,1,1,'a']
2156
#
2157
def split_version_name(name):
2158
    result = []
2159
    accu = ''
2160
    type = 0
2161
    for c in name:
2162
        if type==0:
2163
            if c.isdigit():
2164
                type = 1
2165
            else:
2166
                type = 2
2167
            accu += c
2168
        elif c=='.':
2169
            if type==1:
2170
                result.append(int(accu))
2171
            else:
2172
                result.append(accu)
2173
            accu = ''
2174
            type = 0
2175
        elif type==1:
2176
            # Digits
2177
            if c.isdigit():
2178
                accu += c
2179
            else:
2180
                result.append(int(accu))
2181
                type = 2
2182
                accu = c
2183
        else:
2184
            if c.isdigit():
2185
                result.append(accu)
2186
                type = 1
2187
                accu = c
2188
            else:
2189
                accu += c
2190
    if accu!='':
2191
        result.append(accu)
2192
    return result
2193
2194
###########################################################################
2195
#
2196
# Returns:
2197
# -1 if a < b
2198
# 0 if a and b are equal
2199
# 1 if a > b
2200
def compare_versions(a,b):
2201
    aparts = split_version_name(a)
2202
    bparts = split_version_name(b)
2203
    if len(aparts)>len(bparts):
2204
        compmax = len(aparts)
2205
    else:
2206
        compmax = len(bparts)
2207
    i = 0
2208
    for i in range(compmax):
2209
        abit = 0
2210
        if i<len(aparts):
2211
            abit = aparts[i]
2212
        bit = 0
2213
        if i<len(bparts):
2214
            bbit = bparts[i]
2215
        if isinstance(abit,str) and not isinstance(bbit,str):
2216
            return 1
2217
        elif not isinstance(abit,str) and isinstance(bbit,str):
2218
            return -1
2219
        else:
2220
            if abit>bbit:
2221
                return 1
2222
            elif abit<bbit:
2223
                return -1
2224
    return 0
2225
2226
###########################################################################
2227
def get_qt_kde_versions():
2228
    versioninfo = ask_kde_config('--version')
2229
    qtver = None
2230
    kdever = None
2231
    if versioninfo!=None:
2232
        for line in versioninfo.splitlines():
2233
            if line.startswith("Qt: "):
2234
                qtver = line[4:]
2235
            elif line.startswith("TDE: "):
2236
                kdever = line[5:]
2237
    return qtver,kdever
2238
2239
###########################################################################
2240
def compile_qtdesigner(ui_files,
2241
                  force=0,
2242
                  prefix=None, base_dir=None,
2243
                  verbose=1, dry_run=0):
2244
    """Compile a collection of QT Designer UI files to .py
2245
2246
    If 'dry_run' is true, doesn't actually do anything that would
2247
    affect the filesystem.
2248
    """
2249
    generated_files = []
2250
    for file in ui_files:
2251
        if not file.endswith(".ui"):
2252
            continue
2253
2254
        # Terminology from the py_compile module:
2255
        #   cfile - byte-compiled file
2256
        #   dfile - purported source filename (same as 'file' by default)
2257
        if base_dir:
2258
            file = os.path.join(base_dir ,file)
2259
2260
        pyfile = file[:-3] + '.py'
2261
        uifile = file
2262
2263
        pyfile_base = os.path.basename(pyfile)
2264
        if force or newer(uifile, pyfile):
2265
            log.info("compiling Qt-Designer UI %s to %s", file, pyfile_base)
2266
            if not dry_run:
2267
                qtuicompiler.CompileUI(uifile, pyfile)
2268
            generated_files.append(pyfile)
2269
        else:
2270
            log.debug("skipping Qt-Designer compilation of %s to %s",
2271
                      file, pyfile_base)
2272
    return generated_files
2273
2274
###########################################################################
2275
def get_libdir_name():
2276
    if os.uname()[4] in ['x86_64','mips64','ppc64','sparc64','s390x']:
2277
        return 'lib64'
2278
    else:
2279
        return 'lib'

Return to bug 1790