Confused about Makefile (C/unix) - c

http://puu.sh/7OiDL.png
Ok so what does export: StackImplementation.o do? Like where does it export that to?
Also, what is gcc -l doing? I googled it and it says "gcc -l links with a library file". What's linking to the library file?
Lastly, what does "substitute a print command of your choice for lpr below" mean? What's lpr do? and what's clean: rm -f *.o?

The export is the name of a phony target. You can say
% make export
And make will build the its dependencies. There is no action specifying how to convert the dependencies into a file called export, and in the absence of an implicit rule, the make will stop after building the dependencies.
The -I to gcc is adding a path to search for include files. You are confusing it with the -l option which specifies the name of a library to link (a pre-built collection of object files from which unresolved symbols can be satisfied).
The lpr command sends a file to the default line printer. Again, print is a phony target; doing
% make print
sends the source file to the printer.
Most makefiles include a clean rule to delete generated files. It is necessary when the dependencies are not properly specified, and a change to a source file does not cause the target to be built. The rm command is short for remove; it deletes files. If you do
% make clean
it will force-delete all files that end with .o.
Most of these targets are phony, and will not work correctly if there happen to be files with those names that are newer than their dependencies (if any). Most makes allow you to specify which targets are phony by listing them as dependencies of a super phony .PHONY target. Make will then ignore the filesystem, and will always apply the rules.

export:
this is a target named "export" and is the first target in the makefile so it will get called by default if no target is specified on the command line. Not clear to me why it is called "export" but that's the name somebody chose for it
export: StackImplementation.o
this says that export depends on StackImplementation.o so it will invoke the target StackImplementation.o when export is invoked
StackImplementation.o: StackImplementation.c ...
StackImplementaiton.o depends on the source file StackImplementation.c and the include files listed. This will run gcc which has the flag -I../Include which tells gcc to include .h files in adjacent directory "Include"
# substitute...
this is a comment indicating to change the print command lpr to some other print command if you want to
clean:
this is a common target that will delete object files with the -f option, forcing remove even if write permission is not set

1) lpr submits files for printing. Files named on the command line are sent to the named printer
(or the default destination if no destination is specified). If no files are listed on the com‐
mand-line, lpr reads the print file from the standard input.
for more information about "lpr " use user manual of linux.
2)gcc -l link external library to your program if any dependency .
example::
gcc hello.c -o hello -lpthread -ldrm -ldrm_omap
in Make file::
clean:
rm -rf *.o
here clean is a rule of make and when we call make clean then it will invoke rm -rf *.o to remove all object files.

Related

What is wrong with my makefile for C?

