0

After reading the first few chapters of Managing Projects with GNU Make, I've come up with my first non-trivial Makefile

all: libTest.a

libTest.a : Test.o MWE.o Test.dlink.o MWE.dlink.o
    nvcc -ccbin g++ -m64 -gencode arch=compute_30,code=sm_30 -lib -o $@ $^

%.a : %.dlink.o %.o
    nvcc -ccbin g++ -m64 -gencode arch=compute_30,code=sm_30 -lib -o $@ $^

%.dlink.o : %.o
    nvcc -ccbin g++ -m64 -gencode arch=compute_30,code=sm_30 -dlink -o $@ $<

%.o: %.cu
    nvcc -ccbin g++ -m64 -gencode arch=compute_30,code=sm_30 -dc -o $@ -c $<

clean:
    rm -f *.o *.dlink.o

This Makefile works but I really don't like specifying the intermediate files Test.o MWE.o Test.dlink.o MWE.dlink.o as prerequisites to libTest. I'd rather specify the input files Test.cu and MWE.cu or better still the wildcard %.u.

Olumide
  • 5,397
  • 10
  • 55
  • 104
  • You don't have to specify *any* prerequisites if you don't want to, it's just that Make can do a better job for you if you do. Do you have a clear idea of what you want this makefile to do? – Beta Jun 17 '17 at 00:54
  • @Beta Yes I have a clear idea of what I'd like to do. Please refer to ArturFX's answer as well as my following comments. I welcome your comments on how to get Make to specify prerequisites for me. – Olumide Jun 18 '17 at 12:15

1 Answers1

1

As long as you can prepare a command (or set of commands) to build libTest.a from Test.cu and MWE.cu, you can have just a rule:

libTest.a: Test.cu MWE.cu
    list
    of
    commands
    needed
    to
    build
    the
    library

but this is hardly a reasonable way of using make. What you have shown us in original question is a make-ish way of doing things. However if that's your whole Makefile the rule %.a : %.dlink.o %.o is superfluous here.

What you can do is to generate those prerequisites automatically:

SOURCES=Test.cu MWE.cu
libTest.a: $(SOURCES:%.cu=%.o) $(SOURCES:%.cu=%.dlink.o)
    nvcc -ccbin g++ -m64 -gencode arch=compute_30,code=sm_30 -lib -o $@ $^

If you prefer to not add filenames manually to SOURCES but prefer to use all *.cu files available in current directory, replace the SOURCES assignment with:

SOURCES=$(wildcard *.cu)
ArturFH
  • 1,697
  • 15
  • 28
  • `SOURCES=$(wildcard *.cu)` gives me a make error `Makefile:13: *** missing separator. Stop.` – Olumide Jun 16 '17 at 23:54
  • What is in line 13? What is first non-empty line above line 13? – ArturFH Jun 17 '17 at 00:00
  • The first non-empty line *above* line 13 is `libTest.a: $(SOURCES:%.cu=%.o) $(SOURCES:%.cu=%.dlink.o)`. As you may recall this line is part of the original Makefile. – Olumide Jun 17 '17 at 21:42
  • 1
    Please make sure you have tabs not spaces as indentations, as suggested [here](https://stackoverflow.com/questions/10097193/error-in-make-command-makefile18-missing-separator-stop). – ArturFH Jun 18 '17 at 13:40
  • Indeed the probem was spaces instead of a tab. What is the name of the features `SOURCES=$(wildcard *.cu)` and `$(SOURCES:%.cu=%.o) $(SOURCES:%.cu=%.dlink.o)`. I'd like to read about them so I can understand what the makefile is doing and be in a position to maintain it. At the moment I don't understand exactly what's going on. – Olumide Jun 18 '17 at 19:39
  • `$(something)` refers either to variable or to function. `$(wildcard)` is a function. `$(SOURCES)` is a variable. $(SOURCES:%.cu=%.o) is a short form of using `$(patsubst)` function. On Linux system you can run `info make` (or `pinfo make`). There is also [manual](https://www.gnu.org/software/make/manual/make.html) available. – ArturFH Jun 18 '17 at 19:44