Compiling multiple C and header files with 1 main - c

[Files in my directory][1]
Need help compiling in a make file.
So I have this link list assignment i'm doing and the directions were.
stringlist.h is supposed to contain the node and the function prototypes
stringlist.c is supposed to have the functions completed that are defined in stringlist.h. BUT stringlist.c is not supposed to contain main at all. Then, namelist.c is supposed to contain main and just have the I/O and its just supposed to call the command functions that are in stringlist.c.
So to compile this we are supposed to create a make file. Whenever I try to I get an error because main doesn't exit in one of the c files. Throughout the term we compiled code like this "gcc -std=gnu99 -m32 -Wall -g -o file file.c"
But it doesn't work.
How would I create the make file? Been spending hours and can't figure it out.

As stated by Jonathan Leffler, the sample Makefile I provided had a few bad ideas. Here's an improvement:
# compiler:
CC = gcc
# compiler flags:
CFLAGS = -g -Wall
# the build target executable:
TARGET = executable
# object files to build:
OBJ = namelist.o stringlist.o
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ)

Try this:
OBJ := namelist.c stringlist.c
GCC := gcc -g
CFLAGS := -std=gnu99 -m32 -Wall
compile: $(OBJ)
$(GCC) $(CFLAGS) $(OBJ) -o executable

Related

Why am I getting this error Makefile: No rule to make target 'timer.c', needed by 'timer.o'. Stop

My working directory looks like this:
main.c
Makefile
my_memmove.h
my_memmove.c
c-timer-lib
timer.c
timer.h
My makefile looks like this:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib
TARGET := output
output: main.o my_memmove.o timer.o
$(CC) $(CFLAGS) main.o my_memmove.o timer.o -o $(TARGET)
main.o: main.c
gcc -c main.c
my_memmove.o: my_memmove.c my_memmove.h
gcc -c my_memmove.c
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $#
clean:
rm *.o $(TARGET)
I don't understand why I keep getting the "Makefile: No rule to make target 'timer.c', needed by 'timer.o'. Stop." error. I believe that it's because the timer.c and timer.h files can't be found.
So much confusion here! :)
First, this is definitely wrong:
$(CC) $(CFLAGS) -I main.o ...
The -I main.o tells the compiler that it should use main.o as the name of a directory to search for include files. That clearly won't work. You should remove the -I here.
On to your problem: you have to realize that there are two completely different programs at play here: make which figures out how to run commands, and the commands that are being run, in this case the compiler gcc.
The -I option is an option to the compiler so that the compiler knows where to look for header files that are included by your source code with #include.
That option means nothing to make; it doesn't understand that option. It's just some text to pass to the compiler. Make is looking for the source file timer.c and it can't find it because you haven't told make where it is.
You have to write your rule to look in the correct place, like this:
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $#
(you should always use -o $# so that your compile line puts the output file where make expects to find it, which will be put into the $# variable by make before it evaluates your recipe.)
ETA
Also, are you sure that -DUNITS="ms" is right? We can't tell without seeing how UNITS is used in the source, but I suspect you probably need an extra level of quotes here, like -DUNITS='"ms"'
Really, you are trying to do too much in this makefile. Make already knows how to correctly build object files from source files. If you don't force the issue by writing your own rules, then make's built-in rules will do the job for you. Your makefile can be written like this:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib -DUNITS='"ms"'
TARGET := output
$(TARGET): main.o my_memmove.o c-timer-lib/timer.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LDLIBS)
my_memmove.o: my_memmove.h
c-timer-lib/timer.o: c-timer-lib/timer.h
clean:
rm *.o $(TARGET)
make doesn't know which headers your source requires so you have to add the prerequisites by hand, although you can add extra rules to allow it to figure that out for itself.

Trouble creating a generic make file

Hey so I'm a little new to makefiles and I'm trying to make a generic makefile that will compile whatever files end with .c in the current directory, instead of specifically named files for a project. I've searched a few places, re-read my lecture notes, tried a few changes and I can't seem to get it working. Here's what I have:
CFLAGS= -Wall -g -o
%.o : %.c
gcc ${CFLAGS} .c $<
This is the error I keep getting when I try to run it:
make: *** No targets. Stop.
I would be grateful for any help really, I really despise typing in gcc over and over!
The file is named Makefile
a generic makefile that will compile whatever files end with .c in the current directory
This is an atypical use for make, but can be done using GNU make's text functions:
SOURCES = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SOURCES))
all: $(OBJS)
If you have foo.c and bar.c in your directory, running make will produce foo.o and bar.o.
If you meant that you want the command make to compile and link each .c into an executable, try:
SOURCES = $(wildcard *.c)
EXECS = $(patsubst %.c,%,$(SOURCES))
all: $(EXECS)
What is more typical, is to want to compile and link a single program. In that case, you don't need any makefile whatsoever, just run these commands:
make foo
make bar
The wildcard function can be used to compile all C source files in the directory and then link them together.
CFLAGS= -Wall -g -o
SRC=$(wildcard *.c)
foo: $(SRC)
gcc -o $# $^ $(CFLAGS)
You have a couple of syntax errors, and your makefile builds the objects but doesn't link the objects into an executable.
myTest.c:
int main()
{
return 0;
}
makefile if your source file is "myTest.c":
CFLAGS= -Wall -g
all: myTest
myTest: myTest.o
gcc $(CFLAGS) $< -o $#
%.o : %.c
gcc $(CFLAGS) -c $<
Build with
make myTest
gcc -Wall -g -c myTest.c
gcc -Wall -g myTest.o -o myTest

