5

我有一个像这样的 Makefile:

.SECONDARY:

NVCC = nvcc
NVCCFLAGS = --gpu-architecture compute_20

CXX = g++
CXXFLAGS = -O3 -std=c++0x -Wall

CXXLINT = python cpplint.py
CXXLINTFLAGS = --filter=-build/include,-readability/streams,-runtime/sizeof,-whitespace/parens

PROTOC = protoc
PROTOCFLAGS = --cpp_out=.

BINS = my_binary
LIBS = -lcublas -lcusparse
PROTOS = $(wildcard *.proto)
SOURCES = $(wildcard *.cu)
HEADERS = $(wildcard *.cuh)
PBS = $(PROTOS:%.proto=%.pb)
DEPS = $(SOURCES:%.cu=%.d)
TESTS = my_test

all: lint protos
all: deps
all: bins
protos: ${PBS}
deps: ${DEPS}
bins: ${BINS}

clean:
    rm -rf *.o *.d *.pb.cc *.pb.h ${BINS} ${TESTS}

lint:
    ${CXXLINT} ${CXXLINTFLAGS} ${SOURCES}
    ${CXXLINT} ${CXXLINTFLAGS} ${HEADERS}

tests: lint protos
tests: deps
tests: ${TESTS}
tests: tests-run
tests-run: ${TESTS}
    for f in $^; do eval "/usr/bin/time -f \"$$f runtime: %E\" ./$$f"; done

%: %.o
    ${NVCC} ${NVCCFLAGS} -o $@ $^ ${LIBS}

%.d: %.cu
#   ${CXXLINT} ${CXXLINTFLAGS} $*.cu
    ${NVCC} -M -o $*.d $*.cu

%.o: %.cu
    ${NVCC} ${NVCCFLAGS} -c -o $@ $*.cu
    rm $*.d

%.pb: %.proto
    ${PROTOC} ${PROTOCFLAGS} $*.proto
    ${CXX} ${CXXFLAGS} -c -o $*.pb.o $*.pb.cc

ifneq ($(MAKECMDGOALS),clean)
-include ${DEPS}
endif

出现问题是因为在构建原型目标之前我无法生成 DEPS。因为构建协议缓冲区会在树中添加一个新的头文件,如果这不是在 DEPS 之前首先完成,nvcc -M(make 依赖)将失败,因为它找不到生成的 *.pb.h . 任何想法如何解决这一问题?

4

2 回答 2

7

另一种解决方案是使您的依赖文件依赖于协议缓冲区生成的结果。以下代码段包含所有步骤,因为很难一一解释,底部有一些项目的解释:

CXX_FLAGS      := $(shell pkg-config --cflags protobuf) -xc++
LD_FLAGS       := $(shell pkg-config --libs protobuf)

PROTOS         := $(wildcard *.proto)
PROTO_OBJS     := $(PROTOS:.proto=.pb.o)

BINS     := my_binary

SRCS     := $(wildcard *.cu)
OBJS     := $(SRCS:.cu=.o)
DEPS     := $(SRCS:.cu=.d)

PBSRCS   := $(wildcard *.proto)
PBOBJS   := $(PROTOS:.proto=.pb.o)
PBGENS   := $(PROTOS:.proto=.pb.cc) $(PROTOS:.proto=.pb.h)

all: $(BINS)

clean:
        rm -f $(BINS) $(OBJS) $(DEPS) $(PBOBJS) $(PBGENS)

$(BINS): $(OBJS)
$(OBJS): $(DEPS)
$(DEPS): $(PBOBJS)

.PRECIOUS: $(PBGENS)

%.d: %.cu
        $(CXX) -M $(CXX_FLAGS) $< > $@

%.pb.cc: %.proto
        protoc --cpp_out=. $<

%.pb.o : %.pb.cc
        $(CXX) $(CXX_FLAGS) -c -o $@ $<

%.o: %.cu
        $(CXX) $(CXX_FLAGS) -c -o $@ $<

$(BINS): %: %.o
        $(CXX) $(LD_FLAGS) -o $@ $(PROTO_OBJS) $^

ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif

pkg-config命令不是必需的,但如果您想自动获取与 protobuf 文件相关的编译和链接标志,则很方便。当然,您必须将自己的标志添加到此变量中。

可能对您没用,但在这里使用-xc++是为了能够处理.cu文件并将它们解释为 C++;即使对于不同于nvcc.

该行$(DEPS): $(PBOBJS)指示应该在创建依赖项之前创建和编译 protobuf 文件。有几种方法可以实现这一点,因此这只是一个示例。

.PRECIOUS行指示make保留生成的 protobuf 文件。在此示例代码段中,这些文件被视为中间文件,因此将在没有此行的情况下被删除。

我将此作为单独的答案发布,因为前一个和这个没有太多共同点。

于 2012-07-15T23:52:03.857 回答
1

在构建依赖项时,即使缺少头文件,您也可以选择继续。使用cppor gcc,可以通过使用 options 来实现-MM -MG。我没有使用 NVCC 的经验,但我在手册中没有看到任何支持这些标志。如果这是真的,那么您可以尝试cpp仅切换到依赖项生成。从cpp手册页:

-MG 假定丢失的头文件是生成的文件,并将它们添加到依赖项列表中而不会引发错误。

顺便说一句,你的模式规则%.pb: %.proto对我来说似乎不正确。它依赖于%.pb.h并且使用当前方法,将不知道如何解决任何依赖关系,因为它不知道如何创建文件。%.pb.cc%.protomake%.pb.h.pb.h

于 2012-07-10T12:54:10.723 回答