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 traceback
29import sys
30
31import getopt
32try:
33  my_getopt = getopt.gnu_getopt
34except AttributeError:
35  my_getopt = getopt.getopt
36try:
37  # Python >=3.0
38  import configparser
39except ImportError:
40  # Python <3.0
41  import ConfigParser as configparser
42
43# for the generator modules
44sys.path.insert(0, os.path.join('build', 'generator'))
45
46# for getversion
47sys.path.insert(1, 'build')
48
49gen_modules = {
50  'make' : ('gen_make', 'Makefiles for POSIX systems'),
51  'dsp' : ('gen_msvc_dsp', 'MSVC 6.x project files'),
52  'vcproj' : ('gen_vcnet_vcproj', 'VC.Net project files'),
53  }
54
55def main(fname, gentype, verfname=None,
56         skip_depends=0, other_options=None):
57  if verfname is None:
58    verfname = os.path.join('subversion', 'include', 'svn_version.h')
59
60  gen_module = __import__(gen_modules[gentype][0])
61
62  generator = gen_module.Generator(fname, verfname, other_options)
63
64  if not skip_depends:
65    generator.compute_hdr_deps()
66
67  generator.write()
68  generator.write_sqlite_headers()
69  generator.write_errno_table()
70  generator.write_config_keys()
71
72  if ('--debug', '') in other_options:
73    for dep_type, target_dict in generator.graph.deps.items():
74      sorted_targets = list(target_dict.keys()); sorted_targets.sort()
75      for target in sorted_targets:
76        print(dep_type + ": " + _objinfo(target))
77        for source in target_dict[target]:
78          print("  " + _objinfo(source))
79      print("=" * 72)
80    gen_keys = sorted(generator.__dict__.keys())
81    for name in gen_keys:
82      value = generator.__dict__[name]
83      if isinstance(value, list):
84        print(name + ": ")
85        for i in value:
86          print("  " + _objinfo(i))
87        print("=" * 72)
88
89
90def _objinfo(o):
91  if isinstance(o, str):
92    return repr(o)
93  else:
94    t = o.__class__.__name__
95    n = getattr(o, 'name', '-')
96    f = getattr(o, 'filename', '-')
97    return "%s: %s %s" % (t,n,f)
98
99
100def _usage_exit(err=None):
101  "print ERR (if any), print usage, then exit the script"
102  if err:
103    print("ERROR: %s\n" % (err))
104  print("USAGE:  gen-make.py [options...] [conf-file]")
105  print("  -s        skip dependency generation")
106  print("  --debug   print lots of stuff only developers care about")
107  print("  --release release mode")
108  print("  --reload  reuse all options from the previous invocation")
109  print("            of the script, except -s, -t, --debug and --reload")
110  print("  -t TYPE   use the TYPE generator; can be one of:")
111  items = sorted(gen_modules.items())
112  for name, (module, desc) in items:
113    print('            %-12s  %s' % (name, desc))
114  print("")
115  print("            The default generator type is 'make'")
116  print("")
117  print("  Makefile-specific options:")
118  print("")
119  print("  --assume-shared-libs")
120  print("           omit dependencies on libraries, on the assumption that")
121  print("           shared libraries will be built, so that it is unnecessary")
122  print("           to relink executables when the libraries that they depend")
123  print("           on change.  This is an option for developers who want to")
124  print("           increase the speed of frequent rebuilds.")
125  print("           *** Do not use unless you understand the consequences. ***")
126  print("")
127  print("  UNIX-specific options:")
128  print("")
129  print("  --installed-libs")
130  print("           Comma-separated list of Subversion libraries to find")
131  print("           pre-installed instead of building (probably only")
132  print("           useful for packagers)")
133  print("")
134  print("  Windows-specific options:")
135  print("")
136  print("  --with-apr=DIR")
137  print("           the APR sources are in DIR")
138  print("")
139  print("  --with-apr-util=DIR")
140  print("           the APR-Util sources are in DIR")
141  print("")
142  print("  --with-apr-iconv=DIR")
143  print("           the APR-Iconv sources are in DIR")
144  print("")
145  print("  --with-berkeley-db=DIR")
146  print("           look for Berkeley DB headers and libs in")
147  print("           DIR")
148  print("")
149  print("  --with-serf=DIR")
150  print("           the Serf sources are in DIR")
151  print("")
152  print("  --with-httpd=DIR")
153  print("           the httpd sources and binaries required")
154  print("           for building mod_dav_svn are in DIR;")
155  print("           implies --with-apr{-util, -iconv}, but")
156  print("           you can override them")
157  print("")
158  print("  --with-libintl=DIR")
159  print("           look for GNU libintl headers and libs in DIR;")
160  print("           implies --enable-nls")
161  print("")
162  print("  --with-openssl=DIR")
163  print("           tell serf to look for OpenSSL headers")
164  print("           and libs in DIR")
165  print("")
166  print("  --with-zlib=DIR")
167  print("           tell Subversion to look for ZLib headers and")
168  print("           libs in DIR")
169  print("")
170  print("  --with-jdk=DIR")
171  print("           look for the java development kit here")
172  print("")
173  print("  --with-junit=DIR")
174  print("           look for the junit jar here")
175  print("           junit is for testing the java bindings")
176  print("")
177  print("  --with-swig=DIR")
178  print("           look for the swig program in DIR")
179  print("")
180  print("  --with-sqlite=DIR")
181  print("           look for sqlite in DIR")
182  print("")
183  print("  --with-sasl=DIR")
184  print("           look for the sasl headers and libs in DIR")
185  print("")
186  print("  --enable-pool-debug")
187  print("           turn on APR pool debugging")
188  print("")
189  print("  --enable-purify")
190  print("           add support for Purify instrumentation;")
191  print("           implies --enable-pool-debug")
192  print("")
193  print("  --enable-quantify")
194  print("           add support for Quantify instrumentation")
195  print("")
196  print("  --enable-nls")
197  print("           add support for gettext localization")
198  print("")
199  print("  --disable-shared")
200  print("           only build static libraries")
201  print("")
202  print("  --with-static-apr")
203  print("           Use static apr and apr-util")
204  print("")
205  print("  --with-static-openssl")
206  print("           Use static openssl")
207  print("")
208  print("  --vsnet-version=VER")
209  print("           generate for VS.NET version VER (2002, 2003, 2005, 2008,")
210  print("           2010, 2012, 2013 or 2015)")
211  print("           [only valid in combination with '-t vcproj']")
212  print("")
213  print(" -D NAME[=value]")
214  print("           define NAME macro during compilation")
215  print("           [only valid in combination with '-t vcproj']")
216  print("")
217  print("  --with-apr_memcache=DIR")
218  print("           the apr_memcache sources are in DIR")
219  print("  --disable-gmock")
220  print("           do not use Googlemock")
221  sys.exit(1)
222
223
224class Options:
225  def __init__(self):
226    self.list = []
227    self.dict = {}
228
229  def add(self, opt, val, overwrite=True):
230    if opt in self.dict:
231      if overwrite:
232        self.list[self.dict[opt]] = (opt, val)
233    else:
234      self.dict[opt] = len(self.list)
235      self.list.append((opt, val))
236
237if __name__ == '__main__':
238  try:
239    opts, args = my_getopt(sys.argv[1:], 'st:D:',
240                           ['debug',
241                            'release',
242                            'reload',
243                            'assume-shared-libs',
244                            'with-apr=',
245                            'with-apr-util=',
246                            'with-apr-iconv=',
247                            'with-berkeley-db=',
248                            'with-serf=',
249                            'with-httpd=',
250                            'with-libintl=',
251                            'with-openssl=',
252                            'with-zlib=',
253                            'with-jdk=',
254                            'with-junit=',
255                            'with-swig=',
256                            'with-sqlite=',
257                            'with-sasl=',
258                            'with-apr_memcache=',
259                            'with-static-apr',
260                            'with-static-openssl',
261                            'enable-pool-debug',
262                            'enable-purify',
263                            'enable-quantify',
264                            'enable-nls',
265                            'disable-shared',
266                            'installed-libs=',
267                            'vsnet-version=',
268                            'disable-gmock',
269                            ])
270    if len(args) > 1:
271      _usage_exit("Too many arguments")
272  except getopt.GetoptError:
273    typ, val, tb = sys.exc_info()
274    msg = ''.join(traceback.format_exception_only(typ, val))
275    _usage_exit(msg)
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                 overwrite=False)
311        rest.add('--with-apr-util', os.path.join(val, 'srclib', 'apr-util'),
312                 overwrite=False)
313        rest.add('--with-apr-iconv', os.path.join(val, 'srclib', 'apr-iconv'),
314                 overwrite=False)
315
316  # Remember all options so that --reload and other scripts can use them
317  opt_conf = open('gen-make.opts', 'w')
318  opt_conf.write('[options]\n')
319  for opt, val in rest.list:
320    opt_conf.write(opt + ' = ' + val + '\n')
321  opt_conf.close()
322
323  if gentype not in gen_modules.keys():
324    _usage_exit("Unknown module type '%s'" % (gentype))
325
326  main(conf, gentype, skip_depends=skip, other_options=rest.list)
327
328
329### End of file.
330