gcc builds with -o but not -o3? - c

My Makefile looks like this:
CC=gcc
CFLAGS=-Wall -Wextra -std=c99 -pedantic
OBJECTS=main.o Scene.o Matrix.o Vector.o Triangle.o Color.o Raster.o
render: $(OBJECTS)
$(CC) $(CFLAGS) -lm -o render -g $(OBJECTS)
rm $(OBJECTS)
clean:
rm -f render*
This builds my executable with no errors, but when I change -o to -o2 or -o3, I get the error:
gcc -Wall -Wextra -std=c99 -pedantic -c -o main.o main.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Scene.o Scene.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Matrix.o Matrix.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Vector.o Vector.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Triangle.o Triangle.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Color.o Color.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Raster.o Raster.c
gcc -Wall -Wextra -std=c99 -pedantic -lm -o3 render -g main.o Scene.o Matrix.o Vector.o Triangle.o Color.o Raster.o
gcc.exe: error: render: No such file or directory
make: *** [render] Error 1
There could be some error in my code detected by the optimization flags, but as I don't get any error messages before this it's hard to know what's going wrong. I'm using MinGW/MSYS on Windows 7.

-o render means create the output file with the name render.
Now you are changing this -o to -o3 which is incorrect. Instead you need to keep -o render as it is and add a -O3 flag for optimization. Note the capital letter O.

-o is the output file flag. You were thinking of -O (capital).

Related

C, Refactoring Makefile

My makefile works however if I erase debutliste.o lecturefichier.o statistiques.o tri.o
from the target compile, it still works I imagine bc they are done in the other .o targets.
Make: link
compile: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
listechainee.o: listechainee.c listechainee.h debutliste.o
gcc -g -Wall -Wextra -std=c11 -c listechainee.c
debutliste.o: debutliste.c debutliste.h lecturefichier.o
gcc -g -Wall -Wextra -std=c11 -c debutliste.c
lecturefichier.o: lecturefichier.c lecturefichier.h statistiques.o
gcc -g -Wall -Wextra -std=c11 -c lecturefichier.c
statistiques.o: statistiques.c statistiques.h tri.o
gcc -g -Wall -Wextra -std=c11 -c statistiques.c
tri.o: tri.c
gcc -g -Wall -Wextra -std=c11 -c tri.c
clean:
rm -rf *.o
link: compile
gcc *.o -o tri
If I understand correctly I should delete the debutliste.o lecturefichier.o statistiques.o tri.o that are inside the .o targets bc they will be executed as dependencies from the target compile and it should look like this?
Make: link
compile: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
listechainee.o: listechainee.c listechainee.h
gcc -g -Wall -Wextra -std=c11 -c listechainee.c
debutliste.o: debutliste.c debutliste.h
gcc -g -Wall -Wextra -std=c11 -c debutliste.c
lecturefichier.o: lecturefichier.c lecturefichier.h
gcc -g -Wall -Wextra -std=c11 -c lecturefichier.c
statistiques.o: statistiques.c statistiques.h
gcc -g -Wall -Wextra -std=c11 -c statistiques.c
tri.o: tri.c
gcc -g -Wall -Wextra -std=c11 -c tri.c
clean:
rm -rf *.o
link: compile
gcc *.o -o tri
Yes. If you are using GNU Make, you can simplify your makefile (per above) by relying on the fact it already has a catalog of rules. Those rules tells make how to compile c files into object files and how to link object files into a binary. The recursive flag -r for rm makes me nervous so I removed it. You probably don't need a separate link step so I use the standard all target instead of compile:
.PHONY: all clean
CFLAGS:=-g -Wall -Wextra -std=c11
all: tri
clean:
rm -f *.o ./tri
tri: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
debutliste.o: debutliste.c debutliste.h
lecturefichier.o: lecturefichier.c lecturefichier.h
listechainee.o: listechainee.c listechainee.h
statistiques.o: statistiques.c statistiques.h
If you want to be fancy you can use a pattern rule %.o: %.c %h that says a given file .o depends on it's corresponding .c and .h files which makes the makefile quite compact:
.PHONY: all clean
CFLAGS:=-g -Wall -Wextra -std=c11
all: tri
clean:
rm -f *.o ./tri
tri: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
%.o: %.c %h
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $<
The list of object files is probably just all your c files with a different name. You can write that as:
OBJECTS:=$(patsubst %.c,%.o,$(wildcard *.c))
tri: $(OBJECTS)
However, I don't usually do that step in my projects as the build now become sensitive to temporary .c files that I often create while working.

Why is my makefile not making one of the targets?

