Unix: Project Management with Make - c

My instructions are:
The steps necessary to produce this program are:
Compile cpp2html.c to produce cpp2html.o. (Important: the source code in this project is C, not C++, and so must be compiled and linked with gcc, not g++.)
Run the command
flex cppscanner.l
to produce the file lex.yy.c from the language description in cppscanner.l.
Compile lex.yy.c to produce lex.yy.o. (This often produces a warning message about extra tokens. Ignore it.)
Link the .o files to produce an executable program named cpp2html
Write a makefile that will carry out these steps. Your makefile should result in only the minimum required amount of steps when any input file to this process is changed. (Note: you will probably not be able to base this makefile upon my self-updating makefile as in the earlier part of the assignment. Instead, you will probably find it necessary to write this one from scratch.
Here is my makefile:
cpp2html: cpp2html.o lex.yy.o
gcc -g -DDEBUG cpp2html.o lex.yy.o
mv a.out cpp2html
lex.yy.o: lex.yy.c
gcc -g -DDEBUG lex.yy.c
lex.yy.c:
flex cppscanner.l
cpp2html.o: cpp2html.c
gcc -g -DDEBUG cpp2html.c
What am I doing wrong here? I get an error message saying:
collect2: error: ld returned 1 exit status
make: *** [cpp2html.o] Error 1
Your makefile does not build 'cpp2html' when invoked:
gcc -g -DDEBUG cpp2html.c
This is due tonight, so any suggestions would be greatly appreciated.

It's complaining about the following:
cpp2html.o: cpp2html.c
gcc -g -DDEBUG cpp2html.c
This line is trying to compile cpp2html.c to a.out.
Change that to
cpp2html.o: cpp2html.c
gcc -g -DDEBUG -c cpp2html.c
Do the same thing for the line that compiles lex.yy.c to lex.yy.o. The -c option tells gcc to only generate the object file and write it to the .o file.
You can take advantage of other options and some built-in variables. Here's a suggestion:
cpp2html: cpp2html.o lex.yy.o
gcc -g -DDEBUG -o $# $?
$# evaluates to the name of the target. $? evaluates to the list of dependencies (the .o files). The -o option tells gcc to write the resulting binary to the specified file name instead of a.out.
You can also take advantage of implicit rules:
%.o : %.c
gcc -g -DDEBUG -c $<
This will build any .c file to the corresponding .o file, so you don't need to repeat the same commands for cpp2html.c and lex.yy.c.
Edit
FWIW, here's how I'd structure the makefile (with annotations; assumes Gnu make):
# Variables used by implicit rules
CFLAGS=-g -DDEBUG -Wall -Werror # flags for gcc
LFLAGS= # flags for flex, currently none
LEX=flex # lexer
CC=gcc # C compiler
# Variables to make life easier
LSRCS=cppscanner.l # All of our flex source files
SRCS=cpp2html.c $(patsubst %.l,%.c,${LSRCS}) # All of our C source files
OBJS=$(patsubst %.c,%.o,${SRCS}) # All of our object files
TARGET=cpp2html # Final target name
${TARGET} : ${OBJS}
${CC} ${CFLAGS} -o $# $^ # Explicit rule to build target
# $# expands to target name
# $^ expands to list of all prerequisites
clean:
rm -rf *.o $(patsubst %.l,%.c,${LSRCS})
That's it. We're relying on implicit rules to build the .l file to a .c file, and to build the .c files to .o files. The implicit rules use the LEX, CC, LFLAGS and CFLAGS variables to run the right commands with the right options. We only need the single explicit rule to build our final executable.
The advantage of structuring a makefile like this is that you can add files to the project without having to add new rules.
I think all of the above is correct; my main box is shut down at the moment so I can't test it. Refer to the Gnu Make manual for more details.

Related

GCC appears to be confusing C *.d dependency files with D language source code

When I compile my code, gcc appears to be confusing the .d files in my gcc options with D programming language source, and complains that it can't find the "cc1d" compiler. In summary, I get the following output when I run 'make':
gcc -c -I. -IUnity/src/ -Isrc/ -Ilib/ -DTEST test/Testworker.c -o build/objs/Testworker.o
gcc -c -I. -IUnity/src/ -Isrc/ -Ilib/ -DTEST src/worker.c -o build/objs/worker.o
gcc -o build/Testworker.out build/objs/Testworker.o build/objs/worker.o Unity/src/unity.o build/depends/Testworker.d
gcc: error trying to exec 'cc1d': execvp: No such file or directory
Makefile:56: recipe for target 'build/Testworker.out' failed
make: *** [build/Testworker.out] Error 1
How can I tell gcc that I really mean that my *.d files are dependencies, rather than more source files?
I tried renaming my intermediate *.d files to *.dep in my Makefile, but gcc doesn't recognize these, either...
My Makefile rule that is causing problems is this one:
$(PATHB)Test%.$(TARGET_EXTENSION): $(PATHO)Test%.o $(PATHO)%.o $(PATHU)unity.o $(PATHD)Test%.d
$(LINK) -o $# $^
The dependent Makefile rule to build the .d files is working fine:
$(DEPEND) $# $<
and I know that my .d files are being made. My one issue is when the

Configure automake to target assembly

Is it possible to configure automake to generate a Makefile which, in addition to building the .o files and linked binary, also has targets for %.s? I want to be able to review the compiler output in a text format without having to invoke binutils on the .o files.
Specifically, if I have main.c as a source file, I want to be able to run make main.s. The desired recipe would be the same as that for main.o, but using CC1 := $(CC) -S.
The question is a little XY.
You want to be able make the intermediate assembly file foo.s, where
the source file foo.c is one of the sources in an autotooled project, using
a makefile that is generated by the project's ./configure script. You
assume that to do this you must do something to the automake inputs -
the Makefile.ams? - that will cause ./configure to generate Makefiles
that include assembly targets *.s matching all object targets *.o.
Well you could, but then your project would not be a regular autotooled
project as usually distributed, and there is no need to make it irregular
to get what you want.
The GCC option -save-temps
exists to let developers see the intermediate files of compilation - the preprocessor
output, the assembly.
$ gcc -c -o foo.o foo.c
outputs foo.o
$ gcc -save-temps -c -o foo.o foo.c
outputs:
foo.o
foo.i # preprocessed source
foo.s # assembly
As I expect you know, GNU Make receives compiler options from the make-variable
CFLAGS, and automake respects this convention, independently of and in addition to any compiler
options prescribed by the project's autotooling. So, if you would otherwise generate
makefiles with:
$ ./configure ...
then, to add -save-temps to the C compiler options, generate makefiles instead
with:
$ ./configure CFLAGS=-save-temps ...
And if you are already using CFLAGS, e.g.
$ ./configure CFLAGS="-g -O0" ...
then append -save-temps:
$ ./configure CFLAGS="-g -O0 -save-temps" ...
Then,
$ make main.o
will make main.o, main.i and main.s up-to-date.
To disable -save-temps, of course, rerun ./configure, removing it from
the CFLAGS.
If the project involves C++ compilation, then CXXFLAGS affects the C++
compiler in the same way that CFLAGS affects the C compiler. Note that
the generated preprocessed C++ sources will be called *.ii, not *.i.
With -save-temps enabled, make clean will not delete the *.i and *.s
files. You may not care, since compilation will always clobber them. If you
do care, you may take advantage of automake's standard phony target clean-local,
which is supported to let an autotooling maintainer extend the behaviour of
clean. Add the following recipe to the Makefile.am of each source directory
in the project:
clean-local:
$(RM) *.i *.ii *.s
Then update the autotooling and regenerate Makefiles:
$ autoreconf
$ ./configure ...
While the COMPILE variable in the generated Makefile.in is technically an internal detail, and this solution relies on the compiler to understand -c -S, adding:
.c.s:
$(COMPILE) -c -S $<
to the Makefile.am has worked for as long as I've been using the autotools. It might also be convenient to add:
clean-local:
rm -f *.s
I find this useful in development to have a look at the assembly output for specific configure and CC, CFLAGS options.
The COMPILE variable will be defined as something like:
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
Similarly, for C++ source we have:
.cc.s:
$(CXXCOMPILE) -c -S $<

Creating a make file

I know there is infinite amount of resources on the Internet with regards makefiles, but it is something that I still do not understand it. At the moment I have 3 c files PolyCalculatorMain.c PolyCalculator.c PolyCalculator.h and Polyfunctions.c
So far I have
PolyCalculator: PolyCalculator.o PolyCalculatorMain.c
gcc -Wall -ggdb -o PolyCalculator PolyCalculatorMain.c PolyCalculator.o
PolyCalculator.o: PolyCalculator.c
gcc -Wall -ggdb -c PolyCalculator.c PolyCalculator.h
clean:
rm PolyCalculator *.o *~ *#
Any help or explanation on were to go to complete this file would be much appreciated.
Note Im only beginning so I dont want any complex code as I will not understand it
In compile command you don't normally specify .h files. They are included by the preprocessor (which runs before the compiler) as it encounters #include statements. That is the only thing I can see.
The .h files do show up in Makefiles as dependencies since changes to them can require code that uses them to need to be recompiled.
I would say the basic rule is to include anything on the dependency line which would cause a recompile to be necessary if they changed.
PolyCalculator: PolyCalculator.o PolyFunctions.o PolyCalculatorMain.c
gcc -Wall -ggdb -o PolyCalculator PolyCalculatorMain.c PolyCalculator.o PolyFunctions.o
PolyCalculator.o: PolyCalculator.c PolyCalculator.h
gcc -Wall -ggdb -c PolyCalculator.c
PolyFunctions.o: PolyFunctions.c PolyFunctions.h
gcc -Wall -ggdb -c PolyFunctions.c
clean:
rm PolyCalculator *.o *~ *#
Makefiles allow you to have variables that can be reused. For example, you can have your
compiler options in a variable:
options=-Wall -ggdb
and then you use them with brackets and a dollar sign
gcc ${options}
You can also break them up:
debug=-ggdb
warnings=-Wall
options=${warnings} ${debug}
You can also combine all your object files into a variable:
obj_files=PolyCalculator.o PolyFunctions.o
PolyCalculator: ${obj_files} PolyCalculatorMain.c
gcc -Wall -ggdb -o PolyCalculator PolyCalculatorMain.c ${obj_files}
PolyCalculator.o: PolyCalculator.c PolyCalculator.h
gcc -Wall -ggdb -c PolyCalculator.c
PolyFunctions.o: PolyFunctions.c PolyFunctions.h
gcc -Wall -ggdb -c PolyFunctions.c
clean:
rm PolyCalculator *.o *~ *#
Because you didn't give really clear detains of what you would want changed / modified, I giving you what I would write the makefile as below, although some might (will?) disagree with me in places.
I see that you edited you original post and mention a PolyFunctions.cpp (and I guesssing that there
is a PolyFunctions.h)
CC=gcc
CCFLAGS=-ansi -Wall -pedantic
INCS=
LK=gcc
LKFLAGS=
LIBS=
OBJS = PolyCalculator.o PolyCalculatorMain.o PolyFunctions.o
PROG = PolyCalculator
$(PROG) : $(OBJS)
$(LK) $(LKFLAGS) $(OBJS) $(LIBS) -o $(PROG)
rebuild : clean $(PROG)
PolyCalculatorMain.o : PolyCalculatorMain.cpp PolyCalculator.h PolyFunctions.h
$(GCC) -c $(CCFLAGS) $(INCS) PolyCalculatorMain.cpp -o PolyCalculatorMain.o
PolyCalculator.o : PolyCalculator.cpp PolyCalculator.h
$(GCC) -c $(CCFLAGS) $(INCS) PolyCalculator.cpp -o PolyCalculator.o
PolyFunctions.o : PolyFunctions.c PolyFunctions.h
$(GCC) -c $(CCFLAGS) $(INCS) PolyFunctions.cpp -o PolyFunctions.o
clean:
rm -f $(OBJS) $(PROG) *.o *~ *#
OK, the changes that I made (and why)
First I like using variables that are then expanded as rules are fired. I find this a convenient way to insure that all steps use the same settings. Also, I have added variables that you can use if you need to add headers to compilation (i.e. the INCS variable). I have broken out the commands and flags for the linker as well, the LK, LKFLAGS and LIBS variable. Currently most of these are empty.
I added a variable for the various object files that are created, I like doing this because if I add a new source file to the project I have to do two things, the first would be to write a rule for it and the second would be to add it to the OBJS variable. In my opinion, the more things I need to do when adding a new source file, the greater the chance that I will forget something.
I added a variable for the final program name. Again, makes it simple if I want to change it…and I'm lazy — typing $(PROG) is easier and less error prone than typing PolyCalculator :)
Ordering of targets is a personal choice, I always put the target to rebuild the main program as the first (or default) target in the makefile. That way when I run make I just build what has changed since my last build. I put a rule near the top to do a total rebuild of the application, in the above this is the rebuild rule. Running make rebuild is operationally equivalent to make clean; make; but I prefer a single target to accomplish this
I rewrote your rules using the variable I defined in point 1.
I added the -f flag to rm so clean will do everything even if it can't find a file. Again, this tends to be personal preference.
I make sure to use macros extensively, because you can redefine macros on the make command line if need be. There are also many standard macros, such as CC for the name of the C compiler and CFLAGS for the (majority) of the flags passed to the compiler. Also, make has built-in rules for many operations, such as converting a .c file into a .o file.
The philosophy behind make is that compilation is expensive, so you do as little of it as possible, but as much as necessary. Thus, make is typically commanded to build object files, and then links the object files with libraries to build programs.
You say you have three source files and one header. So, my makefile for your program would include:
FILES.c = PolyCalculatorMain.c PolyCalculator.c Polyfunctions.c
FILES.o = ${FILES.c:.c=.o}
PROGRAM = PolyCalculator
CFLAGS = -Wall -ggdb
all: ${PROGRAM}
${PROGRAM}: ${FILES.o}
${CC} -o $# ${CFLAGS} ${FILES.o} ${LDFLAGS} ${LDLIBS}
PolyCalculatorMain.o: PolyCalculator.h
PolyCalculator.o: PolyCalculator.h
Polyfunctions.o: PolyCalculator.h
clean:
rm -f ${PROGRAM} *.o *~ *# core a.out
The choice between $(XYZ) and ${XYZ} is arbitrary; I chose to use curly brackets 30 years ago, and don't see a reason to change. Being consistent is what matters.
The FILES.c macro (yes, macro names may contain dots, despite the fact that vim doesn't colour them as macros) lists a set of three file names. If I needed to add a fourth, then I'd add it to this list. If the list got too long for a single line, I'd use a macro of the format:
FILES.c = \
PolyCalculatorMain.c \
PolyCalculator.c \
Polyfunctions.c
This allows editing of one line affected when a file is added unless you add it at the end of the list. I normally keep such lists in sorted order.
The FILES.o macro is defined by applying a suffix-transformation rule to the FILES.c macro. The part after the : is .c=.o; it means replace the names that end with .c with .o at the end.
The PROGRAM macro is what I use in a single-program makefile. For a multi-program makefile, each program gets its own macro in all caps. (Although make macros are not constrained to all caps, it is normal to use all caps for macros.) The CFLAGS macros sets your chosen options for the C compiler. Good marks for using -Wall. I use more stringent options like -Wextra -Werror and specify a standard (-std=c11), but -Wall is a good start.
It is conventional to have the first rule in your makefile called all. It says "everything is up to date when ${PROGRAM} is up to date".
The next rule says that the program depends on the object files. If any of the object files is newer than the program, you rebuild the program using the command line shown. The $# hieroglyph is the same as ${PROGRAM} in this rule. Formally, it is the name of the target being built. It makes the command line generic — everything except the -o is a macro. This tends to be the way that makefiles work; the information is almost all in macros. The ${LDFLAGS} and ${LDLIBS} macros are semi-standard; they allow you to pass options to the linker (ld, invoked by the C compiler), and are used to specify library-related options. For example, you might have:
LDFLAGS = -L ${OTHERLIBDIR}
LDLIBS = -l${OTHERLIB}
to link with a library not located in /usr/lib and other standard locations. The macros OTHERLIBDIR and OTHERLIB would be defined earlier in the makefile, of course.
The next three lines say that the object files (note that it is the object files, not the source files) depend on the header file. make is quite capable of deducing that PolyCalculatorMain.o is built from PolyCalculatorMain.c, so you don't have to specify that dependency explicitly. It can't deduce the header dependency so you have to specify it. Note that I've not specified a custom command, so the default command will be used. That's usually:
${CC} -c ${CFLAGS} $*.c
where the $* is a shorthand for the basename of the file being compiled.
I modified the clean command to use rm -f (which won't complain if the arguments are missing), and added a.out and core to the list of debris files.
You can add endless extra stuff to a basic makefile like this. You might add a depend rule to automatically generate the header dependencies; that is useful when your code begins to get complex with multiple headers, and different source files using different sets of headers. If you have a multi-lingual source tree, you have to worry about multiple lists of files. If you have multiple programs, you have to separate the files specific to one program from those common to several, and then think about whether to build the common object files into a local convenience library so that you don't have to list the exact dependencies for each program.
But this outline will get you going.
If you're using GNU make, you might well add a line:
.PHONY: all clean
This tells GNU make that there won't be files called all and clean created.
I note in passing that the name Polyfunctions.c is inconsistent with the other two; the F should be capitalized for consistency.
Here is a proper GNU make file for your project:
# set macro with list of source files in current directory using wildcard
# note: the ':=' states that the list is to only be generated once
# if only '=' were used, the the list would be re-generated each time referenced
SRCS := $(wildcard: *.c)
# set macro with list of object files using pattern substitution
OBJS := $(SRCS:.c=.o)
# set macro with list of header files in the current directory using wildcard
HDRS := $(wildcard: *.h)
# set macro with list of compiler flags
# there are many other very useful compiler flags
# but this list will result in:
# all warnings displayed
# compile only
# debug info being include
# (there are other forms of the -g parameter to get more debug info)
# no optimization
# look for some included files in the current directory
CFLAGS := -Wall -c -g -O0 -I.
# set macro with list of linker flags
# all warnings displayed
# debug info being included
LFLAGS := -Wall -g
# set macro with path+name of pre-processor/compiler/linker utility
# by convention, the utility is referenced by $(CC)
CC := /usr/bin/gcc
# by 'make' design, the make utility is referenced by $(MAKE)
# set macro with path+name of file deletion utility
# by convention, the utility is referenced by $(RM)
RM := /usr/bin/rm -f
# by convention, there are (at least) two phony target names
# tell 'make' that 'all' and 'clean' are targets that will NOT produce an output file
# with those names
.PHONY: all clean
# this is first target so will be performed if:
# user enters 'make' with no parameters
# or user enters 'make all'
# the PolyCalculator executable is stated to be a pre-requisite
all: PolyCalculator
# this is a real target
# state that this target has a pre-requisite of the files listed in the OBJS macro
# the executable name is defined by the '-o' and following name
# use the parameters listed in the LFLAGS macro
PolyCalculator: $(OBJS)
gcc $(LFLAGS) -o PolyCalculator $(OBJS)
# this is a real target (PolyCalculator.o)
# state that this target has a pre-requisite of file: PolyCalculator.c
# state that this target has a pre-requisite of the files listed in the HDRS macro
# use the parameters listed in the CFLAGS macro
# target 'PolyCalculator' lists PolyCalculator.o as a pre-requisite
# so it can be performed automatically
# it can also be performed directly when the user enters 'make PolyCalculator.o'
PolyCalculator.o: PolyCalculator.c $(HDRS)
gcc $(CFLAGS) -o PolyCalculator.o PolyCalculator.c
# this is a real target (PolyCalculatorMain.o)
# state that this target has a pre-requisite of file: PolyCalculatorMain.c
# state that this target has a pre-requisite of the files listed in the HDRS macro
# use the parameters listed in the CFLAGS macro
# target 'PolyCalculator' lists PolyCalculatorMain.o as a pre-requisite
# so it can be performed automatically
# it can also be performed directly when the user enters 'make PolyCalculatorMain.o'
PolyCalculatorMain.o: PolyCalculatorMain.c $(HDRS)
gcc $(CFLAGS) -o PolyCalculatorMain.o PolyCalculatorMain.c
# this is a real target (PolyFunctions.o)
# state that this target has a pre-requisite of file: PolyFunctions.c
# state that this target has a pre-requisite of the files listed in the HDRS macro
# use the parameters listed in the CFLAGS macro
# target 'PolyCalculator' lists PolyFunctions.o as a pre-requisite
# so it can be performed automatically
# it can also be performed directly when the user enters 'make PolyFunctions.o'
PolyFunctions.o: PolyFunctions.c $(HDRS)
gcc $(CFLAGS) -o PolyFunctions.o PolyFunctions.c
# this is a phony target (see .PHONY, above)
# it is performed when the user enters 'make clean'
clean:
$(RM) PolyCalculator *.o *~ *#

creating a makefile

So I have to create a makefile that would generate the application described below and make sure each generated file has its own rule.
For the makefile:
The first tool is flex, which takes a file called spec.l and generates a file called lex.yy.c. Another tool called bison expects a file calledspec.y and will generate the file spec.tab.c. If bison is called using the directives -vd, it will also generate a file called spec.tab.h (which is needed when compiling lex.yy.c). The two C files can be compiled into object files and then linked together with the yacc (-ly) and lex (-ll) libraries to generate the compiler (a.out.
The makefile you describe must generate the following commands if you were starting just with spec.l and spec.y:
flex spec.l
bison -vd spec.y
gcc -c lex.yy.c
gcc -c spec.tab.c
gcc spec.tab.o lex.yy.o -ly -ll
i am not sure where to start with this problem
edit: what i have so far
compiler: spec.tab.o lex.yy.o
gcc spec.tab.o lex.yy.o -ly –ll
lex.yy.c: spec.l
flex spec.l
spec.tab.c: spec.y
bison -vd spec.y
spec.tab.o: spec.tab.c
gcc -c spec.tab.c
lex.yy.o: lex.yy.c spec.tab.h
gcc –c lex.yy.c
clean:
rm –f *.c *.o a.out
You have to tell the make about the dependencies. For example, lex.yy.c depends on spec.l:
lex.yy.c: spec.l
flex spec.l
The first line say lex.yy.c depends on spec.l. The second tells how to generate an updated version of lex.yy.c when spec.l is newer. We pretty much repeat that pattern with the other files. In the case of calledspec.y, we have two results that are produced from the same input/command. At least with GNU make, you can specify that like this:
spec.tab.c spec.tab.h: calledspec.y
bison -vd calledspec.y
Then you pretty much repeat the process for dependencies of .o (or .obj, etc.) files on headers and C files:
lex.yy.o: lex.yy.c spec.tab.h
$(cc) -c lex.yy.c
One final note: unless you specify otherwise, make will build the first target specified in the makefile, so you normally want to arrange it with the final executable first, and other targets after that:
parser: lex.yy.o y.tab.o
$(cc) -o parser lex.yy.o y.tab.o
lex.yy.o: lex.yy.c spec.tab.h
$(cc) -c lex.yy.c
And so on. This only applies to targets though, not to macros, so you'll typically see a few things like:
cflags = -O2
...at the beginning of a make file. Then the lines the invoke the compiler will use that, something like:
lex.yy.o: lex.yy.c spec.tab.h
$(cc) $(cflags) -c lex.yy.c
And when this is executed, the cflags macro will be expanded, so the command that gets executed is gcc -O2 -c lex.yy.c (and it predefines cc to the name of the compiler it normally expects to use, so Microsoft's make sets it to cl, GNU to gcc, etc.)

Determining C executable name

When we are compiling a C program the output is stored in a.out. How can we redirect the compiled output to another file?
Most C compilers provide an option for this, such as the -o option for gcc and some others:
gcc -o gentext gentext.c
cc -o mainprog -Llib -lmymath firstbit.c secondbit.o
xlc -o coredump coredump.c
-ofilename will make filename instead of a.out.
According to the manual:
-o <file> Place the output into <file>
In Unix, where C originated from, C programs are usually compiled module-by-module, and then the compiled modules are linked into an executable. For a project that consists of modules foo.c and bar.c, the commands would be like this:
cc -c foo.c
cc -c bar.c
cc -o myprog foo.o bar.o
(With -c, the output filename becomes the source file with the suffix replaced with .o.)
This allows you to also re-compile only those modules that have changed, which can be a big time saver for big programs, but can also become pretty tricky. (This part is usually automated using make.)
For a single-module program there's not really any point in first compiling to a .o file, and then linking, so a single command suffices:
cc -o foo foo.c
For single-module programs, it is customary to call the resulting executable program the same as the C source file without the .c suffix. For multi-module programs, there is no hard custom on whether the output is named after the file with the main function or not, so you're free to invent whatever strikes your fancy.
With the -o option.
gcc main.c -o myCoolExecutable.o
This is ok if your program consists of a single file. If you have more files I suggest using make: create a Makefile and then run the command make.
A Makefile is a file containing some rules for compilation.
An example can be the following (# means the line is a comment):
CXX = gcc
#CXXFLAGS = -std=c++11
#INC_PATH = ...
#LIBS = ...
SOURCEDIR := yourSourceFolder
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR=$(SOURCEDIR)/obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: yourExecutableName
clean:
$(RM) $(OBJECTS) $(DEPENDS) yourExecutableName
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
yourExecutableName: $(OBJECTS)
$(CXX) $(WARNING) $^ -o $#
#$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $# $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CXX) $(WARNING) -MMD -MP -c $< -o $#
Shortly CXX variable defines your compiler (gcc, g++), with CXXFLAGS you can define flags for your compilation (i.e. -std=c++11). Then you can include and define custom (INC_PATH and LIBS: not set in the example). With SOURCEDIR you can specify your source code directory (where *.c files are).Then SOURCES is basically telling that the source files for the compilation are all the files having extension *.c.
The Makefile contains a set of rules whose structure is the following:
output: inputs
commandToExecute
The rule to generate your executable file is
yourExecutableName: $(OBJECTS)
$(CXX) $(WARNING) $^ -o $#
which is equivalent to gcc -Wall -Wextra $(OBJECTS) -o yourExecutableName.
$(OBJECTS) are the object file resulting from the compilation. When the above rule is executed, if they are not found make will continue scanning the file to find a rule to generate them. In this case the rule to generate these files is:
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CXX) $(WARNING) -MMD -MP -c $< -o $#
If further information is needed let me know.
If foo will be your executable and bar.c is your source file then the command is:
gcc -o foo bar.c
Compile using:
cc -o <opfilename> <filename.c>
Execute using:
./<opfilename>
gcc filename.c -o outputfile
This command will directly create an outputfile.exe OR outputfile.out according to operating system. In place of filename.c OR outputfile we can enter path, as shown below.
gcc ./home/user/filename.c -o ./home/outputfile
The format of giving the Name of .exe file according to the User Choice in C Language
step 1 :- Run the gcc (or the compiler you have) in the below format on the Terminal
gcc -o put_your_name_you_want_to_give (space) your_file_name_you_want_to_execute
NB:- If you are Running "Vs Code" Use the 'Tab' key for the Auto completion.
step 2 :- Write down the name of the program in format
.\the_name_you_have_given.exe
you are done!
Assuming you are in ubuntu
step-1: run gcc with these commands to compile filename.c
gcc filename.c -o filename.out
filename.out will be created, (it might or might not be shown where the other files are stored)
step-2: execute the filename.out by
./filename.out
step-3: wait for the output
thats it , you are done

Resources