makefile not updating .o file with respectively with .h file - c

I have following make file :-
VER = Debug
CC = gcc
objectfiles = Getstr.o ui.o ustreqsol.o main.o
pkg = `pkg-config --cflags --libs gtk+-3.0`
obj = $(addprefix objs/,$(objectfiles))
../$(VER)/Calculator: $(obj)
$(CC) -o $# $(obj) $(pkg)
./objs/ui.o:ui.c
$(CC) -c -o $# $< $(pkg)
./objs/main.o:main.c
$(CC) -c -o $# $< $(pkg)
./objs/%.o: %.c %.h
$(CC) -c -o $# $<
clean:
-rm ../$(VER)/Calculator
-rm /objs/*
and follwing files in my src dir:-
$ ls
Getstr.c main.c Makefile objs ui.c ui.h ustreqsol.c ustreqsol.h
objs is directory. Whenver I change ustreqsol.h file it compiles ustreqsol.c file but not in case for ui.h file
$ touch ustreqsol.h
$ make
gcc -c -o objs/ustreqsol.o ustreqsol.c
gcc -o ../Debug/Calculator objs/Getstr.o objs/ui.o objs/ustreqsol.o objs/main.o `pkg-config --cflags --libs gtk+-3.0`
$ make
make: '../Debug/Calculator' is up to date.
$ touch ui.h
$ make
make: '../Debug/Calculator' is up to date.
As a noob in makefiles i have no idea why is this happening

The reason ui.c is not being rebuilt is because you explictly said ui.h is not a dependency:
./objs/ui.o:ui.c
$(CC) -c -o $# $< $(pkg)
For the general dependency you have set up:
./objs/%.o: %.c %.h
$(CC) -c -o $# $<
The dependency list only takes effect for files that you didn't explicitly set them for, such as ustreqsol.c.
You need to add targets for each object file specifying the dependencies for each one. The targets can be blank, as the %.o target will fill in what to do.
For example:
./objs/ustreqsol.o: ustreqsol.c ustreqsol.h ui.h
./objs/ui.o: ui.c ui.h
./objs/main.o: main.c ui.h ustreqsol.h
./objs/Getstr.o: Getstr.c
./objs/%.o: %.c %.h
$(CC) -c -o $# $<

Related

"clang: error: cannot specify -o when generating multiple output files" fix

I'm trying to compile my C project using clang (I'm on MacOS Monterry) and a Makefile, but I keep getting the same error from clang in the command line:
> make
gcc -c src/ji.c src/main.c -o src/ji.o
clang: error: cannot specify -o when generating multiple output files
make: *** [src/ji.o] Error 1
These are the only files I have in the project so far:
src/main.c
src/ji.c
include/ji.h
The Makefile looks like this:
cc = gcc
src = $(wildcard src/*.c)
obj = $(src:.c=.o)
exec = ji
$(exec): $(obj)
$(cc) -Iinclude $< -o build/$#
%.o: %.c
$(cc) -c $(src) -o $#
clean:
-rm src/*.o
-rm ji
From YouTube videos I've seen, this should be the ideal Makefile for the project but no matter what I change I get the error.
There are a few issues:
-Iinclude needs to be on the %.o: %.c rule command
In %.o: %.c, we don't want $(src) but rather $<
We want patsubst to get the .o list obj
The $(exec) target doesn't match the -o option
The clean doesn't match the placement of the executable
Here's a refactored version (e.g. one way to do this--there are others):
cc = gcc
src = $(wildcard src/*.c)
obj = $(patsubst %.c,%.o,$(src))
exec = build/ji
$(exec): $(obj)
mkdir -p build
$(cc) $^ -o $#
%.o: %.c
$(cc) -c $< -o $# -Iinclude
clean:
rm -f src/*.o
rm -fr build
Here's the output of make:
gcc -c src/ji.c -o src/ji.o -Iinclude
gcc -c src/main.c -o src/main.o -Iinclude
mkdir -p build
gcc src/ji.o src/main.o -o build/ji
Here's the output of make clean:
rm -f src/*.o
rm -fr build

Multiple targets but same dependency

This is a part of my makefile :
SRC = ./
DIRS = src libs/maths libs/struct
BIN_DIR = ./bin/
SRC_DIRS= $(foreach dir, $(DIRS), $(addprefix $(SRC), $(dir)))
SRC_TEST= $(sort $(SRC_DIRS))
SRCS = $(foreach msrc, $(SRC_DIRS), $(wildcard $(msrc)/*.c))
DEL_PRE = $(foreach target, $(SRCS), $(notdir $(target)))
ADD_PRE = $(foreach target, $(DEL_PRE), $(addprefix $(BIN_DIR), $(target)))
OBJS = $(ADD_PRE:.c=.o)
.PHONY: all clean re
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(OBJS) -o $# $(LDLIBS)
$(OBJS): $(SRCS)
$(CC) -o $# -c $<
When i use make all, i have in output :
gcc -o bin/main.o -c src/main.c
gcc -o bin/cosin.o -c src/main.c
gcc -o bin/pears.o -c src/main.c
gcc -o bin/outil.o -c src/main.c
gcc -o bin/verif.o -c src/main.c
But i would like to have for each target, it assigned dependency :
gcc -o bin/main.o -c src/main.c
gcc -o bin/cosin.o -c libs/maths/cosin.c
gcc -o bin/pears.o -c libs/maths/pears.c
gcc -o bin/outil.o -c libs/struct/outil.c
gcc -o bin/verif.o -c libs/struct/verif.c
How can i fix it ?
This seems like a very common misconception; I just answered effectively this same question yesterday. I'm not sure where it comes from or how to combat it.
This rule:
$(OBJS): $(SRCS)
$(CC) -o $# -c $<
does not somehow magically combine the contents of the OBJS variable and the SRCS variable to figure out how they match up. The variable references are simply expanded, and the result is this:
bin/main.o bin/cosin.o ... : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
which is the same as if you'd written this:
bin/main.o : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
bin/cosin.o : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
...
Now, you can hopefully see why you compile the same file: in every rule you have the same prerequisites, so $< is always the first one, which is always src/main.c.
There are multiple ways to work this but if you really want to have all the source files from different directories compiled into object files in the same directory your job is harder, because there's no common pattern that will match them all. In this case the simplest thing to do is use VPATH for directory search: replace the above rule with this:
$(BIN_DIR)/%.o : %.c
$(CC) -o $# -c $<
then tell make how to find your source files, like this:
VPATH := $(sort $(dir $(SRCS))
Be aware this method can't be used for any source files that are themselves generated output that make is expected to create.

makefile exit with no reason when compile .pc and .c at the same time. very strange

I am using pro*c in AIX,I want make my .pc file compile to a .so libary. And link it. This is my directory:
ls
connect.pc func.c get_log.pc main.c makefile sql_err.pc
This is my makefile:
#Makefile
CC = cc -g -brtl
CFLAGS = -g -c
ESQL = proc
RM = rm -f
MYHOME = /home/xxx
OBJ = main.o func.o
LIBOBJ = get_log.o connect.o sql_err.o
DBINC = -I$(ORACLE_HOME)/precomp/public
DBLIB = -L$(ORACLE_HOME)/lib -lclntsh
INCLUDE = -I$(MYHOME)/include
.SUFFIXES: .pc .c .o
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
clean:
rm -f *.o *.lis
when I make I get this:
.......
cc -g -brtl -o sql_err.o -g -c sql_err.c -I/home/xxx/include -I/oracle/product/10.2.0/precomp/public -L/oracle/product/10.2.0/lib -lclntsh
rm -f sql_err.c
rm -f sql_err.lis
cc -g -brtl -qmkshrobj -o libmydb.so get_log.o connect.o sql_err.o -L/oracle/product/10.2.0/lib -lclntsh
mv libmydb.so /home/xxxlib
when it done mv libmydb.so ,it exit!!!without wrong message.why?? I also need my .c to compile to .o and finally to an executable file query link libmydb.so.
when I change the squeuce like this put .c.o before .pc.o:
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
it give this message,although I have libmydb.so last step:
prepaid(wmfe)/home/xxx/src>make
cc -g -brtl -c -g -c main.c -I/home/xxx/include
cc -g -brtl -c -g -c func.c -I/home/xxx/include
cc -o query main.o func.o -L/home/xxx/lib -lmydb
ld: 0706-006 Cannot find or open library file: -l mydb
ld:open(): A file or directory in the path name does not exist.
make: 1254-004 The error code from the last command is 255.
Stop.
I can't handle this ,very strange,Help!!
By default make will make the first rule in your makefile, but it must not start with a dot. So the default rule in your makefile is libmydb.so and that is being built.
That rule is only dependent on the LIBOBJ and OBJ is not a dependency so it doesn't care about those. It doesn't exit with no reason, it exits because it has done the job you defined for it. There is no error to report.
If you change the order then the default rule is changed and it tries to compile query. This has no dependencies to the library, so it doesn't try to compile that.
If you want to compile everything you should have, for example, a rule all that lists the dependencies. In this case probably libmydb.so and query at least, in correct order. If this is the first rule it will be the default and your compilation will succeed.

Using a Makefile to store object files in two different directories? [C]

I need to modify the Makefile I have to store only the object file associated with "record.c" into the bin folder. Here is what my directory structure looks like before executing Make.
bin/
include/
-hash_table.h
-history.h
-parser.h
-record.h
-shell.h
-variables.h
lib/
obj/
src/
-hash_table.c
-history.c
-parser.c
-record.c
-shutil.c
-sshell.c
-variables.c
...and here is the Makefile:
# Beginning of Makefile
SRC = src/shutil.c src/parser.c src/sshell.c src/history.c src/hash_table.c src/variables.c src/record.c
OBJS = obj/shutil.o obj/parser.o obj/sshell.o obj/history.o obj/hash_table.o obj/variables.o bin/record.o //<----
HEADER_FILES = include/shell.h include/parser.h include/history.h include/hash_table.h include/variables.h include/record.h
EXECUTABLE = sshell
LIBS = lib/libshell.so lib/libparser.so lib/libhistory.so lib/libhash_table.so lib/libvariables.so lib/librecord.so
LIBCFLAGS = $(CFLAGS) -D_REENTRANT -fPIC
CFLAGS = -Wall
CC = gcc
# End of configuration options
#What needs to be built to make all files and dependencies
all: $(EXECUTABLE)
#Create the main executable
$(EXECUTABLE): $(OBJS) $(LIBS)
$(CC) -o $(EXECUTABLE) obj/sshell.o -Llib -lparser -lshell -lhistory -lhash_table -lvariables -lrecord
#Create the library files
lib/libparser.so: obj/parser.o
$(CC) $(LIBFLAGS) -shared $^ -o $#
lib/libshell.so: obj/shutil.o
$(CC) $(LIBFLAGS) -shared $^ -o $#
lib/libhistory.so: obj/history.o
$(CC) $(LIBFLAGS) -shared $^ -o $#
lib/libhash_table.so: obj/hash_table.o
$(CC) $(LIBFLAGS) -shared $^ -o $#
lib/libvariables.so: obj/variables.o
$(CC) $(LIBFLAGS) -shared $^ -o $#
lib/librecord.so: bin/record.o //<----
$(CC) $(LIBFLAGS) -shared $^ -o $#
#Recursively build object files
obj/%.o: src/%.c //<---- I feel like this is causing the problem.
$(CC) $(CFLAGS) -I./include/ -c $< -o $#
#Define dependencies for objects based on header files
#We are overly conservative here, parser.o should depend on parser.h only
$(OBJS) : $(HEADER_FILES)
clean:
-rm -f $(EXECUTABLE) obj/*.o lib/*.so lib/*.a bin/*.o
-rm -f .sshell_history.txt
run: $(EXECUTABLE)
(export LD_LIBRARY_PATH=lib; ./$(EXECUTABLE))
# End of Makefile
With what I have done (most likely completely off) it doesn't compile record.c and says bin/record.o does not exist. I am not really experienced with Makefiles so I am wondering if I can have some help. Thanks!
Try using the rule .c.o instead of obj/%.o: src/%.c
Edit:
If that doesn't work, maybe adding the following rule will do the job:
bin/%.o: src/%.c
$(CC) $(CFLAGS) -I./include/ -c $< -o $#

Cannot make the project when files are located in different folders

I'm trying to build project. There are two directories:
A/
foo.c
foo.h
B/
main.c
Makefile
main.c includes "foo.h". What do i have to write in Makefile to build the project.
I did this
INCLUDE_DIR=../A
LIBS=-lm
CC = gcc
CFLAGS = -c -Wall -I$(INCLUDE_DIR)
default:
#make clean
#make main
sample: main.o foo.o
$(CC) $(LIBS) $? -o $#
main.o: main.c
$(CC) $(CFLAGS) $< -c $%
foo.o: foo.c
$(CC) $(CFLAGS) $< -c $%
clean:
#rm -rf *.o
It cant find foo.c
INCLUDE_DIR=../A
LIBS=-lm
CC = gcc
CFLAGS = -c -Wall -I$(INCLUDE_DIR)
default:
#make clean
#make main
sample: main.o $(INCLUDE_DIR)/foo.o
$(CC) $(LIBS) $? -o $#
main.o: main.c
$(CC) $(CFLAGS) $< -c $%
$(INCLUDE_DIR)/foo.o: $(INCLUDE_DIR)/foo.c
$(CC) $(CFLAGS) $< -c $%
clean:
#rm -rf *.o $(INCLUDE_DIR)/*.o
You need to tell make the relative path to the files.
IIRC you can use
foo.o: ../A/foo.c
$(CC) $(CFLAGS) $< -c $%
but I guess that's not really a solution?

Resources