Skip to content

Commit 0a4e5e4

Browse files
authored
CXX-2803 Add ABI tag to library filenames on Windows (#1081)
* Add ABI tag to library filenames on Windows * Update API/ABI documentation with Windows library filename description
1 parent 5b743b1 commit 0a4e5e4

File tree

13 files changed

+506
-121
lines changed

13 files changed

+506
-121
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Note: user-defined forward declarations of any library entity has not been, and is still not, supported.
1414
To obtain the declaration or definition of a library entity, always include the corresponding header.
1515

16+
### Changed
17+
18+
- Library filenames, when compiled with MSVC (as detected by [CMake's MSVC variable](https://cmake.org/cmake/help/v3.15/variable/MSVC.html)), are now embedded with an ABI tag string, e.g. `bsoncxx-v_noabi-rhs-x64-v142-md.lib`.
19+
- This new behavior is enabled by default; disable by setting `ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES=OFF` when configuring the CXX Driver.
20+
- The ABI tag string can also be embedded in pkg-config metadata filenames, e.g. `libbsoncxx-v_noabi-rhs-x64-v142-md.pc`. This is disabled by default; enable by setting `ENABLE_ABI_TAG_IN_PKGCONFIG_FILENAMES=ON` (requires `ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES=ON`).
21+
1622
### Removed
1723

1824
- Deprecated CMake package config files.

CMakeLists.txt

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ endif()
139139
set(CMAKE_CXX_EXTENSIONS OFF)
140140

141141
# Include the required modules
142+
include(CMakeDependentOption)
142143
include(GenerateExportHeader)
143144
include(InstallRequiredSystemLibraries)
144145

@@ -156,6 +157,22 @@ option(BUILD_SHARED_LIBS_WITH_STATIC_MONGOC
156157
OFF
157158
)
158159

160+
if(DEFINED CACHE{ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES} AND NOT MSVC)
161+
message(WARNING "ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES is an MSVC-only option and will be ignored by the current configuration")
162+
unset(ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES CACHE)
163+
endif()
164+
165+
if(DEFINED CACHE{ENABLE_ABI_TAG_IN_PKGCONFIG_FILENAMES} AND NOT $CACHE{ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES})
166+
message(WARNING "ENABLE_ABI_TAG_IN_PKGCONFIG_FILENAMES requires ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES=ON and will be ignored by the current configuration")
167+
unset(ENABLE_ABI_TAG_IN_PKGCONFIG_FILENAMES CACHE)
168+
endif()
169+
170+
# Allow user to disable embedding of ABI tag in library filenames (MSVC only).
171+
cmake_dependent_option(ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES "Embed ABI tag in library filenames" ON "MSVC" OFF)
172+
173+
# Allow user to enable embedding of ABI tag in pkg-config metadata filenames (MSVC only).
174+
cmake_dependent_option(ENABLE_ABI_TAG_IN_PKGCONFIG_FILENAMES "Embed ABI tag in pkg-config metadata filenames" OFF "ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES" OFF)
175+
159176
option(ENABLE_UNINSTALL "Enable creation of uninstall script and associated uninstall build target." ON)
160177

161178
# Allow the user to enable code coverage
@@ -430,26 +447,33 @@ if(NOT(TARGET dist OR TARGET distcheck))
430447

431448
# Ensure distcheck inherits polyfill library selection.
432449
set(polyfill_flags "")
433-
if (NOT "${CMAKE_CXX_STANDARD}" STREQUAL "")
434-
list(APPEND polyfill_flags "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")
435-
endif ()
436-
if (NOT "${BOOST_ROOT}" STREQUAL "")
437-
list(APPEND polyfill_flags "-DBOOST_ROOT=${BOOST_ROOT}")
438-
endif ()
439-
if (NOT "${BSONCXX_POLY_USE_MNMLSTC}" STREQUAL "")
440-
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_MNMLSTC=${BSONCXX_POLY_USE_MNMLSTC}")
450+
451+
if(NOT "${CMAKE_CXX_STANDARD}" STREQUAL "")
452+
list(APPEND polyfill_flags "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")
441453
endif()
442-
if (NOT "${BSONCXX_POLY_USE_STD_EXPERIMENTAL}" STREQUAL "")
443-
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_STD_EXPERIMENTAL=${BSONCXX_POLY_USE_STD_EXPERIMENTAL}")
454+
455+
if(NOT "${BOOST_ROOT}" STREQUAL "")
456+
list(APPEND polyfill_flags "-DBOOST_ROOT=${BOOST_ROOT}")
444457
endif()
445-
if (NOT "${BSONCXX_POLY_USE_SYSTEM_MNMLSTC}" STREQUAL "")
446-
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_SYSTEM_MNMLSTC=${BSONCXX_POLY_USE_SYSTEM_MNMLSTC}")
458+
459+
if(NOT "${BSONCXX_POLY_USE_MNMLSTC}" STREQUAL "")
460+
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_MNMLSTC=${BSONCXX_POLY_USE_MNMLSTC}")
461+
endif()
462+
463+
if(NOT "${BSONCXX_POLY_USE_STD_EXPERIMENTAL}" STREQUAL "")
464+
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_STD_EXPERIMENTAL=${BSONCXX_POLY_USE_STD_EXPERIMENTAL}")
447465
endif()
448-
if (NOT "${BSONCXX_POLY_USE_BOOST}" STREQUAL "")
449-
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_BOOST=${BSONCXX_POLY_USE_BOOST}")
466+
467+
if(NOT "${BSONCXX_POLY_USE_SYSTEM_MNMLSTC}" STREQUAL "")
468+
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_SYSTEM_MNMLSTC=${BSONCXX_POLY_USE_SYSTEM_MNMLSTC}")
450469
endif()
451-
if (NOT "${BSONCXX_POLY_USE_STD}" STREQUAL "")
452-
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_STD=${BSONCXX_POLY_USE_STD}")
470+
471+
if(NOT "${BSONCXX_POLY_USE_BOOST}" STREQUAL "")
472+
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_BOOST=${BSONCXX_POLY_USE_BOOST}")
473+
endif()
474+
475+
if(NOT "${BSONCXX_POLY_USE_STD}" STREQUAL "")
476+
list(APPEND polyfill_flags "-DBSONCXX_POLY_USE_STD=${BSONCXX_POLY_USE_STD}")
453477
endif()
454478

455479
add_custom_target(distcheck DEPENDS dist

cmake/BsoncxxUtil.cmake

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,133 @@ function(bsoncxx_add_library TARGET OUTPUT_NAME LINK_TYPE)
1010
${bsoncxx_sources}
1111
)
1212

13+
# Full ABI tag string to append to library output name.
14+
# The value is determined at generator-time when using a multi-config generator.
15+
# Otherwise, the value is determined at configure-time.
16+
set(abi_tag "")
17+
18+
# ABI tag and properties.
19+
if(1)
20+
# Enforce ABI compatibility in dependent targets.
21+
set_property(TARGET ${TARGET} APPEND PROPERTY COMPATIBLE_INTERFACE_STRING
22+
BSONCXX_ABI_TAG_MONGOC_LINK_TYPE
23+
BSONCXX_ABI_TAG_POLYFILL_LIBRARY
24+
)
25+
26+
# ABI version number. Only necessary for shared library targets.
27+
if(LINK_TYPE STREQUAL "SHARED")
28+
set(soversion _noabi)
29+
set_target_properties(${TARGET} PROPERTIES SOVERSION ${soversion})
30+
string(APPEND abi_tag "-v${soversion}")
31+
endif()
32+
33+
# Build type:
34+
# - 'd' for debug.
35+
# - 'r' for release (including RelWithDebInfo and MinSizeRel).
36+
# - 'u' for unknown (e.g. to allow user-defined configurations).
37+
# Compatibility is handled via CMake's IMPORTED_CONFIGURATIONS rather than interface properties.
38+
string(APPEND abi_tag "-$<IF:$<CONFIG:Debug>,d,$<IF:$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>,r,u>>")
39+
40+
# Link type with libmongoc.
41+
# - 'h' for shared.
42+
# - 't' for static.
43+
if(1)
44+
if(BSONCXX_LINK_WITH_STATIC_MONGOC)
45+
set(mongoc_link_type "t")
46+
else()
47+
set(mongoc_link_type "h")
48+
endif()
49+
50+
set_target_properties(${TARGET} PROPERTIES INTERFACE_BSONCXX_ABI_TAG_MONGOC_LINK_TYPE ${mongoc_link_type})
51+
52+
string(APPEND abi_tag "${mongoc_link_type}")
53+
endif()
54+
55+
# Library used for C++17 polyfills:
56+
# - 'm' for mnmlstc/core.
57+
# - 'b' for Boost.
58+
# - 'x' for experimental standard library.
59+
# - 'i' for bsoncxx implementations.
60+
# - 's' for standard library (no polyfill).
61+
if(1)
62+
if(BSONCXX_POLY_USE_MNMLSTC)
63+
set(polyfill "m")
64+
elseif(BSONCXX_POLY_USE_BOOST)
65+
set(polyfill "b")
66+
elseif(BSONCXX_POLY_USE_STD_EXPERIMENTAL)
67+
set(polyfill "x")
68+
elseif(0) # CXX-2796: reserved for bsoncxx implementations as polyfill.
69+
set(polyfill "i")
70+
elseif(BSONCXX_POLY_USE_STD)
71+
set(polyfill "s")
72+
else()
73+
message(FATAL_ERROR "could not determine polyfill library: must be one of [mbxis]")
74+
endif()
75+
76+
set_target_properties(${TARGET} PROPERTIES INTERFACE_BSONCXX_ABI_TAG_POLYFILL_LIBRARY ${polyfill})
77+
78+
string(APPEND abi_tag "${polyfill}")
79+
endif()
80+
81+
# MSVC-specific ABI tag suffixes.
82+
if(MSVC)
83+
set(vs_suffix "")
84+
85+
# Include the target architecture if applicable (Win32, x64, etc.).
86+
if(CMAKE_VS_PLATFORM_NAME)
87+
string(APPEND vs_suffix "-$<LOWER_CASE:${CMAKE_VS_PLATFORM_NAME}>")
88+
endif()
89+
90+
# Include the platform toolset version if applicable (v140, v142, etc.).
91+
if(CMAKE_VS_PLATFORM_TOOLSET)
92+
string(APPEND vs_suffix "-$<LOWER_CASE:${CMAKE_VS_PLATFORM_TOOLSET}>")
93+
endif()
94+
95+
# Include the C runtime if applicable.
96+
if(1)
97+
get_target_property(runtime ${TARGET} MSVC_RUNTIME_LIBRARY)
98+
99+
if(runtime)
100+
if(runtime STREQUAL "MultiThreaded")
101+
set(runtime_str "mt")
102+
elseif(runtime STREQUAL "MultiThreadedDebug")
103+
set(runtime_str "mtd")
104+
elseif(runtime STREQUAL "MultiThreadedDLL")
105+
set(runtime_str "md")
106+
elseif(runtime STREQUAL "MultiThreadedDebugDLL")
107+
set(runtime_str "mdd")
108+
endif()
109+
else()
110+
# Per CMake documentation: if MSVC_RUNTIME_LIBRARY is not set, then
111+
# CMake uses the default value MultiThreaded$<$<CONFIG:Debug>:Debug>DLL
112+
# to select a MSVC runtime library.
113+
set(runtime_str "m$<$<CONFIG:Debug>:d>d")
114+
endif()
115+
116+
string(APPEND vs_suffix "-${runtime_str}")
117+
endif()
118+
119+
set_target_properties(${TARGET} PROPERTIES BSONCXX_ABI_TAG_VS_SUFFIX ${vs_suffix})
120+
121+
string(APPEND abi_tag "${vs_suffix}")
122+
endif()
123+
endif()
124+
13125
set_target_properties(${TARGET} PROPERTIES
14-
OUTPUT_NAME ${OUTPUT_NAME}
15126
VERSION ${BSONCXX_VERSION}
16127
DEFINE_SYMBOL BSONCXX_EXPORT
17128
)
18129

130+
if(ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES)
131+
set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME}${abi_tag})
132+
else()
133+
set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
134+
endif()
135+
19136
if(LINK_TYPE STREQUAL "SHARED")
20137
set_target_properties(${TARGET} PROPERTIES
21138
CXX_VISIBILITY_PRESET hidden
22139
VISIBILITY_INLINES_HIDDEN ON
23-
SOVERSION _noabi
24140
)
25141
endif()
26142

cmake/MongocxxUtil.cmake

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,90 @@ function(mongocxx_add_library TARGET OUTPUT_NAME LINK_TYPE)
1010
${mongocxx_sources}
1111
)
1212

