3acff3caba
This is a simple Python 3 script to ease rebuilding of FGData embedded resources for FlightGear. It uses fgrcc in conjunction with <FlightGear-repo>/src/EmbeddedResources/FGData-resources.xml and the FGData files mentioned therein to (re)create the FGData-resources.[ch]xx files used in the FlightGear build. The existing files in the FlightGear repository are always overwritten (namely, FGData-resources.[ch]xx in <FlightGear-repo>/src/EmbeddedResources). There are command-line options (--flightgear, --fgdata and --fgrcc) to indicate where the FlightGear and FGData repositories, as well as the fgrcc executable can be found. However, it is most convenient to put these paths once for all in the config file $HOME/.fgmeta/rebuild-fgdata-embedded-resources.json (use 'rebuild-fgdata-embedded-resources --help' to see an example). This way, you can invoke the script without any argument whenever you want to update <FlightGear-repo>/src/EmbeddedResources/FGData-resources.[ch]xx. This script doesn't depend on any module out of the Python standard library (intentionally, in case distributors want to use it to recreate themselves the FGData-resources.[ch]xx files). It should work on Python 3.5 and later versions.
172 lines
6.3 KiB
Python
Executable file
172 lines
6.3 KiB
Python
Executable file
#! /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()
|