blob: 0f2149e2c3736a2b25ea8e1f9338afa5beb6e670 [file] [log] [blame]
#
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#
import os
import sys
import shutil
import getopt
try:
my_getopt = getopt.gnu_getopt
except AttributeError:
my_getopt = getopt.getopt
import glob
import traceback
try:
# Python >=3.0
import configparser
except ImportError:
# Python <3.0
import ConfigParser as configparser
# The script directory and the source base directory
_scriptdir = os.path.dirname(sys.argv[0])
_srcdir = os.path.join(_scriptdir, '..', '..')
_distname = None
_distdir = None
_readme = None
_stdout = sys.stdout
_stderr = sys.stderr
_logname = os.path.abspath(os.path.join(_scriptdir, 'make_dist.log'))
_logfile = open(_logname, 'w')
sys.stdout = _logfile
sys.stderr = _logfile
def _exit(code=0):
if code:
_stderr.write('make_dist: Exit %d\n' % (code,))
sys.exit(code)
# Action classes
class MissingMethodImpl:
pass
class Action:
def run(self, dir, cfg):
raise MissingMethodImpl()
def _expand(self, cfg, value):
cfg.set('__expand__', '__expand__', value)
return cfg.get('__expand__', '__expand__')
def _safe_expand(self, cfg, value):
try:
return self._expand(cfg, value)
except:
return None
def _copy_file(self, source, target):
print('copy: %s' % source)
print(' to: %s' % target)
shutil.copyfile(source, target)
class File(Action):
def __init__(self, path, name=None):
self.path = path
self.name = name
def run(self, dir, cfg):
path = self._expand(cfg, self.path)
if self.name is None:
name = os.path.basename(path)
else:
name = self.name
self._copy_file(path, os.path.join(dir, name))
class OptFile(Action):
def __init__(self, path, name=None):
self.path = path
self.name = name
def run(self, dir, cfg):
path = self._safe_expand(cfg, self.path)
if path is None or not os.path.isfile(path):
print('make_dist: File not found: %s' % self.path)
return
if self.name is None:
name = os.path.basename(path)
else:
name = self.name
self._copy_file(path, os.path.join(dir, name))
class FileGlob(Action):
def __init__(self, pattern):
self.pattern = pattern
def run(self, dir, cfg):
pattern = self._expand(cfg, self.pattern)
for source in glob.glob(pattern):
self._copy_file(source, os.path.join(dir, os.path.basename(source)))
class InstallDocs(Action):
def __init__(self, config, path):
self.config = config
self.path = path
def run(self, dir, cfg):
config = self._expand(cfg, self.config)
pattern = os.path.join(self._expand(cfg, self.path), '*.*')
print('make_dist: Generating documentation')
old_cwd = os.getcwd()
try:
os.chdir(_srcdir)
_system('"%s" "%s"' % (cfg.get('tools', 'doxygen'), config))
os.chdir(old_cwd)
FileGlob(pattern).run(dir, cfg)
except:
os.chdir(old_cwd)
raise
else:
os.chdir(old_cwd)
class InstallIconv(Action):
def __init__(self, source, build_mode):
self.source = source
self.build_mode = build_mode
def run(self, dir, cfg):
source = os.path.abspath(self._expand(cfg, self.source))
build_mode = self._expand(cfg, self.build_mode)
print('make_dist: Installing apr-iconv modules')
install = ('"%s" -nologo -f Makefile.win install'
+ ' INSTALL_DIR="%s"'
+ ' BUILD_MODE=%s BIND_MODE=%s') \
% (cfg.get('tools', 'nmake'),
os.path.abspath(dir),
build_mode,
'shared')
old_cwd = os.getcwd()
try:
os.chdir(os.path.join(source, 'ccs'))
_system(install)
os.chdir(os.path.join(source, 'ces'))
_system(install)
except:
os.chdir(old_cwd)
raise
else:
os.chdir(old_cwd)
class InstallJar(Action):
def __init__(self, jar, source):
self.jar = jar
self.source = source
def run(self, dir, cfg):
source = os.path.abspath(self._expand(cfg, self.source))
jarfile = os.path.abspath(os.path.join(dir, self.jar))
print('make_dist: Creating jar %s' % self.jar)
_system('"%s" cvf "%s" -C "%s" .'
% (cfg.get('tools', 'jar'), jarfile, source))
class InstallMoFiles(Action):
def __init__(self, source):
self.source = source
def run(self, dir, cfg):
pattern = os.path.join(self._expand(cfg, self.source), '*.mo')
for mofile in glob.glob(pattern):
localedir = os.path.join(dir, os.path.basename(mofile)[:-3],
'LC_MESSAGES')
os.makedirs(localedir)
self._copy_file(mofile, os.path.join(localedir, 'subversion.mo'))
# This is the distribution tree
_disttree = {'': OptFile('%(readme)s', 'README.txt'),
'bin': (File('%(blddir)s/svn/svn.exe'),
File('%(blddir)s/svn/svn.pdb'),
File('%(blddir)s/svnsync/svnsync.pdb'),
File('%(blddir)s/svnsync/svnsync.exe'),
File('%(blddir)s/svnadmin/svnadmin.exe'),
File('%(blddir)s/svnadmin/svnadmin.pdb'),
File('%(blddir)s/svnlook/svnlook.exe'),
File('%(blddir)s/svnlook/svnlook.pdb'),
File('%(blddir)s/svndumpfilter/svndumpfilter.exe'),
File('%(blddir)s/svndumpfilter/svndumpfilter.pdb'),
File('%(blddir)s/svnserve/svnserve.exe'),
File('%(blddir)s/svnserve/svnserve.pdb'),
File('%(blddir)s/svnversion/svnversion.exe'),
File('%(blddir)s/svnversion/svnversion.pdb'),
File('%(blddir)s/svnrdump/svnrdump.exe'),
File('%(blddir)s/svnrdump/svnrdump.pdb'),
File('%(blddir)s/svnmucc/svnmucc.exe'),
File('%(blddir)s/svnmucc/svnmucc.pdb'),
File('%(blddir)s/../contrib/client-side/svn-push/svn-push.exe'),
File('%(blddir)s/../contrib/client-side/svn-push/svn-push.pdb'),
File('%(blddir)s/../tools/server-side/svnauthz.exe'),
File('%(blddir)s/../tools/server-side/svnauthz.pdb'),
File('%(blddir)s/../tools/server-side/svnauthz-validate.exe'),
File('%(blddir)s/../tools/server-side/svnauthz-validate.pdb'),
File('%(blddir)s/../tools/server-side/svn-populate-node-origins-index.exe'),
File('%(blddir)s/../tools/server-side/svn-populate-node-origins-index.pdb'),
File('%(blddir)s/../tools/dev/svnraisetreeconflict/svnraisetreeconflict.exe'),
File('%(blddir)s/../tools/dev/svnraisetreeconflict/svnraisetreeconflict.pdb'),
File('%(blddir)s/mod_dav_svn/mod_dav_svn.so'),
File('%(blddir)s/mod_dav_svn/mod_dav_svn.pdb'),
File('%(blddir)s/mod_authz_svn/mod_authz_svn.so'),
File('%(blddir)s/mod_authz_svn/mod_authz_svn.pdb'),
FileGlob('%(blddir)s/libsvn_*/libsvn_*.dll'),
FileGlob('%(blddir)s/libsvn_*/libsvn_*.pdb'),
File('%(@apr)s/%(aprrel)s/libapr-1.dll'),
File('%(@apr)s/%(aprrel)s/libapr-1.pdb'),
File('%(@apr-iconv)s/%(aprrel)s/libapriconv-1.dll'),
File('%(@apr-iconv)s/%(aprrel)s/libapriconv-1.pdb'),
File('%(@apr-util)s/%(aprrel)s/libaprutil-1.dll'),
File('%(@apr-util)s/%(aprrel)s/libaprutil-1.pdb'),
File('%(@berkeley-db)s/bin/libdb%(bdbver)s.dll'),
File('%(@sasl)s/lib/libsasl.dll'),
File('%(@sasl)s/lib/libsasl.pdb'),
File('%(@sasl)s/utils/pluginviewer.exe'),
File('%(@sasl)s/utils/pluginviewer.pdb'),
File('%(@sasl)s/utils/sasldblistusers2.exe'),
File('%(@sasl)s/utils/sasldblistusers2.pdb'),
File('%(@sasl)s/utils/saslpasswd2.exe'),
File('%(@sasl)s/utils/saslpasswd2.pdb'),
OptFile('%(@berkeley-db)s/bin/libdb%(bdbver)s.pdb'),
OptFile('%(@sqlite)s/bin/sqlite3.dll'),
OptFile('%(@openssl)s/out32dll/libeay32.dll'),
OptFile('%(@openssl)s/out32dll/libeay32.pdb'),
OptFile('%(@openssl)s/out32dll/ssleay32.dll'),
OptFile('%(@openssl)s/out32dll/ssleay32.pdb'),
OptFile('%(@openssl)s/out32dll/openssl.exe'),
OptFile('%(@libintl)s/bin/intl3_svn.dll'),
OptFile('%(@libintl)s/bin/intl3_svn.pdb'),
FileGlob('%(@sasl)s/plugins/sasl*.dll'),
FileGlob('%(@sasl)s/plugins/sasl*.pdb'),
),
'doc': InstallDocs('%(srcdir)s/doc/doxygen.conf',
'%(srcdir)s/doc/doxygen/html'),
'iconv': InstallIconv('%(@apr-iconv)s', '%(aprrel)s'),
'include': FileGlob('%(svndir)s/include/*.h'),
'include/apr': FileGlob('%(@apr)s/include/*.h'),
'include/apr-iconv': FileGlob('%(@apr-iconv)s/include/*.h'),
'include/apr-util': FileGlob('%(@apr-util)s/include/*.h'),
'lib': (FileGlob('%(blddir)s/libsvn_*/*.lib'),
FileGlob('%(blddir)s/libsvn_*/*.pdb')),
'lib/apr': File('%(@apr)s/%(aprrel)s/libapr-1.lib'),
'lib/apr-iconv': File('%(@apr-iconv)s/%(aprrel)s/libapriconv-1.lib'),
'lib/apr-util': (File('%(@apr-util)s/%(aprrel)s/libaprutil-1.lib'),
File('%(@apr-util)s/%(aprxml)s/xml.lib'),
File('%(@apr-util)s/%(aprxml)s/xml.pdb'),
),
'lib/serf': (File('%(@serf)s/Release/serf.lib'),
),
'lib/sasl': (File('%(@sasl)s/lib/libsasl.lib'),
File('%(@sasl)s/lib/libsasl.pdb'),
),
'licenses': None,
'licenses/bdb': File('%(@berkeley-db)s/LICENSE'),
'licenses/serf': File('%(@serf)s/LICENSE'),
'licenses/zlib': File('%(@zlib)s/README'),
'licenses/apr-util': (File('%(@apr-util)s/LICENSE'),
File('%(@apr-util)s/NOTICE'),
),
'licenses/apr-iconv': (File('%(@apr-iconv)s/LICENSE'),
File('%(@apr-iconv)s/NOTICE'),
),
'licenses/apr': (File('%(@apr)s/LICENSE'),
File('%(@apr)s/NOTICE'),
),
'licenses/openssl': File('%(@openssl)s/LICENSE'),
'licenses/svn' : File('%(srcdir)s/COPYING'),
'licenses/cyrus-sasl' : File('%(@sasl)s/COPYING'),
'perl': None,
'perl/site': None,
'perl/site/lib': None,
'perl/site/lib/SVN': FileGlob('%(bindsrc)s/swig/perl/native/*.pm'),
'perl/site/lib/auto': None,
'perl/site/lib/auto/SVN': None,
# Perl module DLLs defined below
'python': None,
'python/libsvn': (FileGlob('%(binddir)s/swig/python/libsvn_swig_py/*.dll'),
FileGlob('%(binddir)s/swig/python/libsvn_swig_py/*.pdb'),
FileGlob('%(bindsrc)s/swig/python/*.py'),
FileGlob('%(binddir)s/swig/python/*.dll'),
FileGlob('%(binddir)s/swig/python/*.pdb'),
),
'python/svn': FileGlob('%(bindsrc)s/swig/python/svn/*.py'),
'javahl': (FileGlob('%(binddir)s/javahl/native/libsvn*.dll'),
FileGlob('%(binddir)s/javahl/native/libsvn*.pdb'),
InstallJar('svnjavahl.jar',
'%(bindsrc)s/javahl/classes'),
),
'ruby': None,
'ruby/lib': None,
'ruby/lib/svn': FileGlob('%(bindsrc)s/swig/ruby/svn/*.rb'),
'ruby/ext': None,
'ruby/ext/svn': None,
'ruby/ext/svn/ext':
(FileGlob('%(binddir)s/swig/ruby/*.dll'),
FileGlob('%(binddir)s/swig/ruby/*.pdb'),
FileGlob('%(binddir)s/swig/ruby/libsvn_swig_ruby/*.dll'),
FileGlob('%(binddir)s/swig/ruby/libsvn_swig_ruby/*.pdb'),
FileGlob('%(blddir)s/libsvn_*/*.dll'),
File('%(@berkeley-db)s/bin/libdb%(bdbver)s.dll'),
OptFile('%(@sqlite)s/bin/sqlite3.dll'),
OptFile('%(@libintl)s/bin/intl3_svn.dll'),
File('%(@apr)s/%(aprrel)s/libapr-1.dll'),
File('%(@apr-iconv)s/%(aprrel)s/libapriconv-1.dll'),
File('%(@apr-util)s/%(aprrel)s/libaprutil-1.dll')),
'share': None,
'share/locale': InstallMoFiles('%(srcdir)s/%(svnrel)s/mo'),
}
# Define Perl module DLLs
for module in ('Client', 'Core', 'Delta', 'Fs', 'Ra', 'Repos', 'Wc'):
_disttree['perl/site/lib/auto/SVN/_' + module] = (
File('%(binddir)s/swig/perl/native/_' + module + '.dll'),
File('%(binddir)s/swig/perl/native/_' + module + '.pdb'))
def _system(command):
def reopen_log():
global _logfile
_logfile = open(_logname, 'a')
sys.stdout = _logfile
sys.stderr = _logfile
try:
_logfile.close()
sys.stdout = _stdout
sys.stderr = _stderr
os.system('"%s >>%s 2>&1"' % (command, _logname))
except:
reopen_log()
raise
else:
reopen_log()
def _read_config():
# Read make_dist.conf first. Fill in the default package locations.
path_defaults = {'@berkeley-db':
os.path.abspath(os.path.join(_srcdir, 'db4-win32')),
'@apr':
os.path.abspath(os.path.join(_srcdir, 'apr')),
'@apr-iconv':
os.path.abspath(os.path.join(_srcdir, 'apr-iconv')),
'@apr-util':
os.path.abspath(os.path.join(_srcdir, 'apr-util')),
}
cfg = configparser.ConfigParser(path_defaults)
try:
cfg.readfp(open(os.path.join(_scriptdir, 'make_dist.conf'), 'r'))
except:
_stderr.write('Unable to open and read make_dist.conf\n')
_exit(1)
# Read the options config generated by gen-make.py
optcfg = configparser.ConfigParser()
optcfg.readfp(open(os.path.join(_srcdir, 'gen-make.opts'), 'r'))
# Move the runtime options into the DEFAULT section
for opt in optcfg.options('options'):
if not opt[:7] == '--with-':
continue
optdir = os.path.abspath(os.path.join(_srcdir, optcfg.get('options', opt)))
if not os.path.isdir(optdir):
print('make_dist: %s = %s' % (opt, optdir))
print('make_dist: Target is not a directory')
_exit(1)
cfg.set('DEFAULT', '@' + opt[7:], optdir)
# Also add the global parameters to the defaults
cfg.set('DEFAULT', 'srcdir', os.path.abspath(_srcdir))
cfg.set('DEFAULT', 'blddir', os.path.join(_srcdir,
'%(svnrel)s', 'subversion'))
cfg.set('DEFAULT', 'svndir', os.path.join(_srcdir, 'subversion'))
cfg.set('DEFAULT', 'binddir', '%(blddir)s/bindings')
cfg.set('DEFAULT', 'bindsrc', '%(svndir)s/bindings')
if _distname is not None:
cfg.set('DEFAULT', 'distname', os.path.abspath(_distname))
if _distdir is not None:
cfg.set('DEFAULT', 'distdir', os.path.abspath(_distdir))
if _readme is not None:
cfg.set('DEFAULT', 'readme', os.path.abspath(_readme))
return cfg
def _make_zip(suffix, pathlist, extras):
zipname = '%s%s.zip' % (_distname, suffix)
zipcmd = '"%s" -9 -r "%s"' % (cfg.get('tools', 'zip'), zipname)
for path in pathlist:
zipcmd = zipcmd + ' "' + _distname + path + '"'
if extras:
zipcmd = zipcmd + ' ' + extras
old_cwd = os.getcwd()
try:
os.chdir(_distdir)
if os.path.exists(zipname):
os.remove(zipname)
print('make_dist: Creating %s' % zipname)
_stdout.write('make_dist: Creating %s\n' % zipname)
_system(zipcmd)
except:
os.chdir(old_cwd)
raise
else:
os.chdir(old_cwd)
def _make_dist(cfg):
try:
cfg.add_section('__expand__')
distdir = os.path.abspath(os.path.join(_distdir, _distname))
if os.path.isdir(distdir):
shutil.rmtree(distdir)
os.makedirs(distdir)
dirlist = sorted(_disttree.keys())
for reldir in dirlist:
dir = os.path.join(distdir, reldir)
if not os.path.exists(dir):
print('make_dist: Creating directory %s' % reldir)
_stdout.write('make_dist: Creating directory %s\n' % reldir)
os.makedirs(dir)
action = _disttree[reldir]
if action is None:
continue
if isinstance(action, tuple):
for subaction in action:
subaction.run(dir, cfg)
else:
action.run(dir, cfg)
xpdb = '-x "*.pdb"'
_make_zip('', ('/README.txt', '/bin', '/httpd',
'/iconv', '/licenses', '/share/locale'), xpdb)
_make_zip('_dev', ('/README.txt', '/doc', '/include', '/lib'), xpdb)
_make_zip('_javahl', ('/README.txt', '/javahl'), xpdb)
_make_zip('_pdb', ('',), '-i "*.pdb"')
_make_zip('_pl', ('/README.txt', '/perl'), xpdb)
_make_zip('_py', ('/README.txt', '/python'), xpdb)
_make_zip('_rb', ('/README.txt', '/ruby', '/licenses', '/share/locale'),
xpdb)
_stdout.write('make_dist: Creating ruby gem\n')
gem_script = os.path.join(_scriptdir, 'make_gem.rb')
rubycmd = '"%s" "%s" --output-dir="%s"' % (cfg.get('tools', 'ruby'),
gem_script, _distdir)
rubycmd += ' "' + distdir + '\\README.txt"'
rubycmd += ' "' + distdir + '\\ruby"'
rubycmd += ' "' + distdir + '\\licenses"'
rubycmd += ' "' + distdir + '\\share"'
_system(rubycmd)
except:
traceback.print_exc(None, _stderr)
_exit(1)
if __name__ == '__main__':
opts, args = my_getopt(sys.argv[1:], '', ['readme='])
if len(args) != 2 or len(opts) > 1:
_stderr.write('Usage: make_dist.py [--readme=<file>] <distname> <distdir>\n')
_exit(2)
_distname, _distdir = args
if len(opts) != 0:
_readme = opts[0][1]
cfg = _read_config()
_make_dist(cfg)