File: update_sources.py

package info (click to toggle)
libtcod 1.24.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 5,728 kB
  • sloc: ansic: 46,186; cpp: 13,523; python: 4,814; makefile: 44; sh: 25
file content (118 lines) | stat: -rwxr-xr-x 4,117 bytes parent folder | download | duplicates (2)
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()