Makefile help


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Makefile help
# 1  
Old 10-13-2012
Makefile help

I am creating a make file, but i keep getting an error when i try to run it with the following code:

Code:
make foo . make $(EXE)

i get

Code:
EXE: command not found
make: `foo' is up to date.
make: Nothing to be done for `.'.
make: *** No rule to make target `make'.  Stop.

Here is my Makefile

Code:
cc  = gcc
EXE = foo
JAVAC = javac
JRE = java
PAGER = less
TEST_OUT = test.out
EXP_OUT = expected.out

foo.o: foo.c foo.h
   $(cc) -c foo.c

main.o: main.c foo.h
   $(cc) -c main.c

$(EXE): foo.o main.o
   $(cc) -o$(EXE) main.o foo.o

run-c: $(EXE)
   ./$(EXE)

Not sure what the errors mean
# 2  
Old 10-13-2012
Quote:
Originally Posted by football12345
Code:
make foo . make $(EXE)

i get

Code:
EXE: command not found
make: `foo' is up to date.
make: Nothing to be done for `.'.
make: *** No rule to make target `make'.  Stop.

Not sure what the errors mean
The errors are to take quite literally:

You execute "make" with the arguments "foo" "." "make" and "$(EXE)".

The first error is from the shell, because "$(EXE)" means run command "EXE" in a subshell and put its output here. The shell thinks that the rest of the command depends on what EXE might output and therefor execute it first - as there is no "EXE, this fails.

Next, "make" is executed and takes the argument: "foo". For "foo" exists a target to make and "make" does try to make it but notices that it has already done so and in the meantime "foo" hasn't changed - so it tells you that "foo" is already up to date. Next make tries to "make .". As "." is the current directory and there is no rule in your makefile describing how to make "." "make" tells you so. Finally it tries to make "make", which would be (like ".") a perfectly valid target to make - IF it would exist in your makefile. As it doesn't, "make" tells you the same as with ".": it can't make it, because you haven't told it how.

But instead of writing a long-winded make-exegesis, i could probably tell you what you need to know, so: what exactly do you want to achieve? Have you ever used a makefile and know its purposes? Its syntax?

I hope this helps.

bakunin
# 3  
Old 10-13-2012
Quote:
Originally Posted by bakunin
The errors are to take quite literally:

You execute "make" with the arguments "foo" "." "make" and "$(EXE)".

The first error is from the shell, because "$(EXE)" means run command "EXE" in a subshell and put its output here. The shell thinks that the rest of the command depends on what EXE might output and therefor execute it first - as there is no "EXE, this fails.

Next, "make" is executed and takes the argument: "foo". For "foo" exists a target to make and "make" does try to make it but notices that it has already done so and in the meantime "foo" hasn't changed - so it tells you that "foo" is already up to date. Next make tries to "make .". As "." is the current directory and there is no rule in your makefile describing how to make "." "make" tells you so. Finally it tries to make "make", which would be (like ".") a perfectly valid target to make - IF it would exist in your makefile. As it doesn't, "make" tells you the same as with ".": it can't make it, because you haven't told it how.

But instead of writing a long-winded make-exegesis, i could probably tell you what you need to know, so: what exactly do you want to achieve? Have you ever used a makefile and know its purposes? Its syntax?

I hope this helps.

bakunin
I am trying to Compile a C program. Run a C program. Run a Python program. Compile and run a java program. Check for a README, display it. Compare 2 files. Clean up intermediary files.

I am only on the first part right now, because run does not seem to work.
# 4  
Old 10-13-2012
OK, here is a short introduction to make and makefiles:

Compiling, linking and running programs is a quite repetitive task: every change in any program file will make it necessary to recompile, relink and re-run the program. Well, in fact: no. Yes, you will have to run the program again, but you do not need to compile and link all the program sources - just the relevant parts. What the relevant parts are in each case is called a "dependency": object files are depending on certain source files, libraries and binaries are depending on the objects. What you do in a makefile is to create rules, how to get a depending file from its dependencies.

Lets try an example: we have 5 source files "src1", "src2", etc. and 3 header files "h1", "h2", "h3". Together they should form a library (src2-4) and a binary (src1 and src5). Lets say our compile command is "compile" and our linkage editor is called "link". "link -b" will create binaries, "link -l" will create libraries.

The first you have to do is to consider what is depending on what: every source file goes into one object file, but maybe not every header is used in every source. Lets say "h1" is used in every source, "h2" only in src4 and "h3" only in src2 and src4. The resulting objects will go into two files (see above, a binary and a library). Here are these dependencies:

