brew 升级 cmake 失败:clang++ 找不到 iostream
摘要
- 本机环境
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 警告说明这次为什么要本地编译。Homebrew 在 Intel 上的支持变化见 MacOS软件包管理器--brew 文末「从 4.5 到 7.0」。
升级时的日志
-
下面的
./bootstrap是cmake 4.4.4自己的配置步骤。当时它出现在brew upgrade wget安装依赖的过程中;单独执行brew upgrade cmake或brew install cmake,日志停在同一段:
1 | ==> Upgrading wget dependency: cmake |
-
Bootstrap.cmk/cmake_bootstrap.log里和编译器相关的几行:
1 | CMake 4.4.4, Copyright 2000-2026 Kitware, Inc. and Contributors |
-
CMake 这里只说明自己没能用当前环境编过一段 C++11。它不会写出缺的是哪一个头文件。后面要自己用
clang++编一段最小程序,才能看到iostream。
本机环境
1 | uname -m x86_64 |
-
六核 Core i7 开超线程之后,Homebrew 报成 12 核。
xcrun --find clang++指向/Library/Developer/CommandLineTools/usr/bin/clang++。 -
当时
CC、CXX、CFLAGS、CXXFLAGS、CPPFLAGS、LDFLAGS、SDKROOT都没有设置:
1 | env | grep -E '^(CC|CXX|CFLAGS|CXXFLAGS|CPPFLAGS|LDFLAGS|SDKROOT)=' | sort |
用一段 C++11 程序看头文件
-
clang++ --version只证明编译器可执行文件在。C++ 标准库要靠一次真正的编译。std::unique_ptr在 C++11 里就有,和 CMake bootstrap 检查的语言标准一致:
1 | cat >/tmp/test-cxx11.cpp <<'EOF' |
-
本机结果:
1 | /tmp/test-cxx11.cpp:1:10: fatal error: 'iostream' file not found |
-
SDK 本身是存在的:
1 | xcrun --sdk macosx --show-sdk-path |
头文件在 SDK 里
-
在 Command Line Tools 下面按文件名找,
iostream出现在多个历史 SDK 中,当前默认 SDK 里也有:
1 | /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/iostream |
-
默认 SDK 是一个指向
MacOSX26.2.sdk的符号链接。机器上还留着 13.1、14.5、15.2、15.4、15.5,都是历次系统升级剩下的 SDK。
1 | /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -> MacOSX26.2.sdk |
-
工具链自己的 C++ 头文件目录也还在,
ls -ld显示日期是 2025-11-19。这个目录里没有iostream:
1 | /Library/Developer/CommandLineTools/usr/include/c++/v1 目录存在 |
编译器搜到了残缺目录
-
echo | clang++ -v -E -x c++ -把实际搜索顺序列出来。本机 C++ 头文件的那一项是工具链目录,系统头文件才走当前 SDK:
1 | -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk |
-
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,结果不变,仍然是iostreamfile not found:
1 | SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX26.2.sdk \ |
-
重装 Command Line Tools、从 SDK 里单独拷贝
iostream,或把CXX设成/usr/bin/clang++,都不会改掉上面这条搜索路径。要挪开的是编译器第一个会去看的那份残缺目录。
修复
-
先确认没有别的编译任务在跑。把残缺目录改名,先留着,不删除:
1 | sudo mv \ |
-
目录让开之后,Apple Clang 会改用 SDK 里的 libc++ 头文件。用上面同一段程序再编译一次:
1 | clang++ -std=c++11 /tmp/test-cxx11.cpp -o /tmp/test-cxx11 && /tmp/test-cxx11 |
-
正常输出:
1 | 123 |
-
可以再看一眼搜索路径,确认
include/c++/v1不再指向刚才改名的那份残缺目录:
1 | echo | clang++ -v -E -x c++ - 2>&1 |
再升级 cmake
-
C++11 测试输出
123之后:
1 | brew upgrade cmake |
-
头文件恢复后,其他要从源码编译、并且依赖
cmake的包也可以继续装。c++.backup先留着,cmake升级成功再决定要不要删掉。需要退回时把它改回原名:
1 | sudo mv \ |
改名之后仍然找不到 iostream
-
如果 SDK 里的
iostream也不存在,改名解决不了。那时再重装 Command Line Tools。本机不需要这一步,因为MacOSX26.2.sdk里的头文件是完整的。
1 | sudo rm -rf /Library/Developer/CommandLineTools |
-
装完后确认:
1 | xcode-select -p |
和 Intel Tier 3 的关系
-
同一次升级末尾还有一段:
1 | Warning: You are using macOS on Intel x86_64. |
-
2026 年 9 月起,Homebrew 不再为 Intel Mac 构建新的 bottle。
cmake 4.4.4因此走./bootstrap本地编译,机器上这份残缺的 C++ 头文件目录才被碰到。以前有 bottle 时,Homebrew 直接倒预编译包,不会调用clang++。 -
警告里提到的 MacPorts 是 Intel 上继续使用预编译包的一条路,安装和迁移见 MacOS软件包管理器--MacPorts。继续用 Homebrew 从源码装
cmake时,先把上面的头文件搜索恢复。