Makefile从Windows迁移到Linux报all/xyz目标不存在错误如何解决
问题根因
你的现有修改存在3个核心问题,直接导致运行报错:
- 语法不兼容:原Windows环境用的是微软NMake工具,
$(TARGET,D,D)这类写法是NMake特有的路径提取语法,Linux默认使用的GNU Make完全不支持该语法,所以file.mak里的变量赋值逻辑全部失效,PLATFORM、CONFIG等变量自然为空。 - 变量作用域不匹配:你把
include ../../boxunit/file.mak写在了父Makefile的全局位置,GNU Make读取文件时会立刻加载file.mak,但你定义的TARGET=LINUX64/Release/$(PROJECT)是传给xyz目标下子make进程的参数,父Makefile全程没有定义TARGET变量,加载file.mak时自然取不到值。 - 规则覆盖问题:
file.mak提前加载后,如果内部存在语法错误,或者修改了默认目标规则,就会出现all、xyz目标不存在的报错。
最小改动修复方案
按以下步骤修改即可快速跑通流程:
- 删掉父Makefile末尾的
include ../../boxunit/file.mak行,该行不需要放在父Makefile中,file.mak是子make执行binary目标时才需要加载的逻辑,提前加载只会引发报错。 - 修改
file.mak的变量提取逻辑,替换为GNU Make支持的函数语法:
# 增加TARGET非空校验,提前拦截参数缺失问题 ifeq ($(TARGET),) $(error TARGET variable is not passed, please check make invocation) endif # 对应原NMake的$(TARGET,D,D),提取平台+配置的目录部分 PLATFORM_FULL_PATH:=$(dir $(TARGET)) # 对应原NMake的$(TARGET,D,D),提取平台名(LINUX64/WIN32) PLATFORM:=$(notdir $(patsubst %/,%,$(dir $(PLATFORM_FULL_PATH)))) # 对应原NMake的$(TARGET,D,B),提取配置名(Release/Debug) CONFIG:=$(notdir $(patsubst %/,%,$(PLATFORM_FULL_PATH))) # 对应原NMake的$(TARGET,B),提取不带后缀的程序名 NAME:=$(basename $(notdir $(TARGET))) # 对应原NMake的$(TARGET,E),提取程序后缀名 EXT:=$(suffix $(TARGET))
- 父Makefile中xyz目标的命令可以保留原有写法,注意命令行开头必须是Tab键,不能是空格,否则会触发语法报错。
更优跨平台实现方案
不需要维护Windows、Linux两套Makefile,直接增加系统判断逻辑,适配多环境运行,也方便Jenkins统一调度:
# 自动识别操作系统 ifeq ($(OS),Windows_NT) PROJECT=abc.exe SLASH=\\ EXEREF=C:\Program files\common\$(PROJECT) PLATFORM_PREFIX=WIN32 else PROJECT=abc SLASH=/ EXEREF=/home/common/$(PROJECT) PLATFORM_PREFIX=LINUX64 endif UNITS=$(BOXUNIT)$(SLASH)xyzcom TARGET=$(PLATFORM_PREFIX)$(SLASH)Release$(SLASH)$(PROJECT) # 全局导出TARGET变量,子进程自动继承 export TARGET all:xyz xyz: @"$(MAKE)" $(MFLAGS) binary # 仅当执行binary目标时才加载file.mak,避免提前解析报错 ifeq ($(MAKECMDGOALS),binary) include ../../boxunit/file.mak endif
内容的提问来源于stack exchange,提问作者Pooja CL
相关产品推荐
相关产品推荐

