How to tell Make to search for header files - makefile

If I wanted to compile a simple AVR C program, I would simply go:
avr-gcc -mmcu=atmega2560 -Os avr.c -o avr.o
And the code would compile with no errors. However, as soon as I put the above command in a Makefile, I get a compilation error saying that DDRC, PC2, and PORTC are undeclared (see the error chunk at the bottom). Since these constants are defined in avr/io.h I tried to put an -I parameter to point to the header files, but had no success. Here is my Makefile:
CC=avr-gcc
INCLUDE=-I/usr/avr/include
CCFLAGS+=$(INCLUDE)
build: avr.o
$(CC) -mmcu=atmega2560 -Os avr.c -o avr.o
I found a similar problem here, but I was not lucky applying the solution. I believe the problem is in avr-gcc not being able to find the required libraries, and I thought -I directive would sort that out. But it seems that I am doing some silly mistake I cannot find. What would be the right way of telling a Makefile where header files are?
The error message that happens only when invoked make build:
avr.c: In function 'main':
avr.c:17:5: error: 'DDRC' undeclared (first use in this function)
DDRC |= 1<<PC2; /* PC2 will now be the output pin */
^~~~
avr.c:17:5: note: each undeclared identifier is reported only once for each function it appears in
avr.c:17:16: error: 'PC2' undeclared (first use in this function)
DDRC |= 1<<PC2; /* PC2 will now be the output pin */
^~~
avr.c:19:9: error: 'PORTC' undeclared (first use in this function)
PORTC &= ~(1<<PC2);/* PC2 LOW */
^~~~~
make: *** [<builtin>: avr.o] Error 1
*** Failure: Exit code 2 ***
avr.c I am trying to compile using make:
#define F_CPU 100000000
#include <avr/io.h>
#include <util/delay.h>
void sleep(uint8_t millisec)
{
while (millisec) {
_delay_ms(1);/* 1 ms delay */
millisec--;
}
}
int main()
{
DDRC |= 1<<PC2; /* PC2 will now be the output pin */
while (1) {
PORTC &= ~(1<<PC2);/* PC2 LOW */
sleep(100);/* 100 ms delay */
PORTC |=(1<<PC2); /* PC2 HIGH */
sleep(100);/* 100 ms delay */
}
return 0;
}

This line in your makefile is the cause of your problems:
build: avr.o
What does this mean? It tells make that in order to create a target named build, it should look for a target named avr.o, either already existing or, if it doesn't exist, then make should build it (if it can figure out how to do so).
So before make even tries to run the recipe for this rule, it will FIRST try to create a file avr.o.
Well, you haven't told it how to create such a file, but luckily (or unluckily for you) make has a set of built-in rules that it can use to create some types of files that it knows about. One of those built-in rules says that if make wants to build a file *.o (for some string matching *) and it can find a file *.c (where * is the same as in *.o), then it can create the *.o with this recipe:
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $# $<
How does this expand? Well, you've set CC to avr-cc so it will use that compiler. You haven't set CFLAGS, CXXFLAGS, or TARGET_ARCH so it will use the default value for those variables, which is nothing. So, it will run this compile line:
avr-cc -c -o avr.o avr.c
If you look up at the top of your list of error messages, make will print the compile line it runs and you'll see it's NOT the compile line you wanted it to run.
So, you have lots of ways to fix this problem.
One option is to keep your variables and fix your rule:
CC=avr-gcc
INCLUDE=-I/usr/avr/include
CCFLAGS+=$(INCLUDE)
build: avr.c
$(CC) $(CCFLAGS) -mmcu=atmega2560 -Os avr.c -o avr.o
Here, we list the build prerequisite as avr.c not avr.o, because that's what your recipe expects (it builds a .o from a .c, so the .c is the prerequisite). However, this is really a very bad makefile; it's a "useless use of make" because every time you type make it will rebuild the avr.o file.
A better way is to fix your makefile to use the standard predefined variable settings instead of your own variables, and let make build the object file with its built-in rules:
CC = avr-gcc
CPPFLAGS = -I/usr/avr/include
CFLAGS = -mmcu=atmega2560 -Os
build: avr.o
That's all you have to do (you say "build a simple AVR C program" but your makefile only compiles an object file, it doesn't invoke the linker, so I don't know exactly what you want to do).
If you really want to keep your own rules and not use the built-in rules, then at least write it correctly so that the files built by the recipe are the targets in the makefile rule:
CC=avr-gcc
INCLUDE=-I/usr/avr/include
CCFLAGS+=$(INCLUDE)
build: avr.o
avr.o: avr.c
$(CC) $(CCFLAGS) -mmcu=atmega2560 -Os avr.c -o avr.o

