Makefile在Linux上运行但在Windows下无法运行,无法在子目录

时间:2019-08-13 09:22:17

标签: c++ linux windows makefile

我有一个在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似乎可以在任何地方很好地处理内联代码注释。

通常要感谢您的帮助和建议。

1 个答案:

答案 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)