makefile: search for files in subdirectories - makefile

So I have a GCC command for which I want to use a SIMPLE makefile. Never worked on makefile before and still having problems after referring the tutorial.
So the command on terminal is
link4#link4-VirtualBox:~/link4/G2/G2 module/src$ gcc -I.src/L4COMM -I.src/L4SERIAL -I.src/L4SYSTEM -I.src/main.c -I.src/L4COMM/l4comm.c -I.src/L4SERIAL/l4serial.c ./src/bypass.c ./src/input.c
This works fine, but when I create a makefile, I'm unable to make it search for the files 'l4comm.c and l4serial.c' which are in src/L4COMM and src/L4SERIAL respectively.
This is what my makefile looks like:
CC =gcc
INCLUDE = -I/src/L4COMM \
-I/src/L4SERIAL
VPATH = -I/src/L4COMM \
-I/src/L4SERIAL
cfiles := $(patsubst %.c, %.o, $(wildcard *.c))
hfiles := $(patsubst %.h, %.o, $(wildcard *.h))
g2make: $(cfiles)
$(CC) $(INCLUDE) -o main.c l4comm.c l4serial.c bypass.c input.c
Want the makefile to look for files in the sub directories
Just as I used the 'cfiles/hfiles' to check for changes, I want to wildcard to also check for the files in the sub directories.
Help appreciated! :)

You can use this g2make:
$(CC) $(INCLUDE) -o .src/main.c ./src/L4COMM/l4comm.c ./src/L4SERIAL/l4serial.c ./src/bypass.c ./src/input.c

Related

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.

Make: wildcard to use all object files