I am currently learning C. I tried to make a makefile, but for some reason, it doesn't work. When I type "make" into the console, the following warnings are printed into the console:
makefile.c:1:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
CFLAGS=-Wall -g
^~~~~~
makefile.c:1:9: error: use of undeclared identifier 'Wall'
CFLAGS=-Wall -g
^
makefile.c:1:15: error: use of undeclared identifier 'g'
CFLAGS=-Wall -g
^
makefile.c:4:13: error: expected ';' after top level declarator
rm -f ex1
Here is the makefile's code:
CFLAGS=-Wall -g
clean:
rm -f ex1
The code is expected to compile the file ex1.c . Why doesn't my makefile work?
When you run make it tries to figure out what you want it to do.
By default it looks for a file called Makefile or makefile (and for GNU Make, it first looks for GNUMakefile). If it finds such a file, it assumes it is a makefile and reads it.
It seems that here make finds something that looks a bit like a makefile, but then guesses what to do with it. In your case it finds your file makefile.c which it assumes is a source file containing C code, so it uses its built-in rules for processing C source files and tries to compile it with the C compiler. That fails, because your makefile is not a C program! (You lied by naming it makefile.c)
You can either tell make to read that file explicitly (even though it has an unconventional name) by running make -f makefile.c, or you can just give it a sensible name (either Makefile or makefile) so that it gets found automatically when you run make.
When make processes a makefile the first target it finds is the default target. In your makefile the first target is clean so when make runs it will run the rules for the clean target. If you want it to run a different target then either put another target first in the makefile, or specify a target explicitly, e.g. make ex1 (which will cause make to see the file ex1.c and use its built-in rules for compiling a C source file into an executable).
Makefiles are instruction to make, and they are not programs in the same sense as a c-program. From the error messages it looks like you have named your Makefile as a c-source code file, so
Rename your make file to Makefile
mv makefile.c Makefile
Your makefile does not specify what to make -- it only has a clean tag, but not to worry, if your source code is in a single file then make can figure it out, just;
Specify what you want to make
$ make ex1
or alternatively have an entry in your Makefile to do the same, like
CFLAGS=-Wall -g
ex1: ex1.c # This will tell make that ex1 is compiled from ex1.c
clean:
rm -f ex1
A Makefile is not a C file.
You shall rename it from makefile.c to Makefile (mv ./makefile.c ./Makefile)
After on, in your CFLAGS, use -W -ansi -Werror and don't forget to remove the -g when your done, otherwise, your program will be slower on execution.
And then, as it's not a C file, don't try to compile it with gcc
Just type
make
or any other rule you got preceded by make, as
make re; make clean
if you wanna compile the whole thing, then clean trash files (*.o and auto-saves depending on your rules aswell).
Makefile doesn't have extension. Change makefile.c to makefile then try.
Suppose you want create makefile for file1.c & file2.c, here file1.c is depend on file2.c create makefile as given below
makefile: file1.c file2.c
gcc -o makefile file1.c file2.c
And you can just compile using command
make makefile
I resolved the problem by doing the following:
See your all characters in your file, specially in "clean", does not change color even though you saved.
I don't think you saved correctly.
Open gedit and paste your code, then press ctrl + S to save it and then name it to Makefile, not Makefile.c. Makefile is makefile type.
When you save, check file Makefile by clicking the file property. If you see Type: maketype is Ok or see all the characters in your file, the "clean" will change color from grey to another color.
Finally, in terminal, write make clean, not make Makefile. It will run like it does in the "learnCthehardcode" course.

How to specify default include directory in GCC

I am new in GCC and I am wondering how to tell the compiler that several include directories need to be specified as default for searching .h files. I read that -I dir is the key to accomplish that but doing my makefiles I encounter some problems. For example:
include_dir = C:/Users/rmrd001/Documents/Make/GCC/first/mydir/
FLAGS = -I "$(include_dir)"
func2.o: func2.c func2.h
gcc $(FLAGS) -c func2.c
And I got the error:
make:*** No rule to make target 'func2.c', needed by 'func2.o'. Stop.
The include_dir is not the working directory. It is working_directory/my_dir.
Please help.
-I is used for finding include files, but not for finding the main file. You have to pass an explicit path to the main file.
You can add path with -I option right in command line;
You can specify path with env variable C_INCLUDE_PATH
Also you can find more info on gcc official site and here

Using Makefile to link multiple files

I'm kind of lost in the Makefile business and I'm trying to come to terms with it. I would love if someone could make it clear on an example I'm currently programming.
I have these files:
my-bit-vector.h -> a header file included in eratost.c, ppm.c
ppm.c -> a .c file which includes my-bit-vector.h and error.h
error.h -> a header file included in eratost.c, ppm.c
error.c -> a .c file which includes error.h and defines the functions in it
erato.c -> a .c file which includes my-bit-vector.h and error.h
I need to link these together into one executable file. How would I go about doing that via Makefile? I hope I didn't forget something. Could you please help?
The contents of a Makefile, when put simple, is one or more targets (the things you want built). Each target has dependencies (if any dependencies don't exist yet, they must be built, and if they do exist but they're newer than their target, the target must be rebuilt), and rules (the commands to build the target, presumably from the dependencies).
In your case, lets say your final output is a program called program. You've identified the sources to build it, but you don't build an executable directly from sources, you do it from object files. You could start your makefile like this:
program: ppm.o error.o erato.o
cc -o program ppm.o error.o erato.o
WARNING The spacing on rule lines (the cc command line shown above) requires a TAB, not just spaces!
That's enough to start but not enough to be right. You'll notice that there's no target:dependency/rules for the .o's yet, but it still works because Make has some built-in rules.
With this makefile, if you type "make" twice, the first time you'll see everything gets built and the second time it won't -- nothing changed so no rebuild is needed. Unfortunately if you edit your .h's now, the .c's still won't rebuild, so lets fix that:
program: ppm.o error.o erato.o
cc -o program ppm.o error.o erato.o
ppm.o: ppm.c my-bit-vector.h error.h
error.o: error.c error.h
erato.o: erato.c my-bit-vector.h error.h
Now you've got your dependencies set to cause make to rebuild sources that must be rebuilt when headers change. There's no rules on those source builds because the built-in rule here is (often) sufficient. You can override the built-in if necessary, of course.
Here, when you type "make", the tool will find the first target (program) and inspect its dependencies. It will then make sure each of its dependencies are up to date (based on their target:dependency / rule definitions), recursively as long as there are targets needing to be considered for being built. Finally it will apply the rules for this target to complete its build.
There's much more that can be done with makefiles, this is just a brief intro.
program: ppm.o error.o erato.o
gcc ppm.o error.o erato.o -o program
ppm.o: ppm.c
gcc -c ppm.c -o ppm.o
error.o: error.c
gcc -c error.c -o error.o
erato.o: erato.c
gcc -c erato.c -o erato.o
stuff before the ":" is the target. stuff after ":" are the required targets for this target.
So if you "make program" make is looking for a target named "all". The target all requires ppm.o which is also defined as target in the makefile. So it executes this target first. the target ppm.o requires ppm.c which has no target defined in the makefile, so it is probably a file. I hope this explains the basic functionality to you.
http://mrbook.org/tutorials/make/
is a really good tutorial for beginners, with some basic makefile examples.

