automake cannot deduce `_OBJECTS` from `_SOURCES` when using Pattern-Rules - automake

Automake usually can deduce object names needed for linking from the list of _SOURCES.
The following example using old-fashioned suffix rules works:
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = testam
testam_SOURCES = testam.c c.asn1
.asn1.c:
> $#
_
$ rm -f testam && make
/bin/sh ./libtool --tag=CC --mode=link gcc -g -O2 -o testam.exe testam.o c.o
libtool: link: gcc -g -O2 -o testam.exe testam.o c.o
As you can see, automake added the file c.o to the list of objects required to build testam.
But c.o isn't added, if I try to convert the rule into a pattern-rule:
%.c: %.asn1
> $#
_
$ rm -f testam && make
/bin/sh ./libtool --tag=CC --mode=link gcc -g -O2 -o testam.exe testam.o
libtool: link: gcc -g -O2 -o testam.exe testam.o
I have to use pattern rules, because my tool actually has two outputs: %.c %.h: %.asn1.
Why is this happening and how to explicitly add object files? Should I use _DEPENDENCIES and _LDADD or maybe BUILT_SOURCES?
Update
Automake's dependency tracking does not work for object files added with:
foo_LIBADD: extra1.o extra2.o
.Po files are generated, but Makefile does not include them

Related

Make error: The system cannot find the path specified

I'm getting a Make error when I run the mingw32-make command:
PS D:\> mingw32-make
cd src; mingw32-make
The system cannot find the path specified.
mingw32-make: *** [Makefile:4: all] Error 1
But when I list the actual command listed in the Makefile i.e. cd src; mingw32-make, the build is finished successfully.
PS D:\> cd src; mingw32-make
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c account.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c customer.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c display.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c main.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c passbook.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c security.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c staff.cpp
g++ -o Bank account.o customer.o display.o main.o passbook.o security.o staff.o
However this issue is not present when I build using Make on Ubuntu.
This is the Makefile in my root directory:
DIR = src
all:
cd $(DIR); mingw32-make
clean:
cd $(DIR); mingw32-make clean
This is the Makefile in my src subdirectory:
# Compiler options
# -std=c++17 enables ISO C++ 17 standard
CC = g++
CCFLAGS = -std=c++17 -Wall -Wextra -Wpedantic -
Wformat -Wchkp
i = ../include
# LOCFLAGS used to set tell the compiler where to find a
# header that is not in the same directory as the source
file itself
# LOCFLAGS will be set in directory level makefiles as
needed
LOCFLAGS = -I../include
# The list of object files that can be made in this
subdirectory
# is assigned to the make macro named $OBJECTS
OBJECTS = account.o customer.o display.o main.o
passbook.o \
security.o staff.o
# This rule says that the target named "all" depends on
those
# files. Executing "make all" in this subdirectory will cause
# make to build the object files (.o) listed in the macro
$OBJECTS
# and create an executable named "Bank" by linking them
all: $(OBJECTS)
$(CC) -o Bank $(OBJECTS)
# rule that says how to make a .o object file from a .cpp
source file
# for a given source file in a given directory you could
compile it
# into an object file by executing "make filename.o"
# $< and $# are macros defined by make
# $< refers to the file being processed (i.e., compiled or
linked )
# $# refers to the generated file
%.o: %.cpp
$(CC) $(CCFLAGS) $(LOCFLAGS) -c $<
# target to clean up the object files, core files and
executables
# executing "make clean" in this subdirectory will remove
all
# files named core, "Bank" or any file ending in .o or
.stackdump
clean:
del $(OBJECTS) core *.stackdump Bank
On Windows you're running in a command.com shell, not a POSIX shell. In command.com, the syntax cd src; mingw32-make is not legal. For example if I open a command.com terminal on a Windows system I see:
C:\Users\build> cd src; echo hi
The system cannot find the path specified.
In Windows command.com the command separator is a single & not a semicolon.
If you want to change directories portably you can use the -C option to GNU make. Also you should always use the $(MAKE) variable, not write out the make command by hand:
all:
$(MAKE) -C $(DIR)

makefile with two rules for the same target