13+
# Full ABI tag string to append to library output name.
14+
# The value is determined at generator-time when using a multi-config generator.
15+
# Otherwise, the value is determined at configure-time.
16+
set(abi_tag "")
17+
18+
# ABI tag and properties.
19+
if(1)
20+
# Many ABI tag fields are inherited from bsoncxx (must be consistent).
21+
if(BSONCXX_BUILD_SHARED)
22+
set(bsoncxx_target bsoncxx_shared)
23+
else()
24+
set(bsoncxx_target bsoncxx_static)
25+
endif()
26+
27+
# ABI version number. Only necessary for shared library targets.
28+
if(LINK_TYPE STREQUAL "SHARED")
29+
set(soversion _noabi)
30+
set_target_properties(${TARGET} PROPERTIES SOVERSION ${soversion})
31+
string(APPEND abi_tag "-v${soversion}")
32+
endif()
33+
34+
# Build type. Inherit from bsoncxx.
35+
if(1)
36+
get_target_property(build_type ${bsoncxx_target} INTERFACE_BSONCXX_ABI_TAG_BUILD_TYPE)
37+
38+
set_target_properties(${TARGET} PROPERTIES
39+
BSONCXX_ABI_TAG_BUILD_TYPE ${build_type}
40+
INTERFACE_BSONCXX_ABI_TAG_BUILD_TYPE ${build_type}
41+
)
42+
43+
string(APPEND abi_tag "-${build_type}")
44+
endif()
45+
46+
# Link type with libmongoc. Inherit from bsoncxx.
47+
if(1)
48+
get_target_property(mongoc_link_type ${bsoncxx_target} INTERFACE_BSONCXX_ABI_TAG_MONGOC_LINK_TYPE)
49+
50+
set_target_properties(${TARGET} PROPERTIES
51+
BSONCXX_ABI_TAG_MONGOC_LINK_TYPE ${mongoc_link_type}
52+
INTERFACE_BSONCXX_ABI_TAG_MONGOC_LINK_TYPE ${mongoc_link_type}
53+
)
54+
55+
string(APPEND abi_tag "${mongoc_link_type}")
56+
endif()
57+
58+
# Library used for C++17 polyfills. Inherit from bsoncxx.
59+
if(1)
60+
get_target_property(polyfill ${bsoncxx_target} INTERFACE_BSONCXX_ABI_TAG_POLYFILL_LIBRARY)
61+
62+
set_target_properties(${TARGET} PROPERTIES
63+
BSONCXX_ABI_TAG_POLYFILL_LIBRARY ${polyfill}
64+
INTERFACE_BSONCXX_ABI_TAG_POLYFILL_LIBRARY ${polyfill}
65+
)
66+
67+
string(APPEND abi_tag "${polyfill}")
68+
endif()
69+
70+
# MSVC-specific ABI tag suffixes. Inherit from bsoncxx.
71+
if(MSVC)
72+
get_target_property(vs_suffix ${bsoncxx_target} BSONCXX_ABI_TAG_VS_SUFFIX)
73+
set_target_properties(${TARGET} PROPERTIES
74+
BSONCXX_ABI_TAG_VS_SUFFIX ${vs_suffix}
75+
INTERFACE_BSONCXX_ABI_TAG_VS_SUFFIX ${vs_suffix}
76+
)
77+
78+
string(APPEND abi_tag "${vs_suffix}")
79+
endif()
80+
endif()
81+
1382
set_target_properties(${TARGET} PROPERTIES
14-
OUTPUT_NAME ${OUTPUT_NAME}
1583
VERSION ${MONGOCXX_VERSION}
1684
DEFINE_SYMBOL MONGOCXX_EXPORTS
1785
)
1886

87+
if(ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES)
88+
set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME}${abi_tag})
89+
else()
90+
set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
91+
endif()
92+
1993
if(LINK_TYPE STREQUAL "SHARED")
2094
set_target_properties(${TARGET} PROPERTIES
2195
CXX_VISIBILITY_PRESET hidden
2296
VISIBILITY_INLINES_HIDDEN ON
23-
SOVERSION _noabi
2497
)
2598
endif()
2699

docs/content/mongocxx-v3/api-abi-versioning.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,38 @@ title = "API and ABI versioning"
2929

3030
*DSO = Dynamic Shared Object, to use Ulrich Drepper's terminology*
3131

32+
### Windows (MSVC only)
33+
34+
Since version 3.10.0, the physical filename for CXX Driver libraries is different
35+
from other platforms when built with the MSVC toolchain on Windows
36+
(even when the CMake generator is not Visual Studio).
37+
To restore prior behavior, which is similar to other platforms, set `ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES=OFF`.
38+
39+
* Physical filename for a DSO is `mongocxx-$ABI-$TAG.dll`
40+
* Physical filename for a static library is `mongocxx-static-$TAG.lib`
41+
42+
Where `$TAG` is a triplet of letters indicating:
43+
44+
* Build Type
45+
* mongoc Link Type
46+
* Polyfill Library
47+
48+
followed by a suffix describing the toolset and runtime library used to build the library.
49+
50+
Some examples of common DSO filenames expected to be generated include:
51+
52+
* mongocxx-v_noabi-rhs-x64-v142-md.dll (release build configuration)
53+
* mongocxx-v_noabi-dhs-x64-v142-mdd.dll (debug build configuration)
54+
* mongocxx-v_noabi-rts-x64-v142-md.dll (link with mongoc statically)
55+
* mongocxx-v_noabi-rhm-x64-v142-md.dll (mnmlstc/core polyfill library)
56+
* mongocxx-v_noabi-rhb-x64-v142-md.dll (Boost polyfill library)
57+
58+
This allows libraries built with different build configurations (and different runtime library requirements) to be built and installed without conflicting with each other.
59+
60+
See references to `ENABLE_ABI_TAG_IN_LIBRARY_FILENAMES` and related code in the CMake configuration for more details.
61+
62+
### Other Platforms (Linux, MacOS)
63+
3264
* Physical filename for a DSO is `libmongocxx.so.$MAJOR.$MINOR.$PATCH`
3365

3466
Note that the physical filename is disconnected from ABI version/soname.

0 commit comments

Comments
 (0)