generating a makefile for the dumb

I got 10 C files.
10 h files all in one folder.
I need those files to create 1 executable in the same folder using unix makefile.
EDIT :
the soultion
create a file named "makefile"
write the following make sure you have a single TAB before the word "gcc" this will create a.out executable
all:
gcc *.c
if you need flags just add them for example to make the filename BOB:
all:
gcc *.c -o BOB
I don't think you want what you say you want, but how about:
all:
gcc *.c
"missing separator" is commonly caused by a missing tab in front of a command line. The lines with $(CXX) need to be indented by a tab - not 8 spaces, not any number of spaces, but a tab.
Additionally, I don't think that empty lines between rule and commands are allowed.
Apart from obviously writing the Makefile yourself, you can also use CMake which is a convenient build system generator.
A simple example of a CMakeLists.txt file:
cmake_minimum_required(VERSION 2.6)
project(yourproject C)
add_executable(yourexecutable file1.c file1.h file2.c file2.h ...)
You can then do in a terminal:
$ cmake .
$ make
and your executable will be built.
Be careful however that the generated makefile uses cmake and is therefore not distributable per se.

"cc1: error: /usr/local/include: not a directory" after installing C library

This is the first time I install a library. I followed the instructions here. It's from an online course on programming.
I'm not very Unix savvy. When I tried to compile one of the sample c files, one that #includes the cs50.h file, I get:
cc1: error: /usr/local/include: not a directory
Also, if I write cd /usr/local/include or cd /usr/local/lib, it tells me it's not a directory again, even though when I ls /usr/local they both show up.
Any ideas?
Given that the instructions in the header are:
To compile as a static library on your own system:
% gcc -c -ggdb -std=c99 cs50.c -o cs50.o
% ar rcs libcs50.a cs50.o
% rm -f cs50.o
% cp cs50.h /usr/local/include
% cp libcs50.a /usr/local/lib
Note the use of '%' as a prompt. It indicates that the operations should be done as root.
Unless your system is misconfigured, you will need to use root privileges to copy the files into the directories under /usr/local. For example, you might use sudo as a prefix to the commands:
sudo cp cs50.h /usr/local/include
sudo cp libcs50.a /usr/local/lib
We can deduce (with fairly high confidence) that you did not already have directories /usr/local/include and /usr/local/lib, and that you now have two files (not directories) called:
/usr/local/include that contains the header cs50.h
/usr/local/lib that contains the static library
You should validate this observation with ls -l /usr/local and perhaps file /usr/local/*. Then you should remove the files, create the directories, and copy the files into the newly created directories.
The only thing this explanation does not account for is the missing leading slash in the error message (which originally said 'cc1: error: usr/local/include: not a directory'). At the moment, I put that down to a transcription error in asking this question. (And a comment and edit confirms that diagnosis.)

Resources