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