Makefile: Error referencing source files in "src" directory - makefile

[edit]- The answer is I have incorrectly defined the path to the include directory. Embarrasing mistake.
I am writing a makefile that builds objects from .c files in a src directory with headers in an include directory and stores them in an obj directory, and then builds and exe from those objects. A toy version is below.
# Makefile
IDIR = ../include
CC = gcc
CFLAGS = -I$(IDIR) -Wall
SDIR = src
ODIR = obj
_SOURCES = main.c aux1.c aux2.c aux3.c
SOURCES = $(patsubst %,$(SDIR)/%,$(_SOURCES))
_OBJECTS = $(_SOURCES:.c=.o)
OBJECTS = $(patsubst %,$(ODIR)/%,$(_OBJECTS))
_DEPS = aux1.h aux2.h aux3.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
EXE = exefile
$(ODIR)/%.o: $(SDIR)/%.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$(EXE): $(OBJECTS)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm *o $(EXE)
The directory the makefile is in looks like this (when you ls)
include Makefile obj src trash
When I type make, I get the following error
make: *** No rule to make target `obj/main.o', needed by `exefile'. Stop.
I suspect the problem is with this line
$(ODIR)/%.o: $(SDIR)/%.c $(DEPS)
I am attempting to build each object file in obj/ by referencing the corresponding source file in src/ but the line seems do to something else. Is this the case? Is there an easy way to reference .c files in the source directory without "entering" the directory?
Thanks in advance

I believe your problem is the $(DEPS) dependency.
You set IDIR to ../include but from the toplevel directory (where make is run from) that path is incorrect.

Related

Makefile does not find rules despire of available files

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

Understanding and modifying slightly this makefile