Code:
src1, h1 ---------> obj1 --------------+
src2, h1, h3  ----> obj2 --+           |
src3, h1  --------> obj3 --+--> lib1   |
src4, h1, h2, h3 -> obj4 --+           |
src5, h1 ---------> obj5 --------------+--> bin1

As you see every entry on the right side is depending on one or several entries on the left. "make" now does the following: it compares file dates on the files on the left and the right side and if a target (the right side) is older than any of its dependencies it recreates this target. For instance, if "src1" would change, "make would create "obj1" anew. Now, because "bin1" has a changed dependency, it is also recreated, but "lib1" is not, because nothing has changed in its path. Would you have changed "h1", everything would have been recreated.

We are now ready to create our makefile. A makefile consists of rules, which in turn have three parts:

- the target: the file which has to be created
- the dependencies: all the files necessary to create the target
- the action: the command(s) necessary to create the target from the dependencies.

The format is:

Code:
target: dep1 dep2 dep3 ....
           command1
           command2
           command3
           ...etc.

So we write first the rules to create the objects from the sources and headers:

Code:
# Sample Makefile v1: compiler calls

obj1: src1 h1
       compile src1 h1 --output obj1

obj2: src2 h1 h3
       compile src3 h1 h3 --output obj2

obj3: src3 h1
       compile src3 h1 --output obj3

obj4: src4 h1 h2 h3
       compile src1 h1 h2 h3 --output obj4

obj5: src5 h1
       compile src5 h1 --output obj5


Now all the sources get compiled, but not linked yet. Let us add these rules too:

Code:
# Sample Makefile v2: compiler calls and linkage editor

all: bin1 lib1

obj1: src1 h1
       compile src1 h1 --output obj1

obj2: src2 h1 h3
       compile src3 h1 h3 --output obj2

obj3: src3 h1
       compile src3 h1 --output obj3

obj4: src4 h1 h2 h3
       compile src1 h1 h2 h3 --output obj4

obj5: src5 h1
       compile src5 h1 --output obj5

lib1: obj2 obj3 obj4
       link -l obj2 obj3 obj4 --output lib1

bin1: obj1 obj5
       link -b obj1 obj5 --output bin1

You will notice the rule "all", which has no commands at all. This is the default rule "make" will try to execute if no other rule is given as parameter.

You can name this file simply "Makefile" and call "make" without any parameter. "make" will look for a rule file called "Makefile" (capitalized "M") by default and execute the "all" rule and all necessary rules for this target in it if it finds one. But you can also call one of its rules, for instance "make bin1" or "make obj3". It will execute only this rule then (if that target is not up to date).

Now, ok, the program gets compiled and linked, but is that all "make" can do?

No, not at all. It is true in was invented to compile and link programs, but you can do everything which you can press into such rules. For instance you can create an installation rule. For the installation of our example program the binary should go to "/usr/local/bin/bin1.exe" and the library to "/usr/local/lib/bin1/lib1.a". Lets add such a rule:

Code:
# Sample Makefile v3: compiler calls, linkage editor and installation

all: bin1 lib1

obj1: src1 h1
       compile src1 h1 --output obj1

obj2: src2 h1 h3
       compile src3 h1 h3 --output obj2

obj3: src3 h1
       compile src3 h1 --output obj3

obj4: src4 h1 h2 h3
       compile src1 h1 h2 h3 --output obj4

obj5: src5 h1
       compile src5 h1 --output obj5

lib1: obj2 obj3 obj4
       link -l obj2 obj3 obj4 --output lib1

bin1: obj1 obj5
       link -b obj1 obj5 --output bin1

install: bin1 lib1
       mkdir -p /usr/local/bin 2>/dev/null
       mkdir -p /usr/local/lib/bin1 2>/dev/null
       cp bin1 /usr/local/bin/bin1.exe
       cp lib1 /usr/local/lib/bin1/lib1.a

Notice that there is no file "install" and it isn't created in the process. It is perfectly valid to have rules where the target doesn't exist. As this rule ins not depending on "all" you can still compile and link your program with "make" (without parameter) and install it by "make install".

It is also not necessary for a target to have dependencies: we could also add the following rule, to clean our compile-directory of old objects and binaries or to force a complete recreation of everything in a new run:

Code:
clean:
       rm -f *o
       rm -f bin1
       rm -f lib1

"make clean" would no remove all the compiler leftovers from previous make-runs.

To add even more flexibility to your makefiles, suppose you would want to change the compiler. Right now you use "compiler", but suppose there is a new compiler "comp_new", you would want to use. And suppose, too, that you want to use certain default compiler flags when you create your objects. You could change youe makefile in every line of course, but you can also use variables. The basic syntax for the assignment and the usage of a variable is:

Code:
# the assignment:
VARIABLE = VALUE

# the usage (this will get replaced with the content upon execution):
$(VARIABLE)

So we change the makefile a last time:

Code:
# Sample Makefile v4: compiler calls, linkage editor and installation
# added variables

# switch between these two lines to change compilers:
# COMPILE = compile
COMPILE = comp_new
# our compilers might need different switches:
# CFLAGS = -x1 -y1 -z1
CFLAGS = -X2 -Y2 -Z2

LFLAGS = -a -b -c

obj1: src1 h1
       $(COMPILE) $(CFLAGS) src1 h1 --output obj1

obj2: src2 h1 h3
       $(COMPILE) $(CFLAGS) src3 h1 h3 --output obj2

obj3: src3 h1
       $(COMPILE) $(CFLAGS) src3 h1 --output obj3

obj4: src4 h1 h2 h3
       $(COMPILE) $(CFLAGS) src1 h1 h2 h3 --output obj4

obj5: src5 h1
       $(COMPILE) $(CFLAGS) src5 h1 --output obj5

lib1: obj2 obj3 obj4
       link -l $(LFLAGS) obj2 obj3 obj4 --output lib1

bin1: obj1 obj5
       link -b $(LFLAGS) obj1 obj5 --output bin1

install: bin1 lib1
       mkdir -p /usr/local/bin 2>/dev/null
       mkdir -p /usr/local/lib/bin1 2>/dev/null
       cp bin1 /usr/local/bin/bin1.exe
       cp lib1 /usr/local/lib/bin1/lib1.a

clean:
       rm -f *o
       rm -f bin1
       rm -f lib1


"make" is not limited to programming at all. I have seen people using it to do their backup, process automated mails and what not. The limitation is only what you are able to imagine.

For this you will probably find some more features (which i have intentionally left out for clarity) handy: rules for processing whole classes of files, so that you don't have to write the rule for every file anew, complex variables which change their contents depending on which file has invoked the rule (like: "$<", "$@", and so on) , etc., etc..

I suggest reading the man page and probably one or the other book about "make" (yes, there have been books written about the topic) to find out more. This here is just meant as a starter and I'll keep it at that.

I hope this helps.

bakunin
These 2 Users Gave Thanks to bakunin For This Post:
# 5  
Old 01-08-2013
Makefile rules

