generating a makefile for the dumb - c

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.

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.

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.

How to write a Makefile to compile a simple C program

Compile the following program
#include <stdio.h>
int main(void)
{
printf ("Hello from your first program!\n");
return 0;
}
a)-by using file of type Makefile
b)-the executable will be named Hello
"Please help to do an exercise. I know how to do it in CodeBlocks, but I don't know what Makefile is and how to write it in Linux. I compiled it using command "gcc filename.c" and subsequently "./a.out" but I still don't understand what the Makefile is. Is it a sort of shell script, an instruction? How would a Makefile for this task exactly look? Thanks in advance :) "
This is your simple make file for hello program.
CC = gcc
CFLAGS = -g
RM = rm -f
default: all
all: Hello
Hello: Hello.c
$(CC) $(CFLAGS) -o Hello Hello.c
clean veryclean:
$(RM) Hello
Suppose you have two makefiles in one directory named makefile.m1 and makefile.m2 and if you want build both make file then please use following commands
make -f makefile.m1
make -f makefile.m2
or use single Makefile that contains:
m1:
make -f makefile.m1
m2:
make -f makefile.m2
and use make m1 or make m2
Now lets clear your doubt about name of make file must not require Makefile
You can name makefile whatever you want. suppose i would like to give name myfirstmakefile.mk. To use it later you need to tell make what makefile you want. Use -f option for this:
make -f myfirstmakefile.mk
And again extantion .mk is also not manadatory you can use whatever you want but never forgot to use -f option.
so may this help make sense to you.
A makefile is a recipe for the make utility how to create some file (called a target) from some other files (called dependencies) using a set of commands run by the shell. A makefile typically looks like this:
target: dependency [...]
command1
command2
Try running man make for details.
Now for your task, really there is no need for a Makefile, since make has built-in rules that know how to compile a simple program. All you need to do is place your C source in a file named after the executable name (Hello) and with a .c extension, i.e. Hello.c.
Then a simple
$ make Hello
cc Hello.c -o Hello
does everything. If you want to use gcc instead of cc, you can run
$ rm Hello
$ make CC=gcc Hello
gcc Hello.c -o Hello
If you tell your instructor/teacher/prof that an empty makefile is all you need since you know the built-in rules do the right thing, you'll get some extra credit and maybe your instructor has learnt something new :-) If you are asked for a reference, you could quote the relevant parts of the make manual, or, do it like a pro, quote from the POSIX Standard for the make utility, section Default Rules.
before going for makefile you have to know what's it and why we need it
What is Makefile?
Makefile is a script written in a certain prescribed syntax which helps to build the target output (normally, one or more executables) from source files by compilation and linking. In simple words, makefile will compile your source code in simple & fast way.
Why we need Makefile?
=> Large projects can contain multiple source files which are dependent in one another or arranged in hierarchical manner for example, in order to compile file A, you have to first compile B; in order to compile B, you have to first compile C; and so on.
=> Make is a solution to these problems. It can be used to compile whole project in well arranged manner and generate your target according to your make rule(which we will discuss later) by entering single command that is make.
=> An important feature is that when a project is recompiled after a few changes, it will recompile only those files which are changed, and any other files that are dependent on it. This saves a lot of time.
=> For a large project, when a few changes are made to the source, manually recompiling the entire project each time is tedious, error-prone and time-consuming.
Here is nice link for it :How to write first makefile
A makefile is a recipe for computers with instructions how to perform certain tasks and with dependencies between those tasks.
In the simple form, it looks like so:
a.out: filename.c
gcc filename.c
Read: "To build a.out from filename.c, run the command gcc filename.c. If a.out is newer than filename.c, then don't do anything"
Note: The first character in the gcc line must be a tab.

Include an external library in C

