1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
#!/usr/bin/env python3
"""
Writes out the source and include files needed for AutoTools.
This script will update the collected_files.md file.
"""
from __future__ import annotations
import os
import re
from os import PathLike
from pathlib import Path, PurePosixPath
from typing import Iterable, Sequence, Tuple, Union
BANNER = "# This file was automatically generated by scripts/update_sources.py"
VENDOR_SOURCES = (Path("src/vendor/stb.c"),)
VENDOR_SOURCES_AUTOMAKE = (
Path("src/vendor/lodepng.c"),
Path("src/vendor/stb.c"),
Path("src/vendor/utf8proc/utf8proc.c"),
)
def get_sources(
sources: bool = False,
includes: bool = False,
directory: Union[str, PathLike[str]] = "src/libtcod",
vendor_sources: Tuple[Path, ...] = VENDOR_SOURCES,
) -> Iterable[Tuple[Path, Sequence[Path]]]:
"""Iterate over sources and headers with sub-folders grouped together."""
re_inclusion = []
if sources:
re_inclusion.append("c|cpp")
if includes:
re_inclusion.append("h|hpp")
re_valid = re.compile(r".*\.(%s)$" % ("|".join(re_inclusion),))
for curpath_str, dirs, files_str in os.walk(directory):
curpath = Path(curpath_str)
# Ignore hidden directories.
dirs[:] = [dir for dir in dirs if not dir.startswith(".")]
files = [curpath / f for f in files_str if re_valid.match(f)]
group = curpath.relative_to("src")
yield group, files
if sources:
yield Path("vendor"), vendor_sources
def all_sources(
sources: bool = True,
includes: bool = False,
vendor_sources: Tuple[Path, ...] = VENDOR_SOURCES,
) -> Iterable[Path]:
"""Iterate over all sources needed to compile libtcod."""
for _, sources_ in get_sources(sources=sources, includes=includes, vendor_sources=vendor_sources):
yield from sources_
def generate_am() -> str:
"""Returns an AutoMake script.
This might be run on Windows, so it must return Unix file separators.
"""
out = f"{BANNER}\n"
for group_path, files_str in get_sources(sources=False, includes=True):
group_posix = PurePosixPath(group_path)
include_name = str(group_posix).replace("/", "_")
files = [str(PurePosixPath("../..", f)) for f in files_str]
out += f"\n{include_name}_includedir = $(includedir)/{group_posix}"
out += f"\n{include_name}_include_HEADERS = \\"
out += "\n\t" + " \\\n\t".join(files)
out += "\n"
out += "\nlibtcod_la_SOURCES = \\"
out += "\n\t" + " \\\n\t".join(
str(PurePosixPath("../..", f)) for f in all_sources(vendor_sources=VENDOR_SOURCES_AUTOMAKE)
)
out += "\n"
return out
def generate_cmake() -> str:
"""Returns a CMake script with libtcod's sources."""
out = f"{BANNER}"
out += "\ntarget_sources(${PROJECT_NAME} PRIVATE\n "
out += "\n ".join(str(PurePosixPath(f.relative_to("src"))) for f in all_sources(includes=True))
out += "\n)"
for group_path, files in get_sources(sources=False, includes=True, directory=Path("src/")):
group_posix = PurePosixPath(group_path)
if str(group_posix).startswith("vendor"):
continue
out += "\ninstall(FILES\n "
out += "\n ".join(str(PurePosixPath(f.relative_to("src"))) for f in files)
out += "\n DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/%s" % group_posix
out += "\n COMPONENT IncludeFiles"
out += "\n)"
for group_path, files in get_sources(sources=True, includes=True):
group_str = str(PurePosixPath(group_path)).replace("/", r"\\")
out += f"\nsource_group({group_str} FILES\n "
out += "\n ".join(str(PurePosixPath(f.relative_to("src"))) for f in files)
out += "\n)"
out += "\n"
return out
def main() -> None:
# Change to project root directory, using this file as a reference.
os.chdir(Path(__file__, "../.."))
Path("buildsys/autotools/sources.am").write_text(generate_am(), encoding="utf-8")
Path("src/sources.cmake").write_text(generate_cmake(), encoding="utf-8")
if __name__ == "__main__":
main()
|