Makefile fails at link stage - makefile

I'm using following makefile (simplified variant):
CFLAGS = -Wall -fpermissive -DENV_EMBEDDED -I../utils/ -../usblib/include
CPPFLAGS = $(CFLAGS)
CXXFLAGS = $(CFLAGS)
LDFLAGS = -lmisc -lrt
PNAME=Simulator
OBJ = simulated.o \
buffer.o \
common.o
all: $(OBJ)
$(LDFLAGS) -o $(PNAME) $(OBJ)
Compilation works fine, make automatically chooses the correct compiler and sets the correct flags-variable. But the link-stage fails, I get an error message about "unknown command lmisc". So it seems, there is something wrong with my second "all"-statement, make does not apply a default command for linking.
Any idea what has to be done here in order to let it link successfully?
Thanks!

The recipe is missing the compiler/linker command. It should be something like:
all: $(OBJ)
$(CC) -o $(PNAME) $(OBJ) $(LDFLAGS)

Instead of trying to write your own linker command, it's better to use Make's built-in rule, which is (as revealed by make -f /dev/null --print-data-base | sed -n '/^%: %\.o/,/^$/p'):
%: %.o
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
If you put your libraries in LDLIBS as you should, you can simply use that:
LDLIBS = -lmisc -lrt
# 'all' should be phony, and depend on a real target
# Otherwise, you'll link every build, even when not needed
all: $(PNAME)
.PHONY: all
$(PNAME): $(OBJ)
If some of your source files are C++ (as implied by the presence of CXXFLAGS), you will need to tell Make to use the C++ linker rather than the C linker:
LINK.o = LINK.cc

Related

Generate debug versions of targets in a DRY method

