如何在编译时记录编译机器上的驱动器卷标?
搞定编译时获取驱动器卷标的需求
这个问题我之前也踩过坑——要的是编译机器的驱动器卷标,不是程序跑起来那台机器的,所以GetVolumeInformation这种运行时API肯定不行,它拿的是运行环境的信息,完全不是一回事。
至于__FILE__宏,它确实是编译时展开的,能给出当前源文件在编译机器上的完整路径(比如C:\Projects\MyApp\main.cpp),从这里我们能提取出驱动器号(比如C:),接下来的关键就是在编译阶段就把这个驱动器的卷标硬编码到程序里,下面给你两个靠谱的方案:
方案一:Windows+MSVC专属——预处理器+批处理脚本
Windows下用MSVC的话,直接写个小批处理就能搞定:
- 先建个
GetVolumeLabel.bat脚本,放在源文件同目录,作用是接收驱动器号,输出对应的卷标作为宏定义:
@echo off setlocal enabledelayedexpansion for /f "tokens=2 delims=:" %%a in ('vol %1') do ( set "label=%%a" :: 去掉卷标前后的空格 set "label=!label: =!" echo #define COMPILE_VOLUME_LABEL "!label!" )
- 然后在你的C/C++代码里,直接通过预处理器调用这个脚本:
// 从__FILE__的驱动器号获取编译机器的卷标 #include "GetVolumeLabel.bat %~d0" int main() { printf("编译机器的驱动器卷标:%s\n", COMPILE_VOLUME_LABEL); return 0; }
编译的时候MSVC会自动执行这个批处理,把卷标作为宏嵌入代码,程序运行时直接输出的就是编译那台机器的卷标了。
方案二:跨平台首选——用CMake构建脚本
如果你的项目用CMake,那这个方案更灵活,还能适配其他平台:
- 在
CMakeLists.txt里添加这段代码,自动提取源文件所在驱动器的卷标,然后定义成预处理器宏:
if(WIN32) # 提取当前源目录的驱动器号 string(REGEX MATCH "^[A-Za-z]:" COMPILE_DRIVE ${CMAKE_CURRENT_SOURCE_DIR}) # 调用vol命令获取卷标输出 execute_process( COMMAND cmd /c vol ${COMPILE_DRIVE} OUTPUT_VARIABLE VOL_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ) # 从输出里解析出卷标字符串 string(REGEX REPLACE "^.*Volume in drive ${COMPILE_DRIVE} is (.*)$" "\\1" COMPILE_VOLUME_LABEL ${VOL_OUTPUT}) # 把卷标定义成编译宏 add_compile_definitions(COMPILE_VOLUME_LABEL="${COMPILE_VOLUME_LABEL}") endif()
- 然后代码里直接用这个宏就行:
#include <stdio.h> int main() { printf("编译机器的驱动器卷标:%s\n", COMPILE_VOLUME_LABEL); return 0; }
划重点
- 这两个方案都是编译时获取信息,所以不管程序拿到哪台机器上跑,输出的都是编译那台机器的卷标,完美符合你的需求。
- 如果是Linux/macOS平台,只要把CMake里获取卷标的命令换成对应系统的(比如Linux用
blkid,macOS用diskutil info),就能轻松适配。
内容的提问来源于stack exchange,提问作者Billy Van Der Laar
相关产品推荐
相关产品推荐

