Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e31a97d
feat(cpp): add native installation packages
ColinLeeo Aug 20, 2026
3e4220f
fix(ci): remove redundant install step before cpack
ColinLeeo Aug 20, 2026
5fccdc4
fix(ci): install uuid headers for bundled ANTLR4
ColinLeeo Aug 20, 2026
4f5ed02
feat(ci): add native package development versions
ColinLeeo Sep 10, 2026
15e69f2
fix(ci): validate native package build identity
ColinLeeo Sep 10, 2026
b5a8b30
feat(ci): build native Linux package artifacts
ColinLeeo Sep 10, 2026
0958b56
fix(ci): verify native CLI package ownership
ColinLeeo Sep 10, 2026
8519ed5
feat(ci): build Windows native SDK archive
ColinLeeo Sep 10, 2026
ba595ab
fix(ci): package Windows Release artifacts
ColinLeeo Sep 10, 2026
19192b6
feat(ci): build Homebrew development bottles
ColinLeeo Sep 10, 2026
340d0cd
feat(ci): assemble native package artifact bundle
ColinLeeo Sep 10, 2026
6ffc6c0
fix(ci): verify native package bundle integrity
ColinLeeo Sep 10, 2026
205a813
fix(packaging): omit empty Homebrew bottle spacing
ColinLeeo Sep 10, 2026
b8874a0
docs: document native package artifact workflow
ColinLeeo Sep 10, 2026
8681145
fix(packaging): complete native runtime and install contracts
ColinLeeo Sep 10, 2026
d3bd297
fix(cmake): preserve static SDK ANTLR compatibility bounds
ColinLeeo Sep 10, 2026
485b99f
fix(ci): address native packaging runner failures
ColinLeeo Sep 10, 2026
5094e29
fix(ci): resolve native package portability failures
ColinLeeo Sep 10, 2026
72abe30
fix(packaging): derive package test versions from the checkout
ColinLeeo Sep 17, 2026
46a7a86
build(python): add -Pwith-python-only to reuse the C++ build
ColinLeeo Sep 18, 2026
89fbeda
build(cpp): expose CPack generation via -Denable.cpack=ON
ColinLeeo Sep 18, 2026
724fb1b
build(ci): assemble native packages from Maven builds
ColinLeeo Sep 18, 2026
c4405fd
docs(packaging): describe SDK and wheel consumers
ColinLeeo Sep 18, 2026
1583130
fix(ci): make native SDK consumers path-safe
ColinLeeo Sep 18, 2026
a46bf81
fix(ci): consume platform SDK layouts correctly
ColinLeeo Sep 18, 2026
2fb4464
fix(python): resolve staged SDK headers
ColinLeeo Sep 18, 2026
dafad98
fix(python): ship versioned shared libraries
ColinLeeo Sep 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
938 changes: 938 additions & 0 deletions .github/workflows/native-packages.yml

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ jobs:
-DskipTests -Dspotless.check.skip=true -Dspotless.apply.skip=true \
-Dbuild.test=OFF \
-Dtsfile.dependency.source=BUNDLED \
-Denable.lzma2=ON \
-Dcmake.args="-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0"
otool -l cpp/target/build/lib/libtsfile*.dylib | grep -A2 LC_VERSION_MIN_MACOSX || true

Expand Down Expand Up @@ -140,7 +139,6 @@ jobs:
./mvnw -Pwith-cpp clean package \
-DskipTests -Dbuild.test=OFF \
-Dtsfile.dependency.source=BUNDLED \
-Denable.lzma2=ON \
-Dspotless.check.skip=true -Dspotless.apply.skip=true
test -d cpp/target/build/lib && test -d cpp/target/build/include

