Skip to content

Commit ea2ef8a

Browse files
Refactor pkg-config generation to use target properties
This change uses target properties to fill in the slots in the generated pkg-config files. Previously this was unstructured strings and flag juggling.
1 parent 18146ac commit ea2ef8a

File tree

6 files changed

+192
-73
lines changed

6 files changed

+192
-73
lines changed

build/cmake/ResSearch.cmake

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
include(CheckSymbolExists)
22

3-
set(resolve_libs)
3+
# The name of the library that performs name resolution, suitable for giving to the "-l" link flag
4+
set(RESOLVE_LIB_NAME)
5+
# If TRUE, then the C runtime provides the name resolution that we need
46
set(resolve_is_libc FALSE)
57

68
if(WIN32)
7-
set(resolve_libs Dnsapi)
9+
set(RESOLVE_LIB_NAME Dnsapi)
810
set(_MONGOC_HAVE_DNSAPI 1)
911
else()
1012
# Thread-safe DNS query function for _mongoc_client_get_srv.
@@ -14,7 +16,7 @@ else()
1416
check_symbol_exists(res_nclose resolv.h _MONGOC_HAVE_RES_NCLOSE)
1517
if(MONGOC_HAVE_RES_NSEARCH)
1618
# We have res_nsearch. Call res_ndestroy (BSD/Mac) or res_nclose (Linux)?
17-
set(resolve_libs resolv)
19+
set(RESOLVE_LIB_NAME resolv)
1820
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
1921
# On FreeBSD, the following line does not properly detect res_search,
2022
# which is included in libc on FreeBSD:
@@ -32,7 +34,7 @@ else()
3234
# Thread-unsafe function.
3335
check_symbol_exists(res_search resolv.h _MONGOC_HAVE_RES_SEARCH)
3436
if(_MONGOC_HAVE_RES_SEARCH)
35-
set(resolve_libs resolv)
37+
set(RESOLVE_LIB_NAME resolv)
3638
endif()
3739
endif()
3840
endif()
@@ -43,11 +45,12 @@ _mongo_pick(MONGOC_HAVE_RES_NDESTROY 1 0 _MONGOC_HAVE_RES_NDESTROY)
4345
_mongo_pick(MONGOC_HAVE_RES_NCLOSE 1 0 _MONGOC_HAVE_RES_NCLOSE)
4446
_mongo_pick(MONGOC_HAVE_RES_SEARCH 1 0 _MONGOC_HAVE_RES_SEARCH)
4547

46-
if(resolve_libs OR resolve_is_libc)
48+
if(RESOLVE_LIB_NAME OR resolve_is_libc)
4749
# Define the resolver interface:
4850
add_library(_mongoc-resolve INTERFACE)
49-
target_link_libraries(_mongoc-resolve INTERFACE ${resolve_libs})
50-
add_library(mongo::c::detail::resolve ALIAS _mongoc-resolve)
51-
set_property(TARGET _mongoc-resolve PROPERTY EXPORT_NAME c::detail::resolve)
51+
add_library(mongo::detail::c_resolve ALIAS _mongoc-resolve)
52+
set_target_properties(_mongoc-resolve PROPERTIES
53+
INTERFACE_LINK_LIBRARIES "${RESOLVE_LIB_NAME}"
54+
EXPORT_NAME detail::c_resolve)
5255
install(TARGETS _mongoc-resolve EXPORT mongoc-targets)
5356
endif()

src/libmongoc/CMakeLists.txt

Lines changed: 117 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -720,10 +720,10 @@ set_property(TARGET _mongoc-dependencies PROPERTY EXPORT_NAME dependencies)
720720

721721
if(ENABLE_SRV)
722722
# Interface target defined by ResSearch.cmake:
723-
if(NOT TARGET mongo::c::detail::resolve)
723+
if(NOT TARGET mongo::detail::c_resolve)
724724
message(SEND_ERROR "ENABLE_SRV is “${ENABLE_SRV}”, but we were unable to find a name resolution library")
725725
endif()
726-
target_link_libraries(_mongoc-dependencies INTERFACE mongo::c::detail::resolve)
726+
target_link_libraries(_mongoc-dependencies INTERFACE mongo::detail::c_resolve)
727727
endif()
728728

