Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I've checked out and read all of the answers which I probably should. I've tried adding a tab and checking for spaces. However, I still get errors while running make.
Below is my working tree:
$tree
.
├── bin
├── cu
│ └── kernel_gpu.cu
├── inc
│ └── kernel.h
├── Makefile
├── obj
│ ├── kernel_gpu.o
│ └── main.o
└── src
├── kernel.cxx
└── main.cxx
I try to use wildcard and patsubst to make my Makefile look good.
Here is my Makefile:
DIR_INC = ./inc
DIR_SRC = ./src
DIR_CU = ./cu
DIR_OBJ = ./obj
DIR_BIN = ./bin
SRC = $(wildcard ${DIR_SRC}/*.cxx)
SRC_CU = $(wildcard ${DIR_CU}/*.cu)
OBJ = $(patsubst %.cxx,${DIR_OBJ}/%.o,$(notdir ${SRC}))
CUOBJ = $(patsubst %.cu,${DIR_OBJ}/%.o,$(notdir ${SRC_CU}))
BIN_TARGET = ${DIR_BIN}/${TARGET}
TARGET = test
CXX=g++
CU=nvcc
CUDA_INSTALL_PATH= /usr/local/cuda
CUDAFLAGS= -O2 -I. -I$(CUDA_INSTALL_PATH)/include -I ${DIR_INC}
LDFLAGS= -L$(CUDA_INSTALL_PATH)/lib64 -lcudart
${OBJ}:${SRC}
$(CXX) $(CUDAFLAGS) -c $< -o $#
$(CUOBJ):$(SRC_CU)
$(CU) $(CUDAFLAGS) -o $# -c $<
${BIN_TARGET}:${DIR_OBJ}/%.o
$(CXX) $< -o $# ${LDFLAGS}
.PHONY: clean
clean:
find ${DIR_OBJ} -name *.o -exec rm -rf {} \;
I always get the same error message when typing make in my shell:
$ make
Makefile:45: *** missing separator. Stop.
Line 45 is:
44 ${OBJ}:${SRC}
45 $(CXX) $(CUDAFLAGS) -c $< -o $#
I echoed the variable ${OBJ} and ${SRC} and the result is shown as:
./src/main.cxx ./src/kernel.cxx
./obj/main.o ./obj/kernel.o
You need to replace those four spaces with a hard tab.
If you're using some sort of editor that replaces hard tabs with spaces, you'll need to disable that or use a different editor.
Related
I want Make to automatically compile protos when I update them, here is what I've got so far:
TARGET=main
BIN_DIR=bin
SRC_DIR=src
OBJ_DIR=obj
PROTO_DIR=protos/
PROTO_COMPILE_DIR=src/$(PROTO_DIR)
CC = g++
CFLAGS = -Wall -std=c++17 -ggdb -pipe -I.
LINKER = g++
LFLAGS = $(CFLAGS) -lprotobuf
SOURCES = $(wildcard src/*.cc) \
$(wildcard src/protos/*.cc) \
$(wildcard src/db_handler/*.cc)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.cc=$(OBJ_DIR)/%.o)
$(BIN_DIR)/$(TARGET): proto $(OBJECTS)
#mkdir -p $(BIN_DIR)/
$(LINKER) $(OBJECTS) $(LFLAGS) -o $#
$(OBJECTS): $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cc
#mkdir -p obj/ obj/protos obj/db_handler
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: proto
proto:
#printf "Compiling protos...\n"
#cd $(PROTO_DIR) && protoc * --grpc_out=../$(PROTO_COMPILE_DIR)\
--cpp_out=../$(PROTO_COMPILE_DIR)\
--plugin=protoc-gen-grpc="/usr/local/bin/grpc_cpp_plugin"\
&& cd ../
It successfully compiles protos; but, it does so every time, even if there are no changes in files. How can I prevent this and compile protos only if protos change?
Edit: Added project structure
├── LICENSE
├── makefile
├── protos
│ ├── client.proto
│ └── person.proto
├── README.md
└── src
├── db_handler
│ ├── db_handler.cc
│ └── db_handler.h
├── main.cc
└── protos
├── client.grpc.pb.cc
├── client.grpc.pb.h
├── client.pb.cc
├── client.pb.h
├── person.grpc.pb.cc
├── person.grpc.pb.h
├── person.pb.cc
└── person.pb.h
You want to add the source files of the protocol buffers to the right (the prerequisites) of the rule that cares about them. This is how Make understands and tracks their time stamps.
By adding the files to the prerequisites, Make will understand that this is the rule which cares about those source files.
PROTO_SOURCES := $(wildcard $(PROTO_DIR)/*.proto)
PROTOS := $(patsubst $(PROTO_DIR)/%.proto,$(PROTO_COMPILE_DIR)/%.cc,$(PROTO_SOURCES))
$(PROTOS): $(PROTO_SOURCES)
#printf "Compiling protos...\n"
#cd $(PROTO_DIR) && protoc * --grpc_out=../$(PROTO_COMPILE_DIR)\
--cpp_out=../$(PROTO_COMPILE_DIR)\
--plugin=protoc-gen-grpc="/usr/local/bin/grpc_cpp_plugin"
However, this $(PROTOS) : $(PROTO_SOURCES) is not good if you use parallel builds; because, Make will try to run the command once for each output file. So, make will run N instances of the command at the same time, which means they may clobber each other.
In order to know the fully correct solution you need to provide more information (for those not familiar with protoc). Is it a requirement that you invoke protoc once with all inputs? Or is it valid to run protoc individually on each input .proto file to get its output? Then you can write a pattern rule that generates one file at a time.
Note 1: As to your other attempt, if you use .PHONY to mark the rule then Make will rebuild the rule every time weather it needs to or not.
Note 2: You don't need the cd .. at the end of the second instruction, since it is run in a sub shell.
Thanks to #FiddlingBits I managed to figure out how to do it correctly
TARGET=main
BIN_DIR=bin
SRC_DIR=src
OBJ_DIR=obj
PROTO_DIR=protos/
PROTO_COMPILE_DIR=src/$(PROTO_DIR)
rm = rm -f
CC = g++
CFLAGS = -Wall -std=c++17 -ggdb -pipe -I.
LINKER = g++
LFLAGS = $(CFLAGS) -lprotobuf
SOURCES = $(wildcard src/*.cc) \
$(wildcard src/protos/*.cc) \
$(wildcard src/db_handler/*.cc)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.cc=$(OBJ_DIR)/%.o)
PROTOS := $($(PROTO_DIR)/%.proto=$(PROTO_COMPILE_DIR)/%.cc)
$(BIN_DIR)/$(TARGET): $(PROTOS) $(OBJECTS)
echo $(PROTOS)
#mkdir -p $(BIN_DIR)/
$(LINKER) $(OBJECTS) $(LFLAGS) -o $#
$(OBJECTS): $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cc
#mkdir -p obj/ obj/protos obj/db_handler
$(CC) $(CFLAGS) -c $< -o $#
$(PROTOS):
#printf "Compiling protos...\n"
#cd $(PROTO_DIR) && protoc * --grpc_out=../$(PROTO_COMPILE_DIR)\
--cpp_out=../$(PROTO_COMPILE_DIR)\
--plugin=protoc-gen-grpc="/usr/local/bin/grpc_cpp_plugin"\
&& cd ../
.PHONY: clean
clean:
#$(rm) -r $(OBJ_DIR)/*
#$(rm) -r $(BIN_DIR)/*
#printf "Cleanup complete!\n"
I want to use make and create a static pattern rule that has the target in a output directory, and the prerequisite files are in the preceeding directory, and it has to work recursively.
I have a minimal example here:
.
├── anotherdir
│ ├── output
│ │ ├── source3.md
│ │ └── source4.md
│ ├── source3.json
│ └── source4.json
├── output
│ ├── source1.md
│ └── source2.md
├── source1.json
└── source2.json
I want to generate the output directories if they do not exist, and I want to generate *.md files from the *.json using make if they do not exist, or *.json is updated.
So far, I have the following Makefile:
SOURCE_FILES := $(shell find ./ -name "*.json")
OUTPUT_FILES := $(join $(addsuffix output/,$(dir $(SOURCE_FILES))), $(addsuffix .md,$(basename $(notdir $(SOURCE_FILES)))))
.PHONY: all
all: $(OUTPUT_FILES)
$(OUTPUT_FILES): %.md: %.json
mkdir -p $(dir $#)
# Command to create MD file from json file into the output directory here
The actual command to create the MD file from the json file doesn't matter here, because I have a script that I will call that will do this for me. The problem here, is that when I try to even run this at all, I get the following output:
> make all
make: *** No rule to make target 'anotherdir/output/source4.json', needed by 'anotherdir/output/source4.md'. Stop.
Obviously, source4.json is not in anotherdir/output, but rather, it's in the preceeding directory, which is just anotherdir. I don't know how to make it so that the pattern $(OUTPUT_FILES): %.md: %.json will match it properly.
Or is a static pattern rule not good here? I'm not sure what to do to fit my scenario.
EDIT: I tried to do something like this:
$(OUTPUT_FILES): %.md: $(join $(subst output,,$(dir %)), $(addsuffix .json,$(basename $(notdir %))))
and this doesn't work, I still get:
> make all
make: *** No rule to make target 'anotherdir/output/source4.json', needed by 'anotherdir/output/source4.md'. Stop.
Edit 2: to clarify, i start with the following files
.
├── anotherdir
│ ├── source3.json
│ └── source4.json
├── source1.json
└── source2.json
And then when i run make, i want it to generate the output folders like this
.
├── anotherdir
│ ├── output
│ │ ├── source3.md
│ │ └── source4.md
│ ├── source3.json
│ └── source4.json
├── output
│ ├── source1.md
│ └── source2.md
├── source1.json
└── source2.json
I want to use some kind of smart makefile syntax to pick up these files names without me hard coding it in myself. Hence, i looked at the documentation and saw that static pattern rules might be the solution that i want, except that i can't get the right prerequisite pattern down.
I would do it this way:
First, find the source files just as you did (with a small change to prevent the unsightly double-slash):
SOURCE_FILES := $(shell find . -name "*.json")
A pattern file would be nice, if we could use two wildcards at once, but Make can't quite do that. So I recommend using a template:
define template
TDIR := $(dir $(1))output
TARG := $$(TDIR)/$(notdir $(basename $(1))).md
$$(TARG): $(1)
mkdir -p $$#
#echo building $$# from $$<
# Command to create MD file from json file into the output directory here
endef
$(foreach SOURCE,$(SOURCE_FILES),$(eval $(call template,$(SOURCE))))
If this works, all that's left is to construct a list of output files, and a default rule that has all of them as prerequisites:
define template
TDIR := $(dir $(1))output
TARG := $$(TDIR)/$(notdir $(basename $(1))).md
OUTPUT_FILES += $$(TARG)
$$(TARG): $(1)
mkdir -p $$#
#echo building $$# from $$<
# Command to create MD file from json file into the output directory here
endef
all:
$(foreach SOURCE,$(SOURCE_FILES),$(eval $(call template,$(SOURCE))))
all: $(OUTPUT_FILES)
It isn't pretty, but it seems to work.
If it had not been proposed already in another answer I would have suggested foreach-eval-call. For completeness here are different solutions for GNU make (they may work also with other versions of make but I did not check):
Creating the output directories beforehand
If the output directories exist already you can refer to ../%.json in your pattern rule:
SOURCE_FILES := $(shell find . -name "*.json")
OUTPUT_FILES := $(join $(dir $(SOURCE_FILES)),\
$(patsubst %.json,output/%.md,$(notdir $(SOURCE_FILES))))
$(shell mkdir -p $(dir $(OUTPUT_FILES)))
.PHONY: all
all: $(OUTPUT_FILES)
%.md: ../%.json
: json2md $< -o $#
This may look strange but if you read carefully the Pattern match section of the GNU make manual you should quickly understand. The only constraint for this to work is that the output directories exist before make searches pattern rules that match the targets. If one does not exist make will complain that there is no eligible rule to build the target. This is the reason for the:
$(shell mkdir -p $(dir $(OUTPUT_FILES)))
at the beginning of the Makefile. Demonstration:
$ make
: json2md output/../source2.json -o output/source2.md
: json2md output/../source1.json -o output/source1.md
: json2md anotherdir/output/../source4.json -o anotherdir/output/source4.md
: json2md anotherdir/output/../source3.json -o anotherdir/output/source3.md
Using the secondary expansion
Secondary expansion gives you the possibility to use automatic variables in the list of prerequisites. The $$ are needed to escape the first expansion by make.
SOURCE_FILES := $(shell find . -name "*.json")
OUTPUT_FILES := $(join $(dir $(SOURCE_FILES)),\
$(patsubst %.json,output/%.md,$(notdir $(SOURCE_FILES))))
.PHONY: all
all: $(OUTPUT_FILES)
$(sort $(dir $(OUTPUT_FILES))):
mkdir -p $#
.SECONDEXPANSION:
$(OUTPUT_FILES): $$(patsubst %output,%,$$(#D))$$(basename $$(#F)).json | $$(dir $$#)
: json2md $< -o $#
Demonstration:
$ make
mkdir -p output/
mkdir -p anotherdir/output/
: json2md source2.json -o output/source2.md
: json2md source1.json -o output/source1.md
: json2md anotherdir/source4.json -o anotherdir/output/source4.md
: json2md anotherdir/source3.json -o anotherdir/output/source3.md
Note: instead of creating the output directories in the json-to-md rule (which has the drawback of creating them several times), I added them as order-only prerequisites and added a specific rule to create them.
Note: the sort function also removes duplicates.
Using recursive make
Here we invoke make (with always the same Makefile) recursively in each sub-directory (except output, of course). Each invocation handles only the local json files, which makes the paths of prerequisites and targets much simpler.
MF := $(realpath $(lastword $(MAKEFILE_LIST)))
SUB_DIRS := $(filter-out . ./output,$(shell find . -maxdepth 1 -type d))
SOURCE_FILES := $(filter-out $(SUB_DIRS),$(wildcard *.json))
OUTPUT_FILES := $(patsubst %.json,output/%.md,$(SOURCE_FILES))
.PHONY: $(SUB_DIRS) all
all: $(SUB_DIRS) $(OUTPUT_FILES)
$(OUTPUT_FILES): output/%.md: %.json | output
: json2md $< -o $#
output:
mkdir -p $#
$(SUB_DIRS):
$(MAKE) -C $# -f $(MF)
Demonstration:
$ make
make -C anotherdir -f /home/doe/json2md/Makefile
make[1]: Entering directory '/home/doe/json2md/anotherdir'
mkdir -p output
: json2md source4.json -o output/source4.md
: json2md source3.json -o output/source3.md
make[1]: Leaving directory '/home/doe/json2md/anotherdir'
mkdir -p output
: json2md source2.json -o output/source2.md
: json2md source1.json -o output/source1.md
Is it possible to use a makefile that directs the make process itself to chdir? I want to write a makefile that expects to be executed from the build directory.
Suppose I have a project directory structure that looks like this
project/
├── Makefile
├── include
│ └── Foo.h
├── src
│ └── Foo.cpp
└── test
└── FooTest.cpp
and the first thing the make directory does is make a build directory.
project/
├── Makefile
├── _build
├── include
│ └── Foo.h
├── src
│ └── Foo.cpp
└── test
└── FooTest.cpp
Is it possible to direct the makefile to chdir into _build to simplify my rules?
I want to be able to write (for example)
foo : Foo.o
$(LD) $^ -o $# $(LDFLAGS)
rather than
_build/foo : _build/Foo.o
$(LD) $^ -o $# $(LDFLAGS)
I know I can add the build directory to the VPATH in order to affect path resolution, but it seems cleaner to just chdir Make itself. Is there a way to do this (preferably without using guile)?
You can make a simple Makefile that forwards everything:
.DEFAULT_GOAL := all
.PHONY: ${MAKECMDGOALS}
$(filter-out all,${MAKECMDGOALS}) all: .forward-all ; #:
.forward-all:
${MAKE} -C build ${MAKECMDGOALS}
# Never try to remake this makefile.
${MAKEFILE_LIST}: ;
.SUFFIXES:
GNU Make is not capable of doing this, but NetBSD's bmake can do exactly this.
Suppose we have a project with the following structure:
.
├── foo.c
├── makefile
└── obj/
foo.c is a simple C program that depends only on the standard library.
/* foo.c */
#include <stdio.h>
int main() {
printf("%s\n", "hi there");
}
The makefile uses the common subset of GNU Make and bmake. In general, sticking to the common subset is tedious and not worth doing, this is just for the sake of example.
default: foo
.c.o:
$(CC) -c -o $# $<
foo : foo.o
$(CC) -o $# foo.o
Running bmake produces the following output
$ bmake
cc -c -o foo.o /tmp/make-example/foo.c
cc -o foo foo.o
and produces the following directory structure
.
├── foo.c
├── makefile
└── obj/
├── foo
└── foo.o
It's clear from inspecting the output that bmake almost immediately chdired into the obj directory. Paths to outputs in the obj directory are relative and paths inside the source directory are absolute.
I have this rule in my makefile, but make didn't find it:
$(BUILDDIR)%.o : $(BUILDDIR)%.bin
#echo
$(OBJCOPY) -I binary -O elf32-avr --redefine-sym _binary_$*_bin_start=$* --redefine-sym _binary_$*_bin_end=$*_end $< $#
If I make it explicit, make will use them (called for build/rom1.o and build/rom2.o; BUILDDIR=build/)
$(BUILDDIR)rom1.o : $(BUILDDIR)rom1.bin
#echo
$(OBJCOPY) -I binary -O elf32-avr --redefine-sym _binary_rom1_bin_start=rom1 --redefine-sym _binary_rom1_bin_end=rom1_end $< $#
$(BUILDDIR)rom2.o : $(BUILDDIR)rom2.bin
#echo
$(OBJCOPY) -I binary -O elf32-avr --redefine-sym _binary_rom2_bin_start=rom2 --redefine-sym _binary_rom2_bin_end=rom2_end $< $#
Does anyone has a hint whats wrong with the wildcard in my first try?
Edit:
The version of make is 4.1 running on Ubuntu 16.04.
This is the error message from make when trying to run with the wildcard:
make: *** No rule to make target 'build/rom1.o', needed by 'build/rom1.elf'. Stop.
Let's simplify the problem…
If this is your file structure…
.
├── Makefile
└── build
├── rom1.bin
└── rom2.bin
and this is your Makefile…
BUILDDIR := build/
$(BUILDDIR)%.o: $(BUILDDIR)%.bin
touch $#
and you run $ make build/rom{1,2}.o, your resulting file structure will be…
.
├── Makefile
└── build
├── rom1.bin
├── rom1.o
├── rom2.bin
└── rom2.o
I was wondering what different approaches of using Make in a project with subdirectories exist, and what are their advantages/drawbacks, but could never see a good summary or cookbook.
I have seen in my researches mainly the "recursive" and "single makefile" approaches, but are there others ?
I also assume that there is not only one "recursive" or "single makefile" approaches but several, so could somebody sum it up ?
For my particular case, I would like a directory architecture looking like this:
.
├── build
│ ├── *.d
│ ├── *.o
| ├── subdir1
| │ ├── *.d
| │ └── *.o
| └── subdir2
| ├── *.d
| ├── *.o
| └── subdir3
| ├── *.d
| └── *.o
├── include
│ ├── *.h
│ └── *.h
├── Makefile
└── src
├── *.c
├── *.h
├── subdir1
│ ├── *.c
│ └── *.h
└── subdir2
├── *.c
├── *.h
└── subdir3
├── *.c
└── *.h
Which solution should I choose ? Possibly one which would allow source files with the same name ?
Your project setup is really basic, so should be your Makefile:
SRC_DIR := src
BLD_DIR := build
SRC := $(shell find $(SRC_DIR) -name "*.c")
OBJ := $(SRC:$(SRC_DIR)/%.c=$(BLD_DIR)/%.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS := -MMD -MP # enable auto-dependency generation
CFLAGS := -Wall -W -pedantic
.PHONY: all clean
all: $(OBJ)
clean:
$(RM) -r $(BLD_DIR)
.SECONDEXPANSION:
$(BLD_DIR)/%.o: $(SRC_DIR)/%.c | $$(#D)/ # First check that the destination directory exists
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
%/:
mkdir -p $* # -p flag necessary for recursive directory creation
ifeq "$(MAKECMDGOALS)" ""
-include $(DEP)
endif
The idea here is to list source files recursively using the find command, to supply make with the appropriate pattern rule to compile in the right place and pass the right preprocessor file to your compiler to enable auto-dependency generation.
Tested with GNU Make 4.1 under Windows 8.1 with the GIT Bash shell and the following directory structure:
.
├── Makefile
└── src
├── test.c
├── test1.c
└── subdir1
└── test.c
After reading Recursive Make Considered Harmful, I figured a quite simple and modular way to achieve this, by having files in all subdirectories that would include each other and be included in the main makefile:
CXX := gcc
SRCDIR := src
OBJDIR := build
# These lines are needed to set immediate evaluation for
# these variables, instead of deferred evaluation which is unsuitable.
SRCS :=
SUBDIRS :=
CFLAGS :=
LDFLAGS :=
include $(SRCDIR)/module.mk
OBJS := $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
SRCS := $(addprefix $(SRCDIR)/, $(SRCS))
DEPS := $(OBJS:.o=.d)
TMPS := $(OBJS) $(OBJS:.o=.d)
CFLAGS += -MD
debug: CFLAGS += -g -g3 -ggdb
CFLAGS += $(addprefix -I./$(SRCDIR)/, $(SUBDIRS))
LDFLAGS += -lsomelib
debug: LDFLAGS += -g -g3 -ggdb
NAME := yolo
all: $(NAME)
debug: re
-include $(DEPS)
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(NAME): $(OBJS)
#$(CXX) $(OBJS) -o $(NAME) $(LDFLAGS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
#mkdir -p $(OBJDIR)
#for dir in $(SUBDIRS); \
do \
mkdir -p $(OBJDIR)/$$dir; \
done
clean:
rm -rf $(TMPS)
fclean: clean
rm -rf $(NAME)
rm -rf $(OBJDIR)
re: fclean all
.PHONY: all clean fclean re
And in every subdirectory, a module.mk file (I could have named it anything, but this seemde cool).
For src:
SRCS := main.c file1.c file2.c
SUBDIRS += subdir1 subdir2
include $(SRCDIR)/subdir1/module.mk
include $(SRCDIR)/subdir2/module.mk
For a level 1 subdirectory:
THIS_DIR_L0 := subdir1
MOD_SRC := file3.c file4.c
SRCS += $(addprefix $(THIS_DIR_L0)/, $(MOD_SRC))
SUBDIRS += $(THIS_DIR_L0)/subdir3
include $(SRCDIR)/$(THIS_DIR_L0)/subdir3/module.mk
And for a level 2 subdir (one deeper):
THIS_DIR_L1 := subdir3
MOD_SRC := file5.c file6.c
SRCS += $(addprefix $(THIS_DIR_L0)/$(THIS_DIR_L1)/, $(MOD_SRC))
And so on...
This is quite simple to set up, I find it very modular and it does not use recursive makefiles. It would not be complicated to make librairies and stuff inside your directory structure either.
Anybody having a better idea please tell me.