I have been editing this makefile but it's mostly trial and error.
Basically I have n .c files in the same directory. I want the first one (that has a fixed name) to be compiled and linked using my makefile hacks, that incorporate different .o files in the linking step, and all the other ones to be compiled and linked using only the LIBS (without the other .o files).
This is the 'main' makefile:
MAKEFILE_BASE = ./Build-Assets/Makefile
MAKEFILE_CONTROLLERS = ./Controllers/Makefile
.PHONY: default clean release release-clean
default: release
clean: release-clean
release:
$(MAKE) -f $(MAKEFILE_CONTROLLERS) # This generates the .o files, and it works well
$(MAKE) -f $(MAKEFILE_BASE).Release
release-clean:
$(MAKE) -f $(MAKEFILE_BASE).Release clean
And this is the 'Makefile.Release' that handles the compilation/linking of those .c files.
TARGET = $(notdir $(shell pwd))
LIBS = -lm -lev3dev-c -pthread
D_BIN = Build-Assets
ifeq ($(OS),Windows_NT)
LIBS := $(LIBS) -lws2_32
D_BIN := $(D_BIN)/mingw
endif
D_H = ../../source/ev3
CFLAGS = $(addprefix -I, $(D_H)) -O2 -std=gnu99 -W -Wall -Wno-comment
ifeq ($(OS),Windows_NT)
CC = gcc
else
CC = arm-linux-gnueabi-gcc
endif
ifeq ($(OS),Windows_NT)
E_BIN = .exe
else
E_BIN =
endif
F_BIN = $(TARGET)$(E_BIN)
OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard *.c))) $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard Controllers/*.c)))
.PHONY: default all clean
default: $(F_BIN)
all: default
$(OBJECTS): $(D_BIN)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(F_BIN) $(OBJECTS)
$(F_BIN): $(OBJECTS)
$(info VAR is $#)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f $(D_BIN)/*.o
-rm -f $(F_BIN)
This also gives the output file the name of the main folder (though I don't understand where he does that?).
When linking this throws the 'multiple main' error (I don't have the ARM device at hand, so I can't provide the full error).
This is the folder hierarchy so that hopefully I can solve all your doubts..
# Main folder (This is the name that the compiled exe has)
## Controllers
-- .c & .h files
-- Makefile
## Build-Assets
-- all .o go here to clean up the folders
- Makefile (The one I call)
- main.c (this needs to be compiled with the .o in build-assets, name can be either main or main folder)
- gcheck.c (this needs to be compiled with only the LIBS, name of executable should be filename)
- ... other .c files, same as gcheck.c
Regarding "where the target name as the name of the directory" comes from, it's here:
TARGET = $(notdir $(shell pwd))
This runs the shell command pwd to get the full path of the current directory, then uses notdir to strip off the parent directory. Then the rule to link the executable uses this:
F_BIN = $(TARGET)$(E_BIN)
...
$(F_BIN): $(OBJECTS)
Regarding why you get multiple main errors, it's because you added your new .c file with the new main to the same directory and rather than the makefile listing a specific set of source files to compile and link, it uses wildcard to grab all the source files:
OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard *.c))) $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard Controllers/*.c)))
These $(wildcard *.c) functions will expand to all the *.c files in these directories including any new ones you added. Then they will all be linked into the target, which gives you two different object files containing main.
You'll have to change this to list just the files you want, or put your files somewhere else, or remove your files from the list using make's filter-out function, or something like that.

makefile .mod compilation rule

I'm modifying makefile of a code. After compiling, I see that some *.mod files are generated. looking online, I figured out they are module files, but I don't see a compilation rule for them. I'm trying to change the directory in which these files are generated. I can change the rule for object files, but I can't find the rule that generates *.mod files.
Looking at the makefile, can someone advise me if a line in this file generates them or how to change their directory. Here is the makefile:
# GNU Makefile
# Paths
SDIR=./solver
ODIR=./obj
_CASE=./WorkCases/problem
CASE=$(SDIR)/$(_CASE)
TOP = .
FC = ifort
FFLAGS = -fpp -O1 -DPTR_INTEGER8 -warn nousage
# Define rule to make .f90
$(ODIR)/%.o : $(SDIR)/%.f90
$(FC) -c $(FFLAGS) $< -o $#
# set executable name
EXEC = $(dir ${CASE})/$(basename $(notdir ${CASE})).out
# shared global variables
_SHARED_OBJ = shared_modules.o main_vars.o debug_vars.o
SHARED_OBJ = $(patsubst %,$(ODIR)/%,$(_SHARED_OBJ))
OBJ = ${_SHARED_OBJ} $(_CASE).PARAMS.o
OBJ = $(patsubst %,$(SDIR)/%,$(_OBJ))
MAIN_OBJ = $(ODIR)/main.o
main : ${SHARED_OBJ} $(OBJ) $(MAIN_OBJ)
$(FC) ${FFLAGS} $(OBJ) $(MAIN_OBJ) -o $(EXEC) -lstdc++ -shared-intel
You can specify the destination directory for the .mod files by using the -module compiler option.
-module <directory>
See the ifort documentation here:
You can use the module path compiler option to specify the directory
in which to create the module files. If you do not use this option,
module files are created in the current directory.

Makefile doesn't find source files

I have tried to make a makefile. I have the following folder structure.
Source
- include
- My headerfiles
- objects
- The object files
- src
- My source files
My problem is that the source files in the src directory isn't found.
My make file looks as the following.
# gcc for C
# g++ for c++
CC = gcc
#compiler flags
# -g adds debugging information to the executebells
# -Wall
CFLAGS = -g -Wall
#target
TARGET = gabe_the_dog_server
#directory for the object files
OBJDIR = ./objects
SRCDIR = ./src
default: $(TARGET)
all: default
HEADERS = $(wildcard include/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) $(CFLAGS) $(LIBS) -o $(OBJDIR)/$#
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
Here:
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
You use the variable SOURCES, but you never define it. You need one more line:
SOURCES = $(wildcard $(SRCDIR)/*.c)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
Instead of using the path to your source files, it's recommended that you put this path in the special variable named VPATH. Then you just mention your source file, like this:
OBJDIR = ./obj
SRCDIR = ./src
VPATH = $(SRCDIR)
OBJECTS = $(addprefix $(OBJDIR)/, foo.o bar.o)
all: $(OBJECTS)
$(OBJDIR)/%.o: %.c
$(cc) ...
GNU make will look in the folders present in VPATH for the files that are prerequisites of a target. Note that this could be a problem if you have multiple folders where you can find multiple times the same file name.
See GNU make VPATH manual. If you need additional examples of VPATH good practices, see this link as well: Mad Scientist: How not to use VPATH

Makefile: Compiling from directory to another directory

I am trying to use Makefile to compile a bunch of .cpp files located in src/code/*.cpp, then compile each *.o in build/, and finally generate executable with those in build/ as well.
I have read a couple answers that I tried to work with but have encountered issues I do not understand.
CC = g++
FLAGS = -g -c
SOURCEDIR = /src/code
BUILDDIR = build
EXECUTABLE = DesktopSpecificController
SOURCES = $(wildcard src/code/*.cpp)
OBJECTS = $(patsubst src/code/*.cpp,build/%.o,$(SOURCES))
all: dir $(BUILDDIR)/$(EXECUTABLE)
dir:
mkdir -p $(BUILDDIR)
$(BUILDDIR)/$(EXECUTABLE): $(OBJECTS)
$(CC) $^ -o $#
$(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp
$(CC) $(FLAGS) $< -o $#
clean:
rm -f $(BUILDDIR)/*o $(BUILDDIR)/$(EXECUTABLE)
I do get the following error, and I am not sure why:
Makefile:19: target `src/code/main.cpp' doesn't match the target pattern
I also see that when trying to build the EXECUTABLE, it is not using the .o files, so it seems my rule is wrong here.
Your patsubst function is wrong; you can't use shell wildcard characters like *. You want:
OBJECTS = $(patsubst $(SOURCEDIR)/%.cpp,$(BUILDDIR)/%.o,$(SOURCES))
Also you should be using SOURCEDIR and BUILDDIR everywhere, not just in some places (otherwise you'll get inconsistencies). And finally, your SOURCEDIR value is wrong: it should not start with / I expect:
SOURCEDIR = src/code
SOURCES = $(wildcard $(SOURCEDIR)/*.cpp)

Resources