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

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

Related

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.

Issue when linking with `-lrt` on Mac OSX

On my Mac OSX 10.13, I always use the following makefile to compile C codes:
TARGET = run
LIBS = -O2 -lm -lrt
CC = gcc
.PHONY: default all clean
all: $(TARGET)
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) $(CFLAGS) $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
Note that I use -lrt on purpose because I use #include <aio.h> for some of my codes. Because of that, I keep getting this error:
ld: library not found for -lrt
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [run] Error 1
This error does not show up when running on Linux systems. How do I fix that to be runnable on Mac OSX?

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

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 $# $<

Makefile does not find rule for object

I have a beginner's question about a Makefile. I have a very simple makefile containing:
SHELL = /bin/sh
CC = gcc
CFLAGS = -lm -std=c99 -g -o0
EXEC = test
BUILDDIR = build
OBJDIR = obj
SOURCES = $(shell cat sources.list)
DEPS = $(shell cat headers.list)
OBJ = $(SOURCES:.c=.o)
OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJ))
all: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $(BUILDDIR)/$(EXEC)
$(OBJDIR)/%.o: %.c $(DEPS)
$(CC) -c $< -o $#
clean:
rm -f $(BUILDDIR)/$(EXEC) $(OBJDIR)/*.o
My Problem is, if I try to use this Makefile to compile, it returns the error message:
there is no rule for the target obj/Name.o
What am I doing wrong?
After the first few comments and further research I got to this working Version, but it does not create the object files in the obj folder, so it is not what I aim for
SHELL = /bin/sh
CC = gcc
CFLAGS = -lm -std=c99 -g -o0
EXEC = test
BUILDDIR = build
OBJDIR = obj
SOURCES = $(shell cat sources.list)
DEPS = $(shell cat headers.list)
OBJ = $(SOURCES:.c=.o)
OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJ))
all: $(BUILDDIR)/$(EXEC)
$(BUILDDIR)/$(EXEC): $(OBJ)
$(CC) $(CFLAGS) $(OBJ) -o $(BUILDDIR)/$(EXEC)
%.o: %.c $(DEPS)
$(CC) -c $< -o $#
clean:
rm -f $(BUILDDIR)/$(EXEC) $(OBJDIR)/*.o
Are all the files in headers.list present at the right place ?
By the way, this is not a good way to handle dependencies on headers. You should take a look at -MP and -MDD and other options of your preprocessor to generate dependencies.
A classical makefile which should do what you need:
SHELL=/bin/bash
CC=gcc
CFLAGS=-std=c99 -g -o0
LDFLAGS=-lm
EXEC=test
BUILDDIR=build/
OBJDIR=obj/
SOURCES=$(shell cat sources.list)
OBJECTS=$(patsubst %.c,$(OBJDIR)%.o,$(notdir $(SOURCES)))
vpath %.c $(sort $(dir $(SOURCES)))
.PHONY:all mrproper clean depends
all:$(BUILDDIR)$(EXEC)
$(BUILDDIR)$(EXEC):$(OBJECTS)|$(BUILDDIR)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
$(OBJDIR)%.o:%.c|$(OBJDIR)
$(CC) -c $< -o $#
$(BUILDDIR) $(OBJDIR):
mkdir $#
mrproper:clean
rm -f $(BUILDDIR)$(EXEC)
clean:
rm -f $(OBJECTS)
depends:
#rm -f dependencies.mk
#for i in $(SOURCES); do $(CC) -MM $$i -MT $(OBJDIR)`basename $$i | sed s:.c$$:.o:` >> dependencies.mk; done
include $(wildcard dependencies.mk)
If something is not clear, let me know.
Usage:
make depends
make

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.

Resources