1#!/usr/bin/env python
2#
3#
4# Licensed to the Apache Software Foundation (ASF) under one
5# or more contributor license agreements.  See the NOTICE file
6# distributed with this work for additional information
7# regarding copyright ownership.  The ASF licenses this file
8# to you under the Apache License, Version 2.0 (the
9# "License"); you may not use this file except in compliance
10# with the License.  You may obtain a copy of the License at
11#
12#   http://www.apache.org/licenses/LICENSE-2.0
13#
14# Unless required by applicable law or agreed to in writing,
15# software distributed under the License is distributed on an
16# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17# KIND, either express or implied.  See the License for the
18# specific language governing permissions and limitations
19# under the License.
20#
21#
22#
23# gen-make.py -- generate makefiles for building Subversion
24#
25
26
27import os
28import sys
29import getopt
30try:
31  my_getopt = getopt.gnu_getopt
32except AttributeError:
33  my_getopt = getopt.getopt
34try:
35  # Python >=3.0
36  import configparser
37except ImportError:
38  # Python <3.0
39  import ConfigParser as configparser
40
41# for the generator modules
42sys.path.insert(0, os.path.join('build', 'generator'))
43
44# for getversion
45sys.path.insert(1, 'build')
46
47gen_modules = {
48  'make' : ('gen_make', 'Makefiles for POSIX systems'),
49  'dsp' : ('gen_msvc_dsp', 'MSVC 6.x project files'),
50  'vcproj' : ('gen_vcnet_vcproj', 'VC.Net project files'),
51  }
52
53def main(fname, gentype, verfname=None,
54         skip_depends=0, other_options=None):
55  if verfname is None:
56    verfname = os.path.join('subversion', 'include', 'svn_version.h')
57
58  gen_module = __import__(gen_modules[gentype][0])
59
60  generator = gen_module.Generator(fname, verfname, other_options)
61
62  if not skip_depends:
63    generator.compute_hdr_deps()
64
65  generator.write()
66  generator.write_sqlite_headers()
67
68  if ('--debug', '') in other_options:
69    for dep_type, target_dict in generator.graph.deps.items():
70      sorted_targets = list(target_dict.keys()); sorted_targets.sort()
71      for target in sorted_targets:
72        print(dep_type + ": " + _objinfo(target))
73        for source in target_dict[target]:
74          print("  " + _objinfo(source))
75      print("=" * 72)
76    gen_keys = sorted(generator.__dict__.keys())
77    for name in gen_keys:
78      value = generator.__dict__[name]
79      if isinstance(value, list):
80        print(name + ": ")
81        for i in value:
82          print("  " + _objinfo(i))
83        print("=" * 72)
84
85
86def _objinfo(o):
87  if isinstance(o, str):
88    return repr(o)
89  else:
90    t = o.__class__.__name__
91    n = getattr(o, 'name', '-')
92    f = getattr(o, 'filename', '-')
93    return "%s: %s %s" % (t,n,f)
94
95
96def _usage_exit(err=None):
97  "print ERR (if any), print usage, then exit the script"
98  if err:
99    print("ERROR: %s\n" % (err))
100  print("USAGE:  gen-make.py [options...] [conf-file]")
101  print("  -s        skip dependency generation")
102  print("  --debug   print lots of stuff only developers care about")
103  print("  --release release mode")
104  print("  --reload  reuse all options from the previous invocation")
105  print("            of the script, except -s, -t, --debug and --reload")
106  print("  -t TYPE   use the TYPE generator; can be one of:")
107  items = sorted(gen_modules.items())
108  for name, (module, desc) in items:
109    print('            %-12s  %s' % (name, desc))
110  print("")
111  print("            The default generator type is 'make'")
112  print("")
113  print("  Makefile-specific options:")
114  print("")
115  print("  --assume-shared-libs")
116  print("           omit dependencies on libraries, on the assumption that")
117  print("           shared libraries will be built, so that it is unnecessary")
118  print("           to relink executables when the libraries that they depend")
119  print("           on change.  This is an option for developers who want to")
120  print("           increase the speed of frequent rebuilds.")
121  print("           *** Do not use unless you understand the consequences. ***")
122  print("")
123  print("  UNIX-specific options:")
124  print("")
125  print("  --installed-libs")
126  print("           Comma-separated list of Subversion libraries to find")
127  print("           pre-installed instead of building (probably only")
128  print("           useful for packagers)")
129  print("")
130  print("  Windows-specific options:")
131  print("")
132  print("  --with-apr=DIR")
133  print("           the APR sources are in DIR")
134  print("")
135  print("  --with-apr-util=DIR")
136  print("           the APR-Util sources are in DIR")
137  print("")
138  print("  --with-apr-iconv=DIR")
139  print("           the APR-Iconv sources are in DIR")
140  print("")
141  print("  --with-berkeley-db=DIR")
142  print("           look for Berkeley DB headers and libs in")
143  print("           DIR")
144  print("")
145  print("  --with-serf=DIR")
146  print("           the Serf sources are in DIR")
147  print("")
148  print("  --with-httpd=DIR")
149  print("           the httpd sources and binaries required")
150  print("           for building mod_dav_svn are in DIR;")
151  print("           implies --with-apr{-util, -iconv}, but")
152  print("           you can override them")
153  print("")
154  print("  --with-libintl=DIR")
155  print("           look for GNU libintl headers and libs in DIR;")
156  print("           implies --enable-nls")
157  print("")
158  print("  --with-openssl=DIR")
159  print("           tell serf to look for OpenSSL headers")
160  print("           and libs in DIR")
161  print("")
162  print("  --with-zlib=DIR")
163  print("           tell Subversion to look for ZLib headers and")
164  print("           libs in DIR")
165  print("")
166  print("  --with-jdk=DIR")
167  print("           look for the java development kit here")
168  print("")
169  print("  --with-junit=DIR")
170  print("           look for the junit jar here")
171  print("           junit is for testing the java bindings")
172  print("")
173  print("  --with-swig=DIR")
174  print("           look for the swig program in DIR")
175  print("")
176  print("  --with-sqlite=DIR")
177  print("           look for sqlite in DIR")
178  print("")
179  print("  --with-sasl=DIR")
180  print("           look for the sasl headers and libs in DIR")
181  print("")
182  print("  --enable-pool-debug")
183  print("           turn on APR pool debugging")
184  print("")
185  print("  --enable-purify")
186  print("           add support for Purify instrumentation;")
187  print("           implies --enable-pool-debug")
188  print("")
189  print("  --enable-quantify")
190  print("           add support for Quantify instrumentation")
191  print("")
192  print("  --enable-nls")
193  print("           add support for gettext localization")
194  print("")
195  print("  --enable-bdb-in-apr-util")
196  print("           configure APR-Util to use Berkeley DB")
197  print("")
198  print("  --enable-ml")
199  print("           enable use of ML assembler with zlib")
200  print("")
201  print("  --disable-shared")
202  print("           only build static libraries")
203  print("")
204  print("  --with-static-apr")
205  print("           Use static apr and apr-util")
206  print("")
207  print("  --with-static-openssl")
208  print("           Use static openssl")
209  print("")
210  print("  --vsnet-version=VER")
211  print("           generate for VS.NET version VER (2002, 2003, 2005, 2008, 2010 or 2012)")
212  print("           [only valid in combination with '-t vcproj']")
213  print("")
214  print("  --with-apr_memcache=DIR")
215  print("           the apr_memcache sources are in DIR")
216  sys.exit(1)
217
218
219class Options:
220  def __init__(self):
221    self.list = []
222    self.dict = {}
223
224  def add(self, opt, val):
225    if opt in self.dict:
226      self.list[self.dict[opt]] = (opt, val)
227    else:
228      self.dict[opt] = len(self.list)
229      self.list.append((opt, val))
230
231if __name__ == '__main__':
232  try:
233    opts, args = my_getopt(sys.argv[1:], 'st:',
234                           ['debug',
235                            'release',
236                            'reload',
237                            'assume-shared-libs',
238                            'with-apr=',
239                            'with-apr-util=',
240                            'with-apr-iconv=',
241                            'with-berkeley-db=',
242                            'with-serf=',
243                            'with-httpd=',
244                            'with-libintl=',
245                            'with-openssl=',
246                            'with-zlib=',
247                            'with-jdk=',
248                            'with-junit=',
249                            'with-swig=',
250                            'with-sqlite=',
251                            'with-sasl=',
252                            'with-apr_memcache=',
253                            'with-static-apr',
254                            'with-static-openssl',
255                            'enable-pool-debug',
256                            'enable-purify',
257                            'enable-quantify',
258                            'enable-nls',
259                            'enable-bdb-in-apr-util',
260                            'enable-ml',
261                            'disable-shared',
262                            'installed-libs=',
263                            'vsnet-version=',
264
265                            # Keep distributions that help by adding a path
266                            # working. On unix this would be filtered by
267                            # configure, but on Windows gen-make.py is used
268                            # directly.
269                            'with-neon=',
270                            'without-neon',
271                            ])
272    if len(args) > 1:
273      _usage_exit("Too many arguments")
274  except getopt.GetoptError, e:
275    _usage_exit(str(e))
276
277  conf = 'build.conf'
278  skip = 0
279  gentype = 'make'
280  rest = Options()
281
282  if args:
283    conf = args[0]
284
285  # First merge options with previously saved to gen-make.opts if --reload
286  # options used
287  for opt, val in opts:
288    if opt == '--reload':
289      prev_conf = configparser.ConfigParser()
290      prev_conf.read('gen-make.opts')
291      for opt, val in prev_conf.items('options'):
292        if opt != '--debug':
293          rest.add(opt, val)
294      del prev_conf
295    elif opt == '--with-neon' or opt == '--without-neon':
296      # Provide a warning that we ignored these arguments
297      print("Ignoring no longer supported argument '%s'" % opt)
298    else:
299      rest.add(opt, val)
300
301  # Parse options list
302  for opt, val in rest.list:
303    if opt == '-s':
304      skip = 1
305    elif opt == '-t':
306      gentype = val
307    else:
308      if opt == '--with-httpd':
309        rest.add('--with-apr', os.path.join(val, 'srclib', 'apr'))
310        rest.add('--with-apr-util', os.path.join(val, 'srclib', 'apr-util'))
311        rest.add('--with-apr-iconv', os.path.join(val, 'srclib', 'apr-iconv'))
312
313  # Remember all options so that --reload and other scripts can use them
314  opt_conf = open('gen-make.opts', 'w')
315  opt_conf.write('[options]\n')
316  for opt, val in rest.list:
317    opt_conf.write(opt + ' = ' + val + '\n')
318  opt_conf.close()
319
320  if gentype not in gen_modules.keys():
321    _usage_exit("Unknown module type '%s'" % (gentype))
322
323  main(conf, gentype, skip_depends=skip, other_options=rest.list)
324
325
326### End of file.
327