When I use "gcc" in makefile, after making it, I got a "cc" output

For example:
There are 3 source files {main.c test1.c test2.c} in the directory
and a directory file named test3,
and there is a source file named test.c in the directory of test3.
Now I want to create a makefile to compile and link these four source files.
And this is my Makefile:
# Cancel statement "CC=gcc"
src:=$(wildcard *.c) test3.c
obj:=$(patsubst %.c,%.o,$(src))
main:$(obj)
gcc -o main $(obj)
.PHONY:clean
clean:
rm *.o *~
When I called make to compile them, I got a output like this:
cc -c -o main.o main.c
cc -c -o test1.o test1.c
cc -c -o test2.o test2.c
cc -c -o test3.o test3/test3.c
gcc -o main main.o test1.o test2.o test3.o
I know 'cc' is linked to 'gcc' in Linux.
What I don't understand is why did Make call cc to compile these four source files, but call gcc to link the object files?
You changed one rule: the one that links the program main from the object files. And when make did that link, you can see it used gcc.
You didn't do anything to change the built-in rules that make is using to compile the object files, so they use the default (the value of the variable CC) which is cc.
You wrote only the rule to link the object files, and allowed Make to use its default rule to decide how to build the object files from the source files.
GNU Make will expose its rules if you ask it with --print-data-base. In this case, it tells us
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
and
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
and finally
CC = cc
This explains why Make uses cc to compile your C sources. To change that, simply set CC = gcc. Here's a complete Makefile which does that and also makes best use of Make's built-in rules, to help when you need to extend it:
src := $(wildcard *.c) test3.c
obj := $(patsubst %.c,%.o,$(src))
CC = gcc
main: $(obj)
$(LINK.c) -o $# $^ $(LDLIBS)
.PHONY: clean
clean:
$(RM) *.o *~

Using Make for compiling C

I am trying to learn make to make my compiling easier as I learn C.
I am attempting to do:
gcc -Wall -g 3.c -o 3 -lm
using
CC = gcc
CFLAGS = -Wall -g
clean:
rm -f 3
but I don't know how and where to put -lm in the makefile. I've looked for tutorials online but they haven't specifically addressed the "-lm" option, or if they do it is without little explanation and doesn't work in my situation.
You need a "target" in which to execute the gcc command. Like:
CC = gcc
CFLAGS = -Wall -g
all:
gcc -Wall -g 3.c -o 3 -lm
clean:
rm -f 3
Then you can just replace parts of the "all" command, with your macros; CFLAGS, for example would probably have the "-lm".
It might help if you ran "make -n", that will tell you what make would do if it were to run.
Often you'll see library specific flags in a LIBS variable, e.g.:
CC = gcc
CFLAGS = -Wall -g -I/some/include/directory
LIBS = -lm -L/some/library/directory
all:
$(CC) $(CFLAGS) $(LIBS) 3.c -o 3
The variable you are looking for is called LDLFAGS. From §10.3 of the GNU Make manual:
LDFLAGS
Extra flags to give to compilers when they are supposed to invoke the linker, ‘ld’.
So, simply do:
LDFLAGS += -lm
Hope it helps.
An extremely good tutorial: Make Tutorial: How-To Write A Makefile
and here is a good generic makefile I wrote:
http://pastebin.com/PCk0gNtE
The part that would most interest you would be this section:
# C Preprocessor Flags
CPPFLAGS +=
# compiler flags
CFLAGS += -ansi -Wall -Wextra -pedantic-errors
# libraries to link to ( m == math )
program_LIBRARIES := m
# LDFLAGS is the variable to hold linker flags
LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
GNU make defines a lot of default rules. For C compilation and linking, those rules are:
n.o is made automatically from n.c with a recipe of the form ‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
So the way to add "-lm" option to the linker is by defining:
LDLIBS = -lm
Then when you run make with your Makefile, you following commands will be run:
gcc -Wall -g -c 3.c
gcc 3.o -o 3 -lm
(note that make will compile your C program in 2 steps, first creating the object file 3.o then linking the object file into the executable 3)
(see http://www.gnu.org/software/make/manual/ for the GNU make manual)

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