Set Option in MakeFile to send object files to specific Folder - c

I made a test makefile using an online tutorial. It works, but I also want to have all of my .o files go to a specific sub-folder. Is there a way to do this using a makefile? Here is what I have so far.
CC=gcc # specifies the compiler to use.
CFLAGS=-I. # specifies to look in the current directory.
DEPS = path_tools.h # DEPS stores each .h file to be added.
OBJ = checkpath.o path_tools.o # OBJ stores each object file to compile.
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
checkpath.exe: $(OBJ)
gcc -o $# $^ $(CFLAGS)

For GNU make you can use this Makefile.
ODIR:=obj
CC:=gcc
CFLAGS:=-I.
DEPS:=path_tools.h
OBJ_:= checkpath.o path_tools.o
OBJ:=$(addprefix $(ODIR)/, $(OBJ_))
PROG=checkpath.exe
all:$(PROG)
$(OBJ): $(DEPS)
$(ODIR)/%.o: %.c
$(CC) -c -o $# $&lt $(CFLAGS)
$(PROG): $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
clean:
rm -f $(OBJ) $(PROG)

You can pass the path of your folder to makefile to create and put the results in.
To pass parameter to makefile:
make DPATH=your-path
To use in makefile:
$(DPATH)
Create this path and add it to head of your *.o files as a path.

Related

Makefile how to use logical OR between prerequisites?

