Skip to content

Commit a132dad

Browse files
nunoplopeslucic71
andcommitted
Add WOFF2
Co-authored-by: Lucian Popescu <lucian.popescu@tecnico.ulisboa.pt>
0 parents  commit a132dad

311 files changed

Lines changed: 65219 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Cargo
2+
target/
3+
Cargo.lock
4+
5+
# Python
6+
*.pyc
7+
__pycache__
8+
9+
# VSCode
10+
.vscode
11+
12+
# Clangd
13+
.cache/
14+
15+
tmp
16+
*.swp
17+
18+
build

CMakeLists.txt

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
project(Cpp2Rust-TestSuite)
3+
4+
set(CPP2RUST_PROGRAMS woff2)
5+
set(CPP2RUST_MODELS unsafe refcount)
6+
set(CPP2RUST_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/../cpp2rust)
7+
set(CPP2RUST_BINARY ${CPP2RUST_SRCDIR}/build/cpp2rust/cpp2rust)
8+
9+
# -----------------------------------------------------------------------------
10+
11+
include(${CPP2RUST_SRCDIR}/cmake/rust-toolchain.cmake)
12+
13+
set(FILTER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/filter_compile_commands.py)
14+
15+
foreach(_prog IN LISTS CPP2RUST_PROGRAMS)
16+
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/${_prog}.cmake)
17+
18+
set(_model_regen_targets "")
19+
set(_model_build_targets "")
20+
foreach(_model IN LISTS CPP2RUST_MODELS)
21+
write_rust_toolchain(${CMAKE_CURRENT_SOURCE_DIR}/${_prog}/out/${_model})
22+
23+
add_custom_target("build-${_prog}-${_model}"
24+
COMMAND ${CMAKE_COMMAND} -E env RUSTFLAGS=-Awarnings cargo build --release
25+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_prog}/out/${_model}"
26+
USES_TERMINAL
27+
)
28+
29+
list(APPEND _model_regen_targets "regen-${_prog}-${_model}")
30+
list(APPEND _model_build_targets "build-${_prog}-${_model}")
31+
endforeach()
32+
33+
add_custom_target("build-${_prog}"
34+
DEPENDS "build-${_prog}-original" ${_model_build_targets}
35+
)
36+
37+
add_custom_target("regen-${_prog}"
38+
DEPENDS "build-${_prog}-original" ${_model_regen_targets}
39+
)
40+
41+
add_custom_target("check-${_prog}"
42+
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/scripts/${_prog}-test.sh"
43+
${CMAKE_BINARY_DIR}
44+
${CMAKE_CURRENT_SOURCE_DIR}
45+
${CPP2RUST_MODELS}
46+
DEPENDS "build-${_prog}"
47+
USES_TERMINAL
48+
)
49+
50+
add_custom_target("benchmark-${_prog}"
51+
COMMAND python3
52+
"${CPP2RUST_TESTS_DIR}/scripts/${_prog}_bench.py"
53+
"${CMAKE_BINARY_DIR}"
54+
--models ${CPP2RUST_MODELS}
55+
--csv "${CMAKE_BINARY_DIR}/bench_${_prog}.csv"
56+
--warmup 2
57+
--runs 3
58+
DEPENDS "build-${_prog}"
59+
USES_TERMINAL
60+
)
61+
endforeach()
62+
63+
list(TRANSFORM CPP2RUST_PROGRAMS PREPEND "build-" OUTPUT_VARIABLE _build_targets)
64+
list(TRANSFORM CPP2RUST_PROGRAMS PREPEND "check-" OUTPUT_VARIABLE _check_targets)
65+
list(TRANSFORM CPP2RUST_PROGRAMS PREPEND "regen-" OUTPUT_VARIABLE _regen_targets)
66+
list(TRANSFORM CPP2RUST_PROGRAMS PREPEND "benchmark-" OUTPUT_VARIABLE _bench_targets)
67+
68+
add_custom_target("build" DEPENDS ${_check_targets})
69+
add_custom_target("check" DEPENDS ${_check_targets})
70+
add_custom_target("regen" DEPENDS ${_regen_targets})
71+
add_custom_target("benchmark" DEPENDS ${_bench_targets})

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Cpp2Rust Test Suite
2+
3+
This repository contains open-source C/C++ programs that are known to be
4+
automatically translatable by Cpp2Rust to Rust.
5+
6+
The CI bots of Cpp2Rust run these tests and update the expected output if
7+
needed.
8+
9+
## Current set of included programs
10+
- [WOFF2](https://github.com/google/woff2): TTF font compression/decompression
11+
12+
13+
## To build and run the benchmarks
14+
```
15+
mkdir build
16+
cd build
17+
cmake -GNinja ..
18+
```
19+
20+
Available commands:
21+
- `ninja build` - Compile the original and Rust programs.
22+
- `ninja check` - Run the original and Rust binaries and compare the output.
23+
- `ninja benchmark` - Compare the performance of the original and the Rust
24+
binaries.
25+
- `ninja regen` - Regenerate the Rust code using Cpp2Rust.
26+
27+
Note: All commands can be appended with `-<prog>` to run for a specific program
28+
only (e.g., `ninja build-woff2`).

cmake/woff2.cmake

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
set(WOFF2_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/woff2/src")
2+
set(WOFF2_OUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/woff2/out")
3+
4+
set(WOFF2_INFO_FILES font.cc table_tags.cc variable_length.cc
5+
woff2_common.cc woff2_info.cc)
6+
set(WOFF2_COMPRESS_FILES table_tags.cc variable_length.cc woff2_common.cc
7+
font.cc glyph.cc normalize.cc transform.cc
8+
woff2_enc.cc woff2_compress.cc)
9+
set(WOFF2_DECOMPRESS_FILES table_tags.cc variable_length.cc woff2_common.cc
10+
woff2_dec.cc woff2_out.cc woff2_decompress.cc)
11+
12+
add_custom_target("build-woff2-original"
13+
COMMAND ${CMAKE_COMMAND} -S ${WOFF2_SRC_DIR}
14+
-B ${WOFF2_SRC_DIR}/build
15+
-G Ninja
16+
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
17+
# Only the Makefile build links against the bundled Brotli
18+
# Important so the compressed files match perfectly
19+
COMMAND make
20+
WORKING_DIRECTORY "${WOFF2_SRC_DIR}"
21+
USES_TERMINAL
22+
)
23+
24+
add_custom_target("config-woff2"
25+
# Filter: split compile_commands.json per binary
26+
COMMAND ${CMAKE_COMMAND} -E make_directory
27+
${WOFF2_SRC_DIR}/build/cmd_woff2_info
28+
${WOFF2_SRC_DIR}/build/cmd_woff2_compress
29+
${WOFF2_SRC_DIR}/build/cmd_woff2_decompress
30+
COMMAND python3 ${FILTER_SCRIPT}
31+
${WOFF2_SRC_DIR}/build/compile_commands.json
32+
${WOFF2_SRC_DIR}/build/cmd_woff2_info/compile_commands.json
33+
${WOFF2_INFO_FILES}
34+
COMMAND python3 ${FILTER_SCRIPT}
35+
${WOFF2_SRC_DIR}/build/compile_commands.json
36+
${WOFF2_SRC_DIR}/build/cmd_woff2_compress/compile_commands.json
37+
${WOFF2_COMPRESS_FILES}
38+
COMMAND python3 ${FILTER_SCRIPT}
39+
${WOFF2_SRC_DIR}/build/compile_commands.json
40+
${WOFF2_SRC_DIR}/build/cmd_woff2_decompress/compile_commands.json
41+
${WOFF2_DECOMPRESS_FILES}
42+
)
43+
44+
foreach(_model IN LISTS CPP2RUST_MODELS)
45+
add_custom_target("regen-woff2-${_model}"
46+
COMMAND ${CPP2RUST_BINARY} -dir ${WOFF2_SRC_DIR}/build/cmd_woff2_info
47+
-model ${_model}
48+
-o ${WOFF2_OUT_DIR}/${_model}/src/bin/woff2_info.rs
49+
COMMAND ${CPP2RUST_BINARY} -dir ${WOFF2_SRC_DIR}/build/cmd_woff2_compress
50+
-model ${_model}
51+
-o ${WOFF2_OUT_DIR}/${_model}/src/bin/woff2_compress.rs
52+
COMMAND ${CPP2RUST_BINARY} -dir ${WOFF2_SRC_DIR}/build/cmd_woff2_decompress
53+
-model ${_model}
54+
-o ${WOFF2_OUT_DIR}/${_model}/src/bin/woff2_decompress.rs
55+
DEPENDS "config-woff2"
56+
USES_TERMINAL
57+
)
58+
endforeach()

scripts/filter_compile_commands.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Filter compile_commands.json based on target patterns.
4+
5+
Usage:
6+
filter_compile_commands.py <input.json> <output.json> <pattern1> [pattern2] ...
7+
8+
Patterns are matched against the 'file' field in compile_commands.json.
9+
A file is included if it matches ANY of the include patterns (substring match).
10+
Patterns starting with '!' are exclusion patterns - files matching them are excluded.
11+
Patterns starting with '~!' exclude entries where the command field contains the pattern.
12+
Patterns starting with '~' (without !) remove matching text from the command field.
13+
"""
14+
15+
import json
16+
import sys
17+
18+
19+
def main():
20+
if len(sys.argv) < 4:
21+
print(f"Usage: {sys.argv[0]} <input.json> <output.json> <pattern1> [pattern2] ...", file=sys.stderr)
22+
sys.exit(1)
23+
24+
input_file = sys.argv[1]
25+
output_file = sys.argv[2]
26+
all_patterns = sys.argv[3:]
27+
28+
include_patterns = [p for p in all_patterns if not p.startswith('!') and not p.startswith('~')]
29+
exclude_patterns = [p[1:] for p in all_patterns if p.startswith('!') and not p.startswith('~')]
30+
command_excludes = [p[2:] for p in all_patterns if p.startswith('~!')]
31+
command_filters = [p[1:] for p in all_patterns if p.startswith('~') and not p.startswith('~!')]
32+
33+
with open(input_file, 'r') as f:
34+
commands = json.load(f)
35+
36+
filtered = []
37+
for cmd in commands:
38+
file_path = cmd.get('file', '')
39+
command = cmd.get('command', '')
40+
if any(pattern in file_path for pattern in exclude_patterns):
41+
continue
42+
if any(pattern in command for pattern in command_excludes):
43+
continue
44+
if any(pattern in file_path for pattern in include_patterns):
45+
if command_filters:
46+
cmd = cmd.copy()
47+
for cf in command_filters:
48+
command = command.replace(cf, '')
49+
cmd['command'] = command
50+
filtered.append(cmd)
51+
52+
with open(output_file, 'w') as f:
53+
json.dump(filtered, f, indent=2)
54+
55+
print(f"Filtered {len(commands)} -> {len(filtered)} entries")
56+
57+
58+
if __name__ == '__main__':
59+
main()

scripts/woff2-test.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Usage: woff2-test.sh <build_dir> <source_dir> <model...>
6+
BUILD_DIR="$1"
7+
SRC_DIR="$2/woff2"
8+
shift 2
9+
MODELS=("$@")
10+
11+
FONTS_DIR="$SRC_DIR/tests"
12+
TMP_DIR="$BUILD_DIR/tmp-woff2"
13+
14+
rm -fr "$TMP_DIR"
15+
mkdir -p "$TMP_DIR/original"
16+
17+
for f in "$FONTS_DIR"/**/*.ttf; do
18+
cp "$f" "$TMP_DIR/original"
19+
done
20+
21+
# Run original binaries
22+
for f in "$TMP_DIR"/original/*.ttf; do
23+
"$SRC_DIR/src/woff2_compress" "$f" &
24+
done
25+
wait
26+
27+
for f in "$TMP_DIR"/original/*.woff2; do
28+
"$SRC_DIR/src/woff2_info" "$f" | tail -n2 > "$TMP_DIR/original/$(basename "$f" .woff2).info"
29+
done
30+
31+
# Run each model and compare against original
32+
33+
for model in "${MODELS[@]}"; do
34+
RUST_BIN="$SRC_DIR/out/$model/target/release"
35+
MODEL_DIR="$TMP_DIR/$model"
36+
37+
rm -fr "$MODEL_DIR"
38+
mkdir -p "$MODEL_DIR"
39+
40+
cp "$TMP_DIR"/original/*.ttf "$MODEL_DIR"
41+
42+
for f in "$MODEL_DIR"/*.ttf; do
43+
"$RUST_BIN"/woff2_compress "$f" &
44+
done
45+
wait
46+
47+
# Compare woff2 files against original
48+
for f in "$MODEL_DIR"/*.woff2; do
49+
base=$(basename "$f" .woff2)
50+
diff "$f" "$TMP_DIR/original/$base.woff2" \
51+
|| { echo "FAIL [$model]: woff2 mismatch on $base"; exit 1; }
52+
done
53+
54+
# Decompress and compare ttf roundtrip
55+
for f in "$MODEL_DIR"/*.woff2; do
56+
"$RUST_BIN"/woff2_decompress "$f" &
57+
done
58+
wait
59+
60+
for f in "$MODEL_DIR"/*.ttf; do
61+
base=$(basename "$f" .ttf)
62+
diff "$f" "$TMP_DIR/original/$base.ttf" \
63+
|| { echo "FAIL [$model]: ttf mismatch on $base"; exit 1; }
64+
done
65+
66+
# Compare woff2_info output
67+
for f in "$MODEL_DIR"/*.woff2; do
68+
base=$(basename "$f" .woff2)
69+
"$RUST_BIN"/woff2_info "$f" | tail -n2 > "$MODEL_DIR/$base.info"
70+
diff "$MODEL_DIR/$base.info" "$TMP_DIR/original/$base.info" \
71+
|| { echo "FAIL [$model]: info mismatch on $base"; exit 1; }
72+
done
73+
74+
echo "WOFF2 $model tests passed!"
75+
done
76+
77+
rm -fr "$TMP_DIR"

woff2/out/refcount/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "woff2_refcount"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
brotli-sys = "0.3.2"
8+
libcc2rs = { version = "0.1.0", path = "../../../../cpp2rust/libcc2rs" }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[toolchain]
2+
channel = "1.95.0"

0 commit comments

Comments
 (0)