forked from KhronosGroup/KTX-Software
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update to Basis1.16.3 (KhronosGroup#543)
* git subrepo commit (merge) lib/basisu subrepo: subdir: "lib/basisu" merged: "7e156388" upstream: origin: "https://github.com/BinomialLLC/basis_universal.git" branch: "master" commit: "1f4b564a" git-subrepo: version: "0.4.3" origin: "https://github.com/MarkCallow/git-subrepo.git" commit: "c1f1132" * Fix syntax errors in on_failure.ps1.
- Loading branch information
1 parent
c2c3eec
commit 785fd31
Showing
13 changed files
with
300 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
lib/basisu/contrib/single_file_transcoder/basisu_transcoder-in.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Tool to bundle multiple C/C++ source files, inlining any includes. | ||
# | ||
# Note: there are two types of exclusion options: the '-x' flag, which besides | ||
# excluding a file also adds an #error directive in place of the #include, and | ||
# the '-k' flag, which keeps the #include and doesn't inline the file. The | ||
# intended use cases are: '-x' for files that would normally be #if'd out, so | ||
# features that 100% won't be used in the amalgamated file, for which every | ||
# occurrence adds the error, and '-k' for headers that we wish to manually | ||
# include, such as a project's public API, for which occurrences after the first | ||
# are removed. | ||
# | ||
# Todo: the error handling could be better, which currently throws and halts | ||
# (which is functional just not very friendly). | ||
# | ||
# Author: Carl Woffenden, Numfum GmbH (this script is released under a CC0 license/Public Domain) | ||
|
||
import argparse, re, sys | ||
|
||
from pathlib import Path | ||
from typing import Any, List, Optional, Pattern, Set, TextIO | ||
|
||
# Set of file roots when searching (equivalent to -I paths for the compiler). | ||
roots: Set[Path] = set() | ||
|
||
# Set of (canonical) file Path objects to exclude from inlining (and not only | ||
# exclude but to add a compiler error directive when they're encountered). | ||
excludes: Set[Path] = set() | ||
|
||
# Set of (canonical) file Path objects to keep as include directives. | ||
keeps: Set[Path] = set() | ||
|
||
# Whether to keep the #pragma once directives (unlikely, since this will result | ||
# in a warning, but the option is there). | ||
keep_pragma: bool = False | ||
|
||
# Destination file object (or stdout if no output file was supplied). | ||
destn:TextIO = sys.stdout | ||
|
||
# Set of file Path objects previously inlined (and to ignore if reencountering). | ||
found: Set[Path] = set() | ||
|
||
# Compiled regex Patern to handle the following type of file includes: | ||
# | ||
# #include "file" | ||
# #include "file" | ||
# # include "file" | ||
# #include "file" | ||
# #include "file" // comment | ||
# #include "file" // comment with quote " | ||
# | ||
# And all combinations of, as well as ignoring the following: | ||
# | ||
# #include <file> | ||
# //#include "file" | ||
# /*#include "file"*/ | ||
# | ||
# We don't try to catch errors since the compiler will do this (and the code is | ||
# expected to be valid before processing) and we don't care what follows the | ||
# file (whether it's a valid comment or not, since anything after the quoted | ||
# string is ignored) | ||
# | ||
include_regex: Pattern = re.compile(r'^\s*#\s*include\s*"(.+?)"') | ||
|
||
# Simple tests to prove include_regex's cases. | ||
# | ||
def test_match_include() -> bool: | ||
if (include_regex.match('#include "file"') and | ||
include_regex.match(' #include "file"') and | ||
include_regex.match('# include "file"') and | ||
include_regex.match('#include "file"') and | ||
include_regex.match('#include "file" // comment')): | ||
if (not include_regex.match('#include <file>') and | ||
not include_regex.match('//#include "file"') and | ||
not include_regex.match('/*#include "file"*/')): | ||
found = include_regex.match('#include "file" // "') | ||
if (found and found.group(1) == 'file'): | ||
print('#include match valid') | ||
return True | ||
return False | ||
|
||
# Compiled regex Patern to handle "#pragma once" in various formats: | ||
# | ||
# #pragma once | ||
# #pragma once | ||
# # pragma once | ||
# #pragma once | ||
# #pragma once // comment | ||
# | ||
# Ignoring commented versions, same as include_regex. | ||
# | ||
pragma_regex: Pattern = re.compile(r'^\s*#\s*pragma\s*once\s*') | ||
|
||
# Simple tests to prove pragma_regex's cases. | ||
# | ||
def text_match_pragma() -> bool: | ||
if (pragma_regex.match('#pragma once') and | ||
pragma_regex.match(' #pragma once') and | ||
pragma_regex.match('# pragma once') and | ||
pragma_regex.match('#pragma once') and | ||
pragma_regex.match('#pragma once // comment')): | ||
if (not pragma_regex.match('//#pragma once') and | ||
not pragma_regex.match('/*#pragma once*/')): | ||
print('#pragma once match valid') | ||
return True | ||
return False | ||
|
||
# Finds 'file'. First the list of 'root' paths are searched, followed by the | ||
# the currently processing file's 'parent' path, returning a valid Path in | ||
# canonical form. If no match is found None is returned. | ||
# | ||
def resolve_include(file: str, parent: Optional[Path] = None) -> Optional[Path]: | ||
for root in roots: | ||
found = root.joinpath(file).resolve() | ||
if (found.is_file()): | ||
return found | ||
if (parent): | ||
found = parent.joinpath(file).resolve(); | ||
else: | ||
found = Path(file) | ||
if (found.is_file()): | ||
return found | ||
return None | ||
|
||
# Helper to resolve lists of files. 'file_list' is passed in from the arguments | ||
# and each entry resolved to its canonical path (like any include entry, either | ||
# from the list of root paths or the owning file's 'parent', which in this case | ||
# is case is the input file). The results are stored in 'resolved'. | ||
# | ||
def resolve_excluded_files(file_list: Optional[List[str]], resolved: Set[Path], parent: Optional[Path] = None) -> None: | ||
if (file_list): | ||
for filename in file_list: | ||
found = resolve_include(filename, parent) | ||
if (found): | ||
resolved.add(found) | ||
else: | ||
error_line(f'Warning: excluded file not found: {filename}') | ||
|
||
# Writes 'line' to the open 'destn' (or stdout). | ||
# | ||
def write_line(line: str) -> None: | ||
print(line, file=destn) | ||
|
||
# Logs 'line' to stderr. This is also used for general notifications that we | ||
# don't want to go to stdout (so the source can be piped). | ||
# | ||
def error_line(line: Any) -> None: | ||
print(line, file=sys.stderr) | ||
|
||
# Inline the contents of 'file' (with any of its includes also inlined, etc.). | ||
# | ||
# Note: text encoding errors are ignored and replaced with ? when reading the | ||
# input files. This isn't ideal, but it's more than likely in the comments than | ||
# code and a) the text editor has probably also failed to read the same content, | ||
# and b) the compiler probably did too. | ||
# | ||
def add_file(file: Path, file_name: str = None) -> None: | ||
if (file.is_file()): | ||
if (not file_name): | ||
file_name = file.name | ||
error_line(f'Processing: {file_name}') | ||
with file.open('r', errors='replace') as opened: | ||
for line in opened: | ||
line = line.rstrip('\n') | ||
match_include = include_regex.match(line); | ||
if (match_include): | ||
# We have a quoted include directive so grab the file | ||
inc_name = match_include.group(1) | ||
resolved = resolve_include(inc_name, file.parent) | ||
if (resolved): | ||
if (resolved in excludes): | ||
# The file was excluded so error if the compiler uses it | ||
write_line(f'#error Using excluded file: {inc_name}') | ||
error_line(f'Excluding: {inc_name}') | ||
else: | ||
if (resolved not in found): | ||
# The file was not previously encountered | ||
found.add(resolved) | ||
if (resolved in keeps): | ||
# But the include was flagged to keep as included | ||
write_line(f'/**** *NOT* inlining {inc_name} ****/') | ||
write_line(line) | ||
error_line(f'Not inlining: {inc_name}') | ||
else: | ||
# The file was neither excluded nor seen before so inline it | ||
write_line(f'/**** start inlining {inc_name} ****/') | ||
add_file(resolved, inc_name) | ||
write_line(f'/**** ended inlining {inc_name} ****/') | ||
else: | ||
write_line(f'/**** skipping file: {inc_name} ****/') | ||
else: | ||
# The include file didn't resolve to a file | ||
write_line(f'#error Unable to find: {inc_name}') | ||
error_line(f'Error: Unable to find: {inc_name}') | ||
else: | ||
# Skip any 'pragma once' directives, otherwise write the source line | ||
if (keep_pragma or not pragma_regex.match(line)): | ||
write_line(line) | ||
else: | ||
error_line(f'Error: Invalid file: {file}') | ||
|
||
# Start here | ||
parser = argparse.ArgumentParser(description='Amalgamate Tool', epilog=f'example: {sys.argv[0]} -r ../my/path -r ../other/path -o out.c in.c') | ||
parser.add_argument('-r', '--root', action='append', type=Path, help='file root search path') | ||
parser.add_argument('-x', '--exclude', action='append', help='file to completely exclude from inlining') | ||
parser.add_argument('-k', '--keep', action='append', help='file to exclude from inlining but keep the include directive') | ||
parser.add_argument('-p', '--pragma', action='store_true', default=False, help='keep any "#pragma once" directives (removed by default)') | ||
parser.add_argument('-o', '--output', type=argparse.FileType('w'), help='output file (otherwise stdout)') | ||
parser.add_argument('input', type=Path, help='input file') | ||
args = parser.parse_args() | ||
|
||
# Fail early on an invalid input (and store it so we don't recurse) | ||
args.input = args.input.resolve(strict=True) | ||
found.add(args.input) | ||
|
||
# Resolve all of the root paths upfront (we'll halt here on invalid roots) | ||
if (args.root): | ||
for path in args.root: | ||
roots.add(path.resolve(strict=True)) | ||
|
||
# The remaining params: so resolve the excluded files and #pragma once directive | ||
resolve_excluded_files(args.exclude, excludes, args.input.parent) | ||
resolve_excluded_files(args.keep, keeps, args.input.parent) | ||
keep_pragma = args.pragma; | ||
|
||
# Then recursively process the input file | ||
try: | ||
if (args.output): | ||
destn = args.output | ||
add_file(args.input) | ||
finally: | ||
if (not destn): | ||
destn.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.