Search code examples
cmakefilecudagnu-makenvcc

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

Solution

  • 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))))