I'm required to submit my program along with a makefile for an assignment but for some reason it is not making the target helper.o even though the command for that step (gcc -Wall -std=c99 -c helper.c) works when I type it into the command line manually. When I type the make command I get this error:
gcc -Wall -std=c99 -c createTweet.c
gcc -Wall -std=c99 -c displayTweets.c
gcc -Wall -std=c99 -c searchTweetsByKeyword.c
gcc -Wall -std=c99 -c countStopWords.c
gcc -Wall -std=c99 -c deleteTweet.c
gcc -Wall -std=c99 -c saveTweetsToFile.c
gcc -Wall -std=c99 -c loadTweetsFromFile.c
gcc -Wall -std=c99 -c sortID.c
gcc -Wall -std=c99 -c addNodeToList.c
cc -c -o mainA3.o mainA3.c
gcc -Wall -std=c99 createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o -o matiwosEyoelA3
gcc: error: helper.o: No such file or directory
make: *** [makefile:2: outputA3] Error 1 '''
Here: is my makefile:
outputA3: createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o mainA3.o
gcc -Wall -std=c99 createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o -o outputA3
helper.o: helper.h headerA3.h helper.c
gcc -Wall -std=c99 -c helper.c
createTweet.o: createTweet.c helper.h headerA3.h
gcc -Wall -std=c99 -c createTweet.c
displayTweets.o: displayTweets.c helper.h headerA3.h
gcc -Wall -std=c99 -c displayTweets.c
searchTweetsByKeyword.o: searchTweetsByKeyword.c helper.h headerA3.h
gcc -Wall -std=c99 -c searchTweetsByKeyword.c
countStopWords.o: countStopWords.c helper.h headerA3.h
gcc -Wall -std=c99 -c countStopWords.c
deleteTweet.o: deleteTweet.c helper.h headerA3.h
gcc -Wall -std=c99 -c deleteTweet.c
saveTweetsToFile.o: saveTweetsToFile.c helper.h headerA3.h
gcc -Wall -std=c99 -c saveTweetsToFile.c
loadTweetsFromFile.o: loadTweetsFromFile.c helper.h headerA3.h
gcc -Wall -std=c99 -c loadTweetsFromFile.c
sortID.o: sortID.c helper.h headerA3.h
gcc -Wall -std=c99 -c sortID.c
addNodeToList.o: addNodeToList.c helper.h headerA3.h
gcc -Wall -std=c99 -c addNodeToList.c
clean:
rm *.o outputA3
Why might this be happening?
Your matiwosEyoelA3: ... does not list helper.o as a dependency.
That's a problem because you repeat so many file names and violate the "don't write it twice" rule. Use variables and make's builtin variables like $^.
e.g.
OBJECTS = createTweet.o displayTweets.o searchTweetsByKeyword.o \
countStopWords.o deleteTweet.o saveTweetsToFile.o \
loadTweetsFromFile.o sortID.o addNodeToList.o \
mainA3.o helper.o
outputA3: $(OBJECTS)
gcc -Wall -std=c99 -o $# $^
Your target outputA3: does not depend on helper.o.
Change the first line to -
outputA3: createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o mainA3.o helper.o
gcc -Wall -std=c99 createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o -o outputA3
(notice the extra helper.o at the end)
One way to avoid such issues in the future is to use $^ to refer to all the dependencies instead of listing them.
So you can change the target to -
outputA3: createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o mainA3.o helper.o
gcc -Wall -std=c99 $^ -o $#
This way you don't have to write the dependencies again and if you miss something you get a linker error telling you which file is missing.
helper.o is not in the list of dependencies for outputA3 target, while it is in the linking list of requisites. This makes make not to compile it, but the linker blames at you because it is not found.
A good idea can be to create a make variable with the set of objects of outputA3, as in:
outputA3_objs = createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o
outputA3: $(outputA3_objs)
gcc -Wall -std=c99 $(outputA3_objs) -o $#
and this way, if you need to change the list, you have to do it in only one place, making your Makefile more robust to changes.
make is much more powerful than what you apparently think. Thanks to the other answers you fixed your Makefile. Here is a bit simpler and less error prone Makefile (for GNU make):
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))
CC := gcc
CFLAGS := -Wall -std=c99
outputA3: $(OBJ)
$(CC) $(CFLAGS) $^ -o $#
%.o: %.c helper.h headerA3.h
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -f $(OBJ) outputA3
This assumes that the executable is outputA3 (as in your own Makefile) and not matiwosEyoelA3 (as in the error messages you show), and that all C files are part of the project. Adapt if needed.
Note: GNU make already knows how to compile and link. If you accept that your executable is named mainA3 instead of outputA3 or matiwosEyoelA3, the following should also work:
CC := gcc
CFLAGS := -Wall -std=c99
mainA3: $(patsubst %.c,%.o,$(wildcard *.c))
%.o: helper.h headerA3.h
.PHONY: clean
clean:
rm -f *.o mainA3

R_X86_64_PC32 against undefined symbol `WinMain' on cygwin

When I compile my code on the command line, there are no problems:
$ gcc -Wall -O2 -o mess main.c getmatrix.c toktoint.c prtmatrix.c getdist.c
But when I compile via make, it fails:
$ make clean
$ make
/usr/bin/gcc -O2 -Wall -c toktoint.c -o toktoint.o
/usr/bin/gcc -O2 -Wall -c getmatrix.c -o getmatrix.o
/usr/bin/gcc -O2 -Wall -c prtmatrix.c -o prtmatrix.o
/usr/bin/gcc -O2 -Wall -c getdist.c -o getdist.o
/usr/bin/gcc -O2 -Wall -c -o main.o main.c
/usr/bin/gcc -O2 -Wall -o mess toktoint.o
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: /usr/lib/gcc/x86_64-pc-cygwin/10/../../../../lib/libcygwin.a(libcmain.o): in function `main':
/usr/src/debug/cygwin-3.1.7-1/winsup/cygwin/lib/libcmain.c:37: undefined reference to `WinMain'
/usr/src/debug/cygwin-3.1.7-1/winsup/cygwin/lib/libcmain.c:37:(.text.startup+0x82): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `WinMain'
collect2: error: ld returned 1 exit status
make: *** [Makefile:44: mess] Error 1
Here is my Makefile:
CC=/usr/bin/gcc
OPTIMIZATION=2
CFLAGS=-O$(OPTIMIZATION) -Wall
LFLAGS=
TARGET=mess
OBJECTS=toktoint.o \
getmatrix.o \
prtmatrix.o \
getdist.o \
main.o
SOURCES=toktoint.c \
getmatrix.c \
prtmatrix.c \
getdist.c \
main.c
HEADERS=getmatrix.h \
toktoint.h \
prtmatrix.h \
getdist.h
all: $(TARGET)
mess: $(OBJECTS)
$(CC) $(CFLAGS) -o $# $<
%.o: %.c %.h
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(OBJECTS) $(TARGET)
I tried changing various flags, such as "-m64". And other suggestions which I found on stackoverflow, but no success.
If I compile each module on the command line, it also works:
$ make clean
$ gcc -O2 -Wall -c toktoint.c -o toktoint.o
$ gcc -O2 -Wall -c getmatrix.c -o getmatrix.o
$ gcc -O2 -Wall -c prtmatrix.c -o prtmatrix.o
$ gcc -O2 -Wall -c getdist.c -o getdist.o
$ gcc -O2 -Wall -c main.c -o main.o
$ gcc -Wall -O2 -o mess main.o getdist.o getmatrix.o prtmatrix.o toktoint.o
So it appears the problem is with make or Makefile.
Look at the output from make again, especially the linker line:
/usr/bin/gcc -O2 -Wall -o mess toktoint.o
It does not build with all the object files. Most notably, it misses main.o which I assume contains your main function.
The variable $< is only
The name of the first prerequisite
(from this make manual, emphasis mine).
To get all prerequisites (all object files) use $^:
mess: $(OBJECTS)
$(CC) $(CFLAGS) -o $# $^

error: cannot specify -o when generating multiple output files

How to fix this error?
I am trying to compile the C project, but I get such error
Alekseys-MBP:mmn14 aleksey$ make
gcc -Wall -ansi -pedantic -c -o assembler.o assembler.c
gcc -Wall -ansi -pedantic -c -o utils.o utils.c
gcc -Wall -ansi -pedantic -c -o symbol_table.o symbol_table.c
gcc -Wall -ansi -pedantic -c -o file_scan.o file_scan.c
file_scan.c:323:2: warning: no newline at end of file [-Wnewline-eof]
}
^
1 warning generated.
gcc -Wall -ansi -pedantic -c -o data_block.o data_block.c
gcc -Wall -ansi -pedantic -c -o commands.o commands.c
gcc -Wall -ansi -pedantic assembler.o utils.o symbol_table.o file_scan.o utils.h data_block.o commands.o -o assembler
clang: error: cannot specify -o when generating multiple output files
make: *** [assembler] Error 1
there is my makefile
EXEC_FILE = assembler
C_FILES = assembler.c utils.c symbol_table.c file_scan.c utils.h data_block.c commands.c
H_FILES = common.h symbol_table.h data_block.h commands.h file_scan.h
O_FILES = $(C_FILES:.c=.o)
all: $(EXEC_FILE)
$(EXEC_FILE): $(O_FILES)
gcc -Wall -ansi -pedantic $(O_FILES) -o $(EXEC_FILE)
%.o: %.c $(H_FILES)
gcc -Wall -ansi -pedantic -c -o $# $<
clean:
rm -f *.o $(EXEC_FILE)
What am I doing wrong?
This list of C files:
C_FILES = assembler.c utils.c symbol_table.c file_scan.c utils.h data_block.c commands.c
contains a header, file utils.h.
When this statement:
O_FILES = $(C_FILES:.c=.o)
constructs the list of object files, the substitution .c=.o does not alter utils.h, which results in O_FILES containing a header file. Then this build command:
gcc -Wall -ansi -pedantic $(O_FILES) -o $(EXEC_FILE)
asks GCC to do its default actions with the files, which is to link the object files and write an executable file and to “precompile” (analyze) the header file and write a “precompiled header” data file. Thus, you have two output files.
To fix this, remove utils.h from C_FILES and put it in H_FILES.

Makefile Giving Duplicate Error C

I have created a makefile to run 9 programs simultaneously.
The names of the 9 programs are init_aim.c, register.c, sort.c, schedule.c, add.c, class_schedule.c, class_list.c, grade.c, and report.c.
In each of the files I have implemented the code:
#include "aim.h"
int main(){
return 0;
}
I also have a header file with the code
#ifndef AIM_H
#define AIM_H
#endif
My only goal is to get my makefile working. And also add the "all:" rule. My current makefile looks like this.
AIS: init_aim.o register.o sort.o schedule.o add.o class_schedule.o
class_list.o grade.o report.o
gcc -Wall -ansi -pedantic init_aim.o register.o sort.o
schedule.o add.o class_schedule.o class_list.o grade.o report.o -o AIS
init_aim.o: init_aim.c aim.h
gcc -Wall -ansi -pedantic -c init_aim.c -o init_aim.o
register.o: register.c aim.h
gcc -Wall -ansi -pedantic -c register.c -o register.o
sort.o: sort.c aim.h
gcc -Wall -ansi -pedantic -c sort.c -o sort.o
schedule.o: schedule.c aim.h
gcc -Wall -ansi -pedantic -c schedule.c -o schedule.o
add.o: add.c aim.h
gcc -Wall -ansi -pedantic -c add.c -o add.o
class_schedule.o: class_schedule.c aim.h
gcc -Wall -ansi -pedantic -c class_schedule.c -o
class_schedule.o
class_list.o: class_list.c aim.h
gcc -Wall -ansi -pedantic -c class_list.c -o class_list.o
grade.o: grade.c aim.h
gcc -Wall -ansi -pedantic -c grade.c -o grade.o
report.o: report.c aim.h
gcc -Wall -ansi -pedantic -c report.c -o report.o
Please keep in mind the spacing does not look proper on here because there is too much code.
When I run make I get:
gcc -Wall -ansi -pedantic -c init_aim.c -o init_aim.o
gcc -Wall -ansi -pedantic -c register.c -o register.o
gcc -Wall -ansi -pedantic -c sort.c -o sort.o
gcc -Wall -ansi -pedantic -c schedule.c -o schedule.o
gcc -Wall -ansi -pedantic -c add.c -o add.o
gcc -Wall -ansi -pedantic -c class_schedule.c -o class_schedule.o
gcc -Wall -ansi -pedantic -c class_list.c -o class_list.o
gcc -Wall -ansi -pedantic -c grade.c -o grade.o
gcc -Wall -ansi -pedantic -c report.c -o report.o
gcc -Wall -ansi -pedantic init_aim.o register.o sort.o schedule.o add.o
class_schedule.o class_list.o grade.o report.o -o AIS
clang: warning: argument unused during compilation: '-ansi' [-Wunused-
command-line-argument]
duplicate symbol _main in:
init_aim.o
register.o
duplicate symbol _main in:
init_aim.o
sort.o
duplicate symbol _main in:
init_aim.o
schedule.o
duplicate symbol _main in:
init_aim.o
add.o
duplicate symbol _main in:
init_aim.o
class_schedule.o
duplicate symbol _main in:
init_aim.o
class_list.o
duplicate symbol _main in:
init_aim.o
grade.o
duplicate symbol _main in:
init_aim.o
report.o
ld: 8 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
make: *** [AIS] Error 1
If anyone knows how to solve the duplicate error and add the "all:" command please let me know.
You have defined main() in each code file.
main() is the "start here" point for the executable you are trying to create.
The build fails because of multiple "start here" points.
To put it differently:
You can only have a single main() in a single executable.
You might be thinking of multithread programming.
In that case you need to do some research on the topic.
You might be thinking of running multiple programs from shell.
In that case you need to create multiple executables and start them separatly with the appropriate shell features, e.g. for background execution.
If you are writing nine separate programs you shouldn't try to link them all together at the end. I think this is what you want
all: init_aim register sort schedule add class_schedule class_list grade report
init_aim: init_aim.c aim.h
gcc -Wall -ansi -pedantic init_aim.c -o init_aim
register: register.c aim.h
gcc -Wall -ansi -pedantic register.c -o register
...
I removed -c, removed .o and added the all rule.

Resources