make ignoring include directives - c

I'm using GNU make and have the following in my Makefile:
token_check: token_check.o $(STATIC_LIBRARIES)
$(CC) -o $# $^
%.o: %.c pipeline/*.h compiler/*.h
$(CC) $(COMPILER_FLAGS) -I./pipeline -I./compiler -c $<
However, when I run make, the command actually run is
cc -c -o token_check.o token_check.c
and I get the error
token_check.c:3:10: fatal error: scanner.h: No such file or directory
3 | #include "scanner.h"
| ^~~~~~~~~~~
compilation terminated.
make: *** [<builtin>: token_check.o] Error 1
scanner.h is contained in the compiler subdirectory.
Why are my -I directives being ignored?
EDIT:
I checked and I do have header files in both pipeline and compiler.
What's really weird is, even if I replace the recipe with
%.o: %.c pipeline/*.h compiler/*.h
echo blah
and run
make token_check.o
it still tries to compile the source file and "blah" never gets printed.

Most likely make is using its implicit rule, not yours. And most likely it does so because your pattern rule does not apply. One reason could be that you do not have any header file in pipeline.

Related

GCC issues a warning that my precompiled headers (.h.gch) are invalid

I'm trying to use precompiled headers for the first time. I have the following rules in my Makefile:
$(UNITS_h_gch): $(builddir)/%.h.gch: $(INCLUDEDIR)/%.h $(mk) \
| $$(#D)/. $(builddir)/%.h.d
$(info - CC $$builddir/$*.h.gch)
$(CC) $(CFLAGS) -I $(INCLUDEDIR) -DPCH -S -o $# $<
$(UNITS_c_s): $(builddir)/%.c.s: $(SRCDIR)/%.c $(builddir)/alx/%.h.gch $(mk) \
| $$(#D)/. $(builddir)/%.c.d
$(info - CC $$builddir/$*.c.s)
$(CC) $(CFLAGS) -I $(builddir) -I $(INCLUDEDIR) -S -o $# $<
The rule for the .s files is the same as before, except that it now depends also on the PCH, obviously; and also that it includes $(builddir) in the headers with -I to be able to use the precompiled headers that I generate there.
The nonstandard notation (.c.s) is to simplify the Makefile, as I also have .cxx.s files which follow a slightly different rule, using g++ of course.
As GCC documentation says (https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html), I used the same command line to produce the PCHs. It failed due to #pragma once, so I added a conditional in the headers to remove it when building the PCH; that's why I define PCH with -DPCH.
I've seen that people compiles PCHs with -c, but I also produce temporary assembly files, so I used -S. May that be the cause f the failure?
Logs:
$ make
- CC $builddir/alx/base/assert/array.h.gch
- CC $builddir/base/assert/array.c.s
/home/alx/src/alx/libalx/src/base/assert/array.c:10:35: error: /home/alx/src/alx/libalx/tmp/alx/base/assert/array.h.gch: not a PCH file [-Werror]
10 | #include <alx/base/assert/array.h>
| ^
cc1: all warnings being treated as errors
make[1]: *** [/home/alx/src/alx/libalx/lib/recipes.inc.mk:49: /home/alx/src/alx/libalx/tmp/base/assert/array.c.s] Error 1
make: *** [Makefile:63: base] Error 2
I'm seeing an error because of -Werror, and that appeared after adding -Winvalid-pch. Before that the compilation was successful, but because it was taking the original header file, and not the precompiled one. I suspected of this, because the compilation was twice as slow.
BTW, I use bracket includes (<...>) because this is a library that I install in the system and then use from other programs.

Makefile doesn't use variables

I am refactoring my personal libc and I need to redo my makefile. So far so good, But suddenly, the variables aren't included in the commands executed.
Here's the trouble so far:
➜ libft git:(master) ✗ make
clang -c -o srcs/core/ft_add_to_array.o srcs/core/ft_add_to_array.c
srcs/core/ft_add_to_array.c:13:10: fatal error: 'core/core.h' file not found #include <core/core.h>
^
1 error generated.
<builtin>: recipe for target 'srcs/core/ft_add_to_array.o' failed
make: *** [srcs/core/ft_add_to_array.o] Error 1
Which i suppose come from this line of my makefile :
%.o:$(SRC_PATH)/%.c
$(CC) $(FLAGS) $(INC) -o $# -c $<
So what i've come up so far is that the FLAGS and INC variables are simply not included... Any ideas why ?
I've found the solution
I've removed the addsuffix part and added srcs/ to each line of the sources i've declared manually and it compiled fine !
Here's the makefile after my modifications
Thanks guys

Error 1: no input files when making a c file

I'm trying to compile a c-file with dependencies, using a makefile that gets stuck with this error:
Compiling tpc_lqe.o ...
/cygdrive/c/Sandbox/ZigBee/Tools/ba-elf-ba2/bin/ba-elf-gcc -c -o tpc_lqe.o
[some -options]
-I/cygdrive/c/Sandbox/ZigBee/Components/TPC/Include
-I/cygdrive/c/Sandbox/ZigBee/Components/TPC/Source
-I/cygdrive/c/Sandbox/ZigBee/Components/AppApi/Include
-I/cygdrive/c/Sandbox/ZigBee/Components/Common/Include
-I /cygdrive/c/Sandbox/ZigBee/Components/TPC/Source/tpc_lqe.c -MD -MF tpc_lqe.d -MP
ba-elf-gcc: no input files
make: *** [tpc_lqe.o] Error 1
Makefile:138: recipe for target 'tpc_lqe.o' failed
I saw other questions regarding the same error, but I can't relate to them with my problem.
This is the makefile line that is causing the error, please point out if some context is missing:
%.o: %.c
$(info Compiling $# ...)
$(CC) -c -o $*.o $(CFLAGS) $(INCFLAGS) $< -MD -MF $*.d -MP
Update following unwind's answer:
I didn't include specify a variable (include path of a library), which caused the following inclusion of that variable (INCFLAGS) to contain a blank space in its stead. This blank space ended up in the -I option thus returning the error.
Once defined that variable, everything worked smoothly.
INCFLAGS looks broken, since the compiler invocation has a "bare" -I, without a value immediately following, which causes gcc to interpret the next argument (the source file name) as that argument:
[...] -I /cygdrive/c/Sandbox/ZigBee/Components/TPC/Source/tpc_lqe.c
^
|
???

Handling #include <folder/file.h> in C with makefiles

I am in the process of porting some code that was developed in the codeblocks IDE. I am transferring it to a Linux server where I can only use the command line to compile the code. The code is quite large (maybe 100 files) and I need to update the include commands in many files. For when I try to compile it errors on for instance: #include <gsl/gsl_math.h> with a file cannot be found error. I am assuming it cannot be found because the location of the gsl folder was declared in one of the search directory field options in the IDE. I could go through each file an update to the correct path, but is there a better way of doing this for use with a makefile?
Thanks!
EDIT Makefile In Question
# -c : do not link, just create object file
# -o : output file name
CFLAGS += -c -O2 -I../ctraj -I../cspice/include -I../SGP4 -I../cconj -I../GSL-1.13/include
LIBS = -L../ctraj -lctraj -L../cspice/lib -lcspice -L../SGP4 -lsgp4 -L../cconj -lcconj -L./ -lgsl-0 -lgslcblas-0 -lm
DEPS = light.h ../ctraj/ctraj.h ../cconj/cconj.h
OBJ = light.o tle.o propagator.o orbitfit.o conjunction.o light_displacement.o forces_LF.o
OUT = light.exe
%.o: %.c $(DEPS)
gcc -o $# $< $(CFLAGS)
light: $(OBJ)
cd ../ctraj/; make
gcc -o $(OUT) $(OBJ) $(LIBS)
clean:
rm *.o $(OUT)
Edit 2
Folder Structure
light->(GSL-1.13, Light, cconj, ctraj)
the makefile is inside the Light folder.
Error Message
cd ../ctraj/; make
make[1]: Entering directory `/light/ctraj'
gcc -o forces.o forces.c -c -Wall -Wno-maybe-uninitialized -Wno-unused-but-set-variable -O2 -I../cspice/include -Inrlmsise
In file included from ../Light/../cconj/cconj.h:12:0,
from ../Light/light.h:13,
from forces.c:3:
../Light/../cconj/../GSL-1.13/include/gsl/gsl_blas.h:26:28: fatal error: gsl/gsl_vector.h: No such file or directory
compilation terminated.
make[1]: *** [forces.o] Error 1
make[1]: Leaving directory /light/ctraj'
make: *** [light] Error 2
EDIT 3
Second makefile in cconj
# -c : do not link, just create object file
# -o : output file name
#-L../cconj -lcconj
CFLAGS += -c -O2 -I./ -I../GSL-1.13/include
LIBS = -L./ -lgsl-0 -lgslcblas-0 -lm
INC= -I../GSL-1.13/include
DEPS = cconj.h
OBJ = cconj_util.o ellipse_intersect.o collision_prob_real.o rcs2size.o
OUT = libcconj.a
%.o: %.c $(DEPS)
gcc -o $# $< $(CFLAGS)
cconj: $(OBJ)
ar rcs $(OUT) $(OBJ)
clean:
rm *.o $(OUT)
Try adding this line to your makefile, and tell us if it works:
CFLAGS += -I../GSL-1.13/include
In order to compile source code and produce object files, Make must use a rule. (If you don't put such a rule in the makefile, Make has a default rule for that purpose.) It looks something like this:
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
Without digging too deeply into how that works, we can say that CFLAGS is a list of arguments to be passed to the compiler. When we add -I../GSL-1.13/include, we tell the compiler "if you want to #include something and can't find it elsewhere, look in ../GSL-1.13/include".
If this approach doesn't work, then there's probably a rule in the makefile we must find and alter.
EDIT:
The problem isn't in this makefile (which already contains a reference to GSL-1.13/include). In this command:
cd ../ctraj/; make
this makefile launches a second Make process, which uses the Makefile in light/cconj/. According to the compiler output (gcc -o forces.o ...), that makefile does not include the reference. So try adding the same line there, and if that doesn't work, post that makefile and we'll keep looking.
Use -I option of gcc to specify where to look for includes.

Using the make command without makefiles?

I was compiling some C code for an assignment and I ran "make codeFile", where "codeFile" was the name of my C program, and even though I didn't have a makefile, an executable was created, and it ran and worked correctly.
Does anyone know why this worked? Why does make compile something even if I don't have a makefile? The only reference I could find was this:
http://daly.axiom-developer.org/TimothyDaly_files/class5/node5.html
Make has an internal database with implicit rules. You can use make -p to list them. Also make -d will tell you which rules are being applied, so that would help you discover which implicit rules are being used in this case.
Make has several pre-defined implicit rules. In particular, in your case, it uses two such rules when trying to determine what to do for the target codeFile:
%: %.o # Link object file
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
%.o: %.c # Compile C source code
$(CC) $(CPPFLAGS) $(CFLAGS) -c
Using the make command without makefiles?
make has implicit rules that work as defaults unless you override them.
According to the make man page:
make -p -f/dev/null
will list all of the implicit rules (and relevant environment variables) without attempting to actually remake files.
To demonstrate the usage, I ran make in Cygwin, which gave me an exe file. Note no .c on the name passed to make:
$ ls
hello.c
$ make hello
cc hello.c -o hello
$ ls
hello.c hello.exe
I also ran this in Ubuntu Linux, and my result was nearly the same as above, but the .exe extension was not there, instead I had the plain hello executable:
$ ls
hello.c hello
Step by step derivation
I believe the relevant pieces of the make implicit rules are as follows:
CC = cc
cc is aliased to CC
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
a LINK format is created, where the flags will be empty, and the TARGET_ARCH variable is also empty (to allow users to set values for various target architectures.) Then we have:
%: %.c
# recipe to execute (built-in):
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $#
The ^ variable is the prerequisite, hello.c. The other variables are empty. These are followed by the -o flag and the target name. The empty variables explain the extra spaces in the command make ran:
cc hello.c -o hello
And the %: %.c matched the target given to make with the filename of the same target name ending in .c, which caused the recipe to execute.

Resources