729729
if (WIN32)
@@ -786,8 +786,12 @@ target_include_directories (
786786
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/../../src/common>
787787
)
788788

789-
set_target_properties (mongoc_shared PROPERTIES VERSION 0.0.0 SOVERSION 0)
790-
set_target_properties (mongoc_shared PROPERTIES OUTPUT_NAME "${MONGOC_OUTPUT_BASENAME}-${MONGOC_API_VERSION}")
789+
set_target_properties (mongoc_shared PROPERTIES
790+
OUTPUT_NAME "${MONGOC_OUTPUT_BASENAME}-${MONGOC_API_VERSION}"
791+
VERSION 0.0.0
792+
SOVERSION 0
793+
pc_REQUIRES "libbson-1.0"
794+
)
791795

792796
if (MONGOC_ENABLE_STATIC_BUILD)
793797
add_library (mongoc_static STATIC ${SOURCES} ${HEADERS} ${HEADERS_FORWARDING})
@@ -800,6 +804,10 @@ if (MONGOC_ENABLE_STATIC_BUILD)
800804
target_compile_options (mongoc_static PUBLIC -fPIC)
801805
message (STATUS "Adding -fPIC to compilation of mongoc_static components")
802806
endif ()
807+
if(ENABLE_SRV AND RESOLVE_LIB_NAME)
808+
# The static library needs to link to the resolver in pkg-config:
809+
set_property(TARGET mongoc_static APPEND PROPERTY pc_LIBS "-l${RESOLVE_LIB_NAME}")
810+
endif()
803811
target_include_directories (mongoc_static PRIVATE ${ZLIB_INCLUDE_DIRS})
804812
target_include_directories (mongoc_static PRIVATE ${LIBMONGOCRYPT_INCLUDE_DIRECTORIES})
805813
if (MONGOC_ENABLE_MONGODB_AWS_AUTH)
@@ -827,8 +835,11 @@ if (MONGOC_ENABLE_STATIC_BUILD)
827835
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/../../src>
828836
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/../../src/common>
829837
)
830-
set_target_properties (mongoc_static PROPERTIES VERSION 0.0.0)
831-
set_target_properties (mongoc_static PROPERTIES OUTPUT_NAME "${MONGOC_OUTPUT_BASENAME}-static-${MONGOC_API_VERSION}")
838+
set_target_properties (mongoc_static PROPERTIES
839+
VERSION 0.0.0
840+
OUTPUT_NAME "${MONGOC_OUTPUT_BASENAME}-static-${MONGOC_API_VERSION}"
841+
pc_REQUIRES "libbson-static-1.0"
842+
)
832843
endif ()
833844