My source files are organized nicely in a folder, that contains subfolders, that also contains source files.
The subfolders don't branch any further.
All object files are just meant to be created and stored in the same folder.
I don't want to manually list the name of the subdirs in the prerequisites when writing the target that generates my object files:
Right now this works:
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -c $< -o $# $(CFLAGS)
$(OBJ)/%.o: $(SRC)/$(subdir1)/%.c
$(CC) -c $< -o $# $(CFLAGS)
$(OBJ)/%.o: $(SRC)/$(subdir2)/%.c
$(CC) -c $< -o $# $(CFLAGS)
...
But I want it to look something like this:
$(OBJ)/%.o: $(SRC)/%.c OR $(SRC)/*/%.c
$(CC) -c $< -o $# $(CFLAGS)
I understand that the title most likely isn't the real question to be asked, but I'm looking for any solution. Also, I know that the * doesn't work as a placeholder here.
First, you can simplify the makefile you have by using vpath:
$(OBJ)/%.o: %.c
$(CC) -c $< -o $# $(CFLAGS)
vpath %.c $(SRC) $(SRC)/$(subdir1) $(SRC)/$(subdir2)
Then, if you really don't want to specify the subdirectories:
vpath %.c $(shell find $(SRC) -type d)

How do I get a makefile to compile multiple sources?

I would like my makefile to compile two sources, osmprun.c and echoall.c.
Currently it's just compiling osmprun.c, which creates errors.
Im at my wits end, Im not experienced with makefiles at all and I just don't understand what im doing wrong.
My makefile is:
CC=gcc
CFLAGS= -Wall -Wconversion -g
LIBS=-lm -lpthread
DEPS=
BUILD_DIR := build
SRCS := osmprun.c echoall.c
OBJS := $(addprefix $(BUILD_DIR)/,$(patsubst %.c,%.o,$(SRCS)))
$(BUILD_DIR)/%.o: %.c $(DEPS)
mkdir -p $(BUILD_DIR)
$(CC) -c $(CFLAGS) $< -o $#
echoall: $(OBJS)
mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $< $(LIBS) -o $#
osmprun: $(OBJS)
mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $< $(LIBS) -o $#
.PHONY: clean
clean:
rm -f $(BUILD_DIR)/*.o *~ core
test:
./osmprun
Can somebody help me figure out my mistake and explain what the problem is?
EDIT:
I've now changed the part where it is supposed to compile the two files to:
echoall: echoall.c
$(CC) $(CFLAGS) $^ $(LIBS) -o $#
osmprun: osmprun.c
$(CC) $(CFLAGS) $^ $(LIBS) -o $#
But it is still only compiling echoall, not osmprun
It would help greatly if you included the command you typed and the output you got, and what you wanted to get, especially because your terminology is not quite accurate. It's not true that make is not compiling all the object files. The problem is at the link stage.
However, I don't understand what your makefile is intended to do. You have two targets and they both depend on the SAME set of object files:
echoall: $(OBJS)
osmprun: $(OBJS)
Do you need to link both of those object files together? If so then what is the difference between the echoall program and the osmprun program, if they both contain the same set of object files?
Or, do you want to create the echoall program from the echoall.c source file and the osmprun program from the osmprun.c source file? If so, why do you list both objects as a prerequisite for both programs?
In any event your problem is here:
echoall: $(OBJS)
mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $< $(LIBS) -o $#
osmprun: $(OBJS)
mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $< $(LIBS) -o $#
(the mkdir here are useless: you know that the directory already exists because you already built the object files, but they don't hurt anything).
The problem is you're using $< which is the first prerequisite. Because both prerequisite lists are the same, you're building both programs from the same, single source file.
If you want both programs to contain both object files, you should use $^ here not $<. If you want each program to contain only its related object file, you should change the prerequisites to contain only the object file it should be built from (and also use $^).

Makefile not compiling all C files in directory

Iam working with gcc and MinGW on a Windows platform. I have a directory containing two *.c files:
main.c and funcs.c
I am using the following makefile:
CC=gcc
CFLAGS=-c
LDFLAGS=
SOURCEDIR = src
BUILDDIR = build
SOURCES=$(wildcard $(SOURCEDIR)/*.c)
OBJECTS=$(patsubst $(SOURCEDIR)/%.c,$(BUILDDIR)/%.o,$(SOURCES))
LIBRARIES=-L/mingw64/lib
INC= -I./include
EXECUTABLE=testLink
VPATH = src include build
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBRARIES) -o ./dist/$#
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
Which should take the *.c files and generate *.o files with the same name. However I get the following output on make -
$ make
gcc -I./include -c src/funcs.c -o build/funcs.o
gcc -I./include -c src/funcs.c -o build/main.o
gcc build/funcs.o build/main.o -L/mingw64/lib -o ./dist/testLink
followed of course by a bunch of multiple definition errors. As you can see from the first two lines it is taking the same *.c file and compiling it twice into two different *.o files.
I am new to makefiles but I assume it is something wrong with my $(OBJECTS) rule and I'm pretty sure it's the $< which is causing the problem. I'm trying to create a generic makefile which will always work on my projects which have the same directory structure and take .c files turn them into .o files and link. Am I going about this entirely the wrong way or is there a simple fix to my makefile?
Thanks!
James
This rule:
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
expands to:
funcs.o main.c: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
which is equivalent to:
funcs.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
main.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
$< refers to the first dependency (funcs.c) so your Makefile is trying to generate both funcs.o and main.o from the same source.
You just want a generic rule using % wildcard matching:
%.o: %.c
$(CC) $(INC) $(CFLAGS) $< -o $#
See https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html
Jeff pointed the mistake in his answer (all objects depend on all sources: that isn't a generic compilation rule for c sources).
However, the generic rule must have source & object paths. To sum it up, just replace
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
by
$(BUILDDIR)/%.o : $(SOURCEDIR)/%.c
$(CC) $(INC) $(CFLAGS) $< -o $#
(as explained in How to generate a Makefile with source in sub-directories using just one makefile)
note that this kind of dependency test doesn't take included .h files into account, so it's only intended for first builds. Modifying .h files afterwards doesn't trigger a compilation since the header files are not listed as dependencies.

How to create reference to an .o file in Makefile

I was given two .o files with corresponding .h files to use for an assignment, but I do not know how to get the compiler to use the .o files. This is the Makefile I am currently using:
TARGET = prog
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
I believe I need to add the file1.o and file2.o at the end, but I am not sure if that is right. I do have the .h files in the C source files when appropriate, so the only reason that I can think of for the compilation error is that the .o files are not being compiled with my code.
Add a define for the provided .o's (e.g.):
PREBUILT_O = fludger.o ramble.o plexor.o
Change your target rule to:
$(TARGET): $(OBJECTS) $(PREBUILT_O)
$(CC) $(OBJECTS) $(PREBUILT_O) $(LIBS) -o $#
The compiler doesn't use your .o files. The linker does.
Your link step needs to be
$(TARGET) : $(OBJECTS)
$(LD) $(OBJECTS) $(LIBS) -o $#
(Very possibly missing some other linker flags, but that's the crux of your problem)
Also, you probably don't want the clean step to delete all the .o files since you're provided with at least two of them.

Makefile doesn't rebuild objects on header modification

I have made a Makefile for compiling my C programm but it's not building object when i change one of the headers.
My MakeFile:
CC=gcc
CFLAGS=-O3 -Wall
LDFLAGS=-I/usr/include/mysql -L/usr/lib/x86_64-linux-gnu -lmysqlclient
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=bin/beta_parser
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) -o $# $^ $(CFLAGS) $(LDFLAGS)
%.o:%.c types.h cstes.h headers.h mysql.h
$(CC) -o $# -c $< $(CFLAGS)
.PHONY: clean mrproper
clean:
rm -rf *.o
mrproper:
rm -rf $(EXEC)
What have I done wrong ?
EDIT : Corection of the Makeil after a great comment.
Although there are other more elegant tricks, in your case, I think something like
$(OBJECTS): types.h cstes.h headers.h mysql.h
%.o: %.c
$(CC) -o $# -c $< $(CFLAGS)
should be sufficient.
Scanning your sources for dependencies is outside the scope of Make (although there are other tools, such as CMake which will do this automatically). You need to add an explicit rule to generate these dependencies, but this can be done in many different ways. I've sometimes used the following technique:
OBJECTS = ....
-include $(OBJECTS:.o=.d)
...
$(OBJECTS): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(CC) $(CFLAGS) $(DEPFLAGS) $< > $*.d
Google for "make automatic dependency generation" will show you other ways to do it as well.

Resources