CMake list(REMOVE_ITEM)无法处理转义#,Emacs交换文件编译问题求助
这个问题我之前也碰到过——Emacs生成的以#开头的交换文件(比如#cmaketest.cpp)被CMake当成普通源文件纳入编译,结果Make处理时因为#是注释符号直接炸锅。核心原因和解决办法如下:
问题根源
大概率是你的CMakeLists.txt里用了file(GLOB)或file(GLOB_RECURSE)来自动收集源文件。CMake的GLOB命令默认会匹配所有符合扩展名的文件,不管文件名开头是什么,所以这些Emacs交换文件会被误判为需要编译的源文件。而Makefile里#是注释标记,处理#cmaketest.cpp这种文件名时会直接截断,导致语法错误。
具体解决方案
1. 最稳妥:显式列出源文件
放弃用GLOB自动收集,直接在add_executable或add_library里写出所有需要编译的文件:
add_executable(YourProjectName cmaketest.cpp another_source.cpp # 其他真实源文件... )
这种方式不仅能彻底避免误包含交换文件,还能让项目结构更清晰——新增源文件时必须手动添加,不会因为GLOB没捕获到而漏编译。
2. 若必须用GLOB:过滤掉交换文件
如果因为项目规模大等原因一定要用GLOB,可以用list(FILTER)移除匹配Emacs交换文件模式的条目:
file(GLOB SOURCES *.cpp) # 过滤掉所有以#开头的文件 list(FILTER SOURCES EXCLUDE REGEX "^#.*") add_executable(YourProjectName ${SOURCES})
如果你的协作伙伴用的是Emacs标准自动保存文件(格式为#filename#,首尾都是#),可以把正则改成更精确的"^#.*#$",避免误过滤其他合法文件。
3. 全局排除:设置CMake忽略规则
可以在CMakeLists.txt开头设置全局忽略规则,让所有GLOB操作自动跳过这类文件:
# 全局忽略以#开头的文件 set(CMAKE_IGNORE_FILES_REGEX "^#.*")
这个设置会影响整个项目的GLOB收集,一劳永逸。
4. 从根源解决:让Emacs换地方存交换文件
最好的办法是让你的协作伙伴修改Emacs配置,把自动保存文件放到项目外的临时目录,彻底避免污染源文件目录。在Emacs的配置文件(比如~/.emacs或~/.emacs.d/init.el)里添加:
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/autosaves/\\1" t))) ; 自动创建保存目录(如果不存在) (make-directory "~/.emacs.d/autosaves" t)
这样Emacs的交换文件就会存在~/.emacs.d/autosaves里,不会出现在你的项目目录中。
验证方法
修改CMakeLists.txt后,重新执行cmake ..生成新的Makefile,打开Makefile搜索#cmaketest.cpp,确认它不再被引用,然后执行make应该就能正常编译了。
内容的提问来源于stack exchange,提问作者Dr. Watson

