UltraInstinct
UltraInstinct

Reputation: 44444

GNU Make strange variable substitutions

I have the following Makefile:

CPPCOMPILER=g++
CCOMPILER=gcc
#CPPCOMPILER=i586-mingw32msvc-g++

FLAGS=-Wall -g -O3
LIBRARIES=-lpthread
MODULES=obj/HTTPRequest.o obj/main.o obj/Server.o obj/SocketUtils.o obj/HTTPServer.o \
    obj/CookieManager.o obj/FileLister.o
STATIC=obj/static/files.html.o obj/static/login.html.o

all: $(MODULES) $(STATIC)
    $(CPPCOMPILER) $(MODULES) $(STATIC) $(LIBRARIES) -o httpserver

obj/main.o : main.cpp
    @mkdir -p obj
    $(CPPCOMPILER) -c $(FLAGS) $< -o $@ 

obj/static/%.o : %
    @mkdir -p obj/static
    file2obj $< $(subst .,_,$<) > $<.c
    $(CCOMPILER) $<.c -o $@ -c $(FLAGS)   #<-------***THIS LINE***

obj/%.o : %.cpp %.h
    @mkdir -p obj
    $(CPPCOMPILER) -c $(FLAGS) $< -o $@ 

clean:
    rm -rf $(STATIC) $(MODULES) httpserver

I have files.html for which file2obj emits C source code. This code gets compiled to .o file.

However the make process is somewhat different that what I expected. Here's the output:

thrustmaster@thrustmaster:~/Code/HTTPFileSharer$ make
cc     files.html.c   -o files.html #<--------- ****THIS LINE!****
[and more linker errors here because of wrong command]
make: *** [files.html] Error 1

I am using GNU make 3.81.

Is there anything wrong with my Makefile code? Or is it some known bug in GNU/make?

Any advice/pointers/suggestiosn will be greatly appreciated :-)

Thanks


UPDATE

I am putting here another case, where I am facing a similar problem.

Makefile:

CPPCOMPILER=g++
CCOMPILER=gcc
FLAGS=-Wall -pg -O3
LIBRARIES=`pkg-config --libs libglfw` -lm -lGLU -lGL -lXrandr
UNITS=obj/main.o obj/TextureManager.o obj/Thread.o obj/Tile.o obj/PictureTile.o     obj/Coverflow.o obj/Vector3D.o \
        obj/TilePopulator.o obj/FileLister.o
SOIL_DEPENDS=soil/image_DXT.c  soil/image_helper.c  soil/SOIL.c  soil/stbi_DDS_aug_c.h      soil/stb_image_aug.c \
                soil/image_DXT.h  soil/image_helper.h  soil/SOIL.h  soil/stbi_DDS_aug.h      soil/stb_image_aug.h
SOIL_UNITS=obj/soil/image_DXT.o obj/soil/image_helper.o obj/soil/SOIL.o     soil/stb_image_aug.o

all: $(SOIL_UNITS) $(UNITS)
        $(CPPCOMPILER) $(FLAGS) $(SOIL_UNITS) $(UNITS) $(LIBRARIES) -o coverflow

obj/soil/%.o : soil/%.c
        @mkdir -p obj/soil
        $(CCOMPILER) -c $< -o $@     #<--Issue in this line 

obj/main.o : main.cpp
        @mkdir -p obj
        $(CPPCOMPILER) -c $(FLAGS) $< -o $@ 
obj/%.o : %.cpp %.h
        @mkdir -p obj
        $(CPPCOMPILER) -c $(FLAGS) $< -o $@ 
clean:
        rm -rf $(UNITS) $(SOIL_UNITS) coverflow

OUTPUT:

thrustmaster@thrustmaster:~/Code/Skroll$ make
gcc -c soil/image_DXT.c -o obj/soil/image_DXT.o
gcc -c soil/image_helper.c -o obj/soil/image_helper.o
gcc -c soil/SOIL.c -o obj/soil/SOIL.o
cc    -c -o soil/stb_image_aug.o soil/stb_image_aug.c  #<-----**THIS LINE**
g++ -c -Wall -pg -O3 main.cpp -o obj/main.o 
g++ -c -Wall -pg -O3 TextureManager.cpp -o obj/TextureManager.o 
g++ -c -Wall -pg -O3 Thread.cpp -o obj/Thread.o 
g++ -c -Wall -pg -O3 Tile.cpp -o obj/Tile.o 
g++ -c -Wall -pg -O3 PictureTile.cpp -o obj/PictureTile.o 
g++ -c -Wall -pg -O3 Coverflow.cpp -o obj/Coverflow.o 
g++ -c -Wall -pg -O3 Vector3D.cpp -o obj/Vector3D.o 
g++ -c -Wall -pg -O3 TilePopulator.cpp -o obj/TilePopulator.o 
g++ -c -Wall -pg -O3 FileLister.cpp -o obj/FileLister.o 
g++ -Wall -pg -O3 obj/soil/image_DXT.o obj/soil/image_helper.o obj/soil/SOIL.o     soil/stb_image_aug.o obj/main.o obj/TextureManager.o obj/Thread.o obj/Tile.o     obj/PictureTile.o obj/Coverflow.o obj/Vector3D.o obj/TilePopulator.o obj/FileLister.o `pkg-    config --libs libglfw` -lm -lGLU -lGL -lXrandr -o coverflow

Upvotes: 1

Views: 338

Answers (2)

Beta
Beta

Reputation: 99104

In the first case, you are trying to build obj/static/files.html.o using this rule:

obj/static/%.o : %
    @mkdir -p obj/static
    file2obj $< $(subst .,_,$<) > $<.c
    $(CCOMPILER) $<.c -o $@ -c $(FLAGS)

Before Make runs this rule, it will first check to see if the prerequisite (files.html) can/should be rebuilt. There is an implicit rule that will build files.html from files.html.c, so that's what will happen if files.html.c exists. (You seem to be going in the opposite direction from what Make expects; I don't know enough about building HTML to know if that's a good idea.) And if that works, Make will consider files.html an intermediate file, and will delete it when it is no longer needed.

There's more than one way to solve this problem. The simplest is probably to write your own rule for building files.html, which overrules Make's rule and does nothing:

%.html: %.html.c;

In the second case you made a small mistake in your SOIL_UNITS variable:

SOIL_UNITS=obj/soil/image_DXT.o obj/soil/image_helper.o obj/soil/SOIL.o soil/stb_image_aug.o

Notice the last term. You have a rule for obj/soil/%.o, but not for soil/%.o, so Make falls back on its implicit rule. Just change that term to obj/soil/stb_image_aug.o.

Upvotes: 2

Tim
Tim

Reputation: 336

GNU Make has a built-in implicit rule for building a file, X, from X.c:

%: %.c
#  commands to execute (built-in):
    $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@

It appears this implicit rule is being invoked when you run "make".

While not a good permanent solution, you may be able to avoid this problem by running make with the -r (or --no-builtin-rules) option to disable the implicit rules.

Upvotes: 3

Related Questions