You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Makefile链接步骤无法正确链接全部obj文件的LNK1181报错解决

Make递归构建子项目时MSVC链接器路径识别错误问题

目录结构

  • root
    • bin
    • include
    • project1 ... projectN
    • Makefile
  • root/bin
    • project1 ... projectN
      • bin
      • obj
  • 单项目(以Project1为例)结构
    • include
    • src
    • Makefile

构建逻辑说明

同路径下存放多个子项目,通过递归调用make构建每个项目:首先收集指定项目的所有源文件与头文件完成编译,生成的obj文件存储在root/bin/project/obj路径下,再将所有obj文件链接生成可执行文件,存储到root/bin/project/bin目录。

问题表现

使用现有Makefile配置时,链接器(MSVC link.exe)仅能识别obj目录下的第一个obj文件,其余obj文件会被默认定位到Makefile所在目录,触发报错。

原有错误配置

# expands to root/bin/projname/bin
TARGET_DIR := $(BINARY_DIR)/$(notdir $(patsubst %/,%,$(CURDIR)))/bin
#expands to root/bin/projname/obj
OBJ_DIR := $(BINARY_DIR)/$(notdir $(patsubst %/,%,$(CURDIR)))/obj
# expands to a list of all the obj files created from the source files (a.obj, b.obj..)
OBJECTS := \
    $(notdir $(patsubst %.cpp,%.obj,$(patsubst %.c,%.obj,$(SOURCES))))
SOURCES := $(wildcard src/*.c) $(wildcard src/*.cpp)

# default target
all: dirs $(TARGET).exe

# Link
$(TARGET).exe: $(OBJ_DIR)/$(OBJECTS)
    $(LNK) $(LIB_PATH) $(LIBS) /OUT:$(TARGET_DIR)/$@ $(OBJ_DIR)/$(OBJECTS)

# Compile
$(OBJ_DIR)/$(OBJECTS): $(SOURCES)
    $(CC) /c $(CFLAGS) $(INCLUDES) /Fo$(OBJ_DIR)/ /EHsc $(SOURCES)

.PHONY: build
dirs:
    $(MKDIR) $(TARGET_DIR)
    $(MKDIR) $(OBJ_DIR)
    $(MKDIR) $(TEST_DIR)

报错信息

链接阶段执行的命令如下:

"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\\..\..\VC\vcvarsall.bat" x86_amd64 > NUL && link /NOLOGO /MACHINE:X64  /LIBPATH:"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\x64"  /DEFAULTLIB:shell32.lib /OUT:../bin/project1/bin/project1.exe ../bin/project1/obj/main.obj sort.obj

可见仅第一个obj文件拼接了正确的obj目录路径,第二个obj文件sort.obj被当作当前Makefile目录下的文件处理,最终抛出错误:LINK : fatal error LNK1181: cannot open input file 'sort.obj'

问题根因

Make的原生变量展开逻辑中,$(OBJ_DIR)/$(OBJECTS)只会给OBJECTS列表的第一个元素添加OBJ_DIR前缀,后续元素不会自动拼接路径,导致链接器在当前工作目录查找后续obj文件失败。

修复方案

使用Make内置的addprefix函数给所有obj文件统一添加路径前缀,同时链接命令使用自动变量$^代替手写的obj列表,避免重复逻辑出错,修复后配置如下:

# expands to root/bin/projname/bin
TARGET_DIR := $(BINARY_DIR)/$(notdir $(patsubst %/,%,$(CURDIR)))/bin
#expands to root/bin/projname/obj
OBJ_DIR := $(BINARY_DIR)/$(notdir $(patsubst %/,%,$(CURDIR)))/obj
# expands to a list of all the obj files created from the source files (a.obj, b.obj..)
OBJECTS := \
    $(notdir $(patsubst %.cpp,%.obj,$(patsubst %.c,%.obj,$(SOURCES))))
SOURCES := $(wildcard src/*.c) $(wildcard src/*.cpp)

# default target
all: dirs $(TARGET).exe

# Link
$(TARGET).exe: $(addprefix $(OBJ_DIR)/,$(OBJECTS))
    $(LNK) $(LIB_PATH) $(LIBS) /OUT:$(TARGET_DIR)/$@ $^

# Compile
$(OBJ_DIR)/$(OBJECTS): $(SOURCES)
    $(CC) /c $(CFLAGS) $(INCLUDES) /Fo$(OBJ_DIR)/ /EHsc $(SOURCES)

.PHONY: build
dirs:
    $(MKDIR) $(TARGET_DIR)
    $(MKDIR) $(OBJ_DIR)
    $(MKDIR) $(TEST_DIR)

内容的提问来源于stack exchange,提问作者Adrian Costin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:45:01