I have a makefile to create a library, and I need it to create a 80% library or a complete library, which means a library with 80% of the functions or a library with all of the functions.
When I call make, the "all" rule should create the 80% library (so far so good), and when I call "make complete" the "complete" rule should create the 100% library (still easy), and it should not relink in any case, here I have a problem.
WHAT GOES WELL:
here is what I have :
all: $(NAME)
$(NAME): $(OBJS)
ar -rc $# $^
complete: $(NAME) $(MORE_OBJS)
ar -rc $^
%.o : %.c
gcc -I. -c -o $# $<
.PHONY: complete
so if I run make it goes:
>make
gcc -I. -c -o function01.o function01.c
gcc -I. -c -o function02.o function02.c
gcc -I. -c -o function03.o function03.c
gcc -I. -c -o function04.o function04.c
ar -rc libtest.a function01.o function02.o function03.o function04.o
and make again:
>make
make: Nothing to be done for 'all'.
perfect. then with make complete:
>make complete
gcc -I. -c -o function_05.o function05.c
gcc -I. -c -o function_06.o function06.c
ar -rc libtest.a function05.o function06.o
or of course:
>make fclean
rm *.o
rm libtest.a
>make complete
gcc -I. -c -o function01.o function01.c
gcc -I. -c -o function02.o function02.c
gcc -I. -c -o function03.o function03.c
gcc -I. -c -o function04.o function04.c
ar -rc libtest.a function01.o function02.o function03.o function04.o
gcc -I. -c -o function_05.o function05.c
gcc -I. -c -o function_06.o function06.c
ar -rc libtest.a function05.o function06.o
WHAT GOES WRONG:
but if I prompt make complete again:
>make complete
ar -rc libtest.a function05.o function06.o
I don't recompile but I relink the library.
I've tried a lot of approach, with the target-specific assignment, re-ordering the targets and the rules in many different combination, but I didn't find any way of doing it. am I missing something or is it indeed hard?
also, I can't put the additional functions in another file with its own makefile and use "make -C" to make it and then add it to the library, everything has to be in this makefile and the sources at the root
make complete will always run, because the target name is complete and no file named complete is ever created. So as far as make knows that file is not up to date and needs to be rebuilt.
There is no straightforward way to do this because make doesn't support multiple different recipes creating the same target.
You can fake it out by using a sentinel file to inform make whether the target exists or not. To do this, you need to create the file complete so make can use it to track whether or not it needs to be rebuilt. Try:
complete: $(NAME) $(MORE_OBJS)
ar -rc $^
#touch $#

adding shared library path to Makefile

I want to add the shared library path to my Makefile. I have put in the export command in the makefile, it even gets called, but I still have to manually export it again.
What is the correct approach?
Makefile:
SOURCES = kwest_main.c fusefunc.c dbfuse.c logging.c dbbasic.c dbinit.c dbkey.c metadata_extract.c plugins_extraction.c import.c
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=.
INCLUDE = ../include
LIB = ../lib
EXE = kwest
CC = gcc
CCFLAGS = -g -Wall -Wextra -std=gnu99 -pedantic-errors -I$(INCLUDE)
OFLAGS = -c
ARCH = $(shell getconf LONG_BIT)
X = -D_FILE_OFFSET_BITS=$(ARCH)
OBJECTS = $(SOURCES:.c=.o)
$(EXE) : $(OBJECTS)
$(CC) -o $(EXE) $(OBJECTS) $(LIBS)
%.o: %.c
$(CC) $(OFLAGS) $(CCFLAGS) $<
fusefunc.o: fusefunc.c
$(CC) $(OFLAGS) $(CCFLAGS) $< $X
kwest_libs: kw_taglib
--->export LD_LIBRARY_PATH=$(LIB):$LD_LIBRARY_PATH
kw_taglib: plugin_taglib
plugin_taglib: plugin_taglib.o kwt_upd_meta.o
gcc -g -shared -I$(INCLUDE) -Wl,-soname,libkw_taglib.so -o $(LIB)/libkw_taglib.so -ltag -ltag_c plugin_taglib.o kwt_upd_meta.o
plugin_taglib.o:
gcc -c -g -I$(INCLUDE) -Wall -Wextra -pedantic-errors -std=gnu99 -fPIC -ltag_c -c plugin_taglib.c
kwt_upd_meta.o:
g++ -c -g -I$(INCLUDE) -Wall -Wextra -pedantic-errors -fPIC -ltag kwt_upd_meta.cpp
c: clean
clean:
rm -rf *.o
rm -rf *.db
ca: cleanall
cleanall: clean
rm -rf $(EXE)
ob: cleanall
rm -rf ~/.config/$(EXE)/
Execution:
$ ./kwest mnt
./kwest: error while loading shared libraries: libkw_taglib.so: cannot open shared object file: No such file or directory
$ export LD_LIBRARY_PATH=../lib:D_LIBRARY_PATH
$ ./kwest mnt
"executes correctly"
The usual way is to copy the dynamic library during the default make and to one of the standard library path
/usr/local/bin
or one of your project library path and add the library to executable using
-L/project/specific/path
during make install.
As already mentioned here, the thing you probably want is the linker option -rpath.
Like that, you can set a default search path for the binary. Looks like you even already use -rpath in your makefile, but you specify the wrong path:
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=.
So the binary will search in the current directory for dyn-libraries.
However, you add ../lib to your LD_LIBRARY_PATH later, for execution of the binary, so the given path . seems to be wrong.
Please take a try for the following fix:
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=../lib
Like that you should not need to specify a LD_LIBRARY_PATH for execution.