Expand Down Expand Up @@ -208,7 +206,6 @@ jobs:
./mvnw -Pwith-cpp clean package \
-DskipTests -Dbuild.test=OFF \
-Dtsfile.dependency.source=BUNDLED \
-Denable.lzma2=ON \
-Dspotless.check.skip=true -Dspotless.apply.skip=true
test -d cpp/target/build/lib
test -d cpp/target/build/include
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ python/tsfile/**/*so*
python/data
python/venv/*
python/tests/__pycache__/*
packaging/**/__pycache__/
packaging/**/*.py[cod]
python/tests/*.tsfile
python/tsfile/include

Expand Down
216 changes: 213 additions & 3 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ specific language governing permissions and limitations
under the License.
]]
cmake_minimum_required(VERSION 3.11)
option(TSFILE_MSVC_STATIC_RUNTIME
"Use the static MSVC runtime throughout a portable bundled build" OFF)
if (TSFILE_MSVC_STATIC_RUNTIME)
if (NOT POLICY CMP0091)
message(FATAL_ERROR "TSFILE_MSVC_STATIC_RUNTIME requires CMake 3.15+")
endif ()
# The policy must be selected before the first project(), and inherited by
# upstream projects that reset their policy version in add_subdirectory().
cmake_policy(SET CMP0091 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0091 NEW)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif ()
project(TsFile_CPP)

if (DEFINED ToolChain)
Expand All @@ -34,7 +46,40 @@ if (POLICY CMP0074)
endif ()
set(TsFile_CPP_VERSION 2.3.2.dev)

include(GNUInstallDirs)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/TsFilePublicHeaders.cmake)

# The package version identifies the source release. Development suffixes are
# intentionally removed from generated package metadata and never enter the
# SONAME.
string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" TSFILE_PACKAGE_VERSION
"${TsFile_CPP_VERSION}")
if ("${TSFILE_PACKAGE_VERSION}" STREQUAL "")
message(FATAL_ERROR
"TsFile_CPP_VERSION must start with a semantic version: "
"${TsFile_CPP_VERSION}")
endif ()
set(TSFILE_ARCHIVE_VERSION "${TSFILE_PACKAGE_VERSION}" CACHE STRING
"Version used in portable archive names")
set(TSFILE_DEBIAN_PACKAGE_VERSION "${TSFILE_PACKAGE_VERSION}" CACHE STRING
"Complete Debian package version")
set(TSFILE_RPM_PACKAGE_VERSION "${TSFILE_PACKAGE_VERSION}" CACHE STRING
"RPM Version value")
set(TSFILE_RPM_PACKAGE_RELEASE "1" CACHE STRING
"RPM Release value")
set(TSFILE_ABI_VERSION "1" CACHE STRING
"TsFile shared-library ABI epoch (changes only on ABI breaks)")
if (NOT TSFILE_ABI_VERSION MATCHES "^[0-9]+$")
message(FATAL_ERROR "TSFILE_ABI_VERSION must be a positive integer")
endif ()

include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/DependencySource.cmake)
if (TSFILE_MSVC_STATIC_RUNTIME AND
NOT TSFILE_DEPENDENCY_SOURCE STREQUAL "BUNDLED")
message(FATAL_ERROR
"TSFILE_MSVC_STATIC_RUNTIME requires TSFILE_DEPENDENCY_SOURCE=BUNDLED "
"so prebuilt dependencies cannot introduce a different MSVC runtime")
endif ()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

option(TSFILE_BUILD_SHARED "Build libtsfile as a shared library" ON)
Expand Down Expand Up @@ -64,10 +109,18 @@ endif ()
message("cmake using: USE_CPP11=${USE_CPP11}")
# MSVC has no /std:c++11; CMake maps this to the closest supported standard
# (C++14 default on MSVC), which compiles the C++11 codebase fine.
set(CMAKE_CXX_STANDARD 11)
set(TSFILE_CXX_STANDARD "11" CACHE STRING
"C++ language standard used to build TsFile (11, 14, or 17)")
set_property(CACHE TSFILE_CXX_STANDARD PROPERTY STRINGS 11 14 17)
if (NOT TSFILE_CXX_STANDARD MATCHES "^(11|14|17)$")
message(FATAL_ERROR
"TSFILE_CXX_STANDARD must be one of 11, 14, or 17")
endif ()
set(CMAKE_CXX_STANDARD ${TSFILE_CXX_STANDARD})
set(CMAKE_CXX_STANDARD_REQUIRED OFF)
if (NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++${TSFILE_CXX_STANDARD}")
endif ()

if (DEFINED ENV{CXX})
Expand Down Expand Up @@ -336,7 +389,8 @@ if (MSVC)
# C++17 extensions), so we pin it explicitly for reproducibility.
set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} /W3 /utf-8 /EHsc /bigobj /Zc:__cplusplus /std:c++14")
else ()
set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -Wall -std=c++11")
set(CMAKE_CXX_FLAGS
"$ENV{CXXFLAGS} -Wall -std=c++${TSFILE_CXX_STANDARD}")
endif ()
add_subdirectory(third_party)

Expand Down Expand Up @@ -418,3 +472,159 @@ endif ()
unset(_TSFILE_PROJECT_DEPENDENCIES)

add_subdirectory(examples)

# Install the compatibility header closure from the generated staging tree. The
# staging tree is populated by the existing copy_* targets and contains only
# headers selected by the reviewed closure manifest. The closure is retained
# for source compatibility; it is not the final public API boundary.
foreach (header_dir IN LISTS TSFILE_PUBLIC_HEADER_CLOSURE)
install(DIRECTORY "${LIBRARY_INCLUDE_DIR}/${header_dir}/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tsfile/${header_dir}"
COMPONENT development
FILES_MATCHING PATTERN "*.h")
endforeach()
if (ENABLE_SIMD AND TSFILE_SIMDE_INCLUDE_ROOT)
install(DIRECTORY "${TSFILE_SIMDE_INCLUDE_ROOT}/simde/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/simde"
COMPONENT development
FILES_MATCHING PATTERN "*.h")
endif ()
if (ENABLE_ANTLR4 AND TSFILE_ANTLR4_INCLUDE_ROOT)
install(DIRECTORY "${TSFILE_ANTLR4_INCLUDE_ROOT}/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT development
FILES_MATCHING PATTERN "*.h")
endif ()
if (ENABLE_ANTLR4 AND TSFILE_UTF8CPP_INCLUDE_ROOT)
install(DIRECTORY "${TSFILE_UTF8CPP_INCLUDE_ROOT}/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT development
FILES_MATCHING PATTERN "*.h")
endif ()

set(TSFILE_LICENSE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE")
set(TSFILE_NOTICE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../NOTICE")
if (EXISTS "${TSFILE_LICENSE_FILE}")
install(FILES "${TSFILE_LICENSE_FILE}"
DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/tsfile"
COMPONENT runtime)
endif()
if (EXISTS "${TSFILE_NOTICE_FILE}")
install(FILES "${TSFILE_NOTICE_FILE}"
DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/tsfile"
COMPONENT runtime)
endif()

include(CMakePackageConfigHelpers)
set(TSFILE_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/TsFile")
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/TsFileConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/TsFileConfig.cmake"
INSTALL_DESTINATION "${TSFILE_CMAKE_INSTALL_DIR}")
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/TsFileConfigVersion.cmake"
VERSION "${TSFILE_PACKAGE_VERSION}"
COMPATIBILITY SameMajorVersion)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/TsFileConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/TsFileConfigVersion.cmake"
DESTINATION "${TSFILE_CMAKE_INSTALL_DIR}"
COMPONENT development)

set(TSFILE_PKGCONFIG_CFLAGS "")
if (NOT TSFILE_BUILD_SHARED)
string(APPEND TSFILE_PKGCONFIG_CFLAGS " -DTSFILE_STATIC")
if (ENABLE_ANTLR4 AND (TSFILE_ANTLR4_SOURCE STREQUAL "BUNDLED" OR
TSFILE_ANTLR4_SYSTEM_STATIC))
string(APPEND TSFILE_PKGCONFIG_CFLAGS " -DANTLR4CPP_STATIC")
endif ()
endif ()
foreach (_TSFILE_PUBLIC_FEATURE
ENABLE_ANTLR4
ENABLE_MEM_STAT
ENABLE_SNAPPY
ENABLE_LZ4
ENABLE_LZOKAY
ENABLE_ZLIB
ENABLE_GZIP
ENABLE_ZSTD
ENABLE_LZMA2
ENABLE_THREADS
ENABLE_SIMD)
if (${_TSFILE_PUBLIC_FEATURE})
string(APPEND TSFILE_PKGCONFIG_CFLAGS
" -D${_TSFILE_PUBLIC_FEATURE}")
endif ()
endforeach ()
file(RELATIVE_PATH TSFILE_PKGCONFIG_PREFIX_RELATIVE
"${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig" "${CMAKE_INSTALL_PREFIX}")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/libtsfile.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/libtsfile.pc"
@ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libtsfile.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
COMPONENT development)
unset(_TSFILE_PUBLIC_FEATURE)

# CPack is an opt-in local/package-builder integration. Native release jobs
# can configure the project with TSFILE_DEPENDENCY_SOURCE=SYSTEM when the
# target image provides every compatible dependency; AUTO remains the
# reproducible fallback for distribution images with older packages.
option(TSFILE_ENABLE_CPACK
"Enable CPack native package metadata generation" OFF)
if (TSFILE_ENABLE_CPACK)
set(CPACK_PACKAGE_NAME "tsfile")
set(CPACK_PACKAGE_VENDOR "Apache Software Foundation")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Apache TsFile C++ library")
set(CPACK_PACKAGE_DESCRIPTION
"Columnar storage library and command-line tools for time series data")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://tsfile.apache.org/")
set(CPACK_PACKAGE_CONTACT "dev@tsfile.apache.org")
set(CPACK_RESOURCE_FILE_LICENSE "${TSFILE_LICENSE_FILE}")
set(CPACK_PACKAGE_VERSION "${TSFILE_ARCHIVE_VERSION}")
string(REPLACE "." ";" _TSFILE_PACKAGE_VERSION_PARTS
"${TSFILE_PACKAGE_VERSION}")
list(GET _TSFILE_PACKAGE_VERSION_PARTS 0 CPACK_PACKAGE_VERSION_MAJOR)
list(GET _TSFILE_PACKAGE_VERSION_PARTS 1 CPACK_PACKAGE_VERSION_MINOR)
list(GET _TSFILE_PACKAGE_VERSION_PARTS 2 CPACK_PACKAGE_VERSION_PATCH)

set(CPACK_COMPONENTS_ALL runtime development tools)
set(CPACK_COMPONENT_DEVELOPMENT_DEPENDS runtime)
set(CPACK_COMPONENT_TOOLS_DEPENDS runtime)
# Portable archives contain the complete runtime, SDK, and tools install
# tree in one file. Native DEB and RPM generators remain componentized.
set(CPACK_ARCHIVE_COMPONENT_INSTALL OFF)
if (WIN32)
set(CPACK_PACKAGE_FILE_NAME
"tsfile-${TSFILE_ARCHIVE_VERSION}-windows-x86_64")
endif ()
set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_VERSION "${TSFILE_DEBIAN_PACKAGE_VERSION}")
set(CPACK_DEBIAN_RUNTIME_PACKAGE_NAME "tsfile")
set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_NAME "tsfile-dev")
set(CPACK_DEBIAN_TOOLS_PACKAGE_NAME "tsfile-tools")
set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_DEPENDS
"tsfile (= ${TSFILE_DEBIAN_PACKAGE_VERSION})")
set(CPACK_DEBIAN_TOOLS_PACKAGE_DEPENDS
"tsfile (= ${TSFILE_DEBIAN_PACKAGE_VERSION})")

set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_RPM_FILE_NAME RPM-DEFAULT)
set(CPACK_RPM_PACKAGE_LICENSE "Apache-2.0")
set(CPACK_RPM_PACKAGE_VERSION "${TSFILE_RPM_PACKAGE_VERSION}")
set(CPACK_RPM_PACKAGE_RELEASE "${TSFILE_RPM_PACKAGE_RELEASE}")
set(CPACK_RPM_PACKAGE_AUTOREQPROV ON)
set(CPACK_RPM_RUNTIME_PACKAGE_NAME "tsfile")
set(CPACK_RPM_DEVELOPMENT_PACKAGE_NAME "tsfile-devel")
set(CPACK_RPM_TOOLS_PACKAGE_NAME "tsfile-tools")
set(CPACK_RPM_DEVELOPMENT_PACKAGE_REQUIRES
"tsfile = ${TSFILE_RPM_PACKAGE_VERSION}-${TSFILE_RPM_PACKAGE_RELEASE}")
set(CPACK_RPM_TOOLS_PACKAGE_REQUIRES
"tsfile = ${TSFILE_RPM_PACKAGE_VERSION}-${TSFILE_RPM_PACKAGE_RELEASE}")

include(CPack)
unset(_TSFILE_PACKAGE_VERSION_PARTS)
endif ()
11 changes: 11 additions & 0 deletions cpp/VersionUpdater.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Synchronize the version in CMakeLists.txt and the one used in the maven pom.

// Native package jobs derive their identity from native_package_versions.py.
// Keep that identity stable by leaving source versions untouched in those jobs.
def skipVersionSync = project.properties.getProperty("tsfile.version.sync.skip")
if (skipVersionSync == null) {
skipVersionSync = System.getProperty("tsfile.version.sync.skip")
}
if (skipVersionSync != null && skipVersionSync.equalsIgnoreCase("true")) {
println "Skipping source version synchronization for native packaging"
return
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

def cppProjectFile = new File(project.basedir, "CMakeLists.txt")
Expand Down
43 changes: 43 additions & 0 deletions cpp/cmake/TsFileConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#[[
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
]]

@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
if (@ENABLE_THREADS@)
find_dependency(Threads)
endif()

if (NOT @TSFILE_BUILD_SHARED@)
set(_TSFILE_SAVED_MODULE_PATH "${CMAKE_MODULE_PATH}")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
file(GLOB _TSFILE_STATIC_CONFIGS
"${CMAKE_CURRENT_LIST_DIR}/TsFileStaticDependencies-*.cmake")
foreach (_TSFILE_STATIC_CONFIG IN LISTS _TSFILE_STATIC_CONFIGS)
include("${_TSFILE_STATIC_CONFIG}")
endforeach ()
set(CMAKE_MODULE_PATH "${_TSFILE_SAVED_MODULE_PATH}")
unset(_TSFILE_STATIC_CONFIG)
unset(_TSFILE_STATIC_CONFIGS)
unset(_TSFILE_SAVED_MODULE_PATH)
endif ()

include("${CMAKE_CURRENT_LIST_DIR}/TsFileTargets.cmake")

check_required_components(TsFile)
47 changes: 47 additions & 0 deletions cpp/cmake/TsFilePublicHeaders.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#[[
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
]]

# Public entry points are intentionally listed separately from the transitive
# header closure. The current public headers include implementation-level
# declarations, so the closure is installed until those dependencies can be
# hidden behind a stable facade. Adding a new public entry point requires an
# explicit review of this list.
set(TSFILE_PUBLIC_ENTRYPOINT_HEADERS
cwrapper/tsfile_cwrapper.h
cwrapper/tsfile_cwrapper_expression.h
reader/tsfile_reader.h
writer/tsfile_writer.h
writer/tsfile_table_writer.h
writer/tsfile_tree_writer.h)

# These directories form the reviewed transitive closure of the entry points
# above. This is an installation compatibility closure, not a promise that
# every header is a stable public API. Compression, encoding, parser, and
# utility headers are implementation dependencies today, but are required for
# consumers to parse the installed public declarations.
set(TSFILE_PUBLIC_HEADER_CLOSURE
common
compress
cwrapper
encoding
file
parser
reader
utils
writer)
Loading
Loading