From e3db55dc0c9faeb7b467cd28a74e6634ff63f1f0 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Wed, 29 Jul 2026 12:07:58 +0000 Subject: [PATCH 2/2] Use OpenSSL for content hashing on macOS; make Rust and eden deps saner Three build portability fixes, primarily for older/unusual macOS targets (e.g. powerpc-darwin) where cargo does not exist: - ContentHash: drop the CommonCrypto path on macOS and use OpenSSL's EVP interface on all posix systems. The dependency stack (folly and friends) already links OpenSSL, and EVP avoids the SHA1_* functions that OpenSSL 3 deprecates. OpenSSL is now REQUIRED on non-Windows; Windows keeps the built-in crypt provider API. - Make the Rust components optional: the watchman binary is pure C++ and fully functional without the watchmanctl CLI. RustStaticLibrary demands cargo at include time, so probe for cargo first and skip both the include and watchman/cli when it is absent. - Move find_package(FBThrift) / find_package(fb303) out of the ENABLE_EDEN_SUPPORT block: edencommon_telemetry links against both and edencommon's package config does not chain its dependencies, so a build with -DENABLE_EDEN_SUPPORT=OFF previously failed at configure time with undefined imported targets. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_015ECmTd2wkJqqrArR8VHCDm --- CMakeLists.txt | 33 +++++++++++++++++++++++++++------ watchman/ContentHash.cpp | 33 ++++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33a71ef..b7411da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,7 +150,16 @@ include(CheckFunctionExists) include(CheckIncludeFiles) include(CheckStructHasMember) include(CheckSymbolExists) -include(RustStaticLibrary) +# The Rust components (the watchmanctl CLI) are optional: the watchman +# binary itself is pure C++ and fully functional without them. Note that +# RustStaticLibrary requires cargo at include time, so only pull it in +# when cargo is available. +find_program(CARGO_COMMAND cargo) +if(CARGO_COMMAND) + include(RustStaticLibrary) +else() + message(STATUS "cargo not found: skipping Rust components (watchmanctl)") +endif() # configure_file wants us to define a separate file. I'd rather not # have boilerplate for the same thing in two difference files, so we @@ -324,7 +333,13 @@ if(THREADS_FOUND AND NOT TARGET Threads::Threads) endif() endif() -find_package(OpenSSL) +if(WIN32) + # Windows uses the built-in crypt provider API instead + find_package(OpenSSL) +else() + # ContentHash requires OpenSSL on all posix systems, including macOS + find_package(OpenSSL REQUIRED) +endif() # This block is for cmake 3.0 which doesn't define the OpenSSL::Crypto # interface section. Test for that and define it for ourselves. @@ -369,13 +384,17 @@ find_package(edencommon CONFIG REQUIRED) find_package(fmt CONFIG REQUIRED) find_package(folly CONFIG REQUIRED) +# edencommon_telemetry links against fb303 and thrift, and edencommon's +# package config does not chain its dependencies, so these are required +# even when eden support is disabled. +find_package(FBThrift CONFIG REQUIRED) +find_package(fb303 CONFIG REQUIRED) +include_directories(${FB303_INCLUDE_DIR}) + if (ENABLE_EDEN_SUPPORT) find_package(fizz CONFIG REQUIRED) find_package(wangle CONFIG REQUIRED) - find_package(FBThrift CONFIG REQUIRED) - find_package(fb303 CONFIG REQUIRED) find_package(cpptoml CONFIG REQUIRED) - include_directories(${FB303_INCLUDE_DIR}) endif() if(DEFINED ENV{NODE_BIN}) set(NODE $ENV{NODE_BIN}) @@ -763,7 +782,9 @@ endif() install(TARGETS watchman RUNTIME DESTINATION bin) -add_subdirectory(watchman/cli) +if(CARGO_COMMAND) + add_subdirectory(watchman/cli) +endif() set(tests) # Helper function to define a unit test executable diff --git a/watchman/ContentHash.cpp b/watchman/ContentHash.cpp index cdecf02..bbd416d 100644 --- a/watchman/ContentHash.cpp +++ b/watchman/ContentHash.cpp @@ -15,13 +15,10 @@ #include "watchman/fs/FileSystem.h" #include "watchman/watchman_stream.h" -#ifdef __APPLE__ -#define COMMON_DIGEST_FOR_OPENSSL -#include "CommonCrypto/CommonDigest.h" // @manual -#elif defined(_WIN32) +#ifdef _WIN32 #include // @manual #else -#include +#include #endif namespace watchman { @@ -66,8 +63,21 @@ HashValue ContentHashCache::computeHashImmediate(const char* fullPath) { } #ifndef _WIN32 - SHA_CTX ctx; - SHA1_Init(&ctx); + // Use OpenSSL's EVP interface on all posix systems, including macOS: + // the rest of the dependency stack (folly and friends) already links + // OpenSSL, and the low-level SHA1_* functions are deprecated in + // OpenSSL 3. + auto* ctx = EVP_MD_CTX_new(); + if (!ctx) { + throw std::runtime_error("EVP_MD_CTX_new failed"); + } + SCOPE_EXIT { + EVP_MD_CTX_free(ctx); + }; + + if (EVP_DigestInit_ex(ctx, EVP_sha1(), nullptr) != 1) { + throw std::runtime_error("EVP_DigestInit_ex failed"); + } while (true) { auto n = stm->read(buf, sizeof(buf)); @@ -80,10 +90,15 @@ HashValue ContentHashCache::computeHashImmediate(const char* fullPath) { std::generic_category(), fmt::format("while reading from {}", fullPath)); } - SHA1_Update(&ctx, buf, n); + if (EVP_DigestUpdate(ctx, buf, n) != 1) { + throw std::runtime_error("EVP_DigestUpdate failed"); + } } - SHA1_Final(result.data(), &ctx); + unsigned int digestLen = result.size(); + if (EVP_DigestFinal_ex(ctx, result.data(), &digestLen) != 1) { + throw std::runtime_error("EVP_DigestFinal_ex failed"); + } #else // Use the built-in crypt provider API on windows to avoid introducing a // dependency on openssl in the windows build. -- 2.43.0