Makefile order, doesn't compile everything - c

I have a makefile with this simple rules,
ref_approx_bs2_rsq_5_10_1ulp_arch1 : ref_approx_bs2_rsq_5_10_1ulp_arch1.o
gcc -I../CModels -L../CModels -std=c99 -o ref_approx_bs2_rsq_5_10_1ulp_arch1 ref_approx_bs2_rsq_5_10_1ulp_arch1.o -lm -limg_float
ref_approx_bs2_rsq_5_10_1ulp_arch1.o : ref_approx_rsq.c ../CModels/cogen_fp_bs2_rsq_5_10_1ulp_arch1.cpp ../CModels/cogen_fp_bs2_rsq_5_10_1ulp_arch1.h ../CModels/img_float.h ../CModels/img_float.c
gcc -DCMODELLOC=\"../CModels/cogen_fp_bs2_rsq_5_10_1ulp_arch1.cpp\" -DCMODEL_NAME=cogen_fp_bs2_rsq_5_10_1ulp_arch1 -std=c99 -o ref_approx_bs2_rsq_5_10_1ulp_arch1.o -c ref_approx_rsq.c
libimg_float.a : ../CModels/img_float.o
ar -rcs ../CModels/libimg_float.a ../CModels/img_float.o
img_float.o : ../CModels/img_float.h ../CModels/img_float.c
gcc -I ../CModels/ -o ../CModels/img_float.o -c ../CModels/img_float.c
But basically if I modify img_float.c and try to use the make file again it doesn't compile and create libimg_float.a.
The makefile itself looks correct to me since I've written all the prerequisites.
Any suggestion?

It won't recompile libimg_float.a because nothing depends on it.
Make doesn't go through your makefile and always try to rebuild every target. Make works by finding the first (explicit) target listed and trying to build that. Before building the first target, it will try to build all the prerequisites of that target, and before that it will try to build all the prerequisites of those targets, etc. until no more prerequisites are found.
If there is a target which is not a prerequisite of the first target (or its prerequisites, etc.) then it will not be built, by default. You can request that it be built by listing it on the command line: make libimg_float.a will tell make to build that target, instead of the first explicit target. Of course you can list lots of targets on the command line.
But generally people create one target first, commonly called all, which lists all the targets that should be built by default as a prerequisite.
Here, though, your makefile is not right because your ref_approx_bs2_rsq_5_10_1ulp_arch1 target does use libimg_float.a, but it's not listed as a prerequisite. That means it won't be updated when libimg_float.a is out of date. You should change your makefile to show that prerequisite relationship:
ref_approx_bs2_rsq_5_10_1ulp_arch1 : ref_approx_bs2_rsq_5_10_1ulp_arch1.o libimg_float.a

Related

What is the CMake equivalent of the GCC -c option?

For example, if I had a makefile that contains this:
dynArray.o: dynArray.c dynArray.h type.h
gcc -Wall -ansi -c dynArray.c
How would I translate that into a CMakeLists.txt file?
Probably CMake's object libraries would do that, that mean compile objects but not archive them like normal library would.
add_library(<name> OBJECT <src>...)
Since an object file alone is not the end result of what you are building, I suspect there is more context to the question that is missing. You are probably building an executable from the objects. Just use add_executable to specify your target and the source files that make up the target. Then use target_compile_definitions to specify the compile options you want while compiling source files for that target. For example:
add_executable(dynArray dynArray.c dynArray.h type.h)
target_compile_definitions(dynArray PRIVATE -Wall -ansi)
You can verify that the resulting compile commands are what you expect by using the Unix Makefiles generator and passing VERBOSE=1 to the make command:
mkdir build; cd build
cmake -G "Unix Makefiles" ..
make VERBOSE=1
This will cause the generated Makefile to display the full command lines used on every step of the build.

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.

Makefile: ...is up to date

I have made a makefile for some c files. I have seen too many ways on the internet but i had always the same problem: make: `q_a' is up to date.
q_a:
gcc -o q_a quick_sort_i.c
q_g:
gcc -o q_g quick_sort_g.c
s_a:
gcc -o s_a shell_sort_i.c
s_g:
gcc -o s_g shell_sort_g.c
fork:
gcc -o fork fork.c
I have not files with the same name in my folder and I can compile them when I write in terminal. Can you help? Thanks in advance!
You have not specified dependencies for your targets.
What make does, is first checking if your target (q_a) exists as a file, and if it does, if its dependencies are newer (as in, have more recent modification time) as your target. Only if it needs to be updated (it does not exist or dependencies are newer) the rule is executed.
That means, if you need q_a to be recompiled every time quick_sort_i.c is changed, you need to add it as a dependency to q_a, like this:
q_a: quick_sort_i.c
gcc -o q_a quick_sort_i.c
With that, make will recompile q_a if necessary.

How to make a makefile properly, Why is this makefile not correct

I am trying to understand how to make a make file in Linux, and some one suggested to me to use this:
target: mytalkc.c mytalkd.c
gcc mytalkc.c -o mytalkc
gcc mytalkd.c -o mytalkd
When executing the above code exactly using "make" in the terminal everything ran great and everything compiled and made a executable successfully. So I thought this was correct, and I went with this for my makefile.
After futher documentation I learned that the correct way to make a makefile was not what I had above....
My question is, why does "target:" work and why was make was able to complete everything with no errors. Also why is things like "all:" used in make files over "target:" ?
Thanks in advance and sorry if it seems obvious, but I am new to Linux programming.
Typically a makefile is structured into multiple target rules, which contain dependencies that may rely on other dependences and so on. The word "all" is suggestive of "all targets", which means any dependencies of the "all" target are built. Additionally, some implementations of make allow for phony targets, such as "all", that tell make not to look for a file with one of the suffixes in a predefined suffix list, such as "all.c" to build the binary (program) with the filename "all".
Your actual question regarding why "target" works pertains to the behavior of make. It automatically makes the first target in the makefile unless a specific target is given. In your case, "target" is the first target in your file, so "make" by itself will make it (often "all" is used instead, but it is just a name; you should use "all" to simply because it is common practice).
Here is an example of how your file might be reworked with multiple targets (see the documentation for your make utility to understand the syntax, such as "info make" or "man make"):
all: mytalkc mytalkd
mytalkc: mytalkc.c
gcc $< -o $#
mytalkd: mytalkd.c
gcc $< -o $#
There are a lot of other things to address outside the scope of this answer, including implicit suffix rules and compiling several individual parts of a program/library together to create the program (splitting makefile rules into program/library: object1.o object2.o main.o and then individual rules for e.g. object1.o: object1.c). However, those are the basics that you need to know for now.
For what i know if you compile using gcc mytalkc.c -o mytalkc you are just compiling the source file as an object, it means that the compilation went well, but the file is not executable still because you haven't done any liking.
Try with this:
all: mytalkc.o mytalkd.o
mytalkc.o: mytalkc.c
gcc mytalkc.c -c mytalkc.c
mytalkd.o: mytalkd.d
gcc mytalkc.c -c mytalkd.c
invoking make all

make: Nothing to be done for `all'

I am going through an eg pgm to create a make file.
http://mrbook.org/tutorials/make/
My folder eg_make_creation contains the following files,
desktop:~/eg_make_creation$ ls
factorial.c functions.h hello hello.c main.c Makefile
Makefile
# I am a comment, and I want to say that the variable CC will be
# the compiler to use.
CC=gcc
# Hwy!, I am comment no.2. I want to say that CFLAGS will be the
#options I'll pass to the compiler
CFLAGS=-c -Wall
all:hello
hello:main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
main.o:main.c
$(CC) $(CFLAGS) main.c
factorial.o:factorial.c
$(CC) $(CFLAGS) factorial.c
hello.o:hello.c
$(CC) $(CFLAGS) hello.c
clean:
rm -rf *o hello
error:
desktop:~/eg_make_creation$ make all
make: Nothing to be done for `all'.
Please help me understand to compile this program.
Sometimes "Nothing to be done for all" error can be caused by spaces before command in makefile rule instead of tab. Please ensure that you use tabs instead of spaces inside of your rules.
all:
<\t>$(CC) $(CFLAGS) ...
instead of
all:
$(CC) $(CFLAGS) ...
Please see the GNU make manual for the rule syntax description: https://www.gnu.org/software/make/manual/make.html#Rule-Syntax
Remove the hello file from your folder and try again.
The all target depends on the hello target. The hello target first tries to find the corresponding file in the filesystem. If it finds it and it is up to date with the dependent files—there is nothing to do.
When you just give make, it makes the first rule in your makefile, i.e "all". You have specified that "all" depends on "hello", which depends on main.o, factorial.o and hello.o. So 'make' tries to see if those files are present.
If they are present, 'make' sees if their dependencies, e.g. main.o has a dependency main.c, have changed. If they have changed, make rebuilds them, else skips the rule. Similarly it recursively goes on building the files that have changed and finally runs the top most command, "all" in your case to give you a executable, 'hello' in your case.
If they are not present, make blindly builds everything under the rule.
Coming to your problem, it isn't an error but 'make' is saying that every dependency in your makefile is up to date and it doesn't need to make anything!
Make is behaving correctly. hello already exists and is not older than the .c files, and therefore there is no more work to be done. There are four scenarios in which make will need to (re)build:
If you modify one of your .c files, then it will be newer than hello, and then it will have to rebuild when you run make.
If you delete hello, then it will obviously have to rebuild it
You can force make to rebuild everything with the -B option. make -B all
make clean all will delete hello and require a rebuild. (I suggest you look at #Mat's comment about rm -f *.o hello
I think you missed a tab in 9th line.
The line following all:hello must be a blank tab. Make sure that you have a blank tab in 9th line. It will make the interpreter understand that you want to use default recipe for makefile.
That is not an error; the make command in unix works based on the timestamps. I.e let's say if you have made certain changes to factorial.cpp and compile using make then make shows
the information that only the cc -o factorial.cpp command is executed. Next time if you execute the same command i.e make without making any changes to any file with .cpp extension the compiler says that the output file is up to date. The compiler gives this information until we make certain changes to any file.cpp.
The advantage of the makefile is that it reduces the recompiling time by compiling the only files that are modified and by using the object (.o) files of the unmodified files directly.
Using the comment from Paul R, I found that
make clean
followed by
make
or
make all
fixed my problem.
I arrived at this peculiar, hard-to-debug error through a different route. My trouble ended up being that I was using a pattern rule in a build step when the target and the dependency were located in distinct directories. Something like this:
foo/apple.o: bar/apple.c $(FOODEPS)
%.o: %.c
$(CC) $< -o $#
I had several dependencies set up this way, and was trying to use one pattern recipe for them all. Clearly, a single substitution for "%" isn't going to work here. I made explicit rules for each dependency, and I found myself back among the puppies and unicorns!
foo/apple.o: bar/apple.c $(FOODEPS)
$(CC) $< -o $#
Hope this helps someone!
I was trying to install libuv on Ubuntu and i also got the error make: Nothing to be done for 'all'. As i see it, using make gives two ways to solve the problem, one for check and one for install. But i found a workaround
still use the sudo make check command - it helps to read all the error messages before deciding on further actions. Basically, i've introduced a regression that makes the update workaround inefficient. This error comes from make however, the workaround from install fixes this, just try to run sudo make install and see what happens.
The make command will be a local optimization at the expense of the overall result of check/install - c'est ma façon de parler.
I believe i have narrowed down the problem considerably: in the first case after check i have "FAIL: test/run-tests" and in the second after install i get "specify the full pathname of the library, or use the '-LLIBDIR'" This argument to check/install can be a list object to store information about completed installations.
So install reports partial success when nothing actually happened.
Try running the commands from root:
cd your_program
sh autogen.sh
./configure
make
make check
make install
And then he writes that the installation was successful:
Libraries have been installed in:
/usr/local/lib
In your case, I strongly feel the only and simple problem you had is that you only preprocessed your app. You did so by having the flag -c under CFLAGS.

Resources