What's the proper lib variable for a makefile? - makefile

Running into trouble with libraries in makefiles again. Every time I try to get back into C make gives me a pain with libs.
make -pf /dev/null says the correct vars should be LDLIBS and LOADLIBES but the following doesn't alter the run command at all:
LOADLIBES=testing
LDFLAGS=testing
LDLIBS=testing
Needless to say this gives me errors because the -L flags don't end up in the command. Anyone know what's going on?
Full makefile below (Derivitave of Z Shaw's makefile)
OPTLIBS=$(xml2-config --libs)
OPTFLAGS=$(xml2-config --cflags)
STD=c99
CFLAGS=-std=$(STD) -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LDLIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/lib.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: cls $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-std=$(STD) -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $# $(OBJECTS)
ranlib $#
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $# $(OBJECTS)
build:
#mkdir -p build
#mkdir -p bin
# The Unit Tests
$(TESTS): $(TARGET)
.PHONY: tests
tests: LDLIBS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean: cls
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
#echo Files with potentially dangerous functions.
#egrep $(BADFUNCS) $(SOURCES) || true
# Clear screen for unspammy terminals
cls:
ifdef TERM
clear
endif

You aren't using LDFLAGS, etc in your link command. Make that something along the lines of:
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared $(LDFLAGS) -o $# $(OBJECTS) $(LDLIBS)

It tells the linker to link the dl library, which is located at /usr/lib/libdl.so. -l is the switch to add a library, dl is the name of it (without the lib prefix or .so extension).
This library includes functions for dynamically loading shared libraries.

Related

`Makefile` rule to regenerate object files directory without recompiling from scratch?

I have the following Makefile which works great but everytime it is recompiling from start evenif nothing has changed.
CXX = g++
CXXFLAGS = -std=c++11
INC_PATH = `pkg-config --cflags ../openCV/build/lib/pkgconfig/opencv.pc` \
`pkg-config --cflags ../SDL2-2.0.8/instDir/lib/pkgconfig/sdl2.pc` \
`pkg-config --cflags ../jsoncpp/build/pkg-config/jsoncpp.pc` \
-I ../poco/instDir/include/
#LIB_PATH = -L../cmake_bin_dir/lib/ ./gainput/build/lib -L../SDL2-2.0.8/build/ -L../SDL2-2.0.8/build/lib
LIBS = `pkg-config --libs ../openCV/build//lib/pkgconfig/opencv.pc` \
`pkg-config --libs ../SDL2-2.0.8/instDir/lib/pkgconfig/sdl2.pc` \
`pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc` \
-L../poco/instDir/lib/ -lPocoNetd -lPocoUtild -lPocoFoundationd \
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.cpp)
OBJDIR=$(SOURCEDIR)/obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.cpp,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.cpp,$(OBJDIR)/%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: parking
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
parking: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $# $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.cpp Makefile $(OBJDIR)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) -MMD -MP -c $< -o $#
The problem seems to be these lines
$(OBJDIR)/%.o: $(SOURCEDIR)/%.cpp Makefile $(OBJDIR)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) -MMD -MP -c $< -o $#
and particularly the dependency from $(OBJDIR) (where *.o and *.d files are saved) in fact when I remove it seems not to recompile. The problem is that if I remove the $(OBJDIR), the directory is not regenerated again.
What is the Makefile rule to regenerate the directory where object files are stored without starting all the compilation from scratch?
$(OBJDIR) is a prerequisite of your object files. As with any directory, its last modification time changes every time its content changes... Declare it as an order-only prerequisite instead:
$(OBJDIR)/%.o: $(SOURCEDIR)/%.cpp Makefile | $(OBJDIR)
This way, if it exists already, its last modification time will not be considered by make to decide which targets need to be re-built.

Makefile can't find input files in specified directory

I am working with the following Makefile:
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/lcthw/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libYOUR_LIBRARY.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $# $(OBJECTS)
ranlib $#
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $# $(OBJECTS)
build:
#mkdir -p build
#mkdir -p bin
# The Unit Tests
.PHONY: tests
tests: CFLAGS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
And I'm having trouble with this line:
$(CC) -shared -o $# $(OBJECTS)
I am getting the error:
cc: fatal error: no input files
when I try and run any of the following commands: make, make all and make dev. Why can't my makefile find the .c files in the directories I specified?
You need to specify the full paths in this line:
SOURCES=$(wildcard src/lcthw/.c src/.c)
OTW this becomes a constraint on where you can run the make command from. Possibly what's happening is that the wildcards are not being expanded since the directory you are sitting in, $(CURDIR) , makes it hard for it to see these paths.
You should try printing these variables from inside your makefile, by doing:
$(info source=$(SOURCES))
And if your .obj files are placed in a different location than the sources, then you need to account for that by including that place in the $(OBJECTS) as well.

