Makefile problems with object files

I am trying to write a Makefile that will compile an example project.

As long as I don't define object files it works, but when I do, compilation stops with a source file not found error:

main.cpp:6:19: fatal error: imgui.h: No such file or directory
#include "imgui.h"

If I comment out the object file definition, it compiles but doesn't use object files of course

I'd really like to figure it out, if anyone could help, it would be much appreciated.

This is the Makefile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# imgui example
target := ok.exe

src := main.cpp imgui_impl_glfw_gl3.cpp D:/Libraries/imgui/imgui.cpp D:/Libraries/imgui/imgui_demo.cpp D:/Libraries/imgui/imgui_draw.cpp D:/Libraries/gl3w/src/gl3w.c

# objects = $(addsuffix .o, $(basename $(notdir $(src))))
# objects = main.o 
# defining objects breaks compilation with the error:
# 						g++    -c -o main.o main.cpp
# 						main.cpp:6:19: fatal error: imgui.h: No such file or directory
#  						 #include "imgui.h"

cxx = g++
flags = -Wall

includes = -ID:/Libraries/imgui -ID:/Libraries/gl3w/include -ID:/Libraries/glfw/include 

libs = -LD:/Libraries/glfw/lib-mingw
libs += -lglfw3 -lgdi32 -lopengl32 -limm32

all: $(target)

$(target): $(objects)
	$(cxx) $(includes) $(flags) $(src) -o $(target) $(libs)

clean:
	rm -f $(objects)
	rm -f $(target)

print:
	@echo $(objects)
Last edited on
Here's the reason. BTW, I can get around in Makefiles, but I'm not an expert, and my terminology may be slightly off, but I think you'll get the idea.

Your $(target) depends on $(objects). So, in order to start building $(target), all of the .o files need to be generated before line 24 is executed.

Since you did not define a rule to convert *.cpp to *.o, make will use a default rule which knows nothing about your $(includes) variable. So, the -I directives you think you are passing are really not being passed in.

You need a rule template (I forget what they are officially called in make) to generate your object files. It should be something like this:

1
2
%.o : %.cpp
	$(cxx) $(includes) $(flags) -o $@ $<


$@ is the left-hand side of the rule, $< is the first string in the right-hand side of the rule.

You will need a separate rule for .cpp files found int D:/Libraries/imgui. Or, better yet, build them into a library where they are and link the library.

Next, change your $(target) rule to simply link the objects into an executable:

1
2
$(target) : $(objects)
	$(cxx) -o $@ $^ $(libs)


$^ is all strings on the right-hand side of the rule
@doug4

Yes, that was the problem, and additionally the different source directories weren't specified to compile the objects.

This is the Makefile now:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# imgui example
target = ok.exe

srcdir_2 = D:/Libraries/imgui
srcdir_3 = D:/Libraries/gl3w/src

src := main.cpp imgui_impl_glfw_gl3.cpp 
src += $(srcdir_2)/imgui.cpp $(srcdir_2)/imgui_demo.cpp $(srcdir_2)/imgui_draw.cpp 
src += $(srcdir_3)/gl3w.c

cxx := g++
flags = -Wall

includes = -ID:/Libraries/imgui -ID:/Libraries/gl3w/include -ID:/Libraries/glfw/include 

libs = -LD:/Libraries/glfw/lib-mingw
libs += -lglfw3 -lgdi32 -lopengl32 -limm32

objects = $(addsuffix .o, $(basename $(notdir $(src))))

# compile object files:
%.o: %.cpp
	$(cxx) $(includes) $(flags) -c $< -o $@ $(libs)
	@echo $@
# 2nd source dir
%.o: $(srcdir_2)/%.cpp
	$(cxx) $(includes) $(flags) -c $< -o $@ $(libs)
	@echo $@
# 3rd
%.o: $(srcdir_3)/%.c
	$(cxx) $(includes) $(flags) -c $< -o $@ $(libs)
	@echo $@

all: $(target)

# build exe
$(target): $(objects)
	$(cxx) $(flags) $(objects) -o $(target) $(libs)

clean:
	rm -f $(objects) $(target)

cleanexe:
	rm -f $(target)

print:
	@echo $(objects)
Last edited on
Topic archived. No new replies allowed.