I have a Makefile that looks like this:
CC=cc
CFLAGS=-g -std=c99 -Wfatal-errors
OBJS=$(wildcard *.o)
all: main.o cmdargs.o io.o
$(CC) -o app $(OBJS)
main.o: main.c
$(CC) -c main.c $(CFLAGS)
cmdargs.o: cmdargs.c
$(CC) -c cmdargs.c $(CFLAGS)
io.o: io.c
$(CC) -c io.c $(CFLAGS)
clean:
#rm -rf app $(OBJS)
Whenever I run make all after a clean, there's an error saying
cc -o
undefined reference to `main'
But when I run it a second time everything works as expected. What is wrong with the script, and how can we fix it?
The previous respondents gave good answers but not complete. So let me post one too.
First of all, it is a bad idea to use wildcard in makefiles. It is much better to not be lazy and list your files explicitly.
If you must be lazy, the way to use wildcard is, as shawncorey writes, to use it for sources.
Also, do not have a recipe for phony targets such as all. In your example, the recipe for all will always run, which is inefficient.
CC := gcc
SRCS := $(wildcard *.c)
OBJS := $(SRCS:c=o)
.PHONY: all clean
all: app
app: $(OBJS) Makefile
$(CC) -o $# $(OBJS)
$(OBJS): %.o: %.c Makefile
$(CC) -c $< $(CFLAGS)
clean:
#rm -rf app $(OBJS)
You can automatically create the names of the objects files if you're careful about including all the source files.
# --------------------------------------
# list all source files
CPP_SOURCES := $(wildcard *.cpp)
C_SOURCES := $(wildcard *.c)
# other source files here
# consolidate all sources
SOURCES := $(CPP_SOURCES) $(C_SOURCES)
# --------------------------------------
# list all object files
CPP_OBJECTS := $(CPP_SOURCES:.cpp=.o)
C_OBJECTS := $(C_SOURCES:.c=.o)
# other object files here
# consolidate all objects
OBJECTS := $(CPP_OBJECTS) $(C_OBJECTS)
all:
echo $(SOURCES)
echo $(OBJECTS)
PS: A more compact makefile:
# list all source files
SOURCES := $(wildcard *.cpp) $(wildcard *.c)
# determine all object files
OBJECTS := $(addsuffix .o, $(basename $(notdir $(SOURCES))))
all:
echo $(SOURCES)
echo $(OBJECTS)
The statement
OBJS=$(wildcard *.o)
collects all the *.o files currently in the file system, but it doesn't know about any object files that might be created in the future.
When you run make for the first time, there are no .o files around, so the variable OBJS will be an empty string and the final linking command does not get passed into the command that would tell it which object files to use. But all the other compilation steps are run nevertheless. Upon the second invocation make will skip the compilation phases, because the object files are already there, but because linking failed and the final binary is missing, it will run that step, which will now produce something, because there have been files to collect by the wildcard.
Lesson learned: Don't use file system wildcards in Makefile, it's just causing trouble. Instead learn about implicit rules if you want to save yourself from work.

How to have a sometimes empty dependency in makefiles?

I have the following rule:
EXECS = $(sort $(patsubst %.cpp,%$(EXESUFFIX), $(patsubst %.c,%$(EXESUFFIX), $(filter-out $(IGNORESRCS), $(EXECSRCS)))))
SRCS = $(sort $(filter-out $(EXECSRCS), $(filter-out $(IGNORESRCS), $(wildcard *.c) $(wildcard *.cpp) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.cpp) $(wildcard $(DIR)/*.c) ) )))
#OBJS = $(addprefix $(OBJDIR), $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS))))
OBJS = $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS)))
RESOURCE_SRCS= $(sort $(filter-out $(IGNORESRCS), $(wildcard *.rc) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.rc) ) ))
RESOURCES = $(patsubst %.rc,%$(OBJSUFFIX), $(RESOURCE_SRCS))
%$(EXESUFFIX) : %.cpp $(LIBS) $(RESOURCES)
$(CXX) $(DEFINES) $(CFLAGS) $(INCLUDES) $(LIBPATH) -o $(BINDIR)/$* $< $(RESOURCES) $(LIBINCLUDES)
The problem is that $(RESOURCES) doesnt exist for all platforms. The %$(EXESUFFIX) : %.cpp rule doesnt run, instead it tries to run g++ exec.cpp -o exec which as far as I can tell isnt a rule that I declared anywhere.
How do I get the rule to still build despite the fact that it is empty (and build the resources if it is not empty)?
If the variable is empty it has no effect on the rule. It should just work as written. What is the actual error you're seeing?
ETA:
Your question is very unclear in what, exactly, you mean by $(RESOURCES) doesn't exist. My answer was assuming you meant that the variable was empty. But given your comment below about how the makefile behaves, I now suspect what you mean is that the variable is still set to a list of files, but that those files are not present.
Because they're not there, and make doesn't know how to build them, make decides that this pattern rule cannot be used at all and it chooses a different rule.
If you want these files to only have any impact if they exist, then you can use the $(wildcard ...) function to expand only to those files that exist:
%$(EXESUFFIX) : %.cpp $(LIBS) $(wildcard $(RESOURCES))
$(CXX) ...
One critical point here: the contents of $(RESOURCES) MUST be source files. They cannot be derived files (files that are supposed to be created by make). If they are derived, the situation is far more complex.

Automatic makefile with source and object files in different directories

I'm attempting to put together a makefile that will take source files from a directory (eg. src), compile them into object files in another directory (eg. build), and then take those files and create a static library from them in the main directory.
Here's my effort so far:
LIBNAME := test
LIBNAME := lib$(LIBNAME).a
CC = g++
CFLAGS := -O0 -Wall -g -fPIC
INCLUDE := include
SOURCE := src
BUILD := build
CPPFILES := $(foreach dir, $(SOURCE)/, $(notdir $(wildcard $(SOURCE)/*.cpp)))
OBJFILES := $(addprefix $(BUILD)/, $(CPPFILES:.cpp=.o))
all: $(LIBNAME) $(OBJFILES)
$(LIBNAME): $(OBJFILES)
ar rcs $(LIBNAME) $(OBJFILES)
.cpp.o:
$(CC) $(CFLAGS) -I$(INCLUDE) -c $< -o $#
clean:
rm -rf $(BUILD)
Which gives me this:
make: *** No rule to make target `build/point.o', needed by `libtest.a'. Stop
You seem do be requiring GNU make anyway (foreach function), so rewriting the old-style suffix rule .cpp.o to
$(BUILD)/%.o : $(SOURCE)/%.cpp
should do the trick. You might also try using the VPATH variable or the vpath directive, see the make manual for these.
In general, you might just tackle this problem with automake, which does most of this stuff for you.

Makefile - Generate Targets from Sources

I'm trying to build a growing number of .cpp files with the use of make. They all reside in a subdirectory src/. I want to compile each file into it's own executable, residing in bin/.
This is what I have tried so far, but it doesn't work, and since I'm new to make, all the Patterns, Variables etc. make it difficult to pinpoint what gets expanded into what and so on.
CXX = g++
CXXFLAGS = -Wall -Wextra -pedantic
SRC = $(wildcard src/*.cpp)
BIN = $(patsubst src/%.cpp,bin/%,$(SRC))
all: $(BIN)
%: scr/%.cpp
$(CXX) $(CXXFLAGS) $< -o $#
Also, is there a way to show just the contents of BIN for example to allow me to see what is going on?
This is what your final expansion looks like
file: scr/bin/file.cpp
Why not do this?
BIN = $(patsubst src/%.cpp,%,$(SRC))
all: $(addprefix bin/, $(BIN))
bin/% : src/%
$(GCC) $(FLAGS) $< -o $#
I think that works?
As for showing the contents of BIN
all: $(addprefix bin/, $(BIN))
#echo $(BIN)

Resources