Makefile: How write a rule that is only executed when a certain shared object library doesn't exist?

I am trying to write a rule, which should only execute if a certain shared object library doesn't exist
$(OUTDIR)/libv8-$(ARCH).so: v8
v8: # to be able to build V8 only with "make v8"
cd V8; bash V8Update.sh
However, V8Update.sh is executed every time. Here is the full Makefile:
CC=g++
V8INCLUDEDIR=V8/build/v8/include
CFLAGS=-c -Wall -std=c++0x -fPIC -I$(V8INCLUDEDIR) -I/usr/include -I/usr/include/c++/4.6 \
-I/usr/include/c++/4.6/backward -I/usr/include/c++/4.6/x86_64-linux-gnu -I/usr/include/x86_64-linux-gnu \
-I/usr/lib/gcc/x86_64-linux-gnu/4.6/include -I/usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed \
-I/usr/local/include -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/
DEPS=ProxyTypes.h $(V8INCLUDEDIR)/v8.h $(V8INCLUDEDIR)/v8-debug.h $(V8INCLUDEDIR)/v8stdint.h
ARCH=x64 # TODO: Add support for building 32-bit libraries.
LDFLAGS=-shared -lglib-2.0 -L/usr/lib/x86_64-linux-gnu/ #-Wl,--no-undefined
SOURCES=Exports.cpp FunctionTemplateProxy.cpp HandleProxy.cpp ObjectTemplateProxy.cpp Utilities.cpp V8EngineProxy.cpp \
ValueProxy.cpp
OBJECTS=$(patsubst %,$(OUTDIR)/%,$(SOURCES:.cpp=.o))
LIBRARY=libV8_Net_Proxy.so
.PHONY: all v8 release debug makeoutdir clean copybin
all: debug copybin
v8: # to be able to build V8 only with "make v8"
cd V8; bash V8Update.sh
release: OUTDIR=bin/Release
debug: OUTDIR=bin/Debug
release debug:
$(MAKE) -S makeoutdir $(LIBRARY) OUTDIR=$(OUTDIR)
makeoutdir:
mkdir -p $(OUTDIR)
clean:
rm bin/ -rf
# rm V8/build -rf
copybin:
cp -a bin/Debug/*.so ../bin/Debug
$(LIBRARY): $(OUTDIR)/libv8-$(ARCH).so $(OBJECTS)
$(CC) $(LDFLAGS) -lv8-$(ARCH) -L$(OUTDIR) -o $(patsubst %,$(OUTDIR)/%,$#) $(OBJECTS)
$(OUTDIR)/libv8-$(ARCH).so: v8
$(OUTDIR)/%.o: %.cpp $(DEPS)
$(CC) $(CFLAGS) -o $# $<
What am I doing wrong here?
It should be
v8: $(OUTDIR)/libv8-$(ARCH).so
$(OUTDIR)/libv8-$(ARCH).so:
cd V8; bash V8Update.sh
You can't depend on phony target - it will be executed every time (and that is a feature, btw).

Makefile overwrite old files automatically [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do you force a makefile to rebuild a target
I'm using a slightly modified version of zedshaw's makefile, but when I run it it doesn't recompile .o files.
I just spent 2 hours debugging only to find out make was looking at the existing object files and simply not recompiling them.
How do I force make to recompile $(OBJECTS) in future? Is there a way to do it without adding the clean target before all?
Edit: For clarity: Make is supposed to recompile automatically if something in the source has been changed, this isn't working for the $(OBJECTS) so I either need to force recompiling them or find out why it's not doing it itself.
Edit 2: After copying the whole folder and diffing it at different times I realized that make was correctly seeing all but one dependency. The problem is in the following point:
tests: LDLIBS += $(TARGET)
tests: $(TESTS)
Make doesn't recognize things under LDLIBS as dependencies so I added:
$(TESTS): $(TARGET)
Which resolved the issue. Since Jens called it in the comments I'm going to mark his answer as accepted.
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LDLIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/liblcthw.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: cls $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $# $(OBJECTS)
ranlib $#
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $# $(OBJECTS)
build:
#mkdir -p build
#mkdir -p bin
# The Unit Tests
.PHONY: tests
tests: LDLIBS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean: cls
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
#echo Files with potentially dangerous functions.
#egrep $(BADFUNCS) $(SOURCES) || true
# Clear screen for unspammy terminals
cls:
clear
How do I force make to recompile?
Two options:
touch all source files
If you are using GNU make, make --always-make

Making a better Makefile

so I learned what a Makefile was some time ago, created a template Makefile and all I do is copy and alter the same file for every program I'm doing. I changed it a few times, but it's still a very crude Makefile. How should I improve it? This is an example of my current version:
CC = g++
CFLAGS = -std=gnu++0x -m64 -O3 -Wall
IFLAGS = -I/usr/include/igraph
LFLAGS = -ligraph -lgsl -lgslcblas -lm
DFLAGS = -g -pg
# make all
all: run test
# make a fresh compilation from scratch
fresh: clean test
#makes the final executable binary
run: main.o foo1.o foo2.o
$(CC) $(CFLAGS) $(LFLAGS) $^ -o $#
#makes the test executable with debugging and profiling tags
test: test.o foo1.o foo2.o
$(CC) $(DFLAGS) $(CFLAGS) $(LFLAGS) $^ -o $#
#makes teste.o
teste.o: teste.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#makes main.o
main.o: main.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#file foo1
foo1.o: foo1.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#file foo2
foo2.o: foo2.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
clean: clean-test clean-o clean-annoying
clean-test:
rm test-rfv
clean-o:
rm *.o -rfv
clean-annoying:
rm *~ -rfv
Just by visually comparing with other makefiles I saw around in the web, this seems to be not a very bright Makefile. I don't know how they work, but I can see there's significantly less boilerplate and more generic code in them.
Can this can be made better, safer, and easier to particularize for each project?
You don't want to name specific files in a makefile if you can get away with it, and 99% of the time you can. This page shows how to develop a very general makefile. The following is my own makefile, based on that page's info:
SHELL := bash
PROG := pathed.exe
OUTDIRS := bin/debug bin/rel obj/debug obj/rel
PROG_REL := bin/rel/$(PROG)
PROG_DEBUG := bin/debug/$(PROG)
SRCFILES := $(wildcard src/*.cpp)
OBJFILES_REL := $(patsubst src/%.cpp,obj/rel/%.o,$(SRCFILES))
OBJFILES_DEBUG := $(patsubst src/%.cpp,obj/debug/%.o,$(SRCFILES))
DEPFILES := $(patsubst src/%.cpp,obj/%.d,$(SRCFILES))
CFLAGS := -Iinc -Wall -Wextra -MMD -MP
DBFLAGS := -g
RELFLAGS :=
CC := g++
.PHONY: default all testmake debug release clean dirs
default: debug
all: dirs clean debug release
dirs:
#mkdir -p $(OUTDIRS)
debug: $(PROG_DEBUG)
release: $(PROG_REL)
testmake:
#echo OBJFILES_REL = $(OBJFILES_REL)
#echo OBJFILES_DEBUG = $(OBJFILES_DEBUG)
#echo SRCFILES = $(SRCFILES)
#echo DEPFILES = $(DEPFILES)
clean:
rm -f $(OBJFILES_REL) $(OBJFILES_DEBUG) $(DEPFILES) $(PROG)
$(PROG_REL): $(OBJFILES_REL)
$(CC) $(OBJFILES_REL) -o $(PROG_REL)
strip $(PROG_REL)
#echo "---- created release binary ----"
$(PROG_DEBUG): $(OBJFILES_DEBUG)
$(CC) $(OBJFILES_DEBUG) -o $(PROG_DEBUG)
#echo "---- created debug binary ----"
-include $(DEPFILES)
obj/rel/%.o: src/%.cpp
$(CC) $(RELFLAGS) $(CFLAGS) -MF $(patsubst obj/rel/%.o, obj/%.d,$#) -c $< -o $#
obj/debug/%.o: src/%.cpp
$(CC) $(DBFLAGS) $(CFLAGS) -MF $(patsubst obj/debug/%.o, obj/%.d,$#) -c $< -o $#
Do NOT use CC for the C++ compiler. The standard convention is that CC is the C compiler, CXX is the C++ compiler. CFLAGS are flags for the C compiler, CXXFLAGS are flags for the C++ compiler, and CPPFLAGS are flags for the pre-processor (eg, -I or -D flags). Use LDFLAGS for -L flags to the linker, and LDLIBS (or LOADLIBES) for -l flags.
Using the standard conventions is good not just because it makes things easier for others to understand, but also because it allows you to take advantage of implicit rules. If make needs to make a .o file from a .c file and you have not provided a rule, it will use a standard rule and honor the settings of CC, CFLAGS, and CPPFLAGS. If CC is a C++ compiler, things will probably not work.

Resources