【问题标题】:Makefile link step doesn't properly link obj filesMakefile 链接步骤未正确链接 obj 文件
【发布时间】:2021-11-24 16:50:53
【问题描述】:

我在使用当前的 make 设置将所有生成的 obj 文件链接到可执行文件时遇到问题。我的目录结构如下(仅供参考):

    • bin
    • 包括
    • project1 ... 项目N
    • 生成文件
  • 根/bin
    • 项目1 ...项目N
      • bin
      • 对象
  • 项目 1(例如)
    • 包括
    • 源代码
    • 生成文件

如您所见,我将多个子项目存储在同一目录下,并使用对make 的递归调用来构建每个项目。首先,它从特定项目中收集所有源文件和头文件,然后编译它们并将生成的 obj 文件存储在 root/bin/project/obj 中。从这里,我想链接所有的 obj 文件并生成一个可执行文件,该文件将存储在root/bin/project/bin 目录下。

问题是,通过使用当前的 Makefile 配置,我的链接器(MSVC link.exe)只能看到 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

如您所见,它只链接到 objdir 中的第一个 obj 文件,而尝试链接到 Makefile 目录中的第二个 obj 文件,这当然会导致错误:`LINK : fatal error LNK1181: cannot open输入文件'sort.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)/ /EHscT $(SOURCES)

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

【问题讨论】:

    标签: makefile linker


    【解决方案1】:

    这是不对的:

    $(OBJ_DIR)/$(OBJECTS)
    

    这扩展成什么?假设OBJECTSfoo.o bar.o baz.oOBJDIRobj。那么上面的展开为:

    obj/foo.o bar.o baz.o
    

    这显然不是你想要的。如果您想为列表中的每个单词添加一个值的前缀,您不能只将该值放在整个列表之前。你需要使用类似的东西:

    $(addprefix $(OBJ_DIR)/,$(OBJECTS))
    

    【讨论】:

    • 谢谢,我回家试试看:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多