173 lines
6.3 KiB
Text
173 lines
6.3 KiB
Text
|
#! /usr/bin/env python3
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
# rebuild-fgdata-embedded-resources -- Rebuild FGData-resources.[ch]xx
|
||
|
# Copyright (C) 2017 Florent Rougon
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License as published by
|
||
|
# the Free Software Foundation; either version 2 of the License, or
|
||
|
# (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License along
|
||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
|
||
|
# Only standard modules so that distributors can easily run this script, in
|
||
|
# case they want to recreate FGData-resources.[ch]xx from source.
|
||
|
import argparse
|
||
|
import json
|
||
|
import locale
|
||
|
import logging
|
||
|
import os
|
||
|
import subprocess
|
||
|
import sys
|
||
|
|
||
|
PROGNAME = os.path.basename(sys.argv[0])
|
||
|
CONFIG_FILE = os.path.join(os.path.expanduser('~'),
|
||
|
".fgmeta",
|
||
|
PROGNAME + ".json")
|
||
|
|
||
|
# chLevel: console handler level
|
||
|
def setupLogging(level=logging.NOTSET, chLevel=None):
|
||
|
global logger
|
||
|
|
||
|
if chLevel is None:
|
||
|
chLevel = level
|
||
|
|
||
|
logger = logging.getLogger(__name__)
|
||
|
# Effective level for all child loggers with NOTSET level
|
||
|
logger.setLevel(level)
|
||
|
# Create console handler and set its level
|
||
|
ch = logging.StreamHandler() # Uses sys.stderr by default
|
||
|
ch.setLevel(chLevel) # NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||
|
# Logger name with :%(name)s... many other things available, including
|
||
|
# %(levelname)s
|
||
|
formatter = logging.Formatter("{}: %(message)s".format(PROGNAME))
|
||
|
# Add formatter to ch
|
||
|
ch.setFormatter(formatter)
|
||
|
# Add ch to logger
|
||
|
logger.addHandler(ch)
|
||
|
|
||
|
|
||
|
# Modifies 'params' in-place
|
||
|
def loadCfgFileSection(params, jsonTree, title, items):
|
||
|
# NB: !!! each item is subject to os.path.expanduser() !!!
|
||
|
try:
|
||
|
section = jsonTree[title]
|
||
|
except KeyError:
|
||
|
pass
|
||
|
else:
|
||
|
for name in items:
|
||
|
try:
|
||
|
path = section[name]
|
||
|
except KeyError:
|
||
|
pass
|
||
|
else:
|
||
|
setattr(params, name.lower(), os.path.expanduser(path))
|
||
|
|
||
|
|
||
|
# Modifies 'params' in-place
|
||
|
def loadConfigFile(params):
|
||
|
if not os.path.isfile(CONFIG_FILE):
|
||
|
return
|
||
|
|
||
|
# The log level is set too late for this one -> commented out
|
||
|
# logger.info("Loading config file {}...".format(CONFIG_FILE))
|
||
|
|
||
|
with open(CONFIG_FILE, "r", encoding="utf-8") as cfgFile:
|
||
|
tree = json.load(cfgFile)
|
||
|
|
||
|
loadCfgFileSection(params, tree, "repositories", ("FlightGear", "FGData"))
|
||
|
loadCfgFileSection(params, tree, "executables", ("fgrcc",))
|
||
|
|
||
|
|
||
|
def processCommandLine(params):
|
||
|
parser = argparse.ArgumentParser(
|
||
|
usage="""\
|
||
|
%(prog)s [OPTION ...]
|
||
|
Rebuild FGData embedded resources for FlightGear.""",
|
||
|
description="""\
|
||
|
|
||
|
Use fgrcc with FGData-resources.xml and the corresponding files in FGData to
|
||
|
(re)create the FGData-resources.[ch]xx files used in the FlightGear build. The
|
||
|
existing files in the FlightGear repository are always overwritten
|
||
|
(FGData-resources.[ch]xx in <FlightGear-repo>/src/EmbeddedResources).
|
||
|
|
||
|
This is a dumb script that simply calls fgrcc with appropriate parameters. In
|
||
|
order to save some typing, you may want to use a configuration file like this
|
||
|
(~/.fgmeta/%(prog)s.json):
|
||
|
|
||
|
{"repositories": {"FlightGear": "~/flightgear/src/flightgear",
|
||
|
"FGData": "~/flightgear/src/fgdata"},
|
||
|
"executables": {"fgrcc":
|
||
|
"~/flightgear/src/build-fg/src/EmbeddedResources/fgrcc"
|
||
|
}
|
||
|
}""",
|
||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||
|
# I want --help but not -h (it might be useful for something else)
|
||
|
add_help=False)
|
||
|
|
||
|
parser.add_argument('--flightgear', action='store', help="""\
|
||
|
Path to the FlightGear repository""")
|
||
|
parser.add_argument('--fgdata', action='store', help="""\
|
||
|
Path to the FGData repository""")
|
||
|
parser.add_argument('--fgrcc', action='store', help="""\
|
||
|
Path to the fgrcc executable""")
|
||
|
parser.add_argument('--log-level', action='store',
|
||
|
choices=("debug", "info", "warning", "error",
|
||
|
"critical"),
|
||
|
default=None, help="""Set the log level""")
|
||
|
parser.add_argument('--help', action="help",
|
||
|
help="display this message and exit")
|
||
|
|
||
|
parser.parse_args(namespace=params)
|
||
|
|
||
|
# Don't use the 'default' argparse mechanism for this, in order to allow
|
||
|
# the config file to set the log level in a meaningful way if we want (not
|
||
|
# implemented at the time of this writing).
|
||
|
if params.log_level is not None:
|
||
|
logger.setLevel(getattr(sys.modules["logging"],
|
||
|
params.log_level.upper()))
|
||
|
|
||
|
|
||
|
def main():
|
||
|
locale.setlocale(locale.LC_ALL, '')
|
||
|
setupLogging(level=logging.INFO) # may be overridden by options
|
||
|
|
||
|
params = argparse.Namespace()
|
||
|
loadConfigFile(params) # could set the log level
|
||
|
processCommandLine(params)
|
||
|
|
||
|
if (params.flightgear is None or params.fgdata is None or
|
||
|
params.fgrcc is None):
|
||
|
logger.error(
|
||
|
"--flightgear, --fgdata and --fgrcc must all be specified (they "
|
||
|
"may be set in the config file; use --help for more info)")
|
||
|
sys.exit(1)
|
||
|
|
||
|
resDir = os.path.join(params.flightgear, "src", "EmbeddedResources")
|
||
|
inputXMLFile = os.path.join(resDir, "FGData-resources.xml")
|
||
|
cxxFile = os.path.join(resDir, "FGData-resources.cxx")
|
||
|
hxxFile = os.path.join(resDir, "FGData-resources.hxx")
|
||
|
args = [params.fgrcc,
|
||
|
"--root={}".format(params.fgdata),
|
||
|
"--output-cpp-file={}".format(cxxFile),
|
||
|
"--init-func-name=initFGDataEmbeddedResources",
|
||
|
"--output-header-file={}".format(hxxFile),
|
||
|
"--output-header-identifier=_FG_FGDATA_EMBEDDED_RESOURCES",
|
||
|
inputXMLFile]
|
||
|
|
||
|
# encoding="utf-8" requires Python >= 3.6 -> will add it later
|
||
|
# (it's not really needed, as we don't process the output)
|
||
|
subprocess.run(args, check=True)
|
||
|
|
||
|
sys.exit(0)
|
||
|
|
||
|
if __name__ == "__main__": main()
|