I am using GNUmake and I have a makefile with some targets defined and their respective dependencies. I would like to create a debug version of these targets, so I have this:
TARGET := a b c
all: $(TARGET)
a: a.o e.o
$(CC) $(CFLAGS) $(INCDIRS) -c $(^) -o $(#)
b: b.o g.o
$(CC) $(CFLAGS) $(INCDIRS) -c $(^) -o $(#) -pthread
c: f.o c.o
$(CC) $(CFLAGS) $(INCDIRS) -lm -c $(^) -o $(#)
%.o: %.c
$(CC) $(CFLAGS) $(INCDIRS) -c $(^) -o $(#)
So this is all good, but now I would like to create debug versions of these rules, but I don't want to have to rewrite the rules. I just want to add additional flags like -g -DDEBUG to the CFLAGS variable and change the names of the targets.
I tried this static rule stuff
$(TARGET:%=debug_%): %: * #<--- not sure how to specify the dependencies
# CFLAGS += -g -DDEBUG <-- uncommenting this line is an error
This didn't work. I wanted the above rule to match the targets I already specified, but add additional parameters to CFLAGS which will then generate files like debug_a, debug_b, debug_c etc. I am not sure if this is possible with make but that was just the way I was reasoning about this.
Any help will be appreciated, thanks
So I finally found a suitable solution:
DEBUG_TARGET := $(TARGET:%=debug_%)
debug: $(DEBUG_TARGET)
$(DEBUG_TARGET):
debug_%: CFLAGS += -g -DDEBUG
debug_%: %
#mv $* debug_$*
This will generate a debug version of each target without having to create separate rules.
The last line was the sweet spot for me and this accomplishes what I wanted without having to repeat myself too much

Run a command for the nth target with the nth dependancy

I am having some confusion about how the '$<' and '$#' macros can be used with a list of elements. My ultimate goal is to compile a directory of C source files into executables with the same name, no extensions. Also I do not want to make object files.
Here is a simple makefile which I would like to upgrade using the macros.
CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
all : progA progB progC
progA : progA.c
$(CC) $(CCFLAGS) $< -o $#
progB : progB.c
$(CC) $(CCFLAGS) $< -o $#
progC : progC.c
$(CC) $(CCFLAGS) $< -o $#
This works fine, but I don't like the redundancy of the commands. I have found a workaround that works, and a near solution, but was hoping there might be a clear option.
workaround:
CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
PRGS := $(patsubst %.c,%,$(wildcard *.c))
all :
make $(PRGS)
% : *.c
$(CC) $(CCFLAGS) $#.c -o $#
What I don't like here is the call to make within the command. Running 'make' delivers a message in my terminal that looks something like this:
make[1]: Entering directory '/path/to/dir'
...actual commands...
make[1]: Leaving directory '/path/to/dir'
I am assuming this has to do with opening the same makefile and the [1] refers to the second file descriptor in the open file table (or something along those lines).
near solution:
CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
SRCS := $(wildcard *.c)
PRGS := $(patsubst %.c,%,$(SRCS))
all : $(PRGS)
$(PRGS) : $(SRCS)
$(CC) $(CCFLAGS) $< -o $#
This almost works, except it is always grabbing the first dependancy!
..... progA.c -o progA
..... progA.c -o progB
..... progA.c -o progC
So, does anyone have a cleaner method to my 'workaround' or perhaps a solution to my 'near solution'? Is there anyway to match the nth target to the nth dependency when running the command?
Thanks!
The $(PRGS): $(SRCS) change is just incorrect. It lists every source file as the prerequisites of every target.
You want to set the prerequisites of the all target to be every program you want built by default. To do that you want to use all: $(PRGS). Not a recipe of calling make again like you had originally.
(If you did want to keep the manual recursive call to make you could use make --no-print-directory on that call to avoid the message but that is still the wrong approach (and if you were going to do that you'd want to use $(MAKE) to handle arguments to the original make correctly.)
A second problem with your original makefile is the use of *.c in the prerequisite list of the % target. That sets the prerequisites of every target to be every *.c file in the directory. That's not what you want. You want each target to have its own .c file as its prerequisite.
You want:
all: $(PRGS)
%: %.c
$(CC) $(CCFLAGS) $#.c -o $#
That being said make has a built-in rule for exactly that foo.c -> foo compilation so you should just use that. That rule uses the $(CC) and $(CFLAGS) variables. So just set those to what you want and you are done.
So this makefile should do what you want. (Note how I moved some arguments to CFLAGS instead of CC. CC should generally, to my knowledge, by the compiler itself and not any arguments.)
CC = gcc
CFLAGS = -ansi -std=c99 -Wall -pedantic -O3
PRGS := $(patsubst %.c,%,$(wildcard *.c))
all : $(PRGS)

Makefile not executing to the end

I have the following makefile but it just executes the 1st command where it builds me the .o files and not the .so files. What am I doing wrong?
Thanks,
SHELL = /bin/sh
CC = gcc
CFLAGS = -g -Wall
LDFLAGS = -shared
TARGET = Stepper.so
SOURCES = $(shell echo ./*.c)
HEADERS = $(shell echo ./*.h)
OBJECTS = $(SOURCES:.c=.o)
LIBS = liblua523.a
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
clean:
rm $(OBJECTS)
Unless you specify a different target on the command line, make always builds the first real target found in the makefile. In this case, the first real target is the first object file, so that's all that's built.
This is why you typically see makefiles with a first target of all or similar, which just depends on the various other targets you want built during a standard invocation of "make" with no arguments.
However, your makefile is really not right, in a number of ways. The fact that it's running it all means you actually only have one source file. As soon as you have >1 it will fail.
This:
SOURCES = $(shell echo ./*.c)
is not very efficient; you should use wildcard here:
SOURCES = $(wildcard ./*.c)
This rule:
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
Tells make, "for every object file, if any source file or any header file has changed, recompile it". Basically, it means that if you change ANYTHING in the directory, EVERYTHING will rebuild. If you want that you might as well write a shell script and not bother with make at all.
Further, the compiler will fail when you have >1 source file, as it will try to run:
gcc -g -Wall -c foo.c bar.c -o foo.o bar.o
which is not right.
You don't need to define this rule at all; make has a built-in rule which knows how to build an object file from a source file. Just replace it with this:
$(OBJECTS): $(HEADERS)
(no recipe) so make knows that the objects depend on the headers as well as the source. Note this is not ideal since all objects rebuild if any header changes but it's fine for a simple program.

Makefile: target with pattern does not work

My Makefile looks like this:
BIN = bin
OBJECTS = object1.o \
object2.o \
object3.o
HDR = $(OBJECTS:%.o=%.h) header1.h header2.h
MAIN = main.c
CC = gcc
CFLAGS = -Wall -g -std=c99 -fstack-protector-all
LDFLAGS = -lpthread
$(BIN): $(OBJECTS) $(MAIN)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
%.o: %.c $(HDR)
$(CC) $(CFLAGS) -c $< -o $#
It seems that the %.o: %.c $(HDR) rule is not used. When invoking with option make -r it says that there's no rule to make target object.o. The build of each object file should depend on every header file. What am I missing?
Edit: I should mention that when doing echo $(HDR) than it looks like the variable contains the right values:
object1.h object2.h object3.h header1.h header2.h
In the declaration of HDR, try $(OBJECTS:.o=.h) instead. Or, better yet, use gcc -MM or the like to generate your dependencies instead.
A pattern rule can't have auxilliary dependencies like ${HDR}.
Use:
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
${OBJECTS}: ${HDR}
Ok, the given Makefile should work, I had a typo in one of the header file names.
It's a pitty, but make doesn't warn about that. It seems that when a pattern based rule is missing a prerequisite than it's just ignored. The built-in .o creation rule is used instead.
Jonathan Leffler's proposal of ${OBJECTS}: ${HDR} brought that up, because than there's an error regarding "no rule to make target misspelled.h" - I would have expected that from my rule too.
So I can just agree to fluffy, it's better to use auto-generated dependencies instead.

How to instruct Makefile to use different compilers

I have to build my code for two different platforms at once using two different compilers and libraries. How can I do this with single make file.
Currently my makefile contents are given below. How can I instruct it to change the compiler to gcc within the same makefile?
VPATH = /root/Documents/project/src
CROSS_COMPILE = /opt/compilers/bin/compiler1
CXX = $(CROSS_COMPILE)-g++
CC = $(CROSS_COMPILE)-gcc
AS = $(CROSS_COMPILE)-as
AR = $(CROSS_COMPILE)-ar
NM = $(CROSS_COMPILE)-nm
LD = $(CROSS_COMPILE)-ld
OBJDUMP = $(CROSS_COMPILE)-objdump
OBJCOPY = $(CROSS_COMPILE)-objcopy
RANLIB = $(CROSS_COMPILE)-ranlib
STRIP = $(CROSS_COMPILE)-strip
CFLAGS = -c -Wall -D_REENTRANT -DACE_HAS_AIO_CALLS -D_GNU_SOURCE -DACE_HAS_EXCEPTIONS -D__ACE_INLINE__
LDFLAGS = -L. -L/etc/ACE_wrappers/lib
CPPFLAGS += -I/etc/ACE_wrappers -I/etc/ACE_wrappers/ace
LDLIBS = -lACE
OUTPUT_DIRECTORY=/root/Documents/bin
OBJ=/root/Documents/obj
ifneq ($(OUTPUT_DIRECTORY),)
all: $(OUTPUT_DIRECTORY)
$(OUTPUT_DIRECTORY):
-#$(MKDIR) "$(OUTPUT_DIRECTORY)"
endif
ifneq ($(OBJ),)
all: $(OBJ)
$(OBJ_DIR):
-#$(MKDIR) "$(OBJ)"
endif
SOURCES=File_1.cpp File_2.cpp
OBJECTS=$(SOURCES:%.cpp=$(OBJ)/%.o)
$(OBJ)/%.o: %.cpp
#echo Building Objects
$(CC) $(CFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
EXECUTABLE=MyExecutable
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
#echo $(SOURCES)
$(CC) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(OUTPUT_DIRECTORY)/$#
File_1.o:File_1.cpp
File_1.o:File_1.cpp
.PHONY: clean
clean:
rm $(OBJECTS) $(OUTPUT_DIRECTORY)/$(EXECUTABLE)
I'd start by putting all the platform-specific defines in a separate makefile. That way you can do:
include $(TARGET).make
Where $(TARGET).make defines CC and other variables for each particular platform. Then you can call make recursively setting TARGET to what you want. Something like:
build:
$(MAKE) TARGET=platform1 all
$(MAKE) TARGET=platform2 all
But really there are many, many ways in which you can achieve the same thing.
Use autoconf. When you configure the project with ./configure, it will automatically choose the one available.
That would be a lot easier to read if the linebreaks were properly preserved in your post.
Anyway, I expect that you're going to have to have two copies of a number of things in the Makefile, such that it's of the form
all : all-platform1 all-platform2
stuff-platform1 : requirements
$(CC1) whatever
stuff-platform2 : requirements
$(CC2) whatever
It's possible that you might be able to auto-generate a makefile like this, to save some effort though.

Resources