Makefile dependency being ignored - c

I created a simple makefile to understand the basic idea behind how they work and it's not performing the way I expected. Please see the following:
test: test.c
gcc -o test test.c
My understanding is this should only run when there have been changes to the test.c file. The problem is it runs every time regardless of whether or not there were changes.
I've noticed that this occurs when I use arbitrary target names. If I make the target name an actual file name such as "test.exe", it works correctly, but all the tutorials I've seen show dependencies working with arbitrary target names. Any idea as to why this is occurring?

Under Windows, Make automatically adds the suffix .exe to the generated program.
Since the name of the target is different from the result of the rule, Make tries to generate it again.
You should write your makefile like this:
EXE := test.exe
$(EXE): test.c
gcc -o $# $^
If you need portability and don't want to rewrite the rule, use this:
EXE := test
if ($(OS),Windows_NT)
EXE := $(EXE).exe
endif
$(EXE): test.c
gcc -o $# $^

Related

make command runs only the first row in Makefile

Hi I Have this makefile:
main.o:main.c functionsLab1.c functionsLab1.h
gcc -c main.c
functionsLab1.o: functionsLab1.c functionsLab1.h
gcc-c functionsLab1.c
now when i Run the command "make" it only executes the first command in makefile.
how can I Run all the commands at once?
Thanks in advance :)
I Tried to type "make all" command and it showed an error.
make is able to build what you need, but only if you tell it the right dependencies. In particular, your current Makefile is lying about dependencies, since main.o does not at all depend on functionsLab1.c. Rather, the final executable you are trying to build depends on functionsLab1.o. You can probably make your entire Makefile:
main: main.o functionsLab1.o
(Yes, literally one line.). That ignores the dependency on the header file, but it should work for you. Let make use its default rules; they are pretty good. If you want to include the header dependency, do something like:
main: main.o functionsLab1.o
main.o: main.c functionsLab1.h
functionsLab1.o: functionsLab1.c functionsLab1.h
If for some reason you really want to be explicit (you don't!), you can do:
main: main.o functionsLab1.o
$(CC) -o $# $? # Warning: incomplete. See note below
main.o: main.c functionsLab1.h
functionsLab1.o: functionsLab1.c functionsLab1.h
Again, letting make use its default rules to construct the object files. You can override the default rules, but there is very seldom a reason to do so. Indeed, this is an excellent example where attempting to override the default rule gives you a sub-optimal recipe. The default rule would be something like $(CC) $(LDFLAGS) -o $# $? $(LOADLIBES) $(LDLIBS), and many users would reasonably expect to be able to specify LDLIBS. The example shown above ignores LDLIBS, violating the principal of least surprise.

Including input statements and conditions in the make file

I am trying to create a makefile, for the first time. I went through some tutorials and I managed to create one, but I am having trouble with a couple of things. Below are the details.
Below are the files in the order of execution:
CSV_to_txt.c - no dependency on any other files.
I want to include CSV_files/Equilibrium_trajectories.csv, which is my input, in the make file. Further, I run the command tac Chemical_Equilibrium.txt in the terminal. Can I include this in the make file as well?
fluid_profile.c - depends on pdfutil.h and beta_util.h.
I have the same problem of reading the inputs, for ex:
Enter the number of points
1000 --> to be included in the make file.
This file creates a text file called fluid_points.txt. What I want to include in the makefile is if this file already exists don't execute the command gcc fluid_points.c -o fluid_points.o -lm.
Structure of the make file:
all:
gcc CSV_to_txt.c -o CSV_to_txt.o -lm
./CSV_to_txt.o
#Include the file path and name when asked for it
#ubuntu terminal command --> tac filename.txt > filename_changed.txt
gcc fluid_profile.c -o fluid_profile.o -lm
./fluid_profile.o
#Enter the number of points when prompted to do so
#If fluid_points.txt file is already existing don't execute the above command, instead execute the below one
gcc blah.c -o blah.o -lm
./blah.o
clean:
$(RM) *.o *~
Any sort of help or even a link to a tutorial would be helpful.
A suggested makefile:
run:
.PHONY: run
CSV_to_txt: CSV_to_txt.c
gcc CSV_to_txt.c -o CSV_to_txt -lm
fluid_profile: fluid_profile.c
gcc fluid_profile.c -o fluid_profile -lm
blah: blah.c
gcc blah -o blah.c -lm
run: CSV_to_txt fluid_profile blah
echo "CSV_files/Equilibrium_trajectories.csv" | ./CSV_to_txt.o
tac Chemical_Equilibrium.txt
echo "1000" | ./fluid_profile.o
./blah.o
clean:
$(RM) *.o *~
So, a break down -- first line, predeclare target run, such that it becomes the default target (if you do make, it will run the first target ). Declare this as a phony target (This means there's no actual file called run being produced. You can look up .PHONY for more details)
Then create some rules to generate the executables. Each executable has its own rule to generate it. Typically you would use automatic variables for these like $# and $<, but I wanted to keep it simple for now.
Then the rule for run. This is dependent on the executables (so executables will finish building before this rule runs).
Then, to pass the filename into the executable, you can simply echo the filename, and then pipe that into the executable.
You have a common newbie error... this is to think that a source file depends on other source files (a .c file depends on some .h files) This is an error and probably the cause you are not getting your result.
The objective of a Makefile is to describe file dependencies in order to do the minimum set of commands to build the final target you specify. For this you need to think that a target is something you are goint to create.
Is a source .c file something you create during the build proces? Not, so it cannot be a target of a rule. The target, indeed is the result of the compilation. The source file doesn't depend on a header file... it just includes it to make the compilation of the .o target (this is, actually the target).
Let's say you have a program hello.c that includes modA.h and modB.h. (and even modB.h includes modB2.h) If you modify any of them, you need to recompile hello.c, so your rule will be:
# (1)
hello.o: hello.c modA.h modB.h modB2.h
cc -c hello.c # (2) see below.
(1) a rule line starts at column 1 and has a left hand side (the target file) and a list of sources (dependencies). Each time make sees that the target doesn't exist or has a last change date earlier than the change dates of any of the dependencies, the command lines below are executed, one after the other.
(2) a command rule starts with a <tab> char in the first column of the line. It represents a command (or a list of commands, each in it's command line) that are required to generate the target file from the sources.
a line starting with # is a comment line (also valid to start in the middle of a rule or a command line)
There is anothe type of line (a macro definition) but you need to learn first how to create dependencies and get used to them, before starting learning how to create macros. Read the make(1) doc first.
you see that we only compile hello.c, but we have to do it every time we change any of the other files above. There are two modules, modA.o and modB.o, each of them with their .c file and the includes needed in hello.c. So:
modA.o: modA.c modA.h
cc -c modA.c
modB.o: modB.c modB.h modB2.h
cc -c modB.c
so when we change any of modA.c or modA.h then modA.o will be created. And as modB.h we said above that included modB2.h, then if we modify it, it should be compiled.
Now the dependency of the program to be linked: As the program is compiled, it has just three modules: hello.o, modA.o and modB.o. To create hello all these three modules must be given to the linker.... so the Makefile needs also:
hello: hello.o modA.o modB.o
cc -o hello hello.o modA.o modB.o
and so, the complete Makefile is:
# this rule is put first to become the default target.
# the default target is the final program.
hello: hello.o modA.o modB.o
cc -o hello hello.o modA.o modB.o
# this rule is for the hello.o target only.
hello.o: hello.c modA.h modB.h modB2.h
cc -c hello.c
# this rule is for modA.o
modA.o: modA.c modA.h
cc -c modA.c
# and this one for modB.o
modB.o: modB.c modB.h modB2.h
cc -c modB.c
and with this Makefile you'll enjoy, because you can touch any file, but the compiler will compile only the correct dependencies to generate the final executable program.
Make has a lot of more functionality, but that requires you to know at least the most basic of it. Once after you have succeeded on the creation of the correct dependencies, you can start to study the other facilities of make, that are only there to abbreviate/avoid rewritting the same thing several times. But read at least the make manual page.

Why is my very simple makefile not working

When I say very simple I mean it. I have a main.c and a header file called input_error.h.
main.o : main.c input_error.h
gcc -c main.c
When I run the command "make" gcc -c main.c is executed but it's not updating any changes I make to my main.c file. When I manually type in "gcc main.c" it works fine.
EDIT: It seems like I need to add another rule but I'm not sure what that entails
At the moment your makefile only builds the .o file. You can build your binary in 2 ways. Note that make requires the indentation in the targets statements to be a tab and not 4 spaces, as it may have been converted to by the browser.
build .o separately then link binary. Note that using the -c switch causes gcc to build only the object file.
main: main.o
gcc main.o -o main
main.o : main.c input_error.h
gcc -c main.c -o main.o
build in one step
main: main.c input_error.h
gcc main.c -o main
You can also avoid repetition in your makefile by using special variables to denote the target ($#), the first dependency ($<) and all (#^) the dependencies.
e.g. one of the above lines could become
main.o : main.c input_error.h
gcc -c $< -o $#
Which seems a bit cryptic at first but you get used it. The implicit rules in #kaylums answer will also help to cut down on typing.
The Makefile you have only has a single rule to compile the .o file. That is, it does not have any rule to link the final executable.
make has implicit rules for building many common targets. So your Makefile could be as simple as the following:
all: main
main.o : input_error.h
For further explanation:
all: main: Since this is the first target it is the one that will be built by default if no explicit target is provided to the make command line. It depends on a single target main.
There is no explicit rule for main but make has an implicit rule which will build it from main.c.
main.o : input_error.h: Tells make that main.o needs to be rebuilt if input_error.h changes. There is no need to put main.c here as make has that implicit knowledge. There is also no need for an explicit command as make also has that implicit.

Using LLDB for debugging C

I'm writing a small C library for some basic polygon operations and I'm trying to use LLDB from the command line for debugging. I am able to run LLDB with my compiled test runner, but I can only see assembly instructions and not C code as I step through.
I've compiled my library and test runner with the -g flag as shown here in this Makefile:
#Define compiler flags
CFLAGS = -g -Wall -Werror
#Define objects
OBJECTS = MASClip.o MASGraph.o MASClipTest.o
tests : $(OBJECTS)
cc $(CFLAGS) $(OBJECTS) -o tests
MASClip.o : MASClip.h MASClip.c
cc $(CFLAGS) -c MASClip.c
MASGraph.o : MASGraph.h MASGraph.c
cc $(CFLAGS) -c MASGraph.c
MASClipTest.o : MASClipTest.c
cc $(CFLAGS) -c MASClipTest.c
test :
make
make clean
./tests
.PHONY : clean
clean :
rm *.o
I can set breakpoints by function name so I don't understand why the code is not displayed.
I've searched around, but I don't see that I'm doing anything different from what the tutorials and other questions say. I must be missing something obvious.
Also, I realise I could just do this in Xcode, but when I write straight C I like to use VIM and it would be nice to be able to use LLDB from the command line.
How do I get LLDB to display the actual C code when debugging?
On OS X debug info is stored in .o files. The debugger refers back to the .o files using a "debug map" in the executable. Looks like you are deleting the .o files before you try to debug, so there's no debug information for the debugger.
Either leave the .o files in place when you debug, or run the dsymutil tool on the executable to produce a linked debug output file (.dSYM.) If you put the dSYM next to the executable (or anywhere that Spotlight searches) then lldb will find it automatically.
Note that if you just give the compiler a list of .c files, it will make a dSYM for you automatically - since it will delete the .o files when it is done - so that debugging is still possible.

C project with two examples, only one seems to compile, makefile issue

I'm working on an open source C project that has two example files to run the library, one called example.c, and one called test.c.
The Makefile consists of the following:
test: test.c src/term.c
$(CC) $^ -o $#
example: example.c src/term.c
$(CC) -std=c99 $^ -o $#
.PHONY: test example
However, when I run make and then do ./test, test runs, but when I do ./example, it doesn't. Any ideas why?
When you just type make the first target is being executed, in your case its test. So you will get only test executable. But if you type make example then example target is executed and you will get example binary. I think you need fresh up with Makefile rules.You can refer this for basic concepts or this for in depth understanding

Resources