我有一个在Linux下工作的makefile(gnu make),但是将其移植到Windows时不起作用。 makefile的目标是制作所有位于不同子目录中的* .cpp文件,并将它们编译为单个BUILD_DIR中的* .obj文件。
在linux和Windows之间,我仅调整了SOURCES变量,显示了linux行,但已注释。当我检查所有名称和目录时,它们显示相同的内容(它们在透视符号中的相对路径)和我所期望的。
我在Windows上收到的“错误消息”是:make:***没有规则来创建目标“ DEM.cpp”,这是“ DEM.obj”所需的。停止。
在调试模式下,它说:文件'DEM.cpp'不存在。 (显然是这样)
在linux上,它通过VPATH查找文件,在调试模式下,它说:无需重新制作目标文件'DEM.cpp';使用VPATH名称“ ./Code/DEM.cpp”。
Linux和Windows中的子目录结构相同,并且makefile从同一位置运行。
问题:这里出了什么问题,我觉得这与Windows中对VPATH的处理方式有所不同,但我不确定。
我的makefile是:
# MAKEFILE
# Some makefile settings
SHELL = /bin/sh #Make sure the shell is the standard shell
.SUFFIXES: #Clear al implicit suffixes
.SUFFIXES: .cpp .obj #Set used suffixes
# Variable Declaration
CXX := g++
BUILD_DIR = .\bin\Release
PROGRAM_NAME := DEM.exe
#SOURCES := $(shell find . -name '*.cpp') #All *.cpp files with directory (LINUX style)
SOURCES := $(shell FORFILES /S /M *.cpp /C "CMD /C ECHO @relpath") #All *.cpp files with directory
NAMES := $(notdir $(basename $(SOURCES))) #Get all files names of the *.cpp files without extensions
OBJECTS := $(addsuffix .obj, $(NAMES)) #Get the to be generate *.o files without directory
SRC_DIRS := $(dir $(SOURCES)) #All the directory in which the sources are found
VPATH := $(SRC_DIRS) $(BUILD_DIR)
.PHONY: all
all: build #Standard entry point, run release
@echo "BUILD DONE"
.PHONY: build
build: $(PROGRAM_NAME)
@echo "BUILD DONE"
$(PROGRAM_NAME): $(OBJECTS)
@echo "Link executable"
$(CXX) -o $(BUILD_DIR)/$(PROGRAM_NAME) $(addprefix $(BUILD_DIR)/,$(OBJECTS))
$(OBJECTS): %.obj: %.cpp
@echo "Compile into object code: $<"
${CXX} $(CXXFLAGS) -c $< -o $(BUILD_DIR)/$@ #Compiles object code and places it in the $(BUILD_DIR)
更新1:基于some programmer dude的评论,我用-p运行它,并得到以下有趣的结果:
# Not a target:
DEM.cpp:
# Implicit rule search has been done.
# File does not exist.
# File has not been updated.
# Not a target:
World.cpp:
# Implicit rule search has not been done.
# Modification time never checked.
# File has not been updated.
# Lot more targets below
似乎只能找到DEM.cpp,但可以找到其他所有内容。 DEM.cpp驻留在C:\ Users \ dklomp \ Documents \ Programming \ C ++ Source \ DEM \ DEM \ Code,但应解析为。\ Code \ 其他大多数文件都位于Code的子目录中。 但是stdafx.cpp也驻留在。\ Code \中,并且找到它没有问题。
可以是与目录名称DEM类似于DEM.cpp的名称冲突吗?
更新2:有关信息和结束。 我已经通过打印变量读取变量来检查VPATH,这似乎提供了正确的信息。但是,如果我用@(info $ {VPATH))阅读它,它似乎是空的:
@echo "VPATH print variable: "
@echo "$(VPATH)"
@echo "VPATH print info: "
$(info VPATH)
给予:
"VPATH print variable: "
"./Code/InputOutput/ ./Code/InputOutput/ ./Code/InputOutput/
./Code/InputOutput/ ./Code/ ./Code/ ./Code/Models/ ./Code/Models/
./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Forces/
./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Tools/
./Code/Tools/ ./Code/Tools/ ./Code/Tools/ ./Code/Solvers/ ./Code/Solvers/
./Code/Solvers/ ./Code/World/ ./Code/World/ ./Code/World/ ./Code/World/
./Code/World/ ./Code/Interactions/ ./Code/Interactions/ ./Code/Interactions/
./Code/Interactions/ ./Code/Interactions/ ./Code/Interactions/
bin\Release"
"VPATH print info: "
确实有很多重复(将使用hardcoreHenry的排序建议),但是看起来不错。但是,由于某些原因,VPATH信息为空。
但是,通过code_fodder实现建议的解决方案并删除所有内联代码注释是可行的。变量声明中的内联代码注释似乎无关紧要,规则部分中的注释对于Windows而言无关紧要,Linux似乎可以在任何地方很好地处理内联代码注释。
通常要感谢您的帮助和建议。
答案 0 :(得分:0)
我在当前位置之前有空格的路径(例如,d:\path with spaces\myfolder\sub_folder1\sub_folder2\
)中对此进行了测试。
我认为FORFILES语法/输出存在一些问题-至少我无法使其正常工作。一旦使用了second answer from here中更为通用的rwildcard,它就开始运作良好。然后我添加了创建/清理输出文件夹的规则。
我也删除了任何内联注释,因为我不是100%地确定它们是否有效,因为它们到处都留有空格字符,并且makefile对此的容忍度不是很高。确保您在任何行上都不会留下任何空白。
也-所有这些都假设其为gnu-make
,而不是nmake
# MAKEFILE
# Some makefile settings
SHELL = /bin/sh
.SUFFIXES:
.SUFFIXES: .cpp .obj
# Variable Declaration
CXX := g++
BUILD_DIR = .\bin\Release
PROGRAM_NAME := DEM.exe
# Define a recursive wild card function that is portable.
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
#SOURCES := $(shell FORFILES /S /M *.cpp /C "CMD /C ECHO @relpath")
SOURCES := $(call rwildcard, ./, *.cpp)
$(info SOURCES: $(SOURCES))
NAMES := $(notdir $(basename $(SOURCES)))
OBJECTS := $(addsuffix .obj, $(NAMES))
SRC_DIRS := $(dir $(SOURCES))
VPATH := $(SRC_DIRS) $(BUILD_DIR)
.PHONY: all
all: create_dirs build
@echo "BUILD DONE"
# Has an order dependency on create_dirs to ensure that happens first, and so
# it works with parallel build (e.g. `make -j4`)
.PHONY: build
build: $(PROGRAM_NAME) | create_dirs
@echo "BUILD DONE"
$(PROGRAM_NAME): $(OBJECTS)
@echo "Link executable"
$(CXX) -o $(BUILD_DIR)/$(PROGRAM_NAME) $(addprefix $(BUILD_DIR)/,$(OBJECTS))
$(OBJECTS): %.obj: %.cpp
@echo "Compile into object code: $<"
${CXX} $(CXXFLAGS) -c $< -o $(BUILD_DIR)/$@
.PHONY: create_dirs
create_dirs:
@echo "creating dirs"
mkdir -p $(BUILD_DIR)
.PHONY: clean
clean:
@echo "cleaning"
rm -rf $(BUILD_DIR)