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  'vcproj' : ('gen_vcnet_vcproj', 'VC.Net project files'),
52  }
53
54def main(fname, gentype, verfname=None,
55         skip_depends=0, other_options=None):
56  if verfname is None:
57    verfname = os.path.join('subversion', 'include', 'svn_version.h')
58
59  gen_module = __import__(gen_modules[gentype][0])
60
61  generator = gen_module.Generator(fname, verfname, other_options)
62
63  if not skip_depends:
64    generator.compute_hdr_deps()
65
66  generator.write()
67  generator.write_sqlite_headers()
68  generator.write_errno_table()
69  generator.write_config_keys()
70
71  if ('--debug', '') in other_options:
72    for dep_type, target_dict in generator.graph.deps.items():
73      sorted_targets = sorted(target_dict.keys(), key=str)
74      for target in sorted_targets:
75        print(dep_type + ": " + _objinfo(target))
76        for source in target_dict[target]:
77          print("  " + _objinfo(source))
78      print("=" * 72)
79    gen_keys = sorted(generator.__dict__.keys())
80    for name in gen_keys:
81      value = generator.__dict__[name]
82      if isinstance(value, list):
83        print(name + ": ")
84        for i in value:
85          print("  " + _objinfo(i))
86        print("=" * 72)
87
88
89def _objinfo(o):
90  if isinstance(o, str):
91    return repr(o)
92  else:
93    t = o.__class__.__name__
94    n = getattr(o, 'name', '-')
95    f = getattr(o, 'filename', '-')
96    return "%s: %s %s" % (t,n,f)
97
98
99def _usage_exit(err=None):
100  "print ERR (if any), print usage, then exit the script"
101  if err:
102    print("ERROR: %s\n" % (err))
103  print("USAGE:  gen-make.py [options...] [conf-file]")
104  print("  -s        skip dependency generation")
105  print("  --debug   print lots of stuff only developers care about")
106  print("  --release release mode")
107  print("  --reload  reuse all options from the previous invocation")
108  print("            of the script, except -s, -t, --debug and --reload")
109  print("  -t TYPE   use the TYPE generator; can be one of:")
110  items = sorted(gen_modules.items())
111  for name, (module, desc) in items:
112    print('            %-12s  %s' % (name, desc))
113  print("")
114  print("            The default generator type is 'make'")
115  print("")
116  print("  Makefile-specific options:")
117  print("")
118  print("  --assume-shared-libs")
119  print("           omit dependencies on libraries, on the assumption that")
120  print("           shared libraries will be built, so that it is unnecessary")
121  print("           to relink executables when the libraries that they depend")
122  print("           on change.  This is an option for developers who want to")
123  print("           increase the speed of frequent rebuilds.")
124  print("           *** Do not use unless you understand the consequences. ***")
125  print("")
126  print("  UNIX-specific options:")
127  print("")
128  print("  --installed-libs")
129  print("           Comma-separated list of Subversion libraries to find")
130  print("           pre-installed instead of building (probably only")
131  print("           useful for packagers)")
132  print("")
133  print("  Windows-specific options:")
134  print("")
135  print("  --with-apr=DIR")
136  print("           the APR sources are in DIR")
137  print("")
138  print("  --with-apr-util=DIR")
139  print("           the APR-Util sources are in DIR")
140  print("")
141  print("  --with-apr-iconv=DIR")
142  print("           the APR-Iconv sources are in DIR")
143  print("")
144  print("  --with-berkeley-db=DIR")
145  print("           look for Berkeley DB headers and libs in")
146  print("           DIR")
147  print("")
148  print("  --with-serf=DIR")
149  print("           the Serf sources are in DIR")
150  print("")
151  print("  --with-httpd=DIR")
152  print("           the httpd sources and binaries required")
153  print("           for building mod_dav_svn are in DIR;")
154  print("           implies --with-apr{-util, -iconv}, but")
155  print("           you can override them")
156  print("")
157  print("  --with-libintl=DIR")
158  print("           look for GNU libintl headers and libs in DIR;")
159  print("           implies --enable-nls")
160  print("")
161  print("  --with-openssl=DIR")
162  print("           tell serf to look for OpenSSL headers")
163  print("           and libs in DIR")
164  print("")
165  print("  --with-zlib=DIR")
166  print("           tell Subversion to look for ZLib headers and")
167  print("           libs in DIR")
168  print("")
169  print("  --with-jdk=DIR")
170  print("           look for the java development kit here")
171  print("")
172  print("  --with-junit=DIR")
173  print("           look for the junit jar here")
174  print("           junit is for testing the java bindings")
175  print("")
176  print("  --with-swig=DIR")
177  print("           look for the swig program in DIR")
178  print("  --with-py3c=DIR")
179  print("           look for the py3c library in DIR")
180  print("")
181  print("  --with-sqlite=DIR")
182  print("           look for sqlite in DIR")
183  print("")
184  print("  --with-sasl=DIR")
185  print("           look for the sasl headers and libs in DIR")
186  print("")
187  print("  --enable-pool-debug")
188  print("           turn on APR pool debugging")
189  print("")
190  print("  --enable-purify")
191  print("           add support for Purify instrumentation;")
192  print("           implies --enable-pool-debug")
193  print("")
194  print("  --enable-quantify")
195  print("           add support for Quantify instrumentation")
196  print("")
197  print("  --enable-nls")
198  print("           add support for gettext localization")
199  print("")
200  print("  --disable-shared")
201  print("           only build static libraries")
202  print("")
203  print("  --with-static-apr")
204  print("           Use static apr and apr-util")
205  print("")
206  print("  --with-static-openssl")
207  print("           Use static openssl")
208  print("")
209  print("  --vsnet-version=VER")
210  print("           generate for VS.NET version VER (2005-2017 or 9.0-15.0)")
211  print("           [implies '-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  sys.exit(1)
220
221
222class Options:
223  def __init__(self):
224    self.list = []
225    self.dict = {}
226
227  def add(self, opt, val, overwrite=True):
228    if opt in self.dict:
229      if overwrite:
230        self.list[self.dict[opt]] = (opt, val)
231    else:
232      self.dict[opt] = len(self.list)
233      self.list.append((opt, val))
234
235if __name__ == '__main__':
236  try:
237    opts, args = my_getopt(sys.argv[1:], 'st:D:',
238                           ['debug',
239                            'release',
240                            'reload',
241                            'assume-shared-libs',
242                            'with-apr=',
243                            'with-apr-util=',
244                            'with-apr-iconv=',
245                            'with-berkeley-db=',
246                            'with-serf=',
247                            'with-httpd=',
248                            'with-libintl=',
249                            'with-openssl=',
250                            'with-zlib=',
251                            'with-jdk=',
252                            'with-junit=',
253                            'with-swig=',
254                            'with-py3c=',
255                            'with-sqlite=',
256                            'with-sasl=',
257                            'with-apr_memcache=',
258                            'with-static-apr',
259                            'with-static-openssl',
260                            'enable-pool-debug',
261                            'enable-purify',
262                            'enable-quantify',
263                            'enable-nls',
264                            'disable-shared',
265                            'installed-libs=',
266                            'vsnet-version=',
267                            ])
268    if len(args) > 1:
269      _usage_exit("Too many arguments")
270  except getopt.GetoptError:
271    typ, val, tb = sys.exc_info()
272    msg = ''.join(traceback.format_exception_only(typ, val))
273    _usage_exit(msg)
274
275  conf = 'build.conf'
276  skip = 0
277  gentype = 'make'
278  rest = Options()
279
280  if args:
281    conf = args[0]
282
283  # First merge options with previously saved to gen-make.opts if --reload
284  # options used
285  for opt, val in opts:
286    if opt == '--reload':
287      prev_conf = configparser.ConfigParser()
288      prev_conf.read('gen-make.opts')
289      for opt, val in prev_conf.items('options'):
290        if opt != '--debug':
291          rest.add(opt, val)
292      del prev_conf
293    elif opt == '--with-neon' or opt == '--without-neon':
294      # Provide a warning that we ignored these arguments
295      print("Ignoring no longer supported argument '%s'" % opt)
296    else:
297      rest.add(opt, val)
298
299  # Parse options list
300  for opt, val in rest.list:
301    if opt == '-s':
302      skip = 1
303    elif opt == '-t':
304      gentype = val
305    elif opt == '--vsnet-version':
306      gentype = 'vcproj'
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