I'm attempting to use a C library for an opencourseware course from Harvard. The instructor's instructions for setting up the external lib can be found here.
I am following the instructions specific to ubuntu as I am trying to use this lib on my ubuntu box. I followed the instructions on the page to set it up, but when I run a simple helloWorld.c program using a cs50 library function, gcc doesn't want to play along.
Example:
helloWorld.c
#include <stdio.h>
#include <cs50.h>
int
main(void){
printf("What do you want to say to the world?\n");
string message = GetString();
printf("%s!\n\n", message);
}
$ gcc helloWorld.c
/tmp/ccYilBgA.o: In function `main':
helloWorld.c:(.text+0x16): undefined reference to `GetString'
collect2: ld returned 1 exit status
I followed the instructions to the letter as stated in the instructions, but they didn't work for me. I'm runing ubuntu 12.04. Please let me know if I can clarify further my problem.
First, as a beginner, you should always ask GCC to compile with all warnings and debugging information enabled, i.e. gcc -Wall -g. But at some time read How to invoke gcc. Use a good source code editor (such as GNU emacs or vim or gedit, etc...) to edit your C source code, but be able to compile your program on the command line (so don't always use a sophisticated IDE hiding important compilation details from you).
Then you are probably missing some Harvard specific library, some options like -L followed by a library directory, then -l glued to the library name. So you might need gcc -Wall -g -lcs50 (replace cs50 by the appropriate name) and you might need some -Lsome-dir
Notice that the order of program arguments to gcc is significant. As a general rule, if a depends upon b you should put a before b; more specifically I suggest
Start with the gcc program name; add the C standard level eg -std=c99 if wanted
Put compiler warning, debugging (or optimizing) options, eg -Wall -g (you may even want to add -Wextra to get even more warnings).
Put the preprocessor's defines and include directory e.g. -DONE=1 and -Imy-include-dir/
Put your C source file hello.c
Put any object files with which you are linking i.e. bar.o
Put the library directories -Lmy-lib-dir/ if relevant
Pur the library names -laa and -lbb (when the libaa.so depends upon libbb.so, in that order)
End with -o your-program-name to give the name of the produced binary. Don't use the default name a.out
Directory giving options -I (for preprocessor includes) and -L for libraries can be given several times, order is significant (search order).
Very quickly you'll want to use build automation tools like GNU make (perhaps with the help of remake on Linux)
Learn also to use the debugger gdb.
Get the habit to always ask for warnings from the compiler, and always improve your program till you get no warnings: the compiler is your friend, it is helping you!
Read also How to debug small programs and the famous SICP (which teaches very important concepts; you might want to use guile on Linux while reading it, see http://norvig.com/21-days.html for more). Be also aware of tools like valgrind
Have fun.
I take this course and sometimes I need to practice offline while I am traveling or commuting. Under Windows using MinGW and Notepad++ as an IDE (because I love it and use it usually while codding python) I finally found a solution and some time to write it down.
Starting from scratch. Steps for setting up gcc C compiler, if already set please skip to 5
Download Git and install. It includes Git Bash, which is MINGW64 linux terminal. I prefer to use Git as I need linux tools such as sed, awk, pull, push on my Windows and can replace Guthub's terminal.
Once Git installed make sure that gcc packages are installed. You can use my configuration for reference...
Make sure your compiler works. Throw it this simple code,
by saving it in your working directory Documents/Harvard_CS50/Week2/
hello.c
#include <stdio.h>
int main(void)
{
printf("Hello StackOverflow\n");
}
start Git Bash -> navigate to working directory
cd Documents/Harvard_CS50/Week2/
compile it in bash terminal
gcc helloworld.c -o helloworld.exe
execute it using bash terminal
./helloworld.exe
Hello StackOverflow
If you see Hello StackOverflow, your compiler works and you can write C code.
Now to the important bit, installing CS50 library locally and using it offline. This should be applicable for any other libraries introduced later in the course.
Download latest source code file cs50.c and header file cs50.h from https://github.com/cs50/libcs50/tree/develop/src and save them in Documents/Harvard_CS50/src
Navigate into src directory and list the files to make sure you are on the right location using
ls
cs50.c cs50.h
Cool, we are here. Now we need to compile object file for the library using
gcc -c -ggdb -std=c99 cs50.c -o cs50.o
Now using the generated cs50.o object file we can create our cs50 library archive file.
ar rcs libcs50.a cs50.o
After all this steps we ended with 2 additional files to our original files. We are interested in only 2 of them cs50.h libcs50.a
ls
cs50.c cs50.h cs50.o libcs50.a
Copy Library and header files to their target locations. My MinGW is installed in C:\ so I copy them there
cs50.h --> C:\MinGW\include
libcs50.a --> C:\MinGW\lib
Testing the cs50 Library
To make sure our library works, we can throw one of the example scripts in the lecture and see if we can compile it using cs50.h header file for the get_string() method.
#include <stdio.h>
#include <cs50.h>
int main(void)
{
printf("Please input a string to count how long it is: ");
string s = get_string();
int n = 0;
while (s[n] != '\0')
{
n++;
}
printf("Your string is %i chars long\n", n);
}
Compile cs50 code using gcc and cs50 library. I want to be explicit and use:
gcc -ggdb -std=c99 -Wall -Werror test.c -lcs50 -o test.exe
But you can simply point the source, output filename and cs50 library
gcc test.c -o test.exe -lcs50
Here we go, program is compiled using header and methods can be used within.
If you want Notepad++ as an IDE you can follow this tip to set it up with gcc as a compiler and run your code from there.
Just make sure your nppexec script includes the cs50 library
npp_save
gcc -ggdb -std=c99 -Wall -Werror "$(FULL_CURRENT_PATH)" -lcs50 -o "$(CURRENT_DIRECTORY)\$(NAME_PART).exe"
cmd /c "$(CURRENT_DIRECTORY)\$(NAME_PART).exe"
Download the cs50 from: http://mirror.cs50.net/library50/c/library50-c-5.zip
Extract it. (You will get two files cs50.c and cs50.h)
Now copy both the files to your default library folder. (which includes your stdio.h file)
Now while writing your program use: #include < cs50.c >
You can also copy the files to the folder containing your helloWorld.c file.
You have to use: #include " cs50.c ".
OR =====================================================================>
Open cs50.c and cs50.h files in text editor.
In cs50.h, just below #include < stdlib.h > add #include < stdio.h > and #include < string.h > both on new line.
Now open cs50.c file, copy everything (from: /**Reads a line of text from standard input and returns the equivalent {from line 47 to last}) and paste it in cs50.h just above the #endif and save the files.
Now you can copy the file cs50.h to either your default library folder or to your current working folder.
If you copied the file to default folder then use: #include < cs50.h > and if you copied the files to current working folder then use: #include " cs50.h ".
You need to link against the library during compilation. The library should end in .a or .so if you are on Ubuntu. To link against a library:
gcc -o myProgram myProgram.c -l(library name goes here but no parentheses)
You have to link against the library, how come GCC would know what library you want to use?
gcc helloWorld.c -lcs50
Research Sources:
building on the answers above given by Basile Starynkevitch, and Gunay Anach
combined with instructions from some videos on youtube 1 2
Approach:
covering the minimum things to do, and sharing the "norms" separately
avoiding any modification to anywhere else on the system
including the basic breakdown of the commands used
not including all the fine details, covering only the requirements absolute to task or for effective communication of instructions. leaving the other mundane details to the reader
assuming that the other stuff like compiler, environment variable etc is already setup, and familiarity with shell's file navigation commands is there
My Environment:
compiler: gcc via msys2
shell: bash via msys2
IDE: doesnt matter here
Plan:
getting the source files
building the required files: *.o (object) and *.a (archive)
telling the compiler to use it
Action:
Let's say, current directory = "desktop/cs50"
It contains all the *.c files like test-file.c which I will be creating for assignments/problem sets/practise etc.
Get the *.h and *.c files
Source in this particular case: https://github.com/cs50/libcs50/tree/main/src
Go over each file individually
Copy all the content of it
Say using "Copy raw contents" icon of individual files
Create the corresponding file locally in the computer
Do it in a a separate folder just to keep things clean, let's say in "desktop/cs50/src" aka ./src
Build the required files using in the terminal after changing your current directory to "desktop/cs50/src" :
gcc -c cs50.c to create the "cs50.o" object file from "cs50.c" using "gcc"
ar cr libcs50.a cs50.o to create "libcs50.a" archive file which'll be containing "cs50.o" object file
Here, "libcs50" = "lib" prefix + "cs50" name (same as the header file's name)
This is the norm/standard way where the prefix "lib" is significant as well for a later step
However, prefix can be skipped, and it's not compulsory for name to match the header file's name either. Though, Skipping prefix is not recommended. And I can't say for sure about the name part
To tell the compiler to be able to use this infrastructure, the commands will be in following syntax after going to the parent directory (i.e. to "desktop/cs50"):
gcc test-file.c -Isrc -Lsrc -lcs50 if you used "lib" prefix in step 2.2 above
here, -I flag is for specifying the directory of *.h header file included in your test_file.c
and -L flag is for specifying the directory to be used for -l
and -l is for the name of the *.a file. Here the "lib" prefix talked about earlier, and ".a" extension is not mentioned
the order of these flags matter, keep the -I -L -l flags after the "test-file.c"
Some more notees:
don't forget to use the additional common flags (like those suggested above for errors etc)
if you skipped the "lib" prefix, then you can't use -L -l flags
so, syntax for command will become: gcc test-file.c -Isrc src/libcs50.a
say i created my test-file.c file in "desktop/cs50/psets", so, it can be handled in 2 notable ways (current dir = "desktop/cs50/") :
cd psets then changing the relative address correspondingly in -I -L, so result:
gcc test-file.c -I../src -L../src -lcs50
keeping current directory same, but then changing the file's relative address correspondingly, so result:
gcc psests/test-file.c -Isrc -Lsrc -lcs50
or use absolute addresses 😜
as it can be seen that this becomes quite long, that's when build automation tools such as make kick in (though i am accomplishing that using a shell script 😜)

Makefile related

I have a Makefile where the first line is of the type:
all:client.so simulator
LD_PRELOAD=/path/to/shared/lib/client.so ./simulator
and the other lines to above follows
Now, I have another program say xyz.c whose executable is called from within simulator using execve().
How can I include the compilation linking etc of xyz.c in the same Makefile or do I have to use another makefile.
Thanks
Can't you just make all depend on the executable for xyc as well? And then add targets to build that from xyc.c?
You need to add a dependency and a rule to build it:
simulator: xyz.c
$CC xyz.c -o yxz

Resources