From e9baea943699525b6ec838f006c8e47a9f9c7e04 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:08:46 +0000 Subject: [PATCH 1/2] fix: make CI and Conan packaging fully compliant with Conan 2 Agent-Logs-Url: https://github.com/jbltx/TextMateLib/sessions/c47b1c01-70f0-415f-8301-6ef36cb79245 Co-authored-by: jbltx <1284323+jbltx@users.noreply.github.com> --- .github/workflows/build-and-test.yml | 24 ++++++++++++++++ .github/workflows/release.yml | 20 +++++++------ packages/tml-cpp/CMakeLists.txt | 16 +++++++++-- packages/tml-cpp/conanfile.py | 28 +++++++++++++++++-- packages/tml-cpp/test_package/CMakeLists.txt | 7 +++++ packages/tml-cpp/test_package/conanfile.py | 25 +++++++++++++++++ packages/tml-cpp/test_package/src/example.cpp | 18 ++++++++++++ 7 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 packages/tml-cpp/test_package/CMakeLists.txt create mode 100644 packages/tml-cpp/test_package/conanfile.py create mode 100644 packages/tml-cpp/test_package/src/example.cpp diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 0823359..cfdbdec 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -147,3 +147,27 @@ jobs: - name: Run JS tests working-directory: packages/tml-js run: npm test + + conan-test: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install Conan + run: | + pip install conan + conan profile detect + + - name: Create and test Conan package + run: conan create packages/tml-cpp --build=missing diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 480d91a..b0bc376 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -258,17 +258,19 @@ jobs: pip install conan conan profile detect - - name: Test Conan package locally - working-directory: packages/tml-cpp - run: | - conan create . --build=missing + - name: Create and test Conan package + run: conan create packages/tml-cpp --build=missing - name: Prepare Conan Center submission run: | - echo "Conan package built and tested successfully." + VERSION=$(python3 -c " + import re, pathlib + text = pathlib.Path('packages/tml-cpp/conanfile.py').read_text() + m = re.search(r'version\s*=\s*[\"\']([0-9.]+)[\"\']', text) + print(m.group(1) if m else 'unknown') + ") + echo "Conan package textmatelib/${VERSION} built and tested successfully." echo "To submit to Conan Center:" echo "1. Fork https://github.com/conan-io/conan-center-index" - echo "2. Add recipe to recipes/textmatelib/" - echo "3. Create PR to conan-center-index" - echo "" - echo "Package version: $(grep 'version =' packages/tml-cpp/conanfile.py | head -1)" + echo "2. Add recipe under recipes/textmatelib/${VERSION}/" + echo "3. Create a PR to conan-center-index" diff --git a/packages/tml-cpp/CMakeLists.txt b/packages/tml-cpp/CMakeLists.txt index 70a3244..321a32f 100644 --- a/packages/tml-cpp/CMakeLists.txt +++ b/packages/tml-cpp/CMakeLists.txt @@ -3,6 +3,12 @@ project(tml VERSION 0.1.0 LANGUAGES CXX) include(GenerateExportHeader) +# Allow callers (e.g. Conan) to override the thirdparty directory. +# Defaults to the monorepo layout where thirdparty/ sits two levels above this file. +if(NOT DEFINED THIRDPARTY_DIR) + set(THIRDPARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty") +endif() + # Set C++17 standard for modern features set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -91,7 +97,7 @@ endif() # Include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/src - ${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty/rapidjson/include + ${THIRDPARTY_DIR}/rapidjson/include ) # Source files @@ -208,7 +214,7 @@ if(NOT USE_WASM_BUILD) ExternalProject_Add( oniguruma - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty/oniguruma + SOURCE_DIR ${THIRDPARTY_DIR}/oniguruma BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/oniguruma/build CMAKE_ARGS ${ONIG_CMAKE_ARGS} BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE} @@ -225,7 +231,7 @@ else() ExternalProject_Add( oniguruma_wasm - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty/oniguruma + SOURCE_DIR ${THIRDPARTY_DIR}/oniguruma BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/oniguruma/build_wasm CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release @@ -385,6 +391,10 @@ install(FILES ${TEXTMATE_HEADERS} DESTINATION include/tml ) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tml_export.h + DESTINATION include/tml +) + # Enable testing (skip for WASM builds and shared library builds) # Tests should only use the static library version for proper linking if(NOT USE_WASM_BUILD AND NOT BUILD_SHARED_LIBS) diff --git a/packages/tml-cpp/conanfile.py b/packages/tml-cpp/conanfile.py index bd3453a..5cbcec5 100644 --- a/packages/tml-cpp/conanfile.py +++ b/packages/tml-cpp/conanfile.py @@ -12,6 +12,7 @@ class TextMateLibConan(ConanFile): url = "https://github.com/jbltx/TextMateLib" description = "TextMate syntax highlighting library - a C++ implementation of TextMate grammar parsing and tokenization" topics = ("textmate", "syntax", "highlighting", "grammar", "tokenizer", "parsing") + package_type = "library" settings = "os", "compiler", "build_type", "arch" options = { "shared": [True, False], @@ -21,11 +22,11 @@ class TextMateLibConan(ConanFile): "shared": False, "fPIC": True } + # Only include sources within this package directory; thirdparty deps are + # handled by export_sources() to avoid Conan 2's restriction on ".." patterns. exports_sources = ( "CMakeLists.txt", "src/*", - "../../thirdparty/rapidjson/*", - "../../thirdparty/oniguruma/*" ) def config_options(self): @@ -39,12 +40,35 @@ def configure(self): def layout(self): cmake_layout(self) + def export_sources(self): + # Copy vendored thirdparty dependencies (git submodules) from the monorepo + # root into the Conan export-sources folder so that `conan create` works + # without requiring ".." patterns in exports_sources (which Conan 2 rejects). + thirdparty_root = os.path.normpath( + os.path.join(self.recipe_folder, "..", "..", "thirdparty") + ) + export_thirdparty = os.path.join(self.export_sources_folder, "thirdparty") + copy(self, "rapidjson/*", src=thirdparty_root, dst=export_thirdparty) + copy(self, "oniguruma/*", src=thirdparty_root, dst=export_thirdparty) + def generate(self): deps = CMakeDeps(self) deps.generate() tc = CMakeToolchain(self) tc.variables["BUILD_SHARED_LIBS"] = self.options.shared tc.variables["USE_WASM_BUILD"] = False + # Determine the thirdparty directory. Two cases: + # 1. conan create – thirdparty was exported into source_folder/thirdparty + # 2. conan install (local/monorepo) – thirdparty lives at ../../thirdparty + # relative to the package folder (packages/tml-cpp). + thirdparty_in_source = os.path.join(self.source_folder, "thirdparty") + if os.path.isdir(thirdparty_in_source): + thirdparty_dir = thirdparty_in_source + else: + thirdparty_dir = os.path.normpath( + os.path.join(self.source_folder, "..", "..", "thirdparty") + ) + tc.variables["THIRDPARTY_DIR"] = thirdparty_dir.replace("\\", "/") tc.generate() def build(self): diff --git a/packages/tml-cpp/test_package/CMakeLists.txt b/packages/tml-cpp/test_package/CMakeLists.txt new file mode 100644 index 0000000..968c1a4 --- /dev/null +++ b/packages/tml-cpp/test_package/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.14) +project(PackageTest CXX) + +find_package(TextMateLib REQUIRED CONFIG) + +add_executable(example src/example.cpp) +target_link_libraries(example PRIVATE TextMateLib::tml) diff --git a/packages/tml-cpp/test_package/conanfile.py b/packages/tml-cpp/test_package/conanfile.py new file mode 100644 index 0000000..7a13c5b --- /dev/null +++ b/packages/tml-cpp/test_package/conanfile.py @@ -0,0 +1,25 @@ +import os +from conan import ConanFile +from conan.tools.cmake import CMake, cmake_layout +from conan.tools.build import can_run + + +class TextMateLibTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeDeps", "CMakeToolchain" + + def requirements(self): + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if can_run(self): + cmd = os.path.join(self.cpp.build.bindir, "example") + self.run(cmd, env="conanrun") diff --git a/packages/tml-cpp/test_package/src/example.cpp b/packages/tml-cpp/test_package/src/example.cpp new file mode 100644 index 0000000..671742f --- /dev/null +++ b/packages/tml-cpp/test_package/src/example.cpp @@ -0,0 +1,18 @@ +#include "tml/c_api.h" + +int main() { + TextMateOnigLib lib = textmate_oniglib_create(); + if (!lib) { + return 1; + } + + TextMateRegistry registry = textmate_registry_create(lib); + if (!registry) { + textmate_oniglib_dispose(lib); + return 1; + } + + textmate_registry_dispose(registry); + textmate_oniglib_dispose(lib); + return 0; +} From 66abc32edbfa954cbe6fa98740a5cb21f202015a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:36:39 +0000 Subject: [PATCH 2/2] fix: bundle Oniguruma in Conan package to resolve test_package linker errors Agent-Logs-Url: https://github.com/jbltx/TextMateLib/sessions/a9530db8-612e-4b80-952e-c0a38f6b16f4 Co-authored-by: jbltx <1284323+jbltx@users.noreply.github.com> --- packages/tml-cpp/conanfile.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/tml-cpp/conanfile.py b/packages/tml-cpp/conanfile.py index 5cbcec5..72e4ae0 100644 --- a/packages/tml-cpp/conanfile.py +++ b/packages/tml-cpp/conanfile.py @@ -80,9 +80,22 @@ def package(self): copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) cmake = CMake(self) cmake.install() + # Oniguruma is built via ExternalProject_Add and is not part of cmake --install. + # Copy the static library and public headers so that consumers can link all symbols + # (libtml.a has undefined references to onig_* that the consumer's linker must resolve) + # and so that installed headers like onigLib.h (which include "oniguruma.h") still compile. + onig_install = os.path.join(self.build_folder, "oniguruma") + copy(self, "*.a", src=os.path.join(onig_install, "lib"), + dst=os.path.join(self.package_folder, "lib"), keep_path=False) + copy(self, "*.lib", src=os.path.join(onig_install, "lib"), + dst=os.path.join(self.package_folder, "lib"), keep_path=False) + copy(self, "*.h", src=os.path.join(onig_install, "include"), + dst=os.path.join(self.package_folder, "include"), keep_path=False) def package_info(self): - self.cpp_info.libs = ["tml"] + # tml depends on onig at link time; list both so consumers get all symbols resolved. + # Order matters for static linking: tml first (it references onig), then onig. + self.cpp_info.libs = ["tml", "onig"] self.cpp_info.set_property("cmake_file_name", "TextMateLib") self.cpp_info.set_property("cmake_target_name", "TextMateLib::tml")