Win32/NMake builds: Support builds from GIT (#498)
Add Python scripts to generate the full win32/config.h.win32 and src/hb-version.h which can be used to build directly from a GIT checkout. Since the scripts are currently intended for building from a GIT checkout, these are not distributed in the release tarballs. Also, support the re-build of Ragel-generated .hh headers using the NMake build system, and allow one to specify the path of the Ragel executable if a suitable one cannot be found in the PATH. Update the Win32/NMake build documentation to let people know about how these mechanisms can be utilized.pull/257/merge
parent
3b0e47ca00
commit
ad52e044bc
9 changed files with 353 additions and 3 deletions
@ -0,0 +1,124 @@ |
||||
#!/usr/bin/python |
||||
# |
||||
# Simple utility script to generate the basic info |
||||
# needed in a .pc (pkg-config) file, used especially |
||||
# for introspection purposes |
||||
|
||||
# This can be used in various projects where |
||||
# there is the need to generate .pc files, |
||||
# and is copied from GLib's $(srcroot)/win32 |
||||
|
||||
# Author: Fan, Chun-wei |
||||
# Date: March 10, 2016 |
||||
|
||||
import os |
||||
import sys |
||||
import argparse |
||||
|
||||
class BasePCItems: |
||||
def __init__(self): |
||||
self.base_replace_items = {} |
||||
self.exec_prefix = '' |
||||
self.includedir = '' |
||||
self.libdir = '' |
||||
self.prefix = '' |
||||
self.srcdir = os.path.dirname(__file__) |
||||
self.top_srcdir = self.srcdir + '\\..' |
||||
self.version = '' |
||||
|
||||
def setup(self, argv, parser=None): |
||||
if parser is None: |
||||
parser = argparse.ArgumentParser(description='Setup basic .pc file info') |
||||
parser.add_argument('--prefix', help='prefix of the installed library', |
||||
required=True) |
||||
parser.add_argument('--exec-prefix', |
||||
help='prefix of the installed programs, \ |
||||
if different from the prefix') |
||||
parser.add_argument('--includedir', |
||||
help='includedir of the installed library, \ |
||||
if different from ${prefix}/include') |
||||
parser.add_argument('--libdir', |
||||
help='libdir of the installed library, \ |
||||
if different from ${prefix}/lib') |
||||
parser.add_argument('--version', help='Version of the package', |
||||
required=True) |
||||
args = parser.parse_args() |
||||
|
||||
self.version = args.version |
||||
|
||||
# check whether the prefix and exec_prefix are valid |
||||
if not os.path.exists(args.prefix): |
||||
raise SystemExit('Specified prefix \'%s\' is invalid' % args.prefix) |
||||
|
||||
# use absolute paths for prefix |
||||
self.prefix = os.path.abspath(args.prefix).replace('\\','/') |
||||
|
||||
# check and setup the exec_prefix |
||||
if getattr(args, 'exec_prefix', None) is None: |
||||
exec_prefix_use_shorthand = True |
||||
self.exec_prefix = '${prefix}' |
||||
else: |
||||
if args.exec_prefix.startswith('${prefix}'): |
||||
exec_prefix_use_shorthand = True |
||||
input_exec_prefix = args.prefix + args.exec_prefix[len('${prefix}'):] |
||||
else: |
||||
exec_prefix_use_shorthand = False |
||||
input_exec_prefix = args.exec_prefix |
||||
if not os.path.exists(input_exec_prefix): |
||||
raise SystemExit('Specified exec_prefix \'%s\' is invalid' % |
||||
args.exec_prefix) |
||||
if exec_prefix_use_shorthand is True: |
||||
self.exec_prefix = args.exec_prefix.replace('\\','/') |
||||
else: |
||||
self.exec_prefix = os.path.abspath(input_exec_prefix).replace('\\','/') |
||||
|
||||
# check and setup the includedir |
||||
if getattr(args, 'includedir', None) is None: |
||||
self.includedir = '${prefix}/include' |
||||
else: |
||||
if args.includedir.startswith('${prefix}'): |
||||
includedir_use_shorthand = True |
||||
input_includedir = args.prefix + args.includedir[len('${prefix}'):] |
||||
else: |
||||
if args.includedir.startswith('${exec_prefix}'): |
||||
includedir_use_shorthand = True |
||||
input_includedir = input_exec_prefix + args.includedir[len('${exec_prefix}'):] |
||||
else: |
||||
includedir_use_shorthand = False |
||||
input_includedir = args.includedir |
||||
if not os.path.exists(input_includedir): |
||||
raise SystemExit('Specified includedir \'%s\' is invalid' % |
||||
args.includedir) |
||||
if includedir_use_shorthand is True: |
||||
self.includedir = args.includedir.replace('\\','/') |
||||
else: |
||||
self.includedir = os.path.abspath(input_includedir).replace('\\','/') |
||||
|
||||
# check and setup the libdir |
||||
if getattr(args, 'libdir', None) is None: |
||||
self.libdir = '${prefix}/lib' |
||||
else: |
||||
if args.libdir.startswith('${prefix}'): |
||||
libdir_use_shorthand = True |
||||
input_libdir = args.prefix + args.libdir[len('${prefix}'):] |
||||
else: |
||||
if args.libdir.startswith('${exec_prefix}'): |
||||
libdir_use_shorthand = True |
||||
input_libdir = input_exec_prefix + args.libdir[len('${exec_prefix}'):] |
||||
else: |
||||
libdir_use_shorthand = False |
||||
input_libdir = args.libdir |
||||
if not os.path.exists(input_libdir): |
||||
raise SystemExit('Specified libdir \'%s\' is invalid' % |
||||
args.libdir) |
||||
if libdir_use_shorthand is True: |
||||
self.libdir = args.libdir.replace('\\','/') |
||||
else: |
||||
self.libdir = os.path.abspath(input_libdir).replace('\\','/') |
||||
|
||||
# setup dictionary for replacing items in *.pc.in |
||||
self.base_replace_items.update({'@VERSION@': self.version}) |
||||
self.base_replace_items.update({'@prefix@': self.prefix}) |
||||
self.base_replace_items.update({'@exec_prefix@': self.exec_prefix}) |
||||
self.base_replace_items.update({'@libdir@': self.libdir}) |
||||
self.base_replace_items.update({'@includedir@': self.includedir}) |
@ -0,0 +1,115 @@ |
||||
#!/usr/bin/python |
||||
# |
||||
# Simple utility script to manipulate |
||||
# certain types of strings in a file |
||||
|
||||
# This can be used in various projects where |
||||
# there is the need to replace strings in files, |
||||
# and is copied from GLib's $(srcroot)/win32 |
||||
|
||||
# Author: Fan, Chun-wei |
||||
# Date: September 03, 2014 |
||||
|
||||
import os |
||||
import sys |
||||
import re |
||||
import string |
||||
import argparse |
||||
|
||||
valid_actions = ['remove-prefix', |
||||
'replace-var', |
||||
'replace-str', |
||||
'remove-str'] |
||||
|
||||
def open_file(filename, mode): |
||||
if sys.version_info[0] < 3: |
||||
return open(filename, mode=mode) |
||||
else: |
||||
return open(filename, mode=mode, encoding='utf-8') |
||||
|
||||
def replace_multi(src, dest, replace_items): |
||||
with open_file(src, 'r') as s: |
||||
with open_file(dest, 'w') as d: |
||||
for line in s: |
||||
replace_dict = dict((re.escape(key), value) \ |
||||
for key, value in replace_items.items()) |
||||
replace_pattern = re.compile("|".join(replace_dict.keys())) |
||||
d.write(replace_pattern.sub(lambda m: \ |
||||
replace_dict[re.escape(m.group(0))], line)) |
||||
|
||||
def replace(src, dest, instring, outstring): |
||||
replace_item = {instring: outstring} |
||||
replace_multi(src, dest, replace_item) |
||||
|
||||
def check_required_args(args, params): |
||||
for param in params: |
||||
if getattr(args, param, None) is None: |
||||
raise SystemExit('%s: error: --%s argument is required' % (__file__, param)) |
||||
|
||||
def warn_ignored_args(args, params): |
||||
for param in params: |
||||
if getattr(args, param, None) is not None: |
||||
print('%s: warning: --%s argument is ignored' % (__file__, param)) |
||||
|
||||
def main(argv): |
||||
|
||||
parser = argparse.ArgumentParser(description='Process strings in a file.') |
||||
parser.add_argument('-a', |
||||
'--action', |
||||
help='Action to carry out. Can be one of:\n' |
||||
'remove-prefix\n' |
||||
'replace-var\n' |
||||
'replace-str\n' |
||||
'remove-str', |
||||
choices=valid_actions) |
||||
parser.add_argument('-i', '--input', help='Input file') |
||||
parser.add_argument('-o', '--output', help='Output file') |
||||
parser.add_argument('--instring', help='String to replace or remove') |
||||
parser.add_argument('--var', help='Autotools variable name to replace') |
||||
parser.add_argument('--outstring', |
||||
help='New String to replace specified string or variable') |
||||
parser.add_argument('--removeprefix', help='Prefix of string to remove') |
||||
|
||||
args = parser.parse_args() |
||||
|
||||
input_string = '' |
||||
output_string = '' |
||||
|
||||
# We must have action, input, output for all operations |
||||
check_required_args(args, ['action','input','output']) |
||||
|
||||
# Build the arguments by the operation that is to be done, |
||||
# to be fed into replace() |
||||
|
||||
# Get rid of prefixes from a string |
||||
if args.action == 'remove-prefix': |
||||
check_required_args(args, ['instring','removeprefix']) |
||||
warn_ignored_args(args, ['outstring','var']) |
||||
input_string = args.removeprefix + args.instring |
||||
output_string = args.instring |
||||
|
||||
# Replace an m4-style variable (those surrounded by @...@) |
||||
if args.action == 'replace-var': |
||||
check_required_args(args, ['var','outstring']) |
||||
warn_ignored_args(args, ['instring','removeprefix']) |
||||
input_string = '@' + args.var + '@' |
||||
output_string = args.outstring |
||||
|
||||
# Replace a string |
||||
if args.action == 'replace-str': |
||||
check_required_args(args, ['instring','outstring']) |
||||
warn_ignored_args(args, ['var','removeprefix']) |
||||
input_string = args.instring |
||||
output_string = args.outstring |
||||
|
||||
# Remove a string |
||||
if args.action == 'remove-str': |
||||
check_required_args(args, ['instring']) |
||||
warn_ignored_args(args, ['var','outstring','removeprefix']) |
||||
input_string = args.instring |
||||
output_string = '' |
||||
|
||||
replace(args.input, args.output, input_string, output_string) |
||||
|
||||
if __name__ == '__main__': |
||||
sys.exit(main(sys.argv)) |
@ -0,0 +1,62 @@ |
||||
#!/usr/bin/python |
||||
# vim: encoding=utf-8 |
||||
#expand *.in files |
||||
#this script is only intended for building from git, not for building from the released tarball, which already includes all necessary files |
||||
import os |
||||
import sys |
||||
import re |
||||
import string |
||||
import subprocess |
||||
import optparse |
||||
from pc_base import BasePCItems |
||||
from replace import replace_multi |
||||
|
||||
def get_version_items(srcroot): |
||||
ver = {} |
||||
RE_VERSION_LINE_START = re.compile(r'^AC_INIT\(\[(.+)\], *\n') |
||||
RE_VERSION_LINE_BODY = re.compile(r'^ \[(.+)\], *\n') |
||||
RE_VERSION_LINE_END = re.compile(r'^ \[(.+)\]\) *\n') |
||||
|
||||
# Read from the AC_INIT lines to get the version/name/URLs info |
||||
with open(os.path.join(srcroot, 'configure.ac'), 'r') as ac: |
||||
for i in ac: |
||||
mo_init = RE_VERSION_LINE_START.search(i) |
||||
mo_pkg_info = RE_VERSION_LINE_BODY.search(i) |
||||
mo_pkg_url = RE_VERSION_LINE_END.search(i) |
||||
if mo_init: |
||||
ver['@PACKAGE_NAME@'] = mo_init.group(1) |
||||
if mo_pkg_info: |
||||
if mo_pkg_info.group(1).startswith('http'): |
||||
ver['@PACKAGE_BUGREPORT@'] = mo_pkg_info.group(1) |
||||
elif mo_pkg_info.group(1)[0].isdigit(): |
||||
ver['@PACKAGE_VERSION@'] = mo_pkg_info.group(1) |
||||
else: |
||||
ver['@PACKAGE_TARNAME@'] = mo_pkg_info.group(1) |
||||
if mo_pkg_url: |
||||
ver['@PACKAGE_URL@'] = mo_pkg_url.group(1) |
||||
|
||||
ver['@HB_VERSION@'] = ver['@PACKAGE_VERSION@'] |
||||
|
||||
pkg_ver_parts = ver['@PACKAGE_VERSION@'].split('.') |
||||
ver['@HB_VERSION_MAJOR@'] = pkg_ver_parts[0] |
||||
ver['@HB_VERSION_MINOR@'] = pkg_ver_parts[1] |
||||
ver['@HB_VERSION_MICRO@'] = pkg_ver_parts[2] |
||||
return ver |
||||
|
||||
def main(argv): |
||||
pc = BasePCItems() |
||||
srcroot = pc.top_srcdir |
||||
srcdir = pc.srcdir |
||||
ver = get_version_items(srcroot) |
||||
|
||||
replace_multi(os.path.join(srcdir, 'config.h.win32.in'), |
||||
os.path.join(srcdir, 'config.h.win32'), |
||||
ver) |
||||
|
||||
replace_multi(os.path.join(srcroot, 'src', 'hb-version.h.in'), |
||||
os.path.join(srcroot, 'src', 'hb-version.h'), |
||||
ver) |
||||
return 0 |
||||
|
||||
if __name__ == '__main__': |
||||
sys.exit(main(sys.argv)) |
Loading…
Reference in new issue