摘要
- 本机环境
15.8.1-x86_64。
- Homebrew
7.0.8 不再为 Intel Mac 提供 cmake 的 bottle,brew upgrade cmake 会从源码执行 ./bootstrap。cmake 4.4.4 停在 Cannot find a C++ compiler that supports both C++11。
- 失败点在 C++ 头文件的搜索路径,不在某一个依赖
cmake 的软件包。直接升级或安装 cmake,以及任何要在本机编译 cmake 的 formula,都会停在同一处。这次是升级 wget 时把它作为依赖编出来的。
/usr/bin/clang++ 是 Apple Clang 17.0.0,clang++ --version 正常,CC、CXX、CXXFLAGS 都没有设置。用一段 C++11 程序编译,报错是 fatal error: 'iostream' file not found。
iostream 在各个 SDK 里都有,例如 /Library/Developer/CommandLineTools/SDKs/MacOSX26.2.sdk/usr/include/c++/v1/iostream。编译器实际搜索的是 /Library/Developer/CommandLineTools/usr/include/c++/v1。这条路径按编译器自己的位置计算:InstalledDir 是 CommandLineTools/usr/bin,libc++ 头文件放在它的上一级 usr/include/c++/v1。这个目录还在,里面没有 iostream。目录一旦存在,驱动就只用它,不再把 SDK 里的那份加入搜索路径。
- 把这个目录改名为
c++.backup 之后,同一段 C++11 程序可以编译并输出 123,再执行 brew upgrade cmake。
- 日志里的 Intel x86_64、Tier 3 警告说明这次为什么要本地编译。
升级时的日志
- 下面的
./bootstrap 是 cmake 4.4.4 自己的配置步骤。当时它出现在 brew upgrade wget 安装依赖的过程中;单独执行 brew upgrade cmake 或 brew install cmake,日志停在同一段:
==> Upgrading wget dependency: cmake
==> ./bootstrap --prefix=/usr/local/Cellar/cmake/4.4.4 --no-system-libs --parallel=12
Bootstrap.cmk/cmake_bootstrap.log 里和编译器相关的几行:
CMake 4.4.4, Copyright 2000-2026 Kitware, Inc. and Contributors
C compiler on this system is: clang
Error when bootstrapping CMake:
Cannot find a C++ compiler that supports both C++11 and the specified C++ flags.
Please specify one using environment variable CXX.
The C++ flags are "".
- CMake 这里只说明自己没能用当前环境编过一段 C++11。它不会写出缺的是哪一个头文件。后面要自己用
clang++ 编一段最小程序,才能看到 iostream。
本机环境
uname -m x86_64
macOS 15.8.1-x86_64
clang target x86_64-apple-darwin24.6.0
Homebrew 7.0.8
HOMEBREW_PREFIX /usr/local
clang / clang++ /usr/bin/clang、/usr/bin/clang++
Apple clang 17.0.0 (clang-1700.6.4.2)
InstalledDir /Library/Developer/CommandLineTools/usr/bin
xcode-select -p /Library/Developer/CommandLineTools
CLT 26.3.0.0.1.1771626560
Xcode 未安装
CPU(brew config) dodeca-core 64-bit kabylake
- 六核 Core i7 开超线程之后,Homebrew 报成 12 核。
xcrun --find clang++ 指向 /Library/Developer/CommandLineTools/usr/bin/clang++。
- 当时
CC、CXX、CFLAGS、CXXFLAGS、CPPFLAGS、LDFLAGS、SDKROOT 都没有设置:
env | grep -E '^(CC|CXX|CFLAGS|CXXFLAGS|CPPFLAGS|LDFLAGS|SDKROOT)=' | sort
用一段 C++11 程序看头文件
clang++ --version 只证明编译器可执行文件在。C++ 标准库要靠一次真正的编译。std::unique_ptr 在 C++11 里就有,和 CMake bootstrap 检查的语言标准一致:
cat >/tmp/test-cxx11.cpp <<'EOF'
#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> p(new int(123));
std::cout << *p << '\n';
return 0;
}
EOF
clang++ -std=c++11 /tmp/test-cxx11.cpp -o /tmp/test-cxx11
echo "compile exit code: $?"
/tmp/test-cxx11.cpp:1:10: fatal error: 'iostream' file not found
1 | #include <iostream>
| ^~~~~~~~~~
1 error generated.
compile exit code: 1
xcrun --sdk macosx --show-sdk-path
# 输出
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
头文件在 SDK 里
- 在 Command Line Tools 下面按文件名找,
iostream 出现在多个历史 SDK 中,当前默认 SDK 里也有:
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/iostream
/Library/Developer/CommandLineTools/SDKs/MacOSX14.5.sdk/usr/include/c++/v1/iostream
/Library/Developer/CommandLineTools/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/iostream
/Library/Developer/CommandLineTools/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/iostream
/Library/Developer/CommandLineTools/SDKs/MacOSX15.5.sdk/usr/include/c++/v1/iostream
/Library/Developer/CommandLineTools/SDKs/MacOSX26.2.sdk/usr/include/c++/v1/iostream
- 默认 SDK 是一个指向
MacOSX26.2.sdk 的符号链接。机器上还留着 13.1、14.5、15.2、15.4、15.5,都是历次系统升级剩下的 SDK。
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -> MacOSX26.2.sdk
- 工具链自己的 C++ 头文件目录也还在,
ls -ld 显示日期是 2025-11-19。这个目录里没有 iostream:
/Library/Developer/CommandLineTools/usr/include/c++/v1 目录存在
/Library/Developer/CommandLineTools/usr/include/c++/v1/iostream No such file or directory
/Library/Developer/CommandLineTools/SDKs/MacOSX26.2.sdk/usr/include/c++/v1/iostream
-rw-r--r-- 1 root wheel 1707 Nov 9 2025
编译器搜到了残缺目录
echo | clang++ -v -E -x c++ - 把实际搜索顺序列出来。本机 C++ 头文件的那一项是工具链目录,系统头文件才走当前 SDK:
-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
-internal-isystem /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1
#include <...> search starts here:
/usr/local/include
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1
/Library/Developer/CommandLineTools/usr/lib/clang/17/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
/Library/Developer/CommandLineTools/usr/include
usr/bin/../include/c++/v1 就是 /Library/Developer/CommandLineTools/usr/include/c++/v1。它出现在搜索列表里,是驱动自己加的 -internal-isystem,不是 CPATH、CPLUS_INCLUDE_PATH 或 CMake 传进来的。
/usr/bin/clang++ 会转到 xcode-select -p 选中的编译器。当时选中的是 /Library/Developer/CommandLineTools,所以 InstalledDir 是 /Library/Developer/CommandLineTools/usr/bin。Apple Clang 把 libc++ 头文件放在编译器旁边,路径按 InstalledDir/../include/c++/v1 计算:从 usr/bin 退回 usr,再进 include/c++/v1。v1 是 libc++ 头文件的目录名。
- C 头文件和 C++ 头文件分开找。平台头文件和 C 库走
-isysroot 下的 MacOSX.sdk/usr/include。iostream 属于 libc++,走紧挨着编译器的那条路径。SDK 里的 usr/include/c++/v1/iostream 因此不会自动补进搜索列表。驱动只看工具链这个 c++/v1 目录在不在,不看里面有没有 iostream。目录还在,就固定用它。
- 把工具链的
c++ 目录改名之后,这个位置不存在了,驱动才改用当前 SDK 里的 usr/include/c++/v1。
- 因此把
SDKROOT 指到已经含有 iostream 的 MacOSX26.2.sdk,结果不变,仍然是 iostream file not found:
SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX26.2.sdk \
clang++ -std=c++11 /tmp/test-cxx11.cpp -o /tmp/test-cxx11
- 重装 Command Line Tools、从 SDK 里单独拷贝
iostream,或把 CXX 设成 /usr/bin/clang++,都不会改掉上面这条搜索路径。要挪开的是编译器第一个会去看的那份残缺目录。
修复
- 先确认没有别的编译任务在跑。把残缺目录改名,先留着,不删除:
sudo mv \
/Library/Developer/CommandLineTools/usr/include/c++ \
/Library/Developer/CommandLineTools/usr/include/c++.backup
- 目录让开之后,Apple Clang 会改用 SDK 里的 libc++ 头文件。用上面同一段程序再编译一次:
clang++ -std=c++11 /tmp/test-cxx11.cpp -o /tmp/test-cxx11 && /tmp/test-cxx11
123
- 可以再看一眼搜索路径,确认
include/c++/v1 不再指向刚才改名的那份残缺目录:
echo | clang++ -v -E -x c++ - 2>&1
再升级 cmake
brew upgrade cmake
- 头文件恢复后,其他要从源码编译、并且依赖
cmake 的包也可以继续装。c++.backup 先留着,cmake 升级成功再决定要不要删掉。需要退回时把它改回原名:
sudo mv \
/Library/Developer/CommandLineTools/usr/include/c++.backup \
/Library/Developer/CommandLineTools/usr/include/c++
改名之后仍然找不到 iostream
- 如果 SDK 里的
iostream 也不存在,改名解决不了。那时再重装 Command Line Tools。本机不需要这一步,因为 MacOSX26.2.sdk 里的头文件是完整的。
sudo rm -rf /Library/Developer/CommandLineTools
xcode-select --install
xcode-select -p
ls -l /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/iostream
clang++ -std=c++11 /tmp/test-cxx11.cpp -o /tmp/test-cxx11 && /tmp/test-cxx11
和 Intel Tier 3 的关系
Warning: You are using macOS on Intel x86_64.
We do not provide support for this platform (as-of September 2026, announced August 2025).
Homebrew no longer builds bottles for this configuration.
This is a Tier 3 configuration:
https://docs.brew.sh/Support-Tiers#tier-3
- 2026 年 9 月起,Homebrew 不再为 Intel Mac 构建新的 bottle。
cmake 4.4.4 因此走 ./bootstrap 本地编译,机器上这份残缺的 C++ 头文件目录才被碰到。以前有 bottle 时,Homebrew 直接倒预编译包,不会调用 clang++。
- 警告里提到的 MacPorts 是 Intel 上继续使用预编译包的一条路。继续用 Homebrew 从源码装
cmake 时,先把上面的头文件搜索恢复。