I'm trying to get started with CuTest to do unit testing in C.
When make-ing, I get the following error:
dev:~/bistro# make
cutest/CuTest.c:10: *** missing separator. Stop.
The file cutest/CuTest.c comes directly from the library. I have done no mods to it. Here are the concerned lines:
08 - #include "CuTest.h"
09 -
10 - /*-------------------------------------------------------------------------*
11 - * CuStr
12 - *-------------------------------------------------------------------------*/
13 -
14 - char* CuStrAlloc(int size)
Here's the Makefile I'm using, for complete reference:
NAME = bistro
SOURCES_DIR = src
OBJECTS_DIR = obj
SOURCES = $(shell find $(SOURCES_DIR) -type f -name *.c) cutest/CuTest.c
OBJECTS = $(patsubst $(SOURCES_DIR)/%.c, $(OBJECTS_DIR)/%.o, $(SOURCES))
DEPS = $(OBJECTS:.o=.d)
CFLAGS = -Wall -Werror -Wextra
COMPILER = gcc -I cutest -I $(SOURCES_DIR) $(CFLAGS)
BISTRO_MAIN = $(OBJECTS_DIR)/bistro/bistro_main.o
.PHONY: test all clean fclean re
all: $(NAME)
# header dependencies
-include $(DEPS)
$(NAME): $(OBJECTS)
$(COMPILER) -o $(NAME) $(OBJECTS)
test: $(filter-out $(BISTRO_MAIN), $(OBJECTS))
$(COMPILER) -c all_tests.c -o all_tests.o
$(COMPILER) -o test $(filter-out $(BISTRO_MAIN), $(OBJECTS)) all_tests.o
rm -f all_tests.o
$(OBJECTS_DIR)/%.o: $(SOURCES_DIR)/%.c
#if [ ! -d "$(#D)" ]; then mkdir -p $(#D); fi
$(COMPILER) -MMD -c $< -o $#
clean:
rm -Rf $(OBJECTS_DIR)/*
fclean: clean
rm -f $(NAME)
re: fclean all
What could be the cause of this error message?
EDIT 1: The makefile is indented with 4-space tabs only. Could the call to the "find" command be the cause of that? Also, how come the error says the missing separator is in the .c file?
EDIT 2: The accepted answer shows the error. In addition, the call did not work because it was searching for *.c, which should be "*.c".
It means you are using (four) spaces instead of tab symbol.
Make target's command must be indented with a tab.
See http://www.gnu.org/software/make/manual/make.html#Rule-Introduction:
Please note: you need to put a tab character at the beginning of every recipe line! This is an obscurity that catches the unwary. If you prefer to prefix your recipes with a character other than tab, you can set the .RECIPEPREFIX variable to an alternate character
Your error comes because you include a C source file into Makefile.
SOURCES = $(shell find $(SOURCES_DIR) -type f -name *.c) cutest/CuTest.c
OBJECTS = $(patsubst $(SOURCES_DIR)/%.c, $(OBJECTS_DIR)/%.o, $(SOURCES)) # cutest/CuTest.c stays cutest/CuTest.c
DEPS = $(OBJECTS:.o=.d)
-include $(DEPS) # oops, includes cutest/CuTest.c
Related
I have made a basic makefile which is supposed to compile my library. It goes like this :
NAME = mylib.a
CC = gcc
FLAGS = -Wall -Wextra -Werror
LIB_SRCS = $(shell find . -type f | grep -F ".c")
LIB_OBJ = $(notdir $(LIB_SRCS:%.c=%.o))
OBJ_DIR = obj/
HEADERS_DIR = ./includes
.PHONY: all
all: $(NAME)
.PHONY: $(NAME)
$(NAME):
#$(CC) $(FLAGS) -c $(LIB_SRCS) -I $(HEADERS_DIR)
#mkdir -p $(OBJ_DIR)
#mv $(LIB_OBJ) $(OBJ_DIR)
#ar rc $(NAME) $(addprefix $(OBJ_DIR), $(LIB_OBJ))
#ranlib $(NAME)
It works pretty well, except that when I use my lib for any project, it recompiles all the files (even when I haven't changed any source from the lib).
I've read this : (Makefile compiles all the files everytime) but it's said I have to create a rule for every source file (or group of source files), which I don't want since there is a lot of source files. I wanted only one rule that compiles file by file.
So I've googled a bit and found a makefile that recompiles only the sources that were modified. And it goes like this :
NAME = mylib.a
CC = gcc
FLAGS = -Wall -Wextra -Werror
INCLUDES = includes/
SRCS_DIR = srcs
OBJ_DIR = obj
ITEMS = $(shell find $(SRCS_DIR) -type f | grep -F ".c" | sed 's/$(SRCS_DIR)//g')
SRCS = $(addprefix $(SRCS_DIR), $(ITEMS))
OBJ = $(addprefix $(OBJ_DIR), $(ITEMS:%.c=%.o))
SRCSUBS = $(shell find $(SRCS_DIR) -type d)
OBJ_SUBDIR = $(SRCSUBS:$(SRCS_DIR)%=$(OBJ_DIR)%)
.PHONY: all
all: $(NAME)
$(OBJ_DIR)/%.o:$(SRCS_DIR)/%.c
#$(CC) $(FLAGS) -o $# -c $< -I $(INCLUDES)
$(OBJ_SUBDIR):
#mkdir $#
.PHONY: $(NAME)
$(NAME): $(OBJ_SUBDIR) $(OBJ)
#ar rc $(NAME) $(OBJ)
#ranlib $(NAME)
It works exactly as expected.
Since I didn't understand everything, I've read about automatic variables and managed to understand almost everything.
I just don't get how the rule that compiles $(OBJ_DIR)/%.o:$(SRCS_DIR)/%.c is called from the $(NAME) $(OBJ_SUBDIR) $(OBJ) rule.
Could anyone explain me how this rule is called since there is no mention to it from the "default" rule called when I execute make command (all: $(NAME)) ?
I was just practising with GNU make and I was trying to write a clean target, the make file is this:
includePath := -I $(CURDIR)
outputDir = $(CURDIR)/output
COMPILER := g++
standard := -std=c++17
#sourceFiles
main.cpp := main.cpp
#output files
binaryPath = $(outputDir)
binary = main.out
#int_binaryPath = intermediate binary
int_binaryPath = $(outputDir)/int_binaries
int_binary = main.o
GPP = $(COMPILER) $(standard) $(includePath)
#print info while make is executing
# $(info $(includeDir) )
VPATH = outputDir/int_binaries $(CURDIR)/glad/src
#build=compile,link and run
$(binary): $(int_binary) glad.c -lGL -lGLU -lglfw -ldl
$(GPP) $(int_binaryPath)/main.o $(CURDIR)/glad/src/glad.c -o $(binaryPath)/$# -lGL -lGLU -lglfw -ldl
$(int_binary): $(main.cpp)
$(GPP) $(main.cpp) -c -o $(int_binaryPath)/$(int_binary)
build: $(binary)
$(binaryPath)/$(binary)
build#bg: $(binary)
$(binaryPath)/$(binary) &
rebuild: clean build
#echo "rebuild successful"
.PHONY: clean
clean:
ifeq($(wildcard $(outputDir)/$(binary)), $(outputDir)/$(binary))
rm -rf $(outputDir)/$(binary)
else ifeq($(wildcard $(outputDir)/$(int_binary)), $(outputDir)/$(int_binary))
rm -rf $(outputDir)/$(int_binary)
endif
now the part that is throwing up error is this:
.PHONY: clean
clean:
ifeq($(wildcard $(outputDir)/$(binary)), $(outputDir)/$(binary)) #this has spaces, line 47
rm -rf $(outputDir)/$(binary) #this has 2 tabs, but even 1 tab didn't work
else ifeq($(wildcard $(outputDir)/$(int_binary)), $(outputDir)/$(int_binary))
rm -rf $(outputDir)/$(int_binary)
endif
now, when I do make clean, it returns the following error:
makefile:47: *** missing separator. Stop.
What exactly am I doing wrong? Why isn't it working and what does the error mean?
You have to have a space between the ifeq and the open paren.
You have other issues; for example there's no comma between words in the wildcard function, so you're literally asking it to look for the file ./output/main.out, (including the ,) exists.
Anyway, this is not needed because rm -rf foo is simply a no-op if foo doesn't exist... you don't need all this complexity.
This is my makefile for a particular C++ project, but when I run make all, I get:
/bin/sh: 1: Syntax error: Unterminated quoted string
Makefile:28: recipe for target '"system' failed
make: *** ["system] Error 2
When I change exe to something with no spaces, it works fine.
EDIT #1: The reason I used quotes was so I could use spaces in the output file name.
cc = g++
exe = "system software version 1.0"
src_dir = src
obj_dir = obj
src = $(wildcard $(src_dir)/*.cpp)
obj = $(patsubst $(src_dir)/%.cpp, $(obj_dir)/%.o, $(src))
libs = -lallegro -lallegro_primitives
include_paths = -I "include" -I "~/allegro5/include/"
lib_paths = -L "/usr/lib/"
flags = -Wall -Wextra -Wpedantic -g -std=c++14
all: $(exe)
play: all
$(exe)
$(exe): $(obj)
$(cc) $(lib_paths) $^ $(libs) -o $#
compile_only: $(obj)
$(obj_dir)/%.o: $(src_dir)/%.cpp
$(cc) $(flags) $(include_paths) -c $^ -o $#
clean:
rm -f $(obj_dir)/*.o
build: all
rebuild: clean build
.PHONY: all clean rebuild
You cannot use paths containing whitespace with make. There are crazy tricks that can make some limited things work, but basically it's simply not supported.
See this recent question and answer: https://stackoverflow.com/a/56411000/939557
Currently I am trying to get a rather big project of mine to work with a Makefile. I used Make before but in a rather crude way and not really "dynamic", this means I am pretty new to good Makefiles.
My Makefile looks like this:
INCLUDE_DIR = /inc
SOURCE_DIR = /src
BUILD_DIR = /build
BUILD_NAME = build
CC = arm-none-eabi-gcc
CFLAGS = -I$(INCLUDE_DIR)
_INCLUDES = main.h pfc.h
INCLUDES = $(patsubst %, $(INCLUDE_DIR)/%, $(_INCLUDES))
_OBJ = main.o pfc.o
OBJ = $(patsubst %, $(BUILD_DIR)/%, $(_OBJ))
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES)
$(CC) -c -o $# $< $(CFLAGS)
$(BUILD_NAME): $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
all: $(BUILD_NAME)
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)/*
When I make the file I get this:
make: *** No rule to make target '/build/main.o', needed by 'build'. Stop.
I guess it is an error in this recipe:
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES)
$(CC) -c -o $# $< $(CFLAGS)
Sadly I am not able to get this done on my own.
All files a available in the correct folders.
I really appreciate all the help!
Tristan
You have a few issues here that I can see. But first off - just check (just incase) that all your rules are only indented with tabs and not spaces..... this can be a real "silent" killer of makefiles as they give crap error messages.
Ok so - lets assume you have:
INCLUDE_DIR = inc
SOURCE_DIR = src
BUILD_DIR = build
instead of /src etc.. as mentioned in the comments.
Do you really have inc/main.h and inc/pfc.h?
I copied and pasted your makefile added your src and inc folders (but I used gcc instead of arm-none-eabi-gcc. It did the compile lines correctly, but failed at the linker stage because you are trying to build an output file called build when there is already a folder called build (not allowed in linux - maybe ok for windows but I don't recommend).
I made an answer for another question - but it might be a better start point then you have here in the case where you have nested src/inc directories and you want to be able to clean your output folders - ill put it here for convenience:
# Get your source list (use wildcard or what ever, but just for clarity you should end up with a list of files with full paths to start with):
# Output folders/targets
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
OUTPUT_FILE = output
# Generate list of source files - this is a linux command - but you can do this in pure make using wildcard and such).
SOURCES := $(shell find $(SOURCEDIR) -name '*.c')
# Create your objects list in the obj directory
OBJECTS = $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(basename $(SOURCES))))
# Create list of unique folders to create
DIRS = $(sort $(dir $(OBJECTS))) $(BIN_DIR)
# Create list of include paths
INCS = $(addprefix -I,$(sort $(dir $(SOURCES))))
# Main target rule
$(BIN_DIR)/$(OUTPUT_FILE): $(OBJECTS) | $(DIRS)
#echo linker: gcc $(OBJECTS) -o $#
#touch $#
# Rule to build your object file - ensure that the folders are created first (also create a dummy obj file) - note this works for parallel builds too (make -j
$(OBJ_DIR)/%.o: %.c | $(DIRS)
#echo compile: gcc $(INCS) -c $? -o $#
#touch $#
# Create your directories here
$(DIRS):
#echo Creating dir: $#
#mkdir -p $#
# Clean if needed
.PHONY: clean
clean:
rm -rf $(OBJ_DIR) $(BIN_DIR)
Note this is just a template, you still need to fill in the gcc/makefile flags - but its a decent start point...
Debugging
$(info ...) is your friend - for example you could do:
$(info OBJ = $(OBJ))
$(info objrule = $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES))
To print our what make has expanded these variables / lines to be - this can yield useful debug.
Here is another version of your makefile with automatic dependency generation:
INCLUDE_DIR := inc
SOURCE_DIR := src
BUILD_DIR := build
CC := arm-none-eabi-gcc
CPPFLAGS := -I$(INCLUDE_DIR)
exes := build
build.obj := main.o pfc.o
all : ${exes:%=${BUILD_DIR}/%}
.SECONDEXPANSION:
${BUILD_DIR}:
mkdir -p $#
# Rule to link all exes.
${exes:%=${BUILD_DIR}/%} : ${BUILD_DIR}/% : $$(addprefix ${BUILD_DIR}/,$${$$*.obj}) | $${#D}
${CC} -o $# ${LDFLAGS} $^ ${LDLIBS}
# Rule to compile C sources. And generate header dependencies.
${BUILD_DIR}/%.o : ${SOURCE_DIR}/%.c | $${#D}
${CC} -o $# -c ${CPPFLAGS} ${CFLAGS} -MD -MP $<
# Include automatically generated header dependencies.
ifneq ($(MAKECMDGOALS),clean)
-include $(foreach exe,${exes},$(patsubst %.o,${BUILD_DIR}/%.d,${${exe}.obj}))
endif
clean:
rm -rf $(BUILD_DIR)
.PHONY: all clean
To add another executable target do:
exes += another
another.obj := another_main.o another_pfc.o
I have a Makefile for a C++ program that uses automatic dependency generation. The %.d recipe is taken from the GNU Make manual.
The problem is that somehow "Makefile" is being added as a target and then an implicit rule is causing it to assume it's an executable and using my src/%.cpp rule to try to compile src/Makefile.cpp. When looking at the debug info, this always happens right after the include is executed.
No need to remake target `build/Sprite.d'.
Considering target file `Makefile'.
Looking for an implicit rule for `Makefile'.
...
Trying pattern rule with stem `Makefile'.
Trying implicit prerequisite `Makefile.o'.
Looking for a rule with intermediate file `Makefile.o'.
I know include causes the given Makefiles to be rebuilt if necessary. Does it also try to rebuild the current Makefile? If so how do I stop it, and if not, then why is "Makefile" being added as a target?
Also, the include is executed, causing the .d files to be remade even if I specify a target on the command line, such as make clean. Is there any way to stop that from happening?
# $(call setsuffix,newsuffix,files)
# Replaces all the suffixes of the given list of files.
setsuffix = $(foreach file,$2,$(subst $(suffix $(file)),$1,$(file)))
# $(call twinfile,newdir,newsuffix,oldfile)
# Turns a path to one file into a path to a corresponding file in a different
# directory with a different suffix.
twinfile = $(addprefix $1,$(call setsuffix,$2,$(notdir $3)))
MAIN = main
SOURCE_DIR = src/
INCLUDE_DIR = include/
BUILD_DIR = build/
SOURCES = $(wildcard $(SOURCE_DIR)*.cpp)
OBJECTS = $(call twinfile,$(BUILD_DIR),.o,$(SOURCES))
DEPENDENCIES = $(call twinfile,$(BUILD_DIR),.d,$(SOURCES))
CXX = g++
LIBS = -lpng
CXXFLAGS = -I $(INCLUDE_DIR)
.PHONY: all
all: $(MAIN)
$(MAIN): $(OBJECTS)
$(CXX) $(LIBS) $^ -o $(MAIN)
include $(DEPENDENCIES)
%.o: $(BUILD_DIR)stamp
$(CXX) $(CXXFLAGS) -c $(call twinfile,$(SOURCE_DIR),.cpp,$#) -o $#
$(BUILD_DIR)%.d: $(SOURCE_DIR)%.cpp $(BUILD_DIR)stamp
# echo Generate dependencies for $ $#.$$$$; \
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)\1.o $# : ,g' $#; \
rm -f $#.$$$$
$(BUILD_DIR)stamp:
mkdir -p $(BUILD_DIR)
touch $#
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
.PHONY: printvars
printvars:
# echo $(SOURCES)
# echo $(OBJECTS)
# echo $(DEPENDENCIES)
Make will always try to remake the Makefile before executing the Makefile. To do so, make will look for rules which can be used to recreate the Makefile. Make will look for quite a few implicit rules and other obscure methods to (re)create the Makefile.
In your case, make somehow decided that the pattern rule %.o: $(BUILD_DIR)/stamp should be used to recreate the Makefile, which failed.
To prevent make from remaking the Makefile you can write a rule with an empty recipe:
Makefile: ;
Read the chapter Remaking Makefiles in the make manual for more explanation.
About the included Makefiles: Included Makefiles will always be included, regardless of the target. If the included makefiles are missing (or older than their prerequisites) then they will first be (re)created. That means a make clean will first generate the .d Makefiles, only to delete them again.
You can prevent the including for specific goals by wraping the include directive in a conditional:
ifneq ($(MAKECMDGOALS),clean)
include $(DEPENDENCIES)
endif
Here is your entire Makefile with some fixes. I marked the places where I changed something.
# Makefile
# $(call setsuffix,newsuffix,files)
# Replaces all the suffixes of the given list of files.
setsuffix = $(foreach file,$2,$(subst $(suffix $(file)),$1,$(file)))
# $(call twinfile,newdir,newsuffix,oldfile)
# Turns a path to one file into a path to a corresponding file in a different
# directory with a different suffix.
twinfile = $(addprefix $1/,$(call setsuffix,$2,$(notdir $3)))
MAIN = main
SOURCE_DIR = src
INCLUDE_DIR = include
BUILD_DIR = build
SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp)
OBJECTS = $(call twinfile,$(BUILD_DIR),.o,$(SOURCES))
DEPENDENCIES = $(call twinfile,$(BUILD_DIR),.d,$(SOURCES))
CXX = g++
LIBS = -lpng
CXXFLAGS = -I $(INCLUDE_DIR)
.PHONY: all
all: $(MAIN)
$(MAIN): $(OBJECTS)
$(CXX) $(LIBS) $^ -o $(MAIN)
# -------> only include if goal is not clean <---------
ifneq ($(MAKECMDGOALS),clean)
include $(DEPENDENCIES)
endif
# ---------> fixed this target <--------------
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp
$(CXX) $(CXXFLAGS) -c $(call twinfile,$(SOURCE_DIR),.cpp,$#) -o $#
# ---------> and this target <---------------
$(BUILD_DIR)/%.d: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp
# echo Generate dependencies for $#;
#set -e; rm -f $#; \
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
$(BUILD_DIR)/stamp:
mkdir -p $(BUILD_DIR)
touch $#
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
.PHONY: printvars
printvars:
# echo $(SOURCES)
# echo $(OBJECTS)
# echo $(DEPENDENCIES)