Skip to content

Commit b1f2cbe

Browse files
committed
Refactor CMake dependency provider setup and enhance argument parsing
- Moved the installation of the dependency provider to occur after all function definitions, ensuring proper setup. - Improved argument parsing in _cpp_library_add_dependency to handle package names and version numbers more robustly, including regex escaping for special characters. - Added a new test to verify handling of version numbers with regex metacharacters, ensuring accurate dependency generation. These changes enhance the reliability and clarity of the CMake configuration for the cpp-library.
1 parent 414ea74 commit b1f2cbe

3 files changed

Lines changed: 49 additions & 13 deletions

File tree

cmake/cpp-library-dependency-provider.cmake

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,8 @@ get_property(_CPP_LIBRARY_PROVIDER_INSTALLED GLOBAL PROPERTY _CPP_LIBRARY_PROVID
3535
if(_CPP_LIBRARY_PROVIDER_INSTALLED)
3636
return()
3737
endif()
38-
set_property(GLOBAL PROPERTY _CPP_LIBRARY_PROVIDER_INSTALLED TRUE)
39-
40-
# Install the dependency provider
41-
cmake_language(SET_DEPENDENCY_PROVIDER _cpp_library_dependency_provider
42-
SUPPORTED_METHODS
43-
FIND_PACKAGE
44-
FETCHCONTENT_MAKEAVAILABLE_SERIAL
45-
)
46-
47-
message(STATUS "cpp-library: Dependency tracking enabled")
4838

39+
# Define all functions BEFORE installing the provider
4940
# The dependency provider implementation
5041
# This function is called before every find_package() and FetchContent_MakeAvailable()
5142
function(_cpp_library_dependency_provider method)
@@ -172,3 +163,14 @@ function(_cpp_library_get_all_tracked_deps OUTPUT_VAR)
172163
set(${OUTPUT_VAR} "${ALL_DEPS}" PARENT_SCOPE)
173164
endfunction()
174165

166+
# Now install the dependency provider (after all functions are defined)
167+
set_property(GLOBAL PROPERTY _CPP_LIBRARY_PROVIDER_INSTALLED TRUE)
168+
169+
cmake_language(SET_DEPENDENCY_PROVIDER _cpp_library_dependency_provider
170+
SUPPORTED_METHODS
171+
FIND_PACKAGE
172+
FETCHCONTENT_MAKEAVAILABLE_SERIAL
173+
)
174+
175+
message(STATUS "cpp-library: Dependency tracking enabled")
176+

cmake/cpp-library-install.cmake

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,32 @@ endfunction()
175175
function(_cpp_library_add_dependency FIND_DEP_ARGS)
176176
# Parse: PackageName [Version] [COMPONENTS component1 component2 ...] [other args]
177177
string(REGEX MATCH "^([^ ]+)" PKG_NAME "${FIND_DEP_ARGS}")
178-
string(REGEX REPLACE "^${PKG_NAME} ?" "" REMAINING_ARGS "${FIND_DEP_ARGS}")
178+
179+
# Remove package name from args - use string(REPLACE) for literal match
180+
string(LENGTH "${PKG_NAME}" PKG_NAME_LEN)
181+
string(LENGTH "${FIND_DEP_ARGS}" TOTAL_LEN)
182+
if(TOTAL_LEN GREATER PKG_NAME_LEN)
183+
math(EXPR START_POS "${PKG_NAME_LEN}")
184+
string(SUBSTRING "${FIND_DEP_ARGS}" ${START_POS} -1 REMAINING_ARGS)
185+
string(STRIP "${REMAINING_ARGS}" REMAINING_ARGS)
186+
else()
187+
set(REMAINING_ARGS "")
188+
endif()
179189

180190
# Extract version (first token that looks like a version number)
181191
set(VERSION "")
182192
if(REMAINING_ARGS MATCHES "^([0-9][0-9.]*)")
183193
set(VERSION "${CMAKE_MATCH_1}")
184-
string(REGEX REPLACE "^${VERSION} ?" "" REMAINING_ARGS "${REMAINING_ARGS}")
194+
# Remove version from args - use substring to avoid regex issues with dots
195+
string(LENGTH "${VERSION}" VERSION_LEN)
196+
string(LENGTH "${REMAINING_ARGS}" TOTAL_LEN)
197+
if(TOTAL_LEN GREATER VERSION_LEN)
198+
math(EXPR START_POS "${VERSION_LEN}")
199+
string(SUBSTRING "${REMAINING_ARGS}" ${START_POS} -1 REMAINING_ARGS)
200+
string(STRIP "${REMAINING_ARGS}" REMAINING_ARGS)
201+
else()
202+
set(REMAINING_ARGS "")
203+
endif()
185204
endif()
186205

187206
# Extract COMPONENTS if present
@@ -192,7 +211,13 @@ function(_cpp_library_add_dependency FIND_DEP_ARGS)
192211
# Extract just the component names (until next keyword or end)
193212
string(REGEX REPLACE " +(REQUIRED|OPTIONAL_COMPONENTS|CONFIG|NO_MODULE).*$" "" COMPONENTS "${COMPONENTS_PART}")
194213
# Remove COMPONENTS and component names from base args
195-
string(REGEX REPLACE "COMPONENTS +${COMPONENTS}" "" BASE_ARGS "${REMAINING_ARGS}")
214+
# Escape COMPONENTS for safe regex use (syntax: string(REGEX ESCAPE <out-var> <string>))
215+
string(REPLACE "." "\\." COMPONENTS_ESCAPED "${COMPONENTS}")
216+
string(REPLACE "*" "\\*" COMPONENTS_ESCAPED "${COMPONENTS_ESCAPED}")
217+
string(REPLACE "+" "\\+" COMPONENTS_ESCAPED "${COMPONENTS_ESCAPED}")
218+
string(REPLACE "[" "\\[" COMPONENTS_ESCAPED "${COMPONENTS_ESCAPED}")
219+
string(REPLACE "]" "\\]" COMPONENTS_ESCAPED "${COMPONENTS_ESCAPED}")
220+
string(REGEX REPLACE "COMPONENTS +${COMPONENTS_ESCAPED}" "" BASE_ARGS "${REMAINING_ARGS}")
196221
string(STRIP "${COMPONENTS}" COMPONENTS)
197222
endif()
198223
string(STRIP "${BASE_ARGS}" BASE_ARGS)

tests/install/test_dependency_provider.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,12 @@ mock_target_links(test26_target "MyPackage::MyPackage")
9898
_cpp_library_generate_dependencies(RESULT test26_target "mylib")
9999
verify_output("${RESULT}" "find_dependency(MyPackage 2.0.0 CONFIG)" "Test 26")
100100

101+
# Test 27: Regex metacharacters in version numbers (bug fix verification)
102+
run_test("Version with dots - regex escaping")
103+
set_property(GLOBAL PROPERTY "_CPP_LIBRARY_TRACKED_DEP_OpenCV" "OpenCV 4.5.3 COMPONENTS core imgproc")
104+
set_property(GLOBAL APPEND PROPERTY _CPP_LIBRARY_ALL_TRACKED_DEPS "OpenCV")
105+
set_property(GLOBAL PROPERTY _CPP_LIBRARY_PROVIDER_INSTALLED TRUE)
106+
mock_target_links(test27_target "OpenCV::core" "OpenCV::imgproc")
107+
_cpp_library_generate_dependencies(RESULT test27_target "mylib")
108+
verify_output("${RESULT}" "find_dependency(OpenCV 4.5.3 COMPONENTS core imgproc)" "Test 27")
109+

0 commit comments

Comments
 (0)