Generic makefile that is independent of source file name - c

I wanted to create a generic makefile that can take the source file name compile it, save it as the object file and executable file. Both files using the original source name. Thank you for your help.
exec: \
compile
./helloworld #I would like to input source outside the make file.
compile: \
helloworld.c
gcc -Wall helloworld.c -o helloworld #<==
echo 'compiling'
touch compile
#I would like makefile to automatically save both object and exec.
#as the source file name.

You can use the $(MAKECMDGOALS) variable thus:
CFLAGS = -Wall
$(MAKECMDGOALS): $(MAKECMDGOALS).o
and then simply call Make like this:
make myfile
If you have Make 3.81 or later, then this can become:
CFLAGS = -Wall
.SECONDARY: # Prevents intermediate files from being deleted
If you're not interested in saving the intermediate object file, then you don't even need a Makefile. You can simply do:
make bar CFLAGS=-Wall

Make has built-in rules that know how to create an executable from a source file, if they have the same name. So you don't even need a makefile at all!
$ ls
foobar.c
$ make foobar
cc foobar.c -o foobar
Not that there's no need to mess with .SECONDARY because make has a direct rule to build an executable from a .c, without compiling the .o first (so there's no intermediate file). Even if it didn't, there's no advantage here to keeping the .o file around so it's not worth the extra effort to do so (IMO).
If you want to change compilers or flags you can have a makefile that consists of nothing other than some variable assignments:
$ ls
foobar.c Makefile
$ cat Makefile
CC = gcc
CFLAGS = -Wall
$ make foobar
gcc -Wall foobar.c -o foobar

Related

How to create Makefile to compile a single arbitrary filename in C

I'm very new to C programming and I want to know what to write in a Makefile to compile a single .c file.
Say I have a multiple .c files in one folder )namely sample1.c, sample2.c, sample3.c, etc) and I only want to compile a specific filename.
I want to only type "make sample2" which will compile and have an output called sample2 (pretty much the .c name will be maintained).
I've read several solutions and someone might have suggested this but didn't work.
SRC = $(shell find . -type f -name \*.c)
executable: $(SRC:.c=.o)
gcc -std=gnu99 $# $^
What do I need to do to make it work?
Converting a comment into an answer.
You don't need a makefile for that: make sample2 will compile sample2.c to create the program sample2.
You could use /dev/null as the name of the makefile if you want (or if you need to ignore an existing makefile):
make -f /dev/null sample2
That compiles with the default options, of course. If you want to use more stringent flags, then you might do this (assuming that the existing makefile is expendable):
echo 'CFLAGS = -Wall -Wextra -Werror -std=c11 -O3 -g' > makefile
make sample2
or some variant on that theme, such as:
make -f /dev/null CFLAGS="-Wall -Wextra -Werror -std=c11 -O3 -g" sample2
In short, make knows how to compile single C files into the executable of the corresponding name (minus the .c suffix) without needing any explicit makefile. You can tweak how it compiles that file if need be.

C: programming: How to create main.o from main.c?

I'm trying to write a makefile and I compiled main.c. Then I'm trying to create main.o, but I'm confused as how to do so. I'm using a vi editor in UNIX. I tried gcc -o main.c, I get a fatal error saying that there's no input files. What went wrong?
You can use gcc's -c option to compile a source file without linking. This will leave you with a .o file:
gcc -c main.c
You can then create an executable by linking that .o file with the standard libraries, and other .o or .c files if you like:
gcc -o myprogram main.o
The primary advantage of this is when you have multiple .c files. In that case you can save time by not recompiling them all when one of them changes.
If you are using a Makefile, then you probably have too much in it. Warning: the following will overwrite your Makefile. Try:
echo 'all: main.o' > Makefile
make
or even:
> Makefile # truncate the Makefile. That is, make it empty
make main.o
or even:
rm Makefile
make main.o
Stop working so hard.

Linux Novice Question: GCC Compiler output

I am a complete novice with Linux. I have Mint on a laptop and have recently been playing around with it.
I wrote a simple C program and saved the file.
Then in the command line I typed
gcc -c myfile
and out popped a file called a.out. I naively (after years of Windows usage) expected a nice .exe file to appear. I have no idea what to do with this a.out file.
Name it with -o and skip the -c:
gcc -Wall -o somefile myfile
You should name your sourcefiles with a .c extension though.
The typical way of compiling e.g. two source files into an executable:
#Compile (the -c) a file, this produces an object file (file1.o and file2.o)
gcc -Wall -c file1.c
gcc -Wall -c file2.c
#Link the object files, and specify the output name as `myapp` instead of the default `a.out`
gcc -o myapp file1.o file2.o
You can make this into a single step:
gcc -Wall -o myapp file1.c file2.c
Or, for your case with a single source file:
gcc -Wall -o myapp file.c
The -Wall part means "enable (almost) all warnings" - this is a habit you should pick up from the start, it'll save you a lot of headaches debugging weird problems later.
The a.out name is a leftover from older unixes where it was an executable format. Linkers still name files a.out by default, event though they tend to produce ELF and not a.out format executables now.
a.out is the executable file.
run it:
./a.out

UNIX cc executable location

When I compile a .c file using the cc command, it creates an a.out executable. I've noticed that it creates the a.out file inside my current directory. Is there a way to make the a.out file be created in the same directory as the .c file wherever I happen to be on the system?
for example if my current path is ~/desktop and I type in the command:
cc path/to/my/file/example.c
It creates the a.out file in the ~/desktop directory. I would like it to create the a.out file in path/to/my/file/a.out
You will have to use the -o switch each time you call cc:
cc -o path/to/my/file/a.out path/to/my/file/example.c
or you can make a wrapper script like this:
mycc
#!/bin/bash
dirname=`dirname "$1"`
#enquoted both input and output filenames to make it work with files that include spaces in their names.
cmd="cc -o \"$dirname/a.out\" \"$1\""
eval $cmd
then you can invoke
./mycc path/to/my/file/example.c
and it will, in turn, call
cc -o "path/to/my/file/a.out" path/to/my/file/example.c
of course you can put mycc in $PATH so you can call it like:
mycc path/to/my/file/example.c
You can give the "-o" flag to define the output file. For example:
cc path/to/my/file/example.c -o path/to/my/file/a.out
Yes, with -o.
cc path/to/my/file/example.c -o path/to/my/file/a.out
It may be not what you're looking for, but you can easily redirect the output of a compilation using the -o siwtch like this:
cc -o /a/dir/output b/dir/input.c
I don't know, how to archieve, what you want (auto replacement), but I guess you can do it with some bash like this: (I'm poor in scripting, untested and may be wrong):
i = "a/path/to/a/file.c" cc -o ${i%.c} $i
This should compile a file specified in i into an output file in same dir, but with the .c-suffix removed.

compile with -ansi -pedantic -Wall switches automatically with gcc

We are required to compile C source codes using gcc in this manner:
gcc -ansi -pedantic -Wall program.c
I'm wondering how can I 'automate' this so when I enter:
gcc program.c
It will automatically compile with the 3 switches. Is this possible?
You can also use the implicit rules of make, so that you don't have to write a makefile for every program. Make will automatically call the compiler if you say make foo and there exists a foo.c file in the current directory. To add flags to this define the variable CFLAGS in your environment, e.g. in bash add export CFLAGS="-Wall -pedantic -ansi" to .bashrc.
If your program depends on multiple files however you'll have to create a makefile, but for C compilation you can get away with just listing dependancies so long as one of them has the same base name as a target.
For example for this makefile:
# Makefile
foo:foo.o bar.o
running make will execute the commands
gcc $CFLAGS -c -o foo.o foo.c
gcc $CFLAGS -c -o bar.o bar.c
gcc -o foo foo.o bar.o
without you having to add any rules.
To automate the build of any number of build steps / complex parameters, you should use a makefile.
Once you have a makefile you simply need to type: make
alias gcc="gcc -ansi -pedantic -Wall"
But as #Brian said, you really should use a makefile, or better, a build system like CMake or SCons.
A makefile would be the traditional way, especially as part of a larger build process.
If you frequently want to build without a makefile, you could define an alias in your .bashrc or equivalent: alias gcc=gcc -ansi -pedantic -Wall.
You can use a shell script that takes some cues by how its called and invokes make after setting CFLAGS appropriately for the occasional one-off build.
Lets say you have /usr/bin/compile , which is a shell script that looks at $0 to see what name actually invoked it. You then make symbolic links to it named pedantic, fullwarn, etc.
In the shell script itself, something like:
OLDCFLAGS=$CFLAGS
WHATAMI=$(basename $0)
case "$WHATAMI" in
pedantic)
export CFLAGS="-Wall -pedantic -ansi"
make $#
exit $?
;;
c99)
export CFLAGS="-std=c99 ... ... ..."
....
Then, to compile foo.c with the extra naggy flags:
pedantic foo
This is handy, as I said for one-off builds, e.g trying to compile code that someone posted in a question, or working out how to use a new library, etc.
For anything else, just use a makefile, as others have said.

Resources