834845
if (ENABLE_APPLE_FRAMEWORK)
@@ -1193,44 +1204,109 @@ set (VERSION "${MONGOC_VERSION}")
11931204
set (prefix "${CMAKE_INSTALL_PREFIX}")
11941205
set (libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
11951206

1196-
foreach (
1197-
FLAG
1198-
${SASL_LIBRARIES} ${SSL_LIBRARIES} ${SHM_LIBRARIES}
1199-
${THREAD_LIB} ${ZLIB_LIBRARIES} ${SNAPPY_LIBRARIES} ${MONGOC_ZSTD_LIBRARIES} ${ICU_LIBRARIES}
1207+
# Collect link items for the static library to be inserted into the pkg-config
1208+
if(TARGET mongoc_static)
1209+
set(link_options
1210+
${SASL_LIBRARIES} ${SSL_LIBRARIES} ${SHM_LIBRARIES} ${THREAD_LIB} ${ZLIB_LIBRARIES}
1211+
${SNAPPY_LIBRARIES} ${MONGOC_ZSTD_LIBRARIES} ${ICU_LIBRARIES}
12001212
${LIBMONGOCRYPT_LIBRARY})
1213+
# Replace all absolute paths with search-dir link-file options:
1214+
list(TRANSFORM link_options
1215+
REPLACE "^(.+)/lib([^/]+)\\.[a-z]+$"
1216+
"-L\\1;-l\\2"
1217+
REGEX "^/")
1218+
# Prepend "-l" to all bare names:
1219+
list(TRANSFORM link_options PREPEND "-l" REGEX "^[^-]")
1220+
list(REMOVE_DUPLICATES link_options)
1221+
message(DEBUG "Computed static library link options: ${link_options}")
1222+
set_property(TARGET mongoc_static APPEND PROPERTY pc_LIBS ${link_options})
1223+
endif()
12011224

1202-
if (IS_ABSOLUTE "${FLAG}")
1203-
get_filename_component (FLAG_DIR "${FLAG}" DIRECTORY)
1204-
get_filename_component (FLAG_FILE "${FLAG}" NAME_WE)
1205-
STRING (REGEX REPLACE "^lib" "" FLAG_FILE "${FLAG_FILE}")
1206-
set (MONGOC_LIBRARIES "${MONGOC_LIBRARIES} -L${FLAG_DIR} -l${FLAG_FILE}")
1207-
elseif (FLAG MATCHES "^-.*")
1208-
# Flag starts with dash, add it as-is.
1209-
set (MONGOC_LIBRARIES "${MONGOC_LIBRARIES} ${FLAG}")
1210-
else ()
1211-
# Flag doesn't start with dash, add it with a dash.
1212-
set (MONGOC_LIBRARIES "${MONGOC_LIBRARIES} -l${FLAG}")
1213-
endif ()
1214-
endforeach ()
1225+
# More pkg-config properties:
1226+
set_target_properties(${TARGETS_TO_INSTALL} PROPERTIES
1227+
pc_NAME "libmongoc"
1228+
pc_DESCRIPTION "The libmongoc MongoDB client library."
1229+
pc_VERSION "${VERSION}")
1230+
# Relative include-path will be given the install prefix:
1231+
set_property(TARGET ${TARGETS_TO_INSTALL} APPEND PROPERTY pc_INCLUDE_DIRECTORIES "${MONGOC_HEADER_INSTALL_DIR}")
1232+
1233+
#[[
1234+
Utility for configuring a file and then evaluating generator expressions on it.
1235+
The content of the file has a tiny templating DSL for writing generator
1236+
expressions. Expansion takes place as follows:
1237+
1. Delete any content starting at hash-tilde "#~" until the next newline
1238+
2. Search for any lines of the form "%define foo bar". For each instance,
1239+
replace "foo" with "bar" in the remainder of the file. The "% foo bar"
1240+
line is deleted.
1241+
3. If a tilde "~" appears adjacent to any of "$,<:>@", delete the tilde and
1242+
all adjacent whitespace.
1243+
4. Run string(CONFIGURE ... @ONLY) on the result to replace variable
1244+
references. Special replacements @space@, @newline, and @empty@ are also
1245+
available for adjusting whitespace after ~ trimming.
1246+
5. Run file(GENERATE).
1247+
]]
1248+
function(_mongoc_configure_and_generate_file input output)
1249+
set(CMAKE_MESSAGE_CONTEXT _mongoc_configure_and_generate_file)
1250+
# If given a relative input path, make it relative to the current source dir:
1251+
get_filename_component(abs_in "${input}" ABSOLUTE)
1252+
file(READ "${input}" content)
1253+
# Some convenience values for @expansion@ in the file:
1254+
set(space " ")
1255+
set(newline "\n")
1256+
set(empty "")
1257+
# Delete "#~" comments:
1258+
string(REGEX REPLACE "#~[^\n]*" "" content "${content}")
1259+
# Replace our simple "%define <name> <value>" macros:
1260+
while(content MATCHES "(.*)\n *%define *([a-zA-Z_\\$<>:-]+) *([^\n]*)\n(.*)")
1261+
set(before "${CMAKE_MATCH_1}")
1262+
set(after "${CMAKE_MATCH_4}")
1263+
set(def "${CMAKE_MATCH_2}")
1264+
set(val "${CMAKE_MATCH_3}")
1265+
message(TRACE "Replace “${def}” with “${val}”")
1266+
# Only perform the replacment on the remainder of the file following that
1267+
# line:
1268+
string(REPLACE "${def}" "${val}" after "${after}")
1269+
# Splice the results:
1270+
set(content "${before}\n${after}")
1271+
endwhile()
1272+
# Whitespace trimming. right-trim when tilde is to the right of special chars:
1273+
string(REGEX REPLACE "([,><:@])~[ \n\t]*" "\\1" content "${content}")
1274+
# Same thing, but on the left-hand side:
1275+
string(REGEX REPLACE "[ \n\t]*~([^ \t\n])" "\\1" content "${content}")
1276+
# Replace @varables@:
1277+
string(CONFIGURE "${content}" content @ONLY)
1278+
# If given a relative output path, make it relative to the current binary dir:
1279+
if(NOT IS_ABSOLUTE "${output}")
1280+
get_filename_component(output "${CMAKE_CURRENT_BINARY_DIR}/${output}" ABSOLUTE)
1281+
endif()
1282+
message(DEBUG "Configure+generate file [${input}] -> [${output}]")
1283+
message(TRACE "Content:\n${content}")
1284+
# Generate it:
1285+
file(GENERATE OUTPUT "${output}" CONTENT "${content}" ${ARGN})
1286+
endfunction()
1287+
1288+
# Generate pkg-config for mongoc_shared
1289+
if(TARGET mongoc_shared)
1290+
set(GENERATE_TARGET mongoc_shared)
1291+
_mongoc_configure_and_generate_file(
1292+
src/libmongoc.pc.in
1293+
src/libmongoc-1.0.pc)
1294+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/libmongoc-1.0.pc
1295+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
1296+
endif()
1297+
1298+
# Now one for mongoc_static:
1299+
if(TARGET mongoc_static)
1300+
set(GENERATE_TARGET mongoc_static)
1301+
_mongoc_configure_and_generate_file(
1302+
src/libmongoc.pc.in
1303+
src/libmongoc-static-1.0.pc)
1304+
if(MONGOC_ENABLE_STATIC_INSTALL)
1305+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/libmongoc-static-1.0.pc
1306+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
1307+
endif()
1308+
endif()
12151309

