From 41eb63fff22fb7b74c8bf2b88e5cb4152136409f Mon Sep 17 00:00:00 2001 From: Toyosatomimi no Miko <110693261+mikomikotaishi@users.noreply.github.com> Date: Sun, 7 Dec 2025 23:16:50 -0500 Subject: [PATCH 1/5] Add C++ modules support --- CMakeLists.txt | 8 ++++ README.md | 5 +++ modules/CMakeLists.txt | 25 ++++++++++++ modules/httplib.cppm | 93 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 modules/CMakeLists.txt create mode 100644 modules/httplib.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a8ab0a8d0..cb63c20191 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,7 @@ option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system cer option(HTTPLIB_USE_NON_BLOCKING_GETADDRINFO "Enables the non-blocking alternatives for getaddrinfo." ON) option(HTTPLIB_REQUIRE_ZSTD "Requires ZSTD to be found & linked, or fails build." OFF) option(HTTPLIB_USE_ZSTD_IF_AVAILABLE "Uses ZSTD (if available) to enable zstd support." ON) +option(HTTPLIB_BUILD_MODULES "Build httplib modules (requires HTTPLIB_COMPILE to be ON)." OFF) # Defaults to static library but respects standard BUILD_SHARED_LIBS if set include(CMakeDependentOption) cmake_dependent_option(HTTPLIB_SHARED "Build the library as a shared library instead of static. Has no effect if using header-only." @@ -365,3 +366,10 @@ if(HTTPLIB_TEST) include(CTest) add_subdirectory(test) endif() + +if(HTTPLIB_BUILD_MODULES) + if(NOT HTTPLIB_COMPILE) + message(FATAL_ERROR "HTTPLIB_BUILD_MODULES requires HTTPLIB_COMPILE to be ON.") + endif() + add_subdirectory(modules) +endif() diff --git a/README.md b/README.md index b595b63ab6..da6e14586e 100644 --- a/README.md +++ b/README.md @@ -1253,6 +1253,11 @@ $ ./split.py Wrote out/httplib.h and out/httplib.cc ``` +Build C++ Modules +----------------- + +If using CMake, it is possible to build this as a C++20 module using the `HTTPLIB_BUILD_MODULES` option (which requires `HTTPLIB_COMPILE` to be enabled). + Dockerfile for Static HTTP Server --------------------------------- diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt new file mode 100644 index 0000000000..a44a80e7ba --- /dev/null +++ b/modules/CMakeLists.txt @@ -0,0 +1,25 @@ +add_library(httplib_module) + +target_sources(httplib_module + PUBLIC + FILE_SET CXX_MODULES FILES + httplib.cppm +) + +target_compile_features(httplib_module PUBLIC cxx_std_20) + +target_include_directories(httplib_module PUBLIC + $ + $ +) + +add_library(httplib::module ALIAS httplib_module) + +# Installation +install(TARGETS httplib_module + EXPORT ${PROJECT_NAME}Targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/httplib/modules +) diff --git a/modules/httplib.cppm b/modules/httplib.cppm new file mode 100644 index 0000000000..695dd861cc --- /dev/null +++ b/modules/httplib.cppm @@ -0,0 +1,93 @@ +// +// httplib.h +// +// Copyright (c) 2025 Yuji Hirose. All rights reserved. +// MIT License +// + +module; + +#include "../httplib.h" + +export module httplib; + +export namespace httplib { + using httplib::SSLVerifierResponse; + using httplib::StatusCode; + using httplib::Headers; + using httplib::Params; + using httplib::Match; + using httplib::DownloadProgress; + using httplib::UploadProgress; + using httplib::Response; + using httplib::ResponseHandler; + using httplib::FormData; + using httplib::FormField; + using httplib::FormFields; + using httplib::FormFiles; + using httplib::MultipartFormData; + using httplib::UploadFormData; + using httplib::UploadFormDataItems; + using httplib::DataSink; + using httplib::ContentProvider; + using httplib::ContentProviderWithoutLength; + using httplib::ContentProviderResourceReleaser; + using httplib::FormDataProvider; + using httplib::FormDataProviderItems; + using httplib::ContentReceiverWithProgress; + using httplib::ContentReceiver; + using httplib::FormDataHeader; + using httplib::ContentReader; + using httplib::Range; + using httplib::Ranges; + using httplib::Request; + using httplib::Response; + using httplib::Error; + using httplib::to_string; + using httplib::operator<<; + using httplib::Stream; + using httplib::TaskQueue; + using httplib::ThreadPool; + using httplib::Logger; + using httplib::ErrorLogger; + using httplib::SocketOptions; + using httplib::default_socket_options; + using httplib::status_message; + using httplib::get_bearer_token_auth; + using httplib::Server; + using httplib::Result; + using httplib::ClientConnection; + using httplib::ClientImpl; + using httplib::Client; + + #ifdef CPPHTTPLIB_OPENSSL_SUPPORT + using httplib::SSLServer; + using httplib::SSLClient; + #endif + + using httplib::hosted_at; + using httplib::encode_uri_component; + using httplib::encode_uri; + using httplib::decode_uri_component; + using httplib::decode_uri; + using httplib::encode_path_component; + using httplib::decode_path_component; + using httplib::encode_query_component; + using httplib::decode_query_component; + using httplib::append_query_params; + using httplib::make_range_header; + using httplib::make_basic_authentication_header; + + using httplib::get_client_ip; + + namespace stream { + using httplib::stream::Result; + using httplib::stream::Get; + using httplib::stream::Post; + using httplib::stream::Put; + using httplib::stream::Patch; + using httplib::stream::Delete; + using httplib::stream::Head; + using httplib::stream::Options; + } +} From 8bda27b878277191b04d40149de3cd9727b5ceff Mon Sep 17 00:00:00 2001 From: Toyosatomimi no Miko <110693261+mikomikotaishi@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:20:58 -0500 Subject: [PATCH 2/5] Add module examples --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.md b/README.md index da6e14586e..c3e5db77c7 100644 --- a/README.md +++ b/README.md @@ -1258,6 +1258,38 @@ Build C++ Modules If using CMake, it is possible to build this as a C++20 module using the `HTTPLIB_BUILD_MODULES` option (which requires `HTTPLIB_COMPILE` to be enabled). +#### Server (Multi-threaded) +```cpp +import httplib; + +using httplib::Request; +using httplib::Response; +using httplib::SSLServer; + +SSLServer svr; + +svr.Get("/hi", []([[maybe_unused]] const Request&, Response& res) -> void { + res.set_content("Hello World!", "text/plain"); +}); + +svr.listen("0.0.0.0", 8080); +``` + +#### Client +```cpp +import httplib; + +using httplib::Client; +using httplib::Result + +Client cli("https://yhirose.github.io"); + +if (Result res = cli.Get("/hi")) { + res->status; + res->body; +} +``` + Dockerfile for Static HTTP Server --------------------------------- From 9e4ca6936baf40cb338f42c240a64a39165f6a55 Mon Sep 17 00:00:00 2001 From: Toyosatomimi no Miko <110693261+mikomikotaishi@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:21:40 -0500 Subject: [PATCH 3/5] Missing semicolon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c3e5db77c7..6722a9c00f 100644 --- a/README.md +++ b/README.md @@ -1280,7 +1280,7 @@ svr.listen("0.0.0.0", 8080); import httplib; using httplib::Client; -using httplib::Result +using httplib::Result; Client cli("https://yhirose.github.io"); From 6eeb13acad84834065647473faeb103649931a49 Mon Sep 17 00:00:00 2001 From: Toyosatomimi no Miko <110693261+mikomikotaishi@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:57:13 -0500 Subject: [PATCH 4/5] Update GitHub Actions script and create a modules updating script --- .github/workflows/update-module-exports.yml | 81 ++++++ modules/httplib.cppm | 2 +- split.py | 110 ++++---- update_modules.py | 296 ++++++++++++++++++++ 4 files changed, 437 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/update-module-exports.yml create mode 100644 update_modules.py diff --git a/.github/workflows/update-module-exports.yml b/.github/workflows/update-module-exports.yml new file mode 100644 index 0000000000..931c08c8c1 --- /dev/null +++ b/.github/workflows/update-module-exports.yml @@ -0,0 +1,81 @@ +name: Update Module Exports + +on: + pull_request: + paths: + - 'httplib.h' + push: + branches: + - master + - main + paths: + - 'httplib.h' + +jobs: + update-exports: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for proper diff + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Check for changes in httplib.h + id: check_changes + run: | + if git diff --name-only HEAD~1 HEAD | grep -q "httplib.h"; then + echo "changes=true" >> $GITHUB_OUTPUT + else + echo "changes=false" >> $GITHUB_OUTPUT + fi + + - name: Update module exports + if: steps.check_changes.outputs.changes == 'true' + run: | + python3 update_modules.py + + - name: Check if module file was modified + if: steps.check_changes.outputs.changes == 'true' + id: check_module_changes + run: | + if git diff --quiet modules/httplib.cppm; then + echo "modified=false" >> $GITHUB_OUTPUT + else + echo "modified=true" >> $GITHUB_OUTPUT + fi + + - name: Commit changes + if: steps.check_module_changes.outputs.modified == 'true' + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add modules/httplib.cppm + git commit -m "chore: update module exports for httplib.h changes" + + - name: Push changes (for push events) + if: steps.check_module_changes.outputs.modified == 'true' && github.event_name == 'push' + run: | + git push + + - name: Push changes (for pull requests) + if: steps.check_module_changes.outputs.modified == 'true' && github.event_name == 'pull_request' + run: | + git push origin HEAD:${{ github.head_ref }} + + - name: Add comment to PR + if: steps.check_module_changes.outputs.modified == 'true' && github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'āœ… Module exports have been automatically updated based on changes to `httplib.h`.' + }) diff --git a/modules/httplib.cppm b/modules/httplib.cppm index 695dd861cc..2687cdf0bd 100644 --- a/modules/httplib.cppm +++ b/modules/httplib.cppm @@ -1,5 +1,5 @@ // -// httplib.h +// httplib.cppm // // Copyright (c) 2025 Yuji Hirose. All rights reserved. // MIT License diff --git a/split.py b/split.py index 4d8b307417..c05066bc08 100755 --- a/split.py +++ b/split.py @@ -2,66 +2,74 @@ """This script splits httplib.h into .h and .cc parts.""" -import argparse import os import sys +from argparse import ArgumentParser, Namespace +from typing import List -border = '// ----------------------------------------------------------------------------' -args_parser = argparse.ArgumentParser(description=__doc__) -args_parser.add_argument( - "-e", "--extension", help="extension of the implementation file (default: cc)", - default="cc" -) -args_parser.add_argument( - "-o", "--out", help="where to write the files (default: out)", default="out" -) -args = args_parser.parse_args() +def main() -> None: + """Main entry point for the script.""" + BORDER: str = '// ----------------------------------------------------------------------------' -cur_dir = os.path.dirname(sys.argv[0]) -lib_name = 'httplib' -header_name = '/' + lib_name + '.h' -source_name = '/' + lib_name + '.' + args.extension -# get the input file -in_file = cur_dir + header_name -# get the output file -h_out = args.out + header_name -cc_out = args.out + source_name + args_parser: ArgumentParser = ArgumentParser(description=__doc__) + args_parser.add_argument( + "-e", "--extension", help="extension of the implementation file (default: cc)", + default="cc" + ) + args_parser.add_argument( + "-o", "--out", help="where to write the files (default: out)", default="out" + ) + args: Namespace = args_parser.parse_args() -# if the modification time of the out file is after the in file, -# don't split (as it is already finished) -do_split = True + cur_dir: str = os.path.dirname(sys.argv[0]) + lib_name: str = 'httplib' + header_name: str = f"/{lib_name}.h" + source_name: str = f"/{lib_name}.{args.extension}" + # get the input file + in_file: str = cur_dir + header_name + # get the output file + h_out: str = args.out + header_name + cc_out: str = args.out + source_name -if os.path.exists(h_out): - in_time = os.path.getmtime(in_file) - out_time = os.path.getmtime(h_out) - do_split = in_time > out_time + # if the modification time of the out file is after the in file, + # don't split (as it is already finished) + do_split: bool = True -if do_split: - with open(in_file) as f: - lines = f.readlines() + if os.path.exists(h_out): + in_time: float = os.path.getmtime(in_file) + out_time: float = os.path.getmtime(h_out) + do_split: bool = in_time > out_time - python_version = sys.version_info[0] - if python_version < 3: - os.makedirs(args.out) + if do_split: + with open(in_file) as f: + lines: List[str] = f.readlines() + + python_version: int = sys.version_info[0] + if python_version < 3: + os.makedirs(args.out) + else: + os.makedirs(args.out, exist_ok=True) + + in_implementation: bool = False + cc_out: str = args.out + source_name + with open(h_out, 'w') as fh, open(cc_out, 'w') as fc: + fc.write('#include "httplib.h"\n') + fc.write('namespace httplib {\n') + for line in lines: + is_border_line: bool = BORDER in line + if is_border_line: + in_implementation: bool = not in_implementation + elif in_implementation: + fc.write(line.replace('inline ', '')) + else: + fh.write(line) + fc.write('} // namespace httplib\n') + + print(f"Wrote {h_out} and {cc_out}") else: - os.makedirs(args.out, exist_ok=True) + print(f"{h_out} and {cc_out} are up to date") - in_implementation = False - cc_out = args.out + source_name - with open(h_out, 'w') as fh, open(cc_out, 'w') as fc: - fc.write('#include "httplib.h"\n') - fc.write('namespace httplib {\n') - for line in lines: - is_border_line = border in line - if is_border_line: - in_implementation = not in_implementation - elif in_implementation: - fc.write(line.replace('inline ', '')) - else: - fh.write(line) - fc.write('} // namespace httplib\n') - print("Wrote {} and {}".format(h_out, cc_out)) -else: - print("{} and {} are up to date".format(h_out, cc_out)) +if __name__ == "__main__": + main() diff --git a/update_modules.py b/update_modules.py new file mode 100644 index 0000000000..2e948bf4df --- /dev/null +++ b/update_modules.py @@ -0,0 +1,296 @@ +#!/usr/bin/env python3 +""" +Script to update the httplib.cppm module file based on changes to httplib.h. + +This script: +1. Reads the existing exported symbols from modules/httplib.cppm +2. Analyses git diff to find added/removed declarations in httplib.h +3. Updates httplib.cppm by adding new exports and removing deleted ones +""" + +import re +import subprocess +import sys +from pathlib import Path +from re import Match +from subprocess import CalledProcessError, CompletedProcess +from typing import Set, List, Tuple, Optional + + +def extract_exported_symbols(cppm_content: str) -> Set[str]: + """ + Extract all symbols that are currently exported in the module file. + + @param cppm_content Content of the .cppm module file + @return Set of symbol names that are already exported + """ + exported: Set[str] = set() + + # Match patterns like: using httplib::SymbolName; + pattern: str = r'using\s+httplib::(\w+);' + matches: List[str] = re.findall(pattern, cppm_content) + exported.update(matches) + + # Match patterns in nested namespace like: using httplib::stream::SymbolName; + pattern: str = r'using\s+httplib::stream::(\w+);' + matches: List[str] = re.findall(pattern, cppm_content) + exported.update(matches) + + return exported + + +def extract_exported_symbols(cppm_content: str) -> Set[str]: + """ + Extract all symbols that are currently exported in the module file. + + @param cppm_content Content of the .cppm module file + @return Set of symbol names that are already exported + """ + exported: Set[str] = set() + + pattern: str = r'using\s+httplib::(\w+);' + matches: List[str] = re.findall(pattern, cppm_content) + exported.update(matches) + + pattern: str = r'using\s+httplib::stream::(\w+);' + matches: List[str] = re.findall(pattern, cppm_content) + exported.update(matches) + + return exported + + +def get_git_diff(file_path: str, base_ref: str = "HEAD") -> Optional[str]: + """ + Get the git diff for a specific file. + + @param file_path Path to the file to diff + @param base_ref Git reference to compare against (default: HEAD) + @return The git diff output, or None if error + """ + try: + result: CompletedProcess = subprocess.run( + ["git", "diff", base_ref, "--", file_path], + capture_output=True, + text=True, + check=True + ) + return result.stdout + except CalledProcessError as e: + print(f"Error getting git diff: {e}", file=sys.stderr) + return None + + +def is_in_detail_namespace(line: str) -> bool: + """ + Check if a line appears to be in a detail namespace. + + @param line The line to check + @return True if the line is likely in a detail namespace + """ + return 'detail::' in line or line.strip().startswith('namespace detail') + + +def is_member_function_or_field(line: str, prev_context: List[str]) -> bool: + """ + Heuristic to detect if a declaration is likely a member function or field. + + @param line The current line + @param prev_context Previous few lines for context + @return True if it looks like a member declaration + """ + # Check if we're inside a class/struct by looking at previous context + for prev_line in reversed(prev_context[-10:]): # Look at last 10 lines + stripped: str = prev_line.strip() + # If we see a class/struct declaration recently without a closing brace, likely inside it + if re.match(r'^(?:public|private|protected):', stripped): + return True + # Common member function patterns + if stripped.startswith('~') or stripped.startswith('explicit '): + return True + + stripped: str = line.strip() + # Lines with multiple leading spaces are often inside class definitions + if line.startswith(' ') and not line.startswith(' '): # Exactly 2 spaces + return True + + return False + + +def extract_declarations_from_diff(diff_content: str) -> Tuple[Set[str], Set[str]]: + """ + Extract added and removed declarations from a git diff. + + @param diff_content The git diff output + @return Tuple of (added_symbols, removed_symbols) + """ + added_symbols: Set[str] = set() + removed_symbols: Set[str] = set() + + lines: List[str] = diff_content.split('\n') + context_lines: List[str] = [] + + for line in lines: + if not line.startswith('@@'): + context_lines.append(line) + if len(context_lines) > 20: + context_lines.pop(0) + + if is_in_detail_namespace(line): + continue + + if is_member_function_or_field(line, context_lines): + continue + + if line.startswith('+') and not line.startswith('+++'): + content: str = line[1:].strip() + + enum_match: Optional[Match[str]] = re.match(r'^enum\s+(?:class\s+)?(\w+)', content) + if enum_match: + added_symbols.add(enum_match.group(1)) + + class_match: Optional[Match[str]] = re.match(r'^(?:struct|class)\s+(\w+)(?:\s+final)?(?:\s*:\s*public)?', content) + if class_match and not content.endswith(';'): + added_symbols.add(class_match.group(1)) + + using_match: Optional[Match[str]] = re.match(r'^using\s+(\w+)\s+=', content) + if using_match: + added_symbols.add(using_match.group(1)) + + func_match: Optional[Match[str]] = re.match(r'^(?:inline\s+)?(?:const\s+)?(?:std::)?[\w:]+\s+(\w+)\s*\([^)]*\)\s*(?:const)?;', content) + if func_match and not '->' in content: + symbol: str = func_match.group(1) + if symbol not in {'operator', 'if', 'for', 'while', 'return', 'const', 'static'}: + if not (symbol.endswith('_internal') or symbol.endswith('_impl') or symbol.endswith('_core')): + added_symbols.add(symbol) + + elif line.startswith('-') and not line.startswith('---'): + content: str = line[1:].strip() + + enum_match: Optional[Match[str]] = re.match(r'^enum\s+(?:class\s+)?(\w+)', content) + if enum_match: + removed_symbols.add(enum_match.group(1)) + + class_match: Optional[Match[str]] = re.match(r'^(?:struct|class)\s+(\w+)(?:\s+final)?(?:\s*:\s*public)?', content) + if class_match and not content.endswith(';'): + removed_symbols.add(class_match.group(1)) + + using_match: Optional[Match[str]] = re.match(r'^using\s+(\w+)\s+=', content) + if using_match: + removed_symbols.add(using_match.group(1)) + + func_match: Optional[Match[str]] = re.match(r'^(?:inline\s+)?(?:const\s+)?(?:std::)?[\w:]+\s+(\w+)\s*\([^)]*\)\s*(?:const)?;', content) + if func_match and not '->' in content: + symbol: str = func_match.group(1) + if symbol not in {'operator', 'if', 'for', 'while', 'return', 'const', 'static'}: + if not (symbol.endswith('_internal') or symbol.endswith('_impl') or symbol.endswith('_core')): + removed_symbols.add(symbol) + + return added_symbols, removed_symbols + + +def update_module_exports(cppm_path: Path, symbols_to_add: Set[str], symbols_to_remove: Set[str]) -> bool: + """ + Update the module file by adding and removing symbols. + + @param cppm_path Path to the .cppm file + @param symbols_to_add Symbols to add to exports + @param symbols_to_remove Symbols to remove from exports + @return True if file was modified + """ + content: str = cppm_path.read_text() + original_content: str = content + + for symbol in symbols_to_remove: + pattern: str = rf'^\s*using httplib::{re.escape(symbol)};$' + content: str = re.sub(pattern, '', content, flags=re.MULTILINE) + + pattern: str = rf'^\s*using httplib::stream::{re.escape(symbol)};$' + content: str = re.sub(pattern, '', content, flags=re.MULTILINE) + + if symbols_to_add: + pattern: str = r'(.*using httplib::\w+;)' + matches: List[Match[str]] = list(re.finditer(pattern, content, re.MULTILINE)) + + if matches: + last_match: Match[str] = matches[-1] + insert_pos: int = last_match.end() + + new_exports: str = '\n'.join(f" using httplib::{symbol};" for symbol in sorted(symbols_to_add)) + content: str = content[:insert_pos] + '\n' + new_exports + content[insert_pos:] + + content: str = re.sub(r'\n\n\n+', '\n\n', content) + + if content != original_content: + cppm_path.write_text(content) + return True + + return False + + +def main() -> None: + """Main entry point for the script.""" + script_dir: Path = Path(__file__).parent + header_path: Path = script_dir / "httplib.h" + cppm_path: Path = script_dir / "modules" / "httplib.cppm" + + if not header_path.exists(): + print(f"Error: {header_path} not found") + sys.exit(1) + + if not cppm_path.exists(): + print(f"Error: {cppm_path} not found") + sys.exit(1) + + print("Analyzing git diff for httplib.h...") + diff_content: Optional[str] = get_git_diff(str(header_path)) + + if diff_content is None: + print("Error: Could not get git diff") + sys.exit(1) + + if not diff_content.strip(): + print("No changes detected in httplib.h") + sys.exit(0) + + print("Extracting declarations from diff...") + added_symbols, removed_symbols = extract_declarations_from_diff(diff_content) + + if not added_symbols and not removed_symbols: + print("No declaration changes detected") + sys.exit(0) + + print(f"\nFound {len(added_symbols)} added declarations:") + for symbol in sorted(added_symbols): + print(f" + {symbol}") + + print(f"\nFound {len(removed_symbols)} removed declarations:") + for symbol in sorted(removed_symbols): + print(f" - {symbol}") + + print("\nReading current module exports...") + cppm_content: str = cppm_path.read_text() + current_exports: Set[str] = extract_exported_symbols(cppm_content) + + symbols_to_add: Set[str] = added_symbols - current_exports + symbols_to_remove: Set[str] = removed_symbols & current_exports + + if not symbols_to_add and not symbols_to_remove: + print("\nModule file is already up to date") + sys.exit(0) + + print(f"\nUpdating module file:") + if symbols_to_add: + print(f" Adding {len(symbols_to_add)} symbols") + if symbols_to_remove: + print(f" Removing {len(symbols_to_remove)} symbols") + + modified: bool = update_module_exports(cppm_path, symbols_to_add, symbols_to_remove) + + if modified: + print(f"\nāœ“ Successfully updated {cppm_path}") + else: + print(f"\nāœ“ No changes needed to {cppm_path}") + + +if __name__ == "__main__": + main() From 36b1c1683637a247b8d1a2bdd13c27f3cee7c525 Mon Sep 17 00:00:00 2001 From: Toyosatomimi no Miko <110693261+mikomikotaishi@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:58:07 -0500 Subject: [PATCH 5/5] Name the unused param --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6722a9c00f..03e26686cc 100644 --- a/README.md +++ b/README.md @@ -1268,7 +1268,7 @@ using httplib::SSLServer; SSLServer svr; -svr.Get("/hi", []([[maybe_unused]] const Request&, Response& res) -> void { +svr.Get("/hi", []([[maybe_unused]] const Request& req, Response& res) -> void { res.set_content("Hello World!", "text/plain"); });