makefile which get also the name of the file compile

I need a makefile which get also the name of the file compile
For example:
make foo
and the makefile should compile foo.c to foo.
This is my makefile. How to change it?
all: out
out: out.o
gcc -g -m32 -Wall -o out out.o
out.o: out.c
gcc -m32 -g -Wall -ansi -c -o out.o out.c
.PHONY: clean
#Clean the build directory
clean:
rm -f *.o out
There is no direct way where you can pass arguments to the Makefile but instead you can take advantage of variables to achieve what you want. Check the modifications done to the Makefile below
NAME ?=out #Default binary generated is out if you dont pass any argument
${NAME}: ${NAME}.o
gcc -g -m32 -Wall -o ${NAME} ${NAME}.o
${NAME}.o: ${NAME}.c
gcc -m32 -g -Wall -ansi -c -o ${NAME}.o out.c
.PHONY: clean
#Clean the build directory
clean:
`rm -f *.o ${NAME}`
And you should call the Makefile by typing
$ make NAME=foo
$ make clean NAME=foo
Passing arguments directly to Make is trivially easy.
Your current makefile can be invoked with make foo, and will compile foo.c to produce foo, because Make has implicit rules for handling cases like foo.c => foo; there will be no error even though "foo" is not the target of any rule. (At least, this is the case with GNU Make 3.81, which is what I am using.)
If you want to control the choice of compiler and flags (as in your out rule), there is more than one way to do it. The simplest (though not strictly the best) is to modify a couple of variables in the makefile:
CC = gcc
CFLAGS = -g -m32 -Wall -ansi
Another option is to override the implicit rule with a pattern rule of your own:
%: %.c
gcc -g -m32 -Wall -ansi -o $# $<
If you want it to build foo.o in a separate step, you must split the rule into two rule-- and also put in a rule with no recipe to cancel Make's implicit rule:
%: %.o
gcc -g -m32 -Wall -o $# $^
%.o: %.c
gcc -m32 -g -Wall -ansi -c -o $# $<
%: %.c
Further refinements are possible, once you have mastered the basics.

Why does make delete my temporary files?

I have a simple Makefile,
.PHONY: clean
PROGRAMS=$(patsubst main%.cpp,example%,$(wildcard main*.cpp))
all: ${PROGRAMS}
GCCVERSION=$(shell gcc -dumpversion)
GLCFLAGS=$(shell pkg-config --cflags gl)
CPPFLAGS=-Wall -O2 ${GLCFLAGS}
ifeq "${GCCVERSION}" "4.5.2"
CXXFLAGS=-std=c++0x
else
CXXFLAGS=-std=c++11
endif
GLLIBS=$(shell pkg-config --libs gl)
LIBS=${GLLIBS} -lglut
example%: main%.o shaders.o fileutils.o
${CXX} $^ ${LIBS} -o $#
clean:
rm -f *.o ${PROGRAMS}
But when I executed it, it delete the *.o files as last command. I don't know why:
$ make
g++ -std=c++11 -Wall -O2 -I/usr/include/libdrm -c -o main01.o main01.cpp
g++ -std=c++11 -Wall -O2 -I/usr/include/libdrm -c -o shaders.o shaders.cpp
g++ -std=c++11 -Wall -O2 -I/usr/include/libdrm -c -o fileutils.o fileutils.cpp
g++ main01.o shaders.o fileutils.o -lGL -lglut -o example01
rm main01.o fileutils.o shaders.o
Is there anything wrong with my Makefile?
Intermediate files are deleted by design: see Chained Rules in GNU make manual.
Use .SECONDARY or .PRECIOUS targets to keep your precioussss temp files.
Just to clarify the previous response, you need to add a special rule like
.PRECIOUS: myfile.o

Resources