1216-
configure_file (
1217-
${CMAKE_CURRENT_SOURCE_DIR}/src/libmongoc-1.0.pc.in
1218-
${CMAKE_CURRENT_BINARY_DIR}/src/libmongoc-1.0.pc
1219-
@ONLY)
1220-
install (
1221-
FILES ${CMAKE_CURRENT_BINARY_DIR}/src/libmongoc-1.0.pc
1222-
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
1223-
)
1224-
if (MONGOC_ENABLE_STATIC_INSTALL)
1225-
configure_file (
1226-
${CMAKE_CURRENT_SOURCE_DIR}/src/libmongoc-static-1.0.pc.in
1227-
${CMAKE_CURRENT_BINARY_DIR}/src/libmongoc-static-1.0.pc
1228-
@ONLY)
1229-
install (
1230-
FILES ${CMAKE_CURRENT_BINARY_DIR}/src/libmongoc-static-1.0.pc
1231-
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
1232-
)
1233-
endif ()
12341310
# Deprecated alias for libmongoc-1.0.pc, see CDRIVER-2086.
12351311
if (MONGOC_ENABLE_SSL)
12361312
configure_file (

src/libmongoc/src/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ add_subdirectory (mongoc)
22

33
set_local_dist (src_libmongoc_src_DIST_local
44
CMakeLists.txt
5-
libmongoc-1.0.pc.in
5+
libmongoc.pc.in
66
libmongoc-ssl-1.0.pc.in
7-
libmongoc-static-1.0.pc.in
87
mongoc-config.cmake
98
)
109

src/libmongoc/src/libmongoc-1.0.pc.in

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/libmongoc/src/libmongoc-static-1.0.pc.in

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/libmongoc/src/libmongoc.pc.in

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
prefix=@prefix@
2+
exec_prefix=${prefix}
3+
libdir=@libdir@
4+
includedir=${exec_prefix}/include
5+
6+
Name: $<TARGET_PROPERTY:@GENERATE_TARGET@,pc_NAME>
7+
Description: $<TARGET_PROPERTY:@GENERATE_TARGET@,pc_DESCRIPTION>
8+
Version: $<TARGET_PROPERTY:@GENERATE_TARGET@,pc_VERSION>
9+
10+
%define $<is-empty: $<STREQUAL:@empty@,
11+
%define $<<not-empty: $<NOT:$<is-empty:
12+
13+
#~ "Requires" dependencies:
14+
%define requires_joiner @newline@~ Requires: ~@space@
15+
%define requires_prop $<TARGET_PROPERTY:@GENERATE_TARGET@,pc_REQUIRES>
16+
#~ Conditional: Only expand a first "\nRequires: " if Requires is non-empty:
17+
%define has_requires $<<not-empty:requires_prop>>
18+
~$<has_requires:requires_joiner>
19+
#~ The rest:
20+
~$<JOIN:requires_prop,requires_joiner>
21+
22+
~@newline@~
23+
24+
#~ Link options:
25+
Libs: -L${libdir} -l$<TARGET_PROPERTY:@GENERATE_TARGET@,OUTPUT_NAME> ~@space@~
26+
#~ Join each "Libs" item with spaces. This could be more robust, but it suites our purposes:
27+
%define libs_prop $<TARGET_PROPERTY:@GENERATE_TARGET@,pc_LIBS>
28+
#~ Remove duplicate items, which will usually be redundant link paths:
29+
%define libs $<REMOVE_DUPLICATES:libs_prop>
30+
$<JOIN:libs,@space@>~
31+
32+
#~ Add link options. Don't remove duplicates, because they may be important
33+
%define link_opts $<TARGET_PROPERTY:@GENERATE_TARGET@,INTERFACE_LINK_OPTIONS>
34+
$<$<<not-empty:link_opts>>:@space@$<JOIN:link_opts,@space@>>
35+
36+
~@newline@~
37+
38+
#~ Compile-flags:
39+
%define cflags_prop $<TARGET_PROPERTY:@GENERATE_TARGET@,pc_CFLAGS>
40+
Cflags: $<JOIN:cflags_prop,@space@> ~@space@~
41+
42+
#~ Options:
43+
%define opts_prop $<TARGET_PROPERTY:@GENERATE_TARGET@,INTERFACE_COMPILE_OPTIONS>
44+
%define opts $<REMOVE_DUPLICATES:opts_prop>
45+
$<JOIN:opts,@space@>~
46+
47+
#~ Preprocessor definitions:
48+
%define defs_prop $<TARGET_PROPERTY:@GENERATE_TARGET@,INTERFACE_COMPILE_DEFINITIONS>
49+
%define defs $<REMOVE_DUPLICATES:defs_prop>
50+
$<$<<not-empty:defs>>: -D>~
51+
$<JOIN:defs, -D>~
52+
53+
#~ Inclusions:
54+
%define inc_prop $<TARGET_PROPERTY:@GENERATE_TARGET@,pc_INCLUDE_DIRECTORIES>
55+
%define incs $<REMOVE_DUPLICATES:inc_prop>
56+
#~ Absolute path includes are kept absolute:
57+
%define abs_includes $<FILTER:incs,INCLUDE,^/>
58+
$<$<<not-empty:abs_includes>>: -I>~
59+
$<JOIN:abs_includes, -I>~
60+
#~ Relative includes are made relative to ${prefix}
61+
%define relative_includes $<FILTER:incs,EXCLUDE,^/>
62+
$<$<<not-empty:relative_includes>>: -I${prefix}/>~
63+
$<JOIN:relative_includes, -I${prefix}/>

0 commit comments

Comments
 (0)