Merge remote-tracking branch 'gvdb/master'
[platform/upstream/glib.git] / build / win32 / setup.py
1 #!/usr/bin/python
2 # vim: encoding=utf-8
3 #expand *.in files
4 #this script is only intended for building from git, not for building from the released tarball, which already includes all necessary files
5 import os
6 import sys
7 import re
8 import string
9 import subprocess
10 import optparse
11
12 def get_version(srcroot):
13     ver = {}
14     RE_VERSION = re.compile(r'^m4_define\(\[(glib_\w+)\],\s*\[(\d+)\]\)')
15     with open(os.path.join(srcroot, 'configure.ac'), 'r') as ac:
16         for i in ac:
17             mo = RE_VERSION.search(i)
18             if mo:
19                 ver[mo.group(1).upper()] = int(mo.group(2))
20     ver['GLIB_BINARY_AGE'] = 100 * ver['GLIB_MINOR_VERSION'] + ver['GLIB_MICRO_VERSION']
21     ver['GLIB_VERSION'] = '%d.%d.%d' % (ver['GLIB_MAJOR_VERSION'],
22                                         ver['GLIB_MINOR_VERSION'],
23                                         ver['GLIB_MICRO_VERSION'])
24     ver['LT_RELEASE'] = '%d.%d' % (ver['GLIB_MAJOR_VERSION'], ver['GLIB_MINOR_VERSION'])
25     ver['LT_CURRENT'] = 100 * ver['GLIB_MINOR_VERSION'] + ver['GLIB_MICRO_VERSION'] - ver['GLIB_INTERFACE_AGE']
26     ver['LT_REVISION'] = ver['GLIB_INTERFACE_AGE']
27     ver['LT_AGE'] = ver['GLIB_BINARY_AGE'] - ver['GLIB_INTERFACE_AGE']
28     ver['LT_CURRENT_MINUS_AGE'] = ver['LT_CURRENT'] - ver['LT_AGE']
29     return ver
30
31 def process_in(src, dest, vars):
32     RE_VARS = re.compile(r'@(\w+?)@')
33     with open(src, 'r') as s:
34         with open(dest, 'w') as d:
35             for i in s:
36                 i = RE_VARS.sub(lambda x: str(vars[x.group(1)]), i)
37                 d.write(i)
38
39 def process_include(src, dest, includes):
40     RE_INCLUDE = re.compile(r'^\s*#include\s+"(.*)"')
41     with open(src, 'r') as s:
42         with open(dest, 'w') as d:
43             for i in s:
44                 mo = RE_INCLUDE.search(i)
45                 if mo:
46                     target = ''
47                     for j in includes:
48                         #print "searching in ", j
49                         if mo.group(1) in os.listdir(j):
50                             target = os.path.join(j, mo.group(1))
51                             break
52                     if not target:
53                         raise Exception("Couldn't fine include file %s" % mo.group(1))
54                     else:
55                         with open(target, 'r') as t:
56                             for inc in t.readlines():
57                                 d.write(inc)
58                 else:
59                     d.write(i)
60
61 def generate_libgio_sourcefiles(srcroot, dest, stype):
62     vars = read_vars_from_AM(os.path.join(srcroot, 'gio', 'Makefile.am'),
63                              vars = {'top_srcdir': srcroot},
64                              conds = {'OS_WIN32': True},
65                              filters = ['libgio_2_0_la_SOURCES', 'win32_more_sources_for_vcproj'])
66
67     files = vars['libgio_2_0_la_SOURCES'].split() + \
68             vars['win32_more_sources_for_vcproj'].split()
69
70     sources = [i for i in files \
71                     if i != 'gdesktopappinfo.c' and \
72                        not (i.startswith('gunix') and i.endswith('.c')) \
73                        and i.endswith('.c') ]
74     if stype == '9':
75        with open(dest, 'w') as d:
76            for i in sources:
77                d.write('\t\t\t<File RelativePath="..\\..\\..\\gio\\' + i.replace('/', '\\') + '"/>\n')
78     elif stype == '10':
79        with open(dest, 'w') as d:
80            for i in sources:
81                d.write('\t\t\t<ClCompile Include="..\\..\\..\\gio\\' + i.replace('/', '\\') + '"/>\n')
82     elif stype == '10f':
83        with open(dest, 'w') as d:
84            for i in sources:
85                d.write('\t\t\t<ClCompile Include="..\\..\\..\\gio\\' + i.replace('/', '\\') + '"><Filter>Source Files</Filter></ClCompile>\n')
86     else:
87        raise Exception("Must specify project type (9, 10 or 10f)")
88
89 def generate_libgio_enumtypes(srcroot, perl):
90     vars = read_vars_from_AM(os.path.join(srcroot, 'gio', 'Makefile.am'),
91                              vars = {'top_srcdir': srcroot},
92                              conds = {'OS_WIN32': True},
93                              filters = ['gio_headers'])
94     cwd = os.getcwd()
95     os.chdir(os.path.join(srcroot, 'gio'))
96     for suffix in ['.c', '.h']:
97         cmd = [perl, os.path.join(srcroot, 'gobject', 'glib-mkenums'),
98                '--template', 'gioenumtypes' + suffix + '.template'] + vars['gio_headers'].split()
99         with open('gioenumtypes' + suffix, 'w') as d:
100             subprocess.Popen(cmd, stdout = d).communicate()
101     os.chdir(cwd)
102 def generate_libglib_sourcefiles(srcroot, dest, stype):
103     vars = read_vars_from_AM(os.path.join(srcroot, 'glib', 'Makefile.am'),
104                              vars = {'top_srcdir': srcroot},
105                              conds = {'OS_WIN32': True,
106                                       'ENABLE_REGEX': True},
107                              filters = ['libglib_2_0_la_SOURCES'])
108
109     files = vars['libglib_2_0_la_SOURCES'].split()
110
111     sources = [i for i in files \
112                     if not (i.endswith('-gcc.c') or i.endswith('-unix.c')) \
113                        and i.endswith('.c') ]
114     if stype == '9':
115         with open(dest, 'w') as d:
116             for i in sources:
117                 d.write('\t\t\t<File RelativePath="..\\..\\..\\glib\\' + i.replace('/', '\\') + '"/>\n')
118     elif stype == '10':
119         with open(dest, 'w') as d:
120             for i in sources:
121                 d.write('\t\t\t<ClCompile Include="..\\..\\..\\glib\\' + i.replace('/', '\\') + '"/>\n')
122     elif stype == '10f':
123         with open(dest, 'w') as d:
124             for i in sources:
125                 d.write('\t\t\t<ClCompile Include="..\\..\\..\\glib\\' + i.replace('/', '\\') + '"><Filter>Source Files</Filter></ClCompile>\n')
126     else:
127         raise Exception("Must specify project type (9, 10 or 10f)")
128
129 def generate_libgobject_sourcefiles(srcroot, dest, stype):
130     vars = read_vars_from_AM(os.path.join(srcroot, 'gobject', 'Makefile.am'),
131                              vars = {'top_srcdir': srcroot},
132                              conds = {'OS_WIN32': True},
133                              filters = ['libgobject_2_0_la_SOURCES'])
134
135     files = vars['libgobject_2_0_la_SOURCES'].split()
136
137     sources = [i for i in files if i.endswith('.c') ]
138     if stype == '9':
139         with open(dest, 'w') as d:
140             for i in sources:
141                 d.write('\t\t\t<File RelativePath="..\\..\\..\\gobject\\' + i.replace('/', '\\') + '"/>\n')
142     elif stype == '10':
143         with open(dest, 'w') as d:
144             for i in sources:
145                 d.write('\t\t\t<ClCompile Include="..\\..\\..\\gobject\\' + i.replace('/', '\\') + '"/>\n')
146     elif stype == '10f':
147         with open(dest, 'w') as d:
148             for i in sources:
149                 d.write('\t\t\t<ClCompile Include="..\\..\\..\\gobject\\' + i.replace('/', '\\') + '"><Filter>Source Files</Filter></ClCompile>\n')
150     else:
151         raise Exception("Must specify project type (9, 10 or 10f)")
152
153 def read_vars_from_AM(path, vars = {}, conds = {}, filters = None):
154     '''
155     path: path to the Makefile.am
156     vars: predefined variables
157     conds: condition variables for Makefile
158     filters: if None, all variables defined are returned,
159              otherwise, it is a list contains that variables should be returned
160     '''
161     cur_vars = vars.copy()
162     RE_AM_VAR_REF = re.compile(r'\$\((\w+?)\)')
163     RE_AM_VAR = re.compile(r'^\s*(\w+)\s*=(.*)$')
164     RE_AM_INCLUDE = re.compile(r'^\s*include\s+(\w+)')
165     RE_AM_CONTINUING = re.compile(r'\\\s*$')
166     RE_AM_IF = re.compile(r'^\s*if\s+(\w+)')
167     RE_AM_ELSE = re.compile(r'^\s*else')
168     RE_AM_ENDIF = re.compile(r'^\s*endif')
169     def am_eval(cont):
170         return RE_AM_VAR_REF.sub(lambda x: cur_vars.get(x.group(1), ''), cont)
171     with open(path, 'r') as f:
172         contents = f.readlines()
173     #combine continuing lines
174     i = 0
175     ncont = []
176     while i < len(contents):
177         line = contents[i]
178         if RE_AM_CONTINUING.search(line):
179             line = RE_AM_CONTINUING.sub('', line)
180             j = i + 1
181             while j < len(contents) and RE_AM_CONTINUING.search(contents[j]):
182                 line += RE_AM_CONTINUING.sub('', contents[j])
183                 j += 1
184             else:
185                 if j < len(contents):
186                     line += contents[j]
187             i = j
188         else:
189             i += 1
190         ncont.append(line)
191
192     #include, var define, var evaluation
193     i = -1
194     skip = False
195     oldskip = []
196     while i < len(ncont) - 1:
197         i += 1
198         line = ncont[i]
199         mo = RE_AM_IF.search(line)
200         if mo:
201             oldskip.append(skip)
202             skip = False if mo.group(1) in conds and conds[mo.group(1)] \
203                          else True
204             continue
205         mo = RE_AM_ELSE.search(line)
206         if mo:
207             skip = not skip
208             continue
209         mo = RE_AM_ENDIF.search(line)
210         if mo:
211             skip = oldskip.pop()
212             continue
213         if not skip:
214             mo = RE_AM_INCLUDE.search(line)
215             if mo:
216                 cur_vars.update(read_vars_from_AM(am_eval(mo.group(1)), cur_vars, conds, None))
217                 continue
218             mo = RE_AM_VAR.search(line)
219             if mo:
220                 cur_vars[mo.group(1)] = am_eval(mo.group(2).strip())
221                 continue
222
223     #filter:
224     if filters != None:
225         ret = {}
226         for i in filters:
227             ret[i] = cur_vars.get(i, '')
228         return ret
229     else:
230         return cur_vars
231
232 def main(argv):
233     parser = optparse.OptionParser()
234     parser.add_option('-p', '--perl', dest='perl', metavar='PATH', default='C:\\Perl\\bin\\perl.exe', action='store', help='path to the perl interpretor (default: C:\\Perl\\bin\\perl.exe)')
235     opt, args = parser.parse_args(argv)
236     def parent_dir(path):
237         if not os.path.isabs(path):
238             path = os.path.abspath(path)
239         if os.path.isfile(path):
240             path = os.path.dirname(path)
241         return os.path.split(path)[0]
242     srcroot = parent_dir(parent_dir(__file__))
243     #print 'srcroot', srcroot
244     ver = get_version(srcroot)
245     #print 'ver', ver
246     config_vars = ver.copy()
247     config_vars['GETTEXT_PACKAGE'] = 'Glib'
248     process_in(os.path.join(srcroot, 'config.h.win32.in'),
249                os.path.join(srcroot, 'config.h'),
250                config_vars)
251     glibconfig_vars = ver.copy()
252     glibconfig_vars['GLIB_WIN32_STATIC_COMPILATION_DEFINE'] = ''
253     process_in(os.path.join(srcroot, 'glib', 'glibconfig.h.win32.in'),
254                os.path.join(srcroot, 'glib', 'glibconfig.h'),
255                glibconfig_vars)
256
257     for submodule in ['glib', 'gobject', 'gthread', 'gmodule', 'gio']:
258         process_in(os.path.join(srcroot, submodule, submodule + '.rc.in'),
259                    os.path.join(srcroot, submodule, submodule + '.rc'),
260                    ver)
261
262     #------------ submodule gobject -------------------
263     generate_libglib_sourcefiles(srcroot,
264                                 os.path.join(srcroot, 'build', 'win32', 'libglib.sourcefiles'), '9')
265     generate_libglib_sourcefiles(srcroot,
266                                 os.path.join(srcroot, 'build', 'win32', 'libglib.vs10.sourcefiles'), '10')
267     generate_libglib_sourcefiles(srcroot,
268                                 os.path.join(srcroot, 'build', 'win32', 'libglib.vs10.sourcefiles.filters'), '10f')
269     process_include(os.path.join(srcroot, 'build', 'win32', 'vs9', 'glib.vcprojin'),
270                     os.path.join(srcroot, 'build', 'win32', 'vs9', 'glib.vcproj'),
271                     includes = [os.path.join(srcroot, 'build', 'win32')])
272     process_include(os.path.join(srcroot, 'build', 'win32', 'vs10', 'glib.vcxprojin'),
273                     os.path.join(srcroot, 'build', 'win32', 'vs10', 'glib.vcxproj'),
274                     includes = [os.path.join(srcroot, 'build', 'win32')])
275     process_include(os.path.join(srcroot, 'build', 'win32', 'vs10', 'glib.vcxproj.filtersin'),
276                     os.path.join(srcroot, 'build', 'win32', 'vs10', 'glib.vcxproj.filters'),
277                     includes = [os.path.join(srcroot, 'build', 'win32')])
278     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libglib.sourcefiles'))
279     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libglib.vs10.sourcefiles'))
280     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libglib.vs10.sourcefiles.filters'))
281     with open(os.path.join(srcroot, 'glib', 'gspawn-win32-helper-console.c'), 'w') as c:
282         c.write('#define HELPER_CONSOLE\n')
283         c.write('#include "gspawn-win32-helper.c"\n')
284     with open(os.path.join(srcroot, 'glib', 'gspawn-win64-helper-console.c'), 'w') as c:
285         c.write('#define HELPER_CONSOLE\n')
286         c.write('#include "gspawn-win32-helper.c"\n')
287     with open(os.path.join(srcroot, 'glib', 'gspawn-win64-helper.c'), 'w') as c:
288         c.write('#include "gspawn-win32-helper.c"\n')
289     #------------ end of submodule glib -------------------
290
291     #------------ submodule gobject -------------------
292     mkenums_vars = ver.copy()
293     mkenums_vars.update({'PERL_PATH': opt.perl})
294     process_in(os.path.join(srcroot, 'gobject', 'glib-mkenums.in'),
295                os.path.join(srcroot, 'gobject', 'glib-mkenums'),
296                mkenums_vars)
297
298     #gmarshal.strings
299     cwd = os.getcwd()
300     os.chdir(os.path.join(srcroot, 'gobject'))
301     with open(os.path.join(srcroot, 'gobject', 'gmarshal.strings'), 'w') as d:
302         with open(os.path.join(srcroot, 'gobject', 'gmarshal.list'), 'r') as s:
303             for i in s:
304                 if i[0] not in string.ascii_uppercase: #^[A-Z]
305                     continue
306                 line = '"g_cclosure_marshal_' # s/^/"g_cclosure_marshal_/
307                 for c in i:
308                     if c == ':':
309                         line += '__'          # s/:/__
310                     elif c == ',':
311                         line += '_'           # s/,/_
312                     elif c not in '\r\n':
313                         line += c
314                 d.write(line + '",\n')
315         #subprocess.Popen([opt.perl, 'marshal-genstrings.pl'], stdout=d).communicate()
316     os.chdir(cwd)
317
318     generate_libgobject_sourcefiles(srcroot,
319                                 os.path.join(srcroot, 'build', 'win32', 'libgobject.sourcefiles'), '9')
320     generate_libgobject_sourcefiles(srcroot,
321                                 os.path.join(srcroot, 'build', 'win32', 'libgobject.vs10.sourcefiles'), '10')
322     generate_libgobject_sourcefiles(srcroot,
323                                 os.path.join(srcroot, 'build', 'win32', 'libgobject.vs10.sourcefiles.filters'), '10f')
324     process_include(os.path.join(srcroot, 'build', 'win32', 'vs9', 'gobject.vcprojin'),
325                     os.path.join(srcroot, 'build', 'win32', 'vs9', 'gobject.vcproj'),
326                     includes = [os.path.join(srcroot, 'build', 'win32')])
327     process_include(os.path.join(srcroot, 'build', 'win32', 'vs10', 'gobject.vcxprojin'),
328                     os.path.join(srcroot, 'build', 'win32', 'vs10', 'gobject.vcxproj'),
329                     includes = [os.path.join(srcroot, 'build', 'win32')])
330     process_include(os.path.join(srcroot, 'build', 'win32', 'vs10', 'gobject.vcxproj.filtersin'),
331                     os.path.join(srcroot, 'build', 'win32', 'vs10', 'gobject.vcxproj.filters'),
332                     includes = [os.path.join(srcroot, 'build', 'win32')])
333     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libgobject.sourcefiles'))
334     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libgobject.vs10.sourcefiles'))
335     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libgobject.vs10.sourcefiles.filters'))
336     #------------ end of submodule gobject -------------------
337
338     #------------ submodule gio -------------------
339     #depends on glib-mkenums
340     generate_libgio_sourcefiles(srcroot,
341                                 os.path.join(srcroot, 'build', 'win32', 'libgio.sourcefiles'), '9')
342     generate_libgio_sourcefiles(srcroot,
343                                 os.path.join(srcroot, 'build', 'win32', 'libgio.vs10.sourcefiles'), '10')
344     generate_libgio_sourcefiles(srcroot,
345                                 os.path.join(srcroot, 'build', 'win32', 'libgio.vs10.sourcefiles.filters'), '10f')
346     process_include(os.path.join(srcroot, 'build', 'win32', 'vs9', 'gio.vcprojin'),
347                     os.path.join(srcroot, 'build', 'win32', 'vs9', 'gio.vcproj'),
348                     includes = [os.path.join(srcroot, 'build', 'win32')])
349     process_include(os.path.join(srcroot, 'build', 'win32', 'vs10', 'gio.vcxprojin'),
350                     os.path.join(srcroot, 'build', 'win32', 'vs10', 'gio.vcxproj'),
351                     includes = [os.path.join(srcroot, 'build', 'win32')])
352     process_include(os.path.join(srcroot, 'build', 'win32', 'vs10', 'gio.vcxproj.filtersin'),
353                     os.path.join(srcroot, 'build', 'win32', 'vs10', 'gio.vcxproj.filters'),
354                     includes = [os.path.join(srcroot, 'build', 'win32')])
355     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libgio.sourcefiles'))
356     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libgio.vs10.sourcefiles'))
357     os.unlink(os.path.join(srcroot, 'build', 'win32', 'libgio.vs10.sourcefiles.filters'))
358     generate_libgio_enumtypes(srcroot, opt.perl)
359     #------------ end of submodule gio -------------------
360
361     #------------ submodule gmodule -------------------
362     #------------ end of submodule gmodule -------------------
363     return 0
364
365 if __name__ == '__main__':
366     sys.exit(main(sys.argv))