Makefile link 步骤不正确 link obj 文件
Makefile link step doesn't properly link obj files
我在使用当前的 make 设置 link 将所有生成的 obj 文件转换为可执行文件时遇到问题。我的目录结构如下(提供参考):
- 根
- bin
- 包括
- 项目 1 ... 项目 N
- 生成文件
- root/bin
- 项目 1 ... 项目 N
- bin
- 对象
- 项目1(举例)
- 包括
- 源码
- 生成文件
如您所见,我将多个子项目存储在同一目录下,并使用对make
的递归调用来构建每个项目。首先,它从特定项目收集所有源文件和头文件,然后编译它们,将生成的 obj 文件存储在 root/bin/project/obj
中。从这里开始,我想 link 所有的 obj 文件并生成一个可执行文件,该文件将存储在 root/bin/project/bin
目录下。
问题是,通过使用当前的 Makefile 配置,我的 linker (MSVC link.exe) 只能看到 obj 目录中的第一个 obj 文件。下面提供Makefile查看编译和link命令:
# 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)
我遇到的错误如下,在linking过程中:
"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 文件 links,而试图 link 针对 Makefile 目录中的第二个 obj 文件,这当然会导致错误:`LINK:致命错误 LNK1181:无法打开输入文件 '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)
这是不对的:
$(OBJ_DIR)/$(OBJECTS)
这扩展到什么?假设 OBJECTS
是 foo.o bar.o baz.o
,OBJDIR
是 obj
。然后上面展开为:
obj/foo.o bar.o baz.o
这显然不是你想要的。如果您想为列表中的每个单词添加一个值作为前缀,您不能只将该值放在整个列表之前。您需要使用类似:
$(addprefix $(OBJ_DIR)/,$(OBJECTS))
我在使用当前的 make 设置 link 将所有生成的 obj 文件转换为可执行文件时遇到问题。我的目录结构如下(提供参考):
- 根
- bin
- 包括
- 项目 1 ... 项目 N
- 生成文件
- root/bin
- 项目 1 ... 项目 N
- bin
- 对象
- 项目 1 ... 项目 N
- 项目1(举例)
- 包括
- 源码
- 生成文件
如您所见,我将多个子项目存储在同一目录下,并使用对make
的递归调用来构建每个项目。首先,它从特定项目收集所有源文件和头文件,然后编译它们,将生成的 obj 文件存储在 root/bin/project/obj
中。从这里开始,我想 link 所有的 obj 文件并生成一个可执行文件,该文件将存储在 root/bin/project/bin
目录下。
问题是,通过使用当前的 Makefile 配置,我的 linker (MSVC link.exe) 只能看到 obj 目录中的第一个 obj 文件。下面提供Makefile查看编译和link命令:
# 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)
我遇到的错误如下,在linking过程中:
"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 文件 links,而试图 link 针对 Makefile 目录中的第二个 obj 文件,这当然会导致错误:`LINK:致命错误 LNK1181:无法打开输入文件 '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)
这是不对的:
$(OBJ_DIR)/$(OBJECTS)
这扩展到什么?假设 OBJECTS
是 foo.o bar.o baz.o
,OBJDIR
是 obj
。然后上面展开为:
obj/foo.o bar.o baz.o
这显然不是你想要的。如果您想为列表中的每个单词添加一个值作为前缀,您不能只将该值放在整个列表之前。您需要使用类似:
$(addprefix $(OBJ_DIR)/,$(OBJECTS))