Very good introduction! Thank you!
While I was reading a similar instruction about Makefile from LQ forum(http://www.linuxquestions.org), I have a confusion about two Makefile examples :
Makefile1:
Code:
all: temp.txt

temp.txt: target
    @echo "temp.txt has been created."

target: dep3
    echo $(string)                       >> temp.txt
    @echo "That's all I can tell you right now." >> temp.txt

# and let's mix 'em up a bit...

dep1:
    @echo "My name is 'echo'" >> temp.txt

dep3:dep2
    @echo "if you don't mind my asking."  >> temp.txt
    @echo                                 >> temp.txt

dep2:dep1
    @printf "What are you doing? "  >> temp.txt

# this tag/target will run when we type 'make clean'
clean:
    @rm temp.txt

Makefile2:
Code:
string = "I'm doing something!"

all: temp.txt
    @echo "temp.txt has been created."

temp.txt:
    @echo "My name is 'echo'" >> temp.txt
    @printf "What are you doing? "  >> temp.txt
    @echo "if you don't mind my asking."  >> temp.txt
    @echo                                 >> temp.txt
    @echo $(string)                       >> temp.txt
    @echo "That's all I can tell you right now." >> temp.txt

clean:
    @rm temp.txt

After I run make several times, Makefile1 will create temp.txt file of multiple lines, i.e. contents accumulated accordingly.
My confusion is Makefile2 does not give the same result, i.e. I ran make several times, the content of temp.txt does NOT accumulate!
The author stated:
Code:
Why didn't the make file keep writing strings into the file this time?
  [Once the file existed there was nothing more that needed to be done for the 'rule' governing temp.txt.]

which seems unclear to me, as both will create temp.txt at the first "make". Could you explain it for me? I think I missed a very important point about Makefile.

According to the same article, I modified Makefile2 and removed the line below all: @echo "temp.txt has been created."
Makefile3:
Code:
string = "I'm doing something!"

all: temp.txt

temp.txt:
    @echo "My name is 'echo'" >> temp.txt
    @printf "What are you doing? "  >> temp.txt
    @echo "if you don't mind my asking."  >> temp.txt
    @echo                                 >> temp.txt
    @echo $(string)                       >> temp.txt
    @echo "That's all I can tell you right now." >> temp.txt

clean:
    @rm temp.txt

and tried to run make:

Code:
make    #fine, temp.txt created
make    #Error, or warning:
make: Nothing to be done for 'all'.

My understanding for this third (and the 2nd) example is, temp.txt has been created, so that any "make" will not do the job once temp.txt is there. Am I correct? But in Makefile1 the temp.txt is also there? I must have missed one rule of Makefile.
Thanks a lot!
# 6  
Old 01-08-2013
That is confusing indeed. I'm not quite sure what's going on.

Your assignment looks wrong however. Like in shell, you shouldn't have a space before the equal:
Code:
string="I'm doing something!"

# 7  
Old 01-08-2013
Thanks Corona for pointing that out.
Which is one example of the tricks I am trying to get familiar with, but it works.
The examples were from the LQ forum while I was self-study the Makefile skill. I believe the original author left the spaces and . (dots) in the string to show the idea of dependency in Makefile. I posted here to get expert direction about my confusion on the target of Makefile (temp.txt, in this case). By the way, I am aware this is ABC for computer science, not my subject. Thanks anyway.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Programming

Makefile for g++

Hi All, We have moved our OS from Sun Solaris to Linux and also some of the compilers. Our old makefile used to be as below: CC=cc FLAGS=-G -KPIC -DLG_SOLARIS_OS DEFINES=-DSunOS SYSLIBS=-lc .SUFFIXES : .c .c.o : ;$(CC) -c $(FLAGS) $(DEFINES) $*.c -o $*.o ... (3 Replies)
Discussion started by: shash
3 Replies

2. UNIX for Dummies Questions & Answers

MakeFile

Hey everybody, This may be stup*d question for you, but i am new in unix and i wonder how can i make the rules for translating and linking my .c "primjer1.c", "primjer2.c" and "primjer3.c" in makefile. Thank you. (7 Replies)
Discussion started by: jskako
7 Replies

3. Shell Programming and Scripting

Makefile

Dear all, I have a quite simple question about how to manipulate "makefile.am". I intend to: 1. "CFLAGS" and "CXXFLAGS" have no value at all. I know that these values get "-g -O2" by default. On the other hand, when I try to set them as "CFLAGS = " in "makefile.am", I get warning messages... (4 Replies)
Discussion started by: Dandan
4 Replies

4. UNIX for Dummies Questions & Answers

Help with MakeFile

I'm really confused how to use a makefile. Are you supposed to be make a file from emacs called MakeFile and put code in there to compile? I am trying to create a makefile to compile two .cpp files in my current directory to produce two .o files and then link them... What I did was make a... (1 Reply)
Discussion started by: jzhang172
1 Replies

5. Homework & Coursework Questions

Makefile Help

Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted! 1. The problem statement, all variables and given/known data: I have been trying to make the program swap but i have been getting errors with the makefile such as driver.o:... (1 Reply)
Discussion started by: mgyeah
1 Replies

6. Homework & Coursework Questions

Help with Simple Multi-Level Makefile (Extremely New at Makefile)

Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted! 1. The problem statement, all variables and given/known data: Basically, the prompt is make a makefile with various sub makefiles in their respective subdirectories. All code... (1 Reply)
Discussion started by: Tatl
1 Replies

7. UNIX for Advanced & Expert Users

Makefile executing another Makefile first?

I have 2 libraries in 2 different directories that I build with Makefiles. library B depends on library A. If I modify a .cpp file in library A and run lib B's Makefile can I have B's makefile to automatically rebuild library A? I am now rebuilding A, followed by B... but I'd like B to... (0 Replies)
Discussion started by: wwuster
0 Replies

8. UNIX for Advanced & Expert Users

Makefile problem - How to run module load in a Makefile

Hi, I'm trying to run the module load command in a Makefile and i'm getting the following error: make: module: command not found Why is this? Is there any way to run this command in a Makefile? NOTE: command - module load msjava/sunjdk/1.5.0 works fine outside of the Makefile (2 Replies)
Discussion started by: hernandinho
2 Replies

9. High Performance Computing

help with makefile

I am new to creating makefiles. I have several fortran programs in a folder called as "test" and also have several subroutines in another folder (which is inside this test folder) called as libry My makefile is in the folder "test" I want to create a makefile which can access the files in... (2 Replies)
Discussion started by: explorer
2 Replies

10. Programming

about the makefile

can anyone well explain how to create a makefile? especially those commands in the makefile? BTW, what is CFLAG? (2 Replies)
Discussion started by: ligerdave
2 Replies
Login or Register to Ask a Question