thirdparty: migrate googletest to vcpkg; adopt blade default 'auto' linkage (#187)

- googletest: thin wrappers over vcpkg gtest (gtest/gtest_main/gmock/gmock_main,
  pinned 1.17.0); drop the vendored tarballs and generate_dynamic.patch. gtest's
  *_main libs come from vcpkg's lib/manual-link/ (resolved by the updated blade).
- BLADE_ROOT: update blade.zip to the build with default 'auto' linkage + the
  manual-link fix. With 'auto' the default, the explicit linkage='auto' on
  protobuf/gflags/glog/yaml-cpp/gtest is now redundant and removed; only the
  non-default choices remain (benchmark -> 'static' as it has no shared build;
  link_all_symbols / include_prefix / cmake_options where needed).
- BLADE_ROOT: drop the hardcoded vcpkg `root` path -- blade reads $VCPKG_ROOT,
  else finds vcpkg on PATH (portable; CI uses the runner's vcpkg).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
CHEN Feng
2026-06-18 02:15:29 +08:00
committed by GitHub
parent a1678b2278
commit 158f72be83
6 changed files with 70 additions and 233 deletions
+30 -39
View File
@@ -170,54 +170,45 @@ proto_library_config(
# to match the previously vendored sources.
vcpkg_config(
baseline = '06a7fdd564234908731c59ac46a624f808e87b1c',
root = '/Volumes/code/vcpkg',
# root is intentionally unset: blade reads $VCPKG_ROOT, else finds `vcpkg` on
# PATH (CI relies on the runner's preinstalled vcpkg). Don't hardcode a path.
# linkage defaults to 'auto' (static for static-link consumers, shared on
# demand for dynamic-link ones), so process-global singletons -- protobuf's
# descriptor pool, the gflags/glog/gtest registries -- resolve to one shared
# instance across all dylibs with no annotation. Only non-default choices are
# called out below; see doc/*/build_rules/vcpkg.md for the linkage rules.
packages = {
# 3.21.12: the last protobuf release before v22 made Abseil a hard
# dependency. flare's source predates the descriptor name()->string_view
# change (v23+), so it builds against 3.21.
# 3.21.12: the last protobuf before v22 made Abseil a hard dependency;
# flare predates the descriptor name()->string_view change (v23+).
'protobuf': {'version': '3.21.12'},
'fmt': '7.1.3',
# gflags/glog are singletons (global flag registry; glog registers flags
# like logtostderr in gflags). linkage='auto': the static .a is always
# built and the shared lib is built on demand for dynamic_link binaries.
# A dynamic_link release exe shares one .dylib (no duplicate
# registration); a static build-time tool (the protoc plugins, set
# dynamic_link=False) links a self-contained .a with no @rpath dylib to
# resolve. link_all_symbols whole-archives that static .a so the flag
# registration initializers survive even when unreferenced.
'gflags': {'version': '2.2.2', 'linkage': 'auto',
'link_all_symbols': True},
# flare includes "glog/logging.h" -- vcpkg's native layout, no remap.
# GFLAGS_NOTHREADS=OFF: with a *static* gflags, gflags-config.cmake has a
# template bug (it tests an unsubstituted `PACKAGE_NAME@_static` target)
# and defaults GFLAGS_NOTHREADS=TRUE, so glog's find_package(gflags) asks
# for the nonexistent gflags_nothreads_static. Forcing it OFF picks the
# built gflags_static (glog uses Threads anyway).
'glog': {'version': '0.7.1', 'linkage': 'auto', 'link_all_symbols': True,
# link_all_symbols: the static-link protoc plugins (dynamic_link=False)
# whole-archive the .a so gflags/glog's flag-registration static
# initializers run even when unreferenced.
'gflags': {'version': '2.2.2', 'link_all_symbols': True},
# GFLAGS_NOTHREADS=OFF dodges gflags-config.cmake's static-target template
# bug (glog's find_package(gflags) would ask for gflags_nothreads_static).
'glog': {'version': '0.7.1', 'link_all_symbols': True,
'cmake_options': ['-DGFLAGS_NOTHREADS=OFF']},
# Static-safe data/compression libs. flare includes them as
# "<lib>/<header>" but vcpkg ships at include/ top level, so each needs
# include_prefix. Versions follow the baseline (these are ABI-stable).
# include_prefix: flare includes these as "<lib>/<header>", but vcpkg
# ships their headers at the include/ top level.
'zlib': {'include_prefix': 'zlib'},
'lz4': {'include_prefix': 'lz4'},
'zstd': {'include_prefix': 'zstd'},
# vcpkg's snappy forces -fno-rtti unless SNAPPY_WITH_RTTI is set; flare
# uses RTTI on snappy::Sink/Source.
# snappy also needs RTTI on -- vcpkg forces -fno-rtti, but flare uses RTTI
# on snappy::Sink/Source.
'snappy': {'include_prefix': 'snappy',
'cmake_options': ['-DSNAPPY_WITH_RTTI=ON']},
'xxhash': {'include_prefix': 'xxhash'},
# yaml-cpp ships at vcpkg's native include/yaml-cpp/ layout, which
# already matches how flare includes it -- no include_prefix.
# yaml-cpp is pulled into a dynamic_link lib (flare/base/monitoring:init,
# built as a .dylib). linkage='auto' builds the on-demand shared yaml-cpp
# (the old foreign build was shared too); link_all_symbols whole-archives
# the static .a into the wrapper's .dylib so it actually exports the
# yaml-cpp symbols the consumer needs (the wrapper has no srcs of its own).
'yaml-cpp': {'linkage': 'auto', 'link_all_symbols': True},
# benchmark: native include/benchmark/ layout (no include_prefix).
# Pinned to 1.7.1 -- 1.8.0 deprecated benchmark::DoNotOptimize(const&),
# which flare's *_benchmark.cc use, and flare builds with
# -Werror=deprecated-declarations (gcc). 1.7.1 predates that.
'benchmark': {'version': '1.7.1'},
# link_all_symbols: consumers need yaml-cpp's symbols whole-archived in.
'yaml-cpp': {'link_all_symbols': True},
# 1.7.1: 1.8.0 deprecated DoNotOptimize(const&), which flare's
# *_benchmark.cc use under gcc -Werror=deprecated-declarations.
# linkage='static': google/benchmark has no shared build and needs none
# (each *_benchmark exe links it once); the default 'auto' would fail
# trying to build it shared.
'benchmark': {'version': '1.7.1', 'linkage': 'static'},
# vcpkg port name is `gtest`; 1.17.0 matches the previously vendored source.
'gtest': {'version': '1.17.0'},
},
)
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:77cba1ad54838915c1ac87312d78ba12f9adb7de4fe9dbbead2c5832a3998596
size 294781
oid sha256:3a5769c842fd619f9224fb16bb79cf00485b0be4e3a90c6a5ccd0e0097ace157
size 295825
+38 -55
View File
@@ -1,69 +1,52 @@
include('//thirdparty/foreign_build.bld')
cmake_build(
name='googletest_build',
source_package='googletest-1.17.0.tar.gz',
package_name='googletest',
lib_names=['gmock', 'gmock_main', 'gtest', 'gtest_main'],
cmake_options=[
'-DCMAKE_POSITION_INDEPENDENT_CODE=ON',
'-DCMAKE_BUILD_TYPE=Release',
'-DCMAKE_CXX_FLAGS=-Wno-deprecated-copy',
],
# googletest's CMake emits either static or shared per configure (it keys
# solely off BUILD_SHARED_LIBS), so a single pass can't produce both. The
# static pass above yields libgtest.a (used by static_link consumers); this
# shared pass yields libgtest.dylib. Release builds default to dynamic_link
# (BLADE_ROOT), so cc_tests link the dylib -- giving gtest's UnitTest
# registry a single process-wide instance. Without a shared gtest, the
# static archive gets force_loaded (link_all_symbols) into every mock/main
# dylib, producing multiple registries where TEST() registers into one and
# RUN_ALL_TESTS() reads another ("does NOT link in any test case"). Using
# BUILD_SHARED_LIBS directly means the stale generate_dynamic.patch (written
# for 1.10) is no longer needed.
shared_cmake_options=['-DBUILD_SHARED_LIBS=ON'],
generate_dynamic=True,
)
foreign_cc_library(
name='gmock',
deps=[
':gtest',
':googletest_build',
],
visibility='PUBLIC',
has_dynamic=True,
)
foreign_cc_library(
name='gmock_main',
deps=[
':gmock',
':googletest_build',
],
visibility='PUBLIC',
has_dynamic=True,
)
foreign_cc_library(
# Thin wrappers over vcpkg gtest (see BLADE_ROOT vcpkg_config, pinned 1.17.0 to
# match the previously vendored source). Consumers keep depending on
# //thirdparty/googletest:{gtest,gtest_main,gmock,gmock_main}; cc_test_config's
# gtest_libs / gtest_main_libs are unchanged.
#
# linkage='auto' (set in BLADE_ROOT, NO link_all_symbols): gtest's UnitTest
# registry must be a single process-wide instance. dynamic_link tests link the
# shared libgtest, and gmock links *against* that gtest rather than
# whole-archiving a second static copy -- the multiple-registry trap the old
# foreign build documented as "does NOT link in any test case".
cc_library(
name='gtest',
deps=[
':googletest_build',
],
hdrs=[],
deps=['vcpkg#gtest:gtest'],
visibility='PUBLIC',
has_dynamic=True,
)
foreign_cc_library(
cc_library(
name='gtest_main',
hdrs=[],
deps=[
'vcpkg#gtest:gtest_main',
':gtest',
':googletest_build',
],
visibility='PUBLIC',
has_dynamic=True,
)
cc_library(
name='gmock',
hdrs=[],
deps=[
'vcpkg#gtest:gmock',
':gtest',
],
visibility='PUBLIC',
)
cc_library(
name='gmock_main',
hdrs=[],
deps=[
'vcpkg#gtest:gmock_main',
':gmock',
],
visibility='PUBLIC',
)
# Production code includes "gtest/gtest_prod.h" (the FRIEND_TEST macro) without
# linking gtest, so this stays a standalone committed header -- never a lib dep.
cc_library(
name='gtest_prod',
hdrs='gtest/gtest_prod.h',
-134
View File
@@ -1,134 +0,0 @@
diff -uNr a/googlemock/CMakeLists.txt b/googlemock/CMakeLists.txt
--- a/googlemock/CMakeLists.txt 2021-03-25 14:33:28.854567400 +0800
+++ b/googlemock/CMakeLists.txt 2021-03-25 15:02:26.367424950 +0800
@@ -99,18 +99,26 @@
src/gmock_main.cc)
else()
cxx_library(gmock "${cxx_strict}" src/gmock-all.cc)
- target_link_libraries(gmock PUBLIC gtest)
+ target_link_libraries(gmock-static PUBLIC gtest-static)
+ target_link_libraries(gmock-shared PUBLIC gtest-shared)
cxx_library(gmock_main "${cxx_strict}" src/gmock_main.cc)
- target_link_libraries(gmock_main PUBLIC gmock)
+ target_link_libraries(gmock_main-static PUBLIC gmock-static)
+ target_link_libraries(gmock_main-shared PUBLIC gmock-shared)
endif()
# If the CMake version supports it, attach header directory information
# to the targets for when we are part of a parent build (ie being pulled
# in via add_subdirectory() rather than being a standalone build).
if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
- target_include_directories(gmock SYSTEM INTERFACE
+ target_include_directories(gmock-static SYSTEM INTERFACE
"$<BUILD_INTERFACE:${gmock_build_include_dirs}>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
- target_include_directories(gmock_main SYSTEM INTERFACE
+ target_include_directories(gmock_main-shared SYSTEM INTERFACE
+ "$<BUILD_INTERFACE:${gmock_build_include_dirs}>"
+ "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+ target_include_directories(gmock-static SYSTEM INTERFACE
+ "$<BUILD_INTERFACE:${gmock_build_include_dirs}>"
+ "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+ target_include_directories(gmock_main-shared SYSTEM INTERFACE
"$<BUILD_INTERFACE:${gmock_build_include_dirs}>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
endif()
diff -uNr a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake
--- a/googletest/cmake/internal_utils.cmake 2021-03-25 14:33:28.850567400 +0800
+++ b/googletest/cmake/internal_utils.cmake 2021-03-25 15:03:46.454104157 +0800
@@ -198,10 +198,17 @@
cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
endfunction()
-function(cxx_library name cxx_flags)
+function(cxx_static_library name cxx_flags)
cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
endfunction()
+function(cxx_library name cxx_flags)
+ cxx_shared_library(${name}-static ${cxx_flags} ${ARGN})
+ cxx_static_library(${name}-shared ${cxx_flags} ${ARGN})
+ set_target_properties(${name}-static PROPERTIES OUTPUT_NAME ${name})
+ set_target_properties(${name}-shared PROPERTIES OUTPUT_NAME ${name})
+endfunction()
+
# cxx_executable_with_flags(name cxx_flags libs srcs...)
#
# creates a named C++ executable that depends on the given libraries and
@@ -324,35 +331,28 @@
# install_project(targets...)
#
# Installs the specified targets and configures the associated pkgconfig files.
-function(install_project)
+function(install_project_with_name target name)
if(INSTALL_GTEST)
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
# Install the project targets.
- install(TARGETS ${ARGN}
+ install(TARGETS ${target}
EXPORT ${targets_export_name}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
- if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
- # Install PDBs
- foreach(t ${ARGN})
- get_target_property(t_pdb_name ${t} COMPILE_PDB_NAME)
- get_target_property(t_pdb_name_debug ${t} COMPILE_PDB_NAME_DEBUG)
- get_target_property(t_pdb_output_directory ${t} PDB_OUTPUT_DIRECTORY)
- install(FILES
- "${t_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$<$<CONFIG:Debug>:${t_pdb_name_debug}>$<$<NOT:$<CONFIG:Debug>>:${t_pdb_name}>.pdb"
- DESTINATION ${CMAKE_INSTALL_LIBDIR}
- OPTIONAL)
- endforeach()
- endif()
# Configure and install pkgconfig files.
- foreach(t ${ARGN})
- set(configured_pc "${generated_dir}/${t}.pc")
- configure_file("${PROJECT_SOURCE_DIR}/cmake/${t}.pc.in"
- "${configured_pc}" @ONLY)
- install(FILES "${configured_pc}"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
- endforeach()
+ set(configured_pc "${generated_dir}/${name}.pc")
+ configure_file("${PROJECT_SOURCE_DIR}/cmake/${name}.pc.in"
+ "${configured_pc}" @ONLY)
+ install(FILES "${configured_pc}"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endif()
endfunction()
+
+function(install_project)
+ foreach(t ${ARGN})
+ install_project_with_name(${t}-static ${t})
+ install_project_with_name(${t}-shared ${t})
+ endforeach()
+endfunction()
diff -uNr a/googletest/CMakeLists.txt b/googletest/CMakeLists.txt
--- a/googletest/CMakeLists.txt 2021-03-25 14:33:28.850567400 +0800
+++ b/googletest/CMakeLists.txt 2021-03-25 14:54:41.335715758 +0800
@@ -131,14 +131,21 @@
# to the targets for when we are part of a parent build (ie being pulled
# in via add_subdirectory() rather than being a standalone build).
if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
- target_include_directories(gtest SYSTEM INTERFACE
+ target_include_directories(gtest-static SYSTEM INTERFACE
"$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
- target_include_directories(gtest_main SYSTEM INTERFACE
+ target_include_directories(gtest_main-static SYSTEM INTERFACE
+ "$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
+ "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+ target_include_directories(gtest-shared SYSTEM INTERFACE
+ "$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
+ "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
+ target_include_directories(gtest_main-shared SYSTEM INTERFACE
"$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
endif()
-target_link_libraries(gtest_main PUBLIC gtest)
+target_link_libraries(gtest_main-static PUBLIC gtest-static)
+target_link_libraries(gtest_main-shared PUBLIC gtest-shared)
########################################################################
#
Binary file not shown.
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb
size 904349