Related

Run two instances of the same C++ program simultaneously

I've got a C++ program with a Makefile, building (g++) and running on Windows cmd. Thing is, sometimes it takes a while to run and save the results, and I want to run it with different parameters at the same time so that I can do something else while I wait for the first instance to finish. It doesn't work though, because of the executable I guess:
>make
g++ -c -o main.o main.cpp
Assembler messages:
Fatal error: can't create main.o: Permission denied
make: *** [main.o] Error 1
You have two problems: The one you ask about, and the reason you ask this question in the first place.
Lets start with the problem you have...
Judging by the Makefile you show, you have it all wrong.
Rules are in the format
target: sources_the_target_depend_on
The target is usually a file that need to be created. For an object file that is the name of the actual object file itself. The source files that the object files then depend on should be on the right-hand side.
To take an example from you Makefile (before you edited it away):
graph2: graph2.o
g++ -g -c graph.cpp -o graph2.o
Here you tell make that the file graph2 depends on the file graph2.o, and then it creates the graph2.o file. That's wrong. The rule should be that the file graph2.o depends om the file graph.cpp and go on to generate the file graph2.o:
graph2.o: graph.cpp
g++ -g -c graph.cpp -o graph2.o
This indirectly leads to the problem you have, with this line (deduced from your error and the Makefile):
main: main.o utils.o graph.o heuristics.o
g++ -g main.cpp -o main.o utils.o graph.o heuristics.o
This contains the same error as discussed above: You say that the file main depends on main.o and then the rule create main.o. Your rule should be
main: main.cpp utils.o graph.o heuristics.o
g++ -g main.cpp -o main utils.o graph.o heuristics.o
Note also how I no longer name the executable file main.o, as that is supposed to be used for object files.
Now lets continue with the reason you have the problem in the first place: That you need to edit the code to change data or values.
This is a problem that you need to solve. One common way to solve it is through command line arguments. If your program parses the command line arguments passed to your program you can pass it the values that could change from run to run.
How to do this is whole chapter on its own, so I wont give you any more details. There are plenty of tutorials online.
Lastly, you can simplify your Makefile considerably, by using implicit rules and variables.
I would simply create the Makefile to look something like this
# The compiler to use
CXX = g++
# Flags to pass to the compiler (add warnings when building)
CXXFLAGS = -Wall
# The main executable file to generate
TARGET = main
# List the object files needed to generate the main executable file
OBJECTS = main.o utils.o graph.o heuristics.o
# The all target depends on your main executable file
# Also as the first target in the Makefile, if no specific target is specified
# this will be the one that is used (it's the "default" target for the Makefile)
all: $(TARGET)
# The main executable file depends on the object files
$(TARGET): $(OBJECTS)
This is really it. the object files will be built automatically from their respective source files, and then the executable program will be linked using the object files listed.

Cannot pass flags to Makefile to compile my code

I have a project that basically compiles from the command line in the following form:
g++ -o stack_raster stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
I made a Makefile, and this is the content:
CXX =g++
LDDFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
However I got a collect2: error: ld returned 1 exit status.
A second variation of my Makefile I tried was:
CXX = g++
CPPFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rem -f stack_raster
but I still receive the following message (even though the compile flags appear as they should for my program to compile successfully).
collect2: error: ld returned 1 exit status
<builtin>: recipe for target `stack_raster` failed
make: *** [stack_raster] Error 1
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
To begin with, you should have a look at the actual link command that make executed. It should have been echoed to make's output just before the error message from collect2. Understanding what's wrong with the command is the first step in determining how to fix your makefile.
In the first case, the command is probably something like
g++ stack_raster.cpp -o stack_raster
In the second, it is probably something like
g++ -lgdal -lboost_system -lboost_filesystem stack_raster.cpp -o stack_raster
The latter is probably also very similar to what you would get with the first makefile if you corrected the spelling of LDDFLAGS to LDFLAGS.
You will note that the library flags come in a different place in that command than they do in your manual command, and I assume you know that the order of objects and library flags on the linker command line is significant to Unix-style linkers such as GNU's (which is the one that the g++ driver will use).
You can certainly fix this by writing an explicit rule, as you describe in your own answer, but your makes' built-in rules may be up to the task, too. If you are using GNU make then they certainly are. For this purpose it is useful to know what the built-in rules actually are, and essential to know what the variables on which these rules depend mean.
Specifically,
LDFLAGS provides options to pass when invoking the linker, and conventionally, they appear on the command line before the objects being linked. As a result, this variable typically is not appropriate for specifying libraries (but it is fine for other link-specific options, such as -L to add directories to the library search path).
CPPFLAGS provides options for modulating the behavior of the C preprocessor (including when compiling C++). These do not typically appear at all in link(-only) commands executed by make, but they will appear (early) in commands for compiling object files from C or C++ sources, and in rules for building executables directly from C or C++ sources.
Neither of those is what you want, but if you are using GNU make, then its documentation for the former explicitly tells you what (with that make implementation) you should do instead:
Extra flags to give to compilers when they are supposed to invoke the
linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the
LDLIBS variable instead.
(emphasis added)
In GNU make, and perhaps some others, the LDLIBS variable serves exactly the purpose you need: to specify the libraries to link. These will appear at the end of the link command line from built-in rules, as you can confirm from GNU make's catalog of implicit rules, or from the list obtainable by running make -p in a directory containing no makefile.
So, with GNU make you can get the build you seem to want from the built-in rules, with this:
CXX = g++
LDLIBS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
In closing, I note that cleaning before building by default, as your examples do and mine imitates, largely defeats the purpose of using make instead of a simple script. Part of the point of make is to do the minimum work necessary, and if your target executable is present and not out of date with respect to its sources then there is no reason to force it to be rebuilt.
Check out the answer:
Set up my makefile to compile C with just "make"
YOu have to specify in the Makefile the file you want to create in this case stack_raster.exe and the objective file in this case stack_raster.cpp and specify the command line arguments you normally pass for compiling. So the Makefile would be something like:
CXX=g++
stack_raster.exe: stack_raster.cpp
g++ -o stack_raster.exe stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
all: clean stack_raster.exe
clean:
rm -f stack_raster.exe

Cannot specify include file with make and MinGW

