JC2188 JC2188 - 2 months ago 20
C Question

Make: *.h no such file or directory

My project has the following directory structure:


  • main.cu

  • FA_kernels/*.cu

  • FD_kernels/*.cu

  • MEM_kernels/*.cu

  • MOD_kernels/*.cu

  • headers/*.h



Where *.extension means a bunch of files with that extension. I can't seem to get the makefile to work correctly. The error I'm getting is:

FA_kernels/FA_SFD.cu:2:20: fatal error: FA_SFD.h: No such file or directory
#include "FA_SFD.h"
^


My intent was for -I headers to be specified to the compiler, thereby making the headers directory available for searching. Clearly this has not worked. Here is the makefile:

CC := nvcc
LD := nvcc

MODULES := FA_kernels FD_kernels MEM_kernels MOD_kernels .
SRC_DIR := $(MODULES)
BUILD_DIR := $(addprefix build/,$(MODULES))

SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cu))
OBJ := $(patsubst src/%.cu,build/%.o,$(SRC))
INCLUDES := $(addprefix -I,headers)

vpath %.cu $(SRC_DIR)

define make-goal
$1/%.o: %.cu
$(CC) $(INCLUDES) -c $$< -o $$@
endef

.PHONY: all checkdirs clean

all: checkdirs build/lem

build/lem: $(OBJ)
$(LD) $^ -o $@


checkdirs: $(BUILD_DIR)

$(BUILD_DIR):
@mkdir -p $@

clean:
@rm -rf build

$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir))))


Any ideas?

UPDATE: Here is the full console output from running make

nvcc FA_kernels/FA_SFD.cu FA_kernels/partition.cu FA_kernels/contribA.cu FA_kernels/parallel-SFD-List.cu FD_kernels/SFD.cu FD_kernels/flow_routines.cu FD_kernels/floodingDriver.cu FD_kernels/watershed.cu MEM_kernels/memory_dev.cu MEM_kernels/Data.cu MEM_kernels/MapInfo.cu MEM_kernels/memory.cu MOD_kernels/erosion.cu MOD_kernels/eroincidep.cu MOD_kernels/updates.cu MOD_kernels/runoffweight.cu MOD_kernels/depo-List.cu lem.cu -o build/lem
FA_kernels/FA_SFD.cu:2:20: fatal error: FA_SFD.h: No such file or directory
#include "FA_SFD.h"
^
compilation terminated.
Makefile:24: recipe for target 'build/lem' failed
make: *** [build/lem] Error 1

Answer

From your output, apparently patsubst in OBJ was not successful at all. From the way you define SRC, I assume makefile is directly under src/, then you should change src/%.cu to %.cu in the definition of OBJ as such:

OBJ       := $(patsubst %.cu,build/%.o,$(SRC))

Also, if I understand you correctly, you were trying to create a folder structure under build/ that is identical to the folder structure under src/. So, for instance, /src/abc.cu will generate /src/build/abc.o, then you don't need to define functions to get these rules, simply do:

build/%.o: %.cu
    $(CC) $(INCLUDES) -c $< -o $@

and you are good to go.

If instead you wish to create build/ on the same level as src/. i.e. XXX/src/abc.cu -> XXX/build/abc.o. Then simply replace all occurrences of build in your makefile with ../build.

If you would rather put makefile at the same level as src/, then you should edit SRC to reflect that:

SRC       := $(foreach sdir,$(SRC_DIR),$(wildcard src/$(sdir)/*.cpp))

and change the target to:

build/%.o: src/%.cpp
    $(CC) $(INCLUDES) -c $< -o $@

Now you can safely remove vapth ... and the last line $foreach in your makefile.

EDIT: This is what your makefile will look like. I can't test it right now so there may be some mistakes in it, but hopefully it makes you understand the general idea.

CC        := nvcc
LD        := nvcc

MODULES   := FA_kernels FD_kernels MEM_kernels MOD_kernels .
SRC_DIR   := $(MODULES)
BUILD_DIR := $(addprefix build/,$(MODULES))

SRC       := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cu))
OBJ       := $(patsubst %.cu,build/%.o,$(SRC))
INCLUDES  := $(addprefix -I,headers)

# vpath %.cu $(SRC_DIR) 

#define make-goal
build/%.o: %.cu
    $(CC) $(INCLUDES) -c $< -o $@
#endef

.PHONY: all checkdirs clean

all: checkdirs build/lem

build/lem: $(OBJ)
    $(LD) $^ -o $@


checkdirs: $(BUILD_DIR)

$(BUILD_DIR):
    @mkdir -p $@

clean:
    @rm -rf build

#$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir))))