Windows 11下MSYS2环境中make二次编译失败的原因与解决
问题描述
在MSYS2 Bash Shell环境下,使用cmake和make编译C代码:
- 在build目录执行
cmake ../ -DCMAKE_BUILD_TYPE=Debug - 首次运行
make成功生成二进制文件 - 再次执行
make时触发错误:
app/src/CMakeFiles/app.dir/compiler_depend.make:4: *** multiple target patterns. Stop. make[1]: *** [CMakeFiles/Makefile2:112: app/src/CMakeFiles/app.dir/all] Error 2 make: *** [Makefile:91: all] Error 2
只有执行make rebuild_cache && make clean && make才能重新编译成功。
项目文件结构:
. ├── app │ ├── CMakeLists.txt │ └── src │ ├── CMakeLists.txt │ └── main.cpp └── CMakeLists.txt
各CMakeLists.txt内容:
- 根目录CMakeLists.txt:
cmake_minimum_required(VERSION 3.14) project(app) add_subdirectory(app)
- app目录CMakeLists.txt:
add_subdirectory(src)
- src目录CMakeLists.txt:
if (CMAKE_BUILD_TYPE STREQUAL "Debug") message ("Creating Debug build") add_compile_options(-Wall -Wextra -ggdb3) endif () set(SOURCES "main.cpp") add_executable(${PROJECT_NAME} ${SOURCES})
生成的顶层Makefile内容:
# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 3.26 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target # Allow only one "make -f Makefile2" at a time, but pass parallelism. .NOTPARALLEL: #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Disable VCS-based implicit rules. % : %,v # Disable VCS-based implicit rules. % : RCS/% # Disable VCS-based implicit rules. % : RCS/%,v # Disable VCS-based implicit rules. % : SCCS/s.% # Disable VCS-based implicit rules. % : s.% .SUFFIXES: .hpux_make_needs_suffix_list # Command-line flag to silence nested $(MAKE). $(VERBOSE)MAKESILENT = -s #Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake.exe # The command to remove a file. RM = /usr/bin/cmake.exe -E rm -f # Escaping for special characters. EQUALS = = # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /c/Users/malware/Desktop/first_app # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /c/Users/malware/Desktop/first_app/build #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake.exe -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake.exe --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # The main all target all: cmake_check_build_system $(CMAKE_COMMAND) -E cmake_progress_start /c/Users/malware/Desktop/first_app/build/CMakeFiles /c/Users/malware/Desktop/first_app/build//CMakeFiles/progress.marks $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all $(CMAKE_COMMAND) -E cmake_progress_start /c/Users/malware/Desktop/first_app/build/CMakeFiles 0 .PHONY : all # The main clean target clean: $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall .PHONY : preinstall/fast # clear depends depend: $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend #============================================================================= # Target rules for targets named app # Build rule for target. app: cmake_check_build_system $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 app .PHONY : app # fast build rule for target. app/fast: $(MAKE) $(MAKESILENT) -f app/src/CMakeFiles/app.dir/build.make app/src/CMakeFiles/app.dir/build .PHONY : app/fast # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... rebuild_cache" @echo "... app" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system
错误原因
这个multiple target patterns错误的核心是Windows路径格式(带冒号:)在Makefile中被误解析为目标-依赖分隔符:
- 在MSYS2环境中,CMake生成的
compiler_depend.make文件可能包含C:/Users/...这类Windows绝对路径 - Make工具会将路径中的冒号识别为规则分隔符(比如
target: dependency的冒号),导致无法正确解析依赖规则 - 首次
make成功是因为依赖文件尚未生成,不会触发路径解析问题;后续执行时依赖文件已存在,路径格式冲突引发错误
解决办法
方法1:统一使用MSYS2风格路径
执行cmake时,采用MSYS2的Unix风格路径(如/c/Users/malware/Desktop/first_app),确保CMake生成的所有路径都不带Windows格式的冒号:
cd /c/Users/malware/Desktop/first_app/build cmake .. -DCMAKE_BUILD_TYPE=Debug
方法2:强制CMake生成相对/ Unix风格路径
在根目录CMakeLists.txt开头添加配置:
set(CMAKE_USE_RELATIVE_PATHS ON)
或者执行cmake时直接指定参数:
cmake ../ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_USE_RELATIVE_PATHS=ON
方法3:快速清理损坏的依赖文件
无需清空整个build目录,直接删除出错的依赖文件即可:
rm app/src/CMakeFiles/app.dir/compiler_depend.make make
方法4:确认MSYS2工具优先级
确保使用的是MSYS2自带的make而非Windows系统工具,执行以下命令验证:
which make
输出应为/usr/bin/make,若不是则调整环境变量优先级,让MSYS2的工具优先执行。
内容的提问来源于stack exchange,提问作者packet_sniffer
相关产品推荐
相关产品推荐