I'm facing an issue with a simple makefile and gcc (MinGW with Windows 10).
This is my simple makefile
IJNI=-I"C:\Program Files (x86)\Java\jdk1.7.0_79\include"
IJNIWIN32=-I"C:\Program Files (x86)\Java\jdk1.7.0_79\include/win32"
CC=gcc
default: main
main: lowlevelAccess.o
$(CC) $(IJNI) $(IJNIWIN32) -c lowlevelAccess -o lowlevelAccess.o
When from a command promp I launch make, I obtain:
gcc -c -o lowlevelAccess.o lowlevelAccess.c
lowlevelAccess.c:7:17: fatal error: jni.h: No such file or directory
#include <jni.h>
^
compilation terminated.
make: *** [lowlevelAccess.o] Error 1
What is wrong?
Thank you!
You aren't adding your -I flags on the lowlevelAccess.o compilation but that's the rule that needs it (not the linking rule where you have it now).
Try adding CFLAGS += $(IJNI) $(IJNIWIN32) to your makefile (possibly use CPPFLAGS instead I'm not sure offhand which is technically more correct here).
See Variables Used by Implicit Rules for what those variables are and Catalogue of Built-In Rules (or the output from make -qp) to see what the default rules that use those variables look like.

Makefile to view files that has errors in absolute paths

I have the following setup for my project:
~/proj -> includes makefile and other stuff
~/proj/headers -> includes c header files
~/proj/source -> includes C source files
When executing make in the main tree folder ~/proj errors are show with file names like this:
"source1.c" error variable...etc
How is it possible to have make show the absolute paths of files in error. Something like this:
~/proj/source/source1.c" error variable etc...
This is an example of an error:
Dependencies for mem_init.c
Compiling mem_init.c
"mem_init.c", line 513: warning: implicit function declaration: init_mem (E_NO_IMPLICIT_DECL_ALLOWED)
cc: acomp failed for mem_init.c
It's not possible at all, because it's not make that's printing those errors: it's your compiler. What you want to be asking is how (or if) it's possible to have your compiler show the absolute paths in its error messages. And of course in order to ask that question you'll have to specify which compiler you're using.
It's possible that if you passed an absolute path of the source file on the command line to your compiler, that your compiler would use that same path in its error messages. That is, if you run cc -o foo.o foo.c your error messages will be relative to foo.c, but if you run cc -o foo.o /home/me/proj/source/foo.c your error messages will be relative to /home/me/proj/source/foo.c.
If that's true, then you can change your make rule to something like (if you're using GNU make of sufficiently new vintage):
%.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $# $(abspath $<)
or whatever.

compiler directive for compiling on different platforms

I am compiling a demo project.
The project is written for windows and linux. I have written a Makefile. However, I am not sure how to specify the platform the compiler will be compiling on.
I will be compiling on Linux.
In my source file I have this:
#if defined(WIN32)
#include ...
#include ...
#elif defined(LINUX)
#include ...
#include ..
#else
#error "OS not supported"
#endif
My simple Makefile is this. And when I compile I get the error "OS not supported".
How can I add the directive so that it will compile with the #elif defined(LINUX).
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
app: *.cpp *.h Makefile
g++ $(LIBS_PATH) $(INC_PATH) *.cpp -o app
Many thanks for any suggestions,
Decide which is going to be your default platform - say LINUX.
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
PLATFORM = -DLINUX
CXX = g++
app: *.cpp *.h Makefile
${CXX} ${CFLAGS} ${PLATFORM} ${INC_PATH} *.cpp -o $# ${LIBS_PATH} ${LIBS}
You can use round brackets in place of braces. This uses a macro for the C++ compiler, allows you to add other flags via CFLAGS (though that is also usually set by 'make'), and adds a platform, the include path, the library path and the actual library to the compile line.
Note that your rule enforces a complete recompilation of everything every time anything changes. This is 'safe' but not necessarily efficient. Note that wild-cards are dangerous too - more so for the source than the headers. You may include that backup copy of a file in the build (old-reader.cpp - you only wanted reader.cpp in there really). More conventionally, you list the object files needed for the program so that each object file can be individually rebuilt when needed, and the results linked together. If you get your dependencies correct (a moderately big 'if'), then there's no problem. If you get them wrong, you can end up with inconsistent programs.
However, if the difference is between a 5 second recompile and a 5 minute recompile, you should probably take the 5 minute recompilation (as shown) and answer another SO question while waiting.
To compile on Linux (64-bit):
make CFLAGS="-m64"
To compile on Linux (32-bit):
make CFLAGS="-m32"
To compile on Windows 64:
make PLATFORM=-DWIN64
To compile on Windows 32:
make PLATFORM=-DWIN32
Etc.
You can add -DLINUX=1 when compiling.
Also, if you run:
echo "" | cpp -dD
You can see the list of default #define when compiling. In linux, there will always be a:
#define __linux__ 1
in the output. So if you change your LINUX by the above #define, you don't need to do anything special. Ie:
...
#elif defined(__linux__)
...
As for the Makefile itself, I would do something like:
CXX=g++
CPPFLAGS = -I/usr/norton/include
LDFLAGS = -L/usr/norton/lib -lntr
OBJ_FILES = one.o two.o
app: $(OBJ_FILES) Makefile
one.o: one.cpp one.h
two.o: two.cpp two.h
So the implicit rules are used.

Resources