eccodes/memfs.py

217 lines
5.5 KiB
Python
Raw Normal View History

2016-06-14 13:04:48 +00:00
#!/usr/bin/env python
2022-01-25 22:24:53 +00:00
#
# (C) Copyright 2005- ECMWF.
#
# This software is licensed under the terms of the Apache Licence Version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
#
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation
# nor does it submit to any jurisdiction.
#
2016-06-14 13:04:48 +00:00
from __future__ import print_function
2021-08-30 07:34:39 +00:00
import argparse
import binascii
2016-06-14 13:04:48 +00:00
import os
import re
import sys
2020-10-19 11:37:31 +00:00
import time
2016-06-14 13:04:48 +00:00
2021-08-30 07:34:39 +00:00
parser = argparse.ArgumentParser()
parser.add_argument(
"-n",
"--count",
type=int,
default=10,
help="Number of files to generate",
)
parser.add_argument(
"-C",
"--chunk",
type=int,
default=16,
help="Chunk size (MB)",
)
parser.add_argument(
"-o",
"--output",
type=str,
default="memfs_gen",
help="Name of C file to generate",
)
parser.add_argument(
"-e",
"--exclude",
help="Exclude packages",
)
parser.add_argument(
"dirs",
type=str,
nargs="+",
help="The list of directories to process",
)
args = parser.parse_args()
2016-06-14 13:04:48 +00:00
2020-10-19 11:37:31 +00:00
start = time.time()
2022-01-20 21:00:28 +00:00
print("MEMFS: Starting")
2020-10-19 11:37:31 +00:00
# Exclude experimental features e.g. GRIB3 and TAF
# The BUFR codetables is not used in the engine
2022-04-28 13:24:06 +00:00
EXCLUDED = ["grib3", "codetables", "taf", "stations", "grib1_mlgrib2_ieee32"]
2018-03-16 16:47:07 +00:00
2021-08-30 07:34:39 +00:00
EXCLUDE = {
None: [],
"bufr": ["bufr"],
"grib": ["grib1", "grib2"],
}
EXCLUDED.extend(EXCLUDE[args.exclude])
dirs = [os.path.realpath(x) for x in args.dirs]
2022-01-20 21:00:28 +00:00
print("MEMFS: Directories: ", dirs)
print("MEMFS: Excluding: ", EXCLUDED)
2016-06-14 13:04:48 +00:00
FILES = {}
2020-04-02 15:46:49 +00:00
SIZES = {}
2016-06-14 13:04:48 +00:00
NAMES = []
2021-08-30 07:34:39 +00:00
CHUNK = args.chunk * 1024 * 1024 # chunk size in bytes
2016-06-14 13:04:48 +00:00
# Binary to ASCII function. Different in Python 2 and 3
2017-07-23 07:08:54 +00:00
try:
2020-10-19 08:16:24 +00:00
str(b"\x23\x20", "ascii")
ascii = lambda x: str(x, "ascii") # Python 3
2017-07-23 07:08:54 +00:00
except:
2020-10-19 08:16:24 +00:00
ascii = lambda x: str(x) # Python 2
2017-07-23 07:08:54 +00:00
2020-04-16 12:00:49 +00:00
def get_outfile_name(base, count):
return base + "_" + str(count).zfill(3) + ".c"
# The last argument is the base name of the generated C file(s)
2021-08-30 07:34:39 +00:00
output_file_base = args.output
2020-10-19 08:16:24 +00:00
2020-10-19 11:37:31 +00:00
buffer = None
2021-08-29 21:58:18 +00:00
fcount = 0
2021-08-30 07:34:39 +00:00
MAX_FCOUNT = args.count
2020-10-19 08:16:24 +00:00
2016-06-14 13:04:48 +00:00
for directory in dirs:
# print("MEMFS: directory=", directory)
2016-06-14 13:04:48 +00:00
dname = os.path.basename(directory)
NAMES.append(dname)
for dirpath, dirnames, files in os.walk(directory, followlinks=True):
2020-10-19 11:37:31 +00:00
2018-03-16 16:47:07 +00:00
# Prune the walk by modifying the dirnames in-place
dirnames[:] = [dirname for dirname in dirnames if dirname not in EXCLUDED]
2016-06-14 13:04:48 +00:00
for name in files:
2020-10-19 11:37:31 +00:00
if buffer is None:
opath = get_outfile_name(output_file_base, fcount)
2021-08-29 21:58:18 +00:00
fcount += 1
2020-10-19 11:37:31 +00:00
print("MEMFS: Generating output:", opath)
buffer = open(opath, "w")
2020-10-19 11:37:31 +00:00
2020-10-19 08:16:24 +00:00
full = "%s/%s" % (dirpath, name)
2016-06-14 13:04:48 +00:00
_, ext = os.path.splitext(full)
2020-10-19 08:16:24 +00:00
if ext not in [".def", ".table", ".tmpl", ".list", ".txt"]:
continue
2020-10-19 08:16:24 +00:00
if name == "CMakeLists.txt":
2016-06-14 13:04:48 +00:00
continue
full = full.replace("\\", "/")
2020-10-19 08:16:24 +00:00
fname = full[full.find("/%s/" % (dname,)) :]
# print("MEMFS: Add ", fname)
name = re.sub(r"\W", "_", fname)
2016-06-14 13:04:48 +00:00
assert name not in FILES
2020-04-02 15:46:49 +00:00
assert name not in SIZES
2016-06-14 13:04:48 +00:00
FILES[name] = fname
2020-10-19 08:16:24 +00:00
SIZES[name] = os.path.getsize(full)
2016-06-14 13:04:48 +00:00
2020-11-02 14:07:59 +00:00
buffer.write("const unsigned char %s[] = {" % (name,))
2016-06-14 13:04:48 +00:00
2020-10-19 08:16:24 +00:00
with open(full, "rb") as f:
2016-06-14 13:04:48 +00:00
i = 0
# Python 2
2020-10-19 08:16:24 +00:00
# contents_hex = f.read().encode("hex")
2017-02-06 18:03:36 +00:00
# Python 2 and 3
2020-04-02 15:46:49 +00:00
contents_hex = binascii.hexlify(f.read())
2017-02-06 18:03:36 +00:00
# Read two characters at a time and convert to C hex
# e.g. 23 -> 0x23
2020-04-02 15:46:49 +00:00
for n in range(0, len(contents_hex), 2):
2020-10-19 08:16:24 +00:00
twoChars = ascii(contents_hex[n : n + 2])
2020-11-02 14:07:59 +00:00
buffer.write("0x%s," % (twoChars,))
2016-06-14 13:04:48 +00:00
i += 1
if (i % 20) == 0:
2020-11-02 14:07:59 +00:00
buffer.write("\n")
2020-10-19 08:16:24 +00:00
2020-11-02 14:07:59 +00:00
buffer.write("};\n")
2020-10-19 08:16:24 +00:00
if buffer.tell() >= CHUNK:
2020-10-19 11:37:31 +00:00
buffer.close()
buffer = None
2020-10-19 08:16:24 +00:00
2020-10-19 11:37:31 +00:00
if buffer is not None:
buffer.close()
2021-08-29 21:59:06 +00:00
assert fcount <= MAX_FCOUNT, fcount
2021-08-29 21:58:18 +00:00
while fcount < MAX_FCOUNT:
opath = get_outfile_name(output_file_base, fcount)
print("MEMFS: Generating output:", opath, "(empty)")
with open(opath, "w") as f:
# ISO compilers issue a warning for an empty translation unit
# so add a dummy declaration to suppress this
print("struct eccodes_suppress_iso_warning;/* empty */", file=f)
2021-08-29 21:58:18 +00:00
fcount += 1
# The number of generated C files is hard coded.
# See memfs/CMakeLists.txt
2020-04-16 12:00:49 +00:00
opath = output_file_base + "_final.c"
print("MEMFS: Generating output:", opath)
2020-04-16 11:06:19 +00:00
g = open(opath, "w")
2016-06-14 13:04:48 +00:00
2020-11-02 11:41:36 +00:00
f = open(os.path.join(os.path.dirname(__file__), "src", "memfs.c"))
for line in f.readlines():
line = line.rstrip()
if "<MARKER>" in line:
# Write extern variables with sizes
for k, v in SIZES.items():
print("extern const unsigned char %s[%d];" % (k, v), file=g)
print(
"static struct entry entries[] = {",
file=g,
)
items = [(v, k) for k, v in FILES.items()]
for k, v in sorted(items):
print(
'{"/MEMFS%s", &%s[0], sizeof(%s) / sizeof(%s[0]) },' % (k, v, v, v),
file=g,
)
print(
"};",
file=g,
)
else:
print(line, file=g)
2020-04-16 11:06:19 +00:00
2022-01-25 22:24:53 +00:00
elapsed = time.time() - start
print("MEMFS: Done in %.2f seconds" % elapsed)