I have created a simple makefile i.e.
COMMON=hello
all:
gcc $(COMMON).c -o $(COMMON).o
The directory in which I am running the makefile contains three files: hello.c add.c multiply.c factorial.c and subtraction.c.
When I am compiling this in the terminal using the make command, the hello gets printed. Now I want to make changes in the program such that when I write "make add" or "make multiply" or "make factorial", the corresponding program will compile.
Just supply it on the command line.
make COMMON=bye
If the target is predictable from file names in the current directory, you don't really need a Makefile at all, because Make already knows how to make multiply from multiply.c.
.PHONY: all
all: hello add multiply factorial
If you really want an explicit recipe, try something like this.
%: %.c
gcc -o $# $^
Related
SOURCE=a.c b.c c.c
ASM=$(patsubst %.c,%.s, $(SOURCE))
all:%.o
gcc -o test $^
$(ASM):%.c
gcc -S -o $# $<
%.o:%.s
gcc -c -o$# $<
I want to generate assembly code (.s) first, then compile the assembly code to object (.o), then link them.
But it seems above makefile code does not work. What is the correct code?
When asking questions, does not work is never very useful... if it worked you probably wouldn't be asking a question! :-) Instead you should always show the command you ran and the output you received (or at least the failing part of the output if it's long). Please cut and paste the actual text rather than paraphrasing messages. Also, including the version of the make program you're using (make --version) and the platform you're running on is often helpful.
Luckily this time we can figure out the problem without this information:
This:
$(ASM):%.c
gcc -S -o $# $<
where ASM is a.s b.s c.s, is not a pattern rule because the targets don't contain a pattern character %. That means the prerequisite %.c is not treated as a pattern, but as an actual file name, literally %.c which obviously doesn't exist.
Similarly, this:
all: %.o
has the same problem: all is a target, so this depends on the literal file named %.o which doesn't exist, and can't be created.
Also as a general rule every recipe that creates a target must create the actual target you told make it would, so this all rule is wrong because the target name is all but the recipe creates the target test.
Finally, it's a very bad idea to name your program test because test is a common UNIX program and a shell built-in, so if you run test it won't do the right thing (if you run ./test it will work).
You want to have all depend on the program you want to build, say mytest, and mytest should depend on the actual .o files:
all: mytest
mytest: $(SOURCE:.c=.o)
gcc -o $# $^
Next, you need to define a pattern rule that knows how to create an assembly file from a source file:
%.s : %.c
gcc -S -o $# $<
That, along with your other pattern rules, is all you need: make will figure it all out from that.
Finally, make has a built-in rule that tells it how to build object files directly from source files. It's best to get rid of this to force make to use your rules; add this to your makefile to delete it:
%.o : %.c
Hopefully this is a very simple question. I have a makefile pattern rule that looks like this:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
I want the makefile to build a number of .so files, so I tried to get it to build two files (radgrd_py.so and lodiso_py.so) by doing this:
radgrd_py.so lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
and then tried this:
radgrd_py.so:
lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
But in each case, it only builds the first target that I specify. If I run 'make radgrd_py.so' it works fine, I'm just not sure how to specify a list of files that need to be built so I can just run 'make'.
The usual trick is to add a 'dummy' target as the first that depends on all targets you want to build when running a plain make:
all: radgrd_py.so lodiso_py.so
It is a convention to call this target 'all' or 'default'. For extra correctness, let make know that this is not a real file by adding this line to your Makefile:
.PHONY: all
Best way is to add:
.PHONY: all
.DEFAULT: all
all: radgrd_py.so lodiso_py.so
Explanations:
make uses the first target appearing when no .DEFAULT is specified.
.PHONY informs make that the targets (a coma-separated list, in fact) don't create any file or folder.
all: as proposed by schot
New guy learning programming with C in ubuntu
Using a hello.c for example
From some video tutorial I saw the teacher can use "make hello" to compile the hello.c without setting up a Makefile in current directory
And the command goes like
bash$ make hello
gcc -g -Wall hello.c -o hello
I tried to use make on my own ubuntu 14.04
I installed build-essential and tried out the same hello.c
bash$ make hello
cc hello.c -o hello
It goes like above
How can I make changes to get -g, -Wall or any other flags?
What you need
The way make works is that it produces targets out of sources through known recipes.
When you write your own Makefile, you provide the recipes for it, however, make has internal recipes, which can be used. You can list them by make -p.
One of the recipes tells make how to produce <something> out of <something>.c. When you run make hello, make checks how to produce hello, finds that there is a file hello.c and that it knows how to produce hello from hello.c -- using that internal rule.
Now the rule looks like this.
%: %.c
# recipe to execute (built-in):
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $#
and the important part, $(LINK.c) looks like this
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
You don't need to understand the syntax at this point, the important thing is, that your make hello will be transformed into (some unused variables omitted)
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) hello.c -o hello
Now CC, CFLAGS, CPPFLAGS and LDFLAGS may be set by make (in your case, CC is set to "cc" and the rest is not set), but you can override this with your environment variables. What you want is having
CC=gcc
CFLAGS="-g -Wall"
How to get it
To do that for one command only run:
CC=gcc CFLAGS="-g -Wall" make hello
To do that for one session (until you close your terminal) run
export CC=gcc
export CFLAGS="-g -Wall"
and then just make hello or make whatever as long as you want.
To do that permanently, set these variables in your .profile file (open ~/.profile (create it if it doesn't exist) and add
export CC=gcc
export CFLAGS="-g -Wall"
to it. Or just run
echo 'export CC=gcc' >> ~/.profile
echo 'export CFLAGS="-g -Wall"' >> ~/.profile
In both cases, you need to source ~/.profile or start a new terminal. It will work happily ever after.
Make has a number of implicit rules, which are used in the absence of a Makefile.
The one regarding .c files is:
n.o is made automatically from n.c with a recipe of the form $(CC) $(CPPFLAGS) $(CFLAGS) -c
This means you can set the environment variables:
CC to set the compiler used;
CPPFLAGS to set the preprocessor flags used (the same would be used e.g. for C++ .cpp or Fortran .F sources);
CFLAGS to set the compiler flags used.
The implicit rule turns the .c source file into a .o object file, which is then linked to an executable according to another implicit rule:
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)’.
Again, you see the environment variables used.
Is it possible to write universal Makefile which would get any target and act like a wrapper to gcc, but with parameters? For example, this means that
make 01.c
will have the same result as
g++ -o 01.out 01.c
make already has several "implicit rules" to do what you're trying.
For example, even with no makefile,
make 01.o
Will run:
c++ -c -o 01.o 01.cpp
If it finds a file called 01.cpp in your current directory. You can set the CXXFLAGS environment variable if you want to pass more flags. If you're really set on using g++ rather than the system compiler, you can set CXX=g++, too.
Yes - You using implicit rules.
Summat like (if memory serves me right)
.cpp.o:
$(CCC) $(CFLAGS) $< -o $#
Maybe in the set of default implicit rules
You can use a wildcard - %.
However, the thing specified on the commandline is the target, not the source - what you want, not what you have.
It looks like what you want is approximately:
%.out: %.c
g++ -o $# $<
This means: to make (something).out, first make sure you have (something).c, then run g++ -o (something).out (something).c
$# is always the target file, and $< is the first prerequisite.
You will need to run make 01.out, not make 01.c
For example, I have 10 source files named ex1.c, ex2.c, ex3.c....ex10.c and maybe more in the future.
Is it possible that I can use commandline argument as a variable in GNU Make so that when I want to compile ex1.c, I can type in make 1. If I want to compile ex10.c, I can type in make 10. And I don't need to add more lines to makefile when I add more sources like ex100.c later.
This doesn't strike me as a good idea, but yes, you can do it.
To build object files (e.g. ex3.o):
%: ex%.c
$(CC) -c $< -o ex$*.o
To build executables (e.g.ex3):
%: ex%.c
$(CC) $< -o ex$*