-
Notifications
You must be signed in to change notification settings - Fork 509
Description
Brief Issue Summary
这些bug是关于cmake、vscode-cmake-tools、cpptools在处理framework和include的路径的若干问题
1、我们先创建一个测试工程bug-sample,工程文件如下
2、我们要知道搜索路径的优先级(同级别的标志设置的路径,谁在前面谁先优先级高)
-I(或者-F) 添加的路径,
-isystem 添加的路径
-iframework 添加的路径
编译器默认路径(c++头文件、编译器内置的头文件、c头文件、工具链额外头文件 、还有默认的sdk framework路径)
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1
/Library/Developer/CommandLineTools/usr/lib/clang/16/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
/Library/Developer/CommandLineTools/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
3、我们对搜索路径优先级做一下测试
编译命令:clang -F /Users/admin/Desktop/bug-sample/build -I /Users/admin/Desktop/bug-sample/abc sample.cpp -c -v
输出:
ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/Users/admin/Desktop/bug-sample/build (framework directory)
/Users/admin/Desktop/bug-sample/abc
/usr/local/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1
/Library/Developer/CommandLineTools/usr/lib/clang/16/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
/Library/Developer/CommandLineTools/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.
In file included from sample.cpp:3:
/Users/admin/Desktop/bug-sample/build/dynamicFramework.framework/Headers/dynamicFramework.h:1:9: warning: framework dir dynamicFramework.h [-W#pragma-messages]
1 | #pragma message ("framework dir dynamicFramework.h")
| ^
1 warning generated.
我们看到sample.cpp中包含的头文件用的是framework目录中的,因为 -F 在 -I前面
编译命令:clang -I /Users/admin/Desktop/bug-sample/abc -F /Users/admin/Desktop/bug-sample/build sample.cpp -c -v
输出:
ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/Users/admin/Desktop/bug-sample/abc
/Users/admin/Desktop/bug-sample/build (framework directory)
/usr/local/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1
/Library/Developer/CommandLineTools/usr/lib/clang/16/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
/Library/Developer/CommandLineTools/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.
In file included from sample.cpp:3:
/Users/admin/Desktop/bug-sample/abc/dynamicFramework/dynamicFramework.h:1:9: warning: abc dynamicFramework.h [-W#pragma-messages]
1 | #pragma message ("abc dynamicFramework.h")
| ^
1 warning generated.
我们把 -I和-F换位置之后,sample.cpp使用的是abc目录中的dynamicFramework.h文件
-isystem 添加的路径 在 -I添加的路径 的后面
-iframework 添加的路径 在 -isystem添加的路径 的后面 (就算-iframework 标志在 -isystem 前面设置)
我们看到clang还会添加一个默认的/user/local/include (-I级别)
4、好了,我们知道编译器逻辑之后,我们在看看cmake、cmake-tools、cpptools是如何处理错误的
首先我会列出来我使用的各个插件、cmake、vscode等的版本信息,(我保证新版本也有问题,我也测试过新版本)
cpptools: 1.28.3
cmaketools: 1.19.52
vscode:
Version: 1.102.3
Commit: 488a1f239235055e34e673291fb8d8c810886f81
Date: 2025-07-29T03:00:23.339Z
Electron: 35.6.0
ElectronBuildId: 11847422
Chromium: 134.0.6998.205
Node.js: 22.15.1
V8: 13.4.114.21-electron.0
OS: Darwin x64 23.6.0
cmake:3.31.5
5、cmake会生产一些json给cmake-tools使用,cmake-tools使用它来配置cpptools
我们看到生成了frameworks, 通过下面的讨论链接,说是解决frameworks无法找到头文件的问题,实际并没有处理好
[1](https://github.com//pull/3247)
[2](https://github.com//issues/2324)
[3](https://gitlab.kitware.com/cmake/cmake/-/commit/b3a6a11e95f805ab7411d395bd426561cfb4d4d0)
实际处理逻辑是
参考cmake代码
/Users/admin/cmake-3.31.5/Source/cmFileAPICodemodel.cxx

我们看到cmake通过判断includePathList 表中的路径尾部是不是.framework然后把includePathList分成2部分存放到json中,分别是Frameworks和Includes
这样处理会丢失了优先级吗?
一般是不会的,因为cmake 最后处理framework类型的引入,前面先引入include_directories和interface_include_directories (继承)

不管是这样引入framework
target_link_libraries(sample PRIVATE /Users/admin/Desktop/bug-sample/build/dynamicFramework.framework/dynamicFramework)
还是这样引入
target_link_libraries(sample PRIVATE dynamicFramework)
都会最后处理,并添加一个/Users/admin/Desktop/bug-sample/build/dynamicFramework.framework路径到includes路径中.
并生成CXX_INCLUDES到build/CMakeFiles/flag.cmake中.
然后cmake还会生成CXX_FLAGS到build/CMakeFiles/flag.cmake中,
手动添加的路径(-I 或者 -iframework或者-F),例如target_compile_options(sample PRIVATE -I/Users/admin)
会反应到CXX_FLAGS 上或者cmake fileapi中的json 中类似
并且cmake-tools是直接把Frameworks附加在Includes后面
/Users/admin/Downloads/vscode-cmake-tools-main/src/cpptools.ts
也就是说includes是分cxx_includes部分和cxx_flags部分,是分开处理的,并由cmake-tools投递给cpptools使用
===========
问题1、cmake-tools 把framework当简单的include使用,导致cpptools在#include <framework/xxxxx.h>类型的识别有问题.
我们看看这个链接的问题
https://github.com/microsoft/vscode-cmake-tools/issues/2324.其实并没有处理好这个问题,因为framework被当作include使用了.
#include 可以正常goto,因为qt的cmake文件全路径/Users/admin/Qt/6.7.2/macos/lib/QtWidgets.framework/Headers会添加INTERFACE_INCLUDE_DIRECTORIES到
这里注意还添加了一个/Users/admin/Qt/6.7.2/macos/lib/QtWidgets.framework到INTERFACE_INCLUDE_DIRECTORIES中,这里会导致优先级错误

如果我们这样
add_library(test INTERFACE)
set_target_properties(test PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "/Users/admin/Desktop/bug-sample/build/dynamicFramework.framework;/Users/admin/Desktop/bug-sample/build/dynamicFramework.framework/Headers"
)
就会导致这样的优先级
显然-F不再是cxx_includes的尾部
但是cmake把Frameworks从Includes分离出来了,显然优先级信息丢失了.
cmake-tools又直接把Frameworks添加到includes的尾部,显然
[build] /Users/admin/Desktop/bug-sample/build (framework directory) 和
[build] /Users/admin/Desktop/bug-sample/build/dynamicFramework.framework/Headers
的顺序会错误.
并且这里面还隐藏这一个cpptools的问题,前面的链接里面没人发现问题的根本
我们先手动解决一下framework路径/users/admin/qt/6.7.2/macos/lib被当作include使用的问题
但是从main.cpp到QMessageBox没问题,从QMessageBox到qmessagebox.h也没有问题
进入qmessagebox.h就有问题了
因为QMessageBox没有文件后缀,导致后面的goto动作,把QMessageBox当作一个cpp源文件,而这个文件没有在工程的sources 中,也就没有编译参数,然后就出错了,简单点, QMessageBox是一个新的Translation unit
好了,设计一开始就是不对的,导致优先级存在问题,cmake-tools直接把framework当include使用的错误,cpptools解析单元跟踪丢失
问题2、cxx_flags部分手动-I添加的路径应该在cxx_includes部分中 -isystem和-iframework添加的路径的前面,因为这种设计导致,cpptools根本不可能知道正确的优先级
编译命令:
{
"directory": "/Users/admin/Desktop/bug-sample/build",
"command": "/usr/bin/clang++ -I/Users/admin/Desktop/bug-sample/abc -I/Users -iframework /Users/admin/Desktop/bug-sample/build -g -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX15.2.sdk -mmacosx-version-min=14.6 -v -I/Users/admin -o CMakeFiles/sample.dir/sample.cpp.o -c /Users/admin/Desktop/bug-sample/sample.cpp",
"file": "/Users/admin/Desktop/bug-sample/sample.cpp",
"output": "CMakeFiles/sample.dir/sample.cpp.o"
}
正确的应该是/Users/admin在/Users/admin/Desktop/bug-sample/build前面
CMake Tools Diagnostics
.Debug Log
.Additional Information
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status