当前位置: 首页 > ops >正文

Visual Studio中VC++目录、C/C++和链接器配置的区别与最佳实践

一、背景

  • 在 VS 的项目属性里,常见几处看似相似的配置项:

    • VC++ 目录:包含目录、库目录

    • C/C++:附加包含目录

    • 链接器:附加库目录、附加依赖项

  • 我在配置 OpenCV 时,尝试两种方案:

    1. 只在 VC++ 目录里配置包含目录库目录,再在链接器中配置附加依赖项,程序可以运行。

    2. 改为在 C/C++ 里配置“附加包含目录”、在“链接器”里配置“附加库目录 + 附加依赖项”,同样可以运行。


  • 这两种都能成功,但它们的语义、作用范围与维护性并不相同。本文讲清楚它们的区别,并给出推荐做法。

二、各配置项的作用与区别

1. VC++ 目录

  • 本质

    • 这页的“包含目录/库目录”是在修改一组 MSBuild 宏:$(IncludePath)、$(LibraryPath)、$(ExecutablePath) 等。等于给编译器/链接器提供“默认的搜索路径”。

  • 层级与“全局可见”

    • 这些宏可以在多个层级被定义或叠加:工具集、Windows SDK、用户级属性表、项目/共享属性表。

    • 构建时,会使用最终合成的宏值:编译器从 IncludePath 里找头文件,链接器从 LibraryPath 里找库。

  • 为什么说“可见性差”

    • 改动常发生在用户级属性表或环境变量,不写进项目文件,代码仓库里看不见,团队不易感知

    • 属性页里显示的是宏名而非最终路径;要知道真正生效的路径,需要展开宏并追踪多层继承,排查成本高

  • 对应关系(直观记忆)

    • VC++ 目录 → 包含目录:叠加到 $(IncludePath) → 默认头文件搜索路径(对应编译器的 INCLUDE)

    • VC++ 目录 → 库目录:叠加到 $(LibraryPath) → 默认库搜索路径(对应链接器的 LIB)

    • VC++ 目录 → 可执行文件目录:叠加到 $(ExecutablePath) → VS 查找编译工具的路径

2. C/C++ → 附加包含目录

  • 作用:告诉编译器“本项目额外到哪些目录找头文件”。

  • 只影响编译阶段,不处理库或符号实现。

3. 链接器 → 附加库目录

  • 作用:告诉链接器“到哪些目录去找 .lib 文件”。

  • 只是路径,不等于已经链接某个库

4. 链接器 → 附加依赖项

  • 作用:列出“要链接的具体库文件名”,例如 opencv_world4xx.lib 或分模块库名。

  • 链接器会到“附加库目录”(以及默认库路径)里寻找这些文件并装入

  • 与“附加库目录”的区别:一个是“去哪找”,一个是“找哪些”。

三、为什么两种配置都能跑

先看构建的三个阶段:编译(找头文件)→ 链接(找库并装入实现)→ 运行(找 DLL)。

1. 方案 A(在 VC++ 目录里配包含/库目录,在“链接器→附加依赖项”里列出库名)

  • 编译阶段:编译器通过“默认的头文件搜索路径集合”找到 OpenCV 的头文件。

  • 链接阶段:链接器通过“默认的库文件搜索路径集合”找到 .lib;再根据“附加依赖项”里列出的库名,把这些库装入最终程序。

  • 这里的“默认集合”来自你在 VC++ 目录里对包含目录/库目录的设置。

2. 方案 B(在 C/C++ 里配“附加包含目录”,在“链接器”里配“附加库目录 + 附加依赖项”)

  • 编译阶段:为当前项目明确添加“额外的头文件搜索路径”,让编译器能找到 OpenCV 的头文件。

  • 链接阶段:为当前项目明确添加“额外的库文件搜索路径”,并给出“需要链接的库清单”,让链接器把相应库装入最终程序。

  • 这些设置直接体现在本项目的配置里,可一目了然地看到“去哪找”和“找哪些”。

3. 结论

  • 两种方案都会让编译器找到头文件、让链接器找到并装入需要的库,因此都能跑。

  • 但方案 B 更推荐:配置更直观(清楚区分头文件路径、库路径、库清单)、作用范围更可控(只影响当前项目/当前配置)、迁移与协作更省心(项目文件或共享属性表里一眼能看到并随仓库提交)。

四、总结

  • 编译看“附加包含目录”(找头文件)

  • 链接看“附加库目录 + 附加依赖项”(去哪找库 + 找哪些库)

  • 运行看“DLL 是否在 PATH 或 exe 同目录”

  • VC++ 目录是“默认路径宏”的旧式入口,能用但不推荐作为日常放第三方库的地方。将配置放在 C/C++ 与 链接器页面,更清晰、更稳、更易迁移。

http://www.xdnf.cn/news/17609.html

相关文章:

  • 北京JAVA基础面试30天打卡08
  • 【问题解决】从Anaconda环境迁移到miniforge并在IDEA中完成环境配置
  • K8S学习---- Kubernetes 架构:从控制平面到工作节点的协作逻辑
  • Vue接口平台十三——测试记录
  • Git 撤回已推送到远程的最近push
  • 【数据结构入门】堆
  • NLP—词向量转换评论学习项目分析真实案例
  • 4.运算符
  • Docker命令及操作
  • imx6ull-驱动开发篇20——linux互斥体实验
  • 图解软件系统组成
  • 什么是iOS超级签名?为何它能解决企业签名的“掉签”难题?
  • 云原生高级---TOMCAT
  • [激光原理与应用-250]:理论 - 几何光学 - 透镜成像的优缺点,以及如克服缺点
  • 机器学习-集成学习(EnsembleLearning)
  • ETCD的简介和使用
  • 17、CryptoMamba论文笔记
  • 导入文件到iPhone实现
  • C++11-下
  • QT6 如何在Linux Wayland 桌面系统抓屏和分享屏幕
  • AT F-Intervals 题解
  • 深入理解数据库架构:从原理到实践的完整指南
  • DEA模型MATLAB实现(CCR、BCC、超效率)
  • 云原生应用的DevOps3(CI/CD十大安全风险、渗透场景)
  • LeetCode189~191、198~214题解
  • Day52 Java面向对象07 类与对象总结
  • 鸿蒙har包打包与引用,其它主工程entry引用本地har
  • 【19】万集科技——万集科技嵌入式,校招 一面,二面,面试问答记录
  • 【基于Redis的手语翻译序列存储设计】
  • 淘宝API列表:高效获取商品详情图主图商品视频参数item_get