Does GNU make prepend a "./" to the path of included makefiles? - windows

Running GNU Make 4.4 on Windows 10.
I'm trying to include a generated makefile from another. When the included file is given as an absolute directory, I get the following error:
makefile:6: ./D:/Users/xxxxxxxx/Workspace/test/make/makefile-deps.mk: Invalid argument
make: *** No rule to make target './D:/Users/xxxxxxxx/Workspace/test/make/makefile-deps.mk'. Stop.
Here is a makefile which re-creates the problem:
OUTPUT_DIR := $(abspath .)
DEPS_FILE := $(OUTPUT_DIR)/makefile-deps.mk
include $(DEPS_FILE)
CSRCS := a.c b.c c.c d.c
$(DEPS_FILE): $(CSRCS) $(OUTPUT_DIR)
#echo MAKEDEPS
#$(MAKEDEPS) --output-file $# $(CSRCS)
show:
#echo DEPS_FILE=$(DEPS_FILE)
If I comment out the include line, the show target shows that the directory is not prepended:
─▶ make show
DEPS_FILE=D:/Users/xxxxxxxx/Workspace/test/make/makefile-deps.mk
So it must be the include directive prepending the ./ to the path name, causing the failure. Does any know a work-around for this?

Related

Driver is not compiling "No rule to make target"

Compile this driver with:
echo "obj-m := tiny_i2c_adap.o" > Makefile
make -C SUBDIRS=$PWD modules
Makefile:
obj-m := tiny_i2c_adap.o
Error :
prashanth#prashanth-Lenovo-ideapad-520-15IKB:~$ make -C /usr/src/linux-headers-$(uname -r) M=$PWD modules
make: Entering directory '/usr/src/linux-headers-5.1.7-050107-generic'
make[1]: * No rule to make target '/home/prashanth/tiny_i2c_adap.c', needed by '/home/prashanth/tiny_i2c_adap.o'. Stop.
Makefile:1571: recipe for target 'module/home/prashanth' failed
make: * [module/home/prashanth] Error 2
make: Leaving directory '/usr/src/linux-headers-5.1.7-050107-generic'
Remember $PWD is a shell variable, which contains the current working directory. So when you run:
~$ make -C /usr/src/linux-headers-$(uname -r) M=$PWD modules
the value of $PWD here is the directory you are in when you run make (in this case your home directory) so you're running:
~$ make -C /usr/src/linux-headers-$(uname -r) M=/home/prashanth modules
So the kernel makefile assumes that your module lives in /home/prashanth because that's where you set the M variable to.
You need to either use the correct path for M, or else use cd to switch to the directory containing your source before invoking make so that $PWD will contain the right path.

Ensure that make is invoked from a specific directory

I would like all my recipes to be executed from a specific directory, the directory where the Makefile is located.
This is the default behaviour when invoking make without options, but an user could always run :
(cd /somewhere; make -f /path/to/directory/Makefile)
To ensure that make working directory is the same as the directory where the Makefile is located, there are multiple solutions :
run make without options (default), from this specific directory (cd /path/to/directory; make)
use make -C /path/to/directory
cd to /path/to/directory for each recipe, like this :
MAKEFILE_DIR_LOCATION := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
a:
cd ${MAKEFILE_DIR_LOCATION} && do_something_from_makefile_folder
b:
cd ${MAKEFILE_DIR_LOCATION} && do_another_thing_from_makefile_folder
The problem is that the first two solutions requires actions from the user invoking the Makefile, while the last one clutters the Makefile.
Is there a prettier way to ensure that all recipes are executed from the directory where the Makefile is located?
Extra solution (does not work)
I also thought comparing the working directory ($(shell pwd)) to ${MAKEFILE_DIR_LOCATION}, and exit if it does not match (at least to warn the user that make is not correctly invoked), but I can't find how to do this. I tried :
MAKEFILE_DIR_LOCATION := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
WORKING_DIR := $(shell pwd)
ifneq (${MAKEFILE_DIR_LOCATION}, ${WORKING_DIR})
#error "Please run make from the directory of the Makefile, or use make -C"
endif
a:
do_something_from_makefile_folder
b:
do_another_thing_from_makefile_folder
But I got a missing separator error (line #error), or a recipe commences before first target if #error line is indented.
Answering the question you asked without commenting on whether it's a good idea or not, I'm not sure where you found this syntax:
#error "Please run make from the directory of the Makefile, or use make -C"
but it's definitely wrong. error is a make function, so you want this:
$(error Please run make from the directory of the Makefile, or use make -C)
A variant on your last attempt would re-invoke Make in the correct directory, with the same target:
ifneq (${MAKEFILE_DIR_LOCATION},${WORKING_DIR})
%:
$(MAKE) -C ${MAKEFILE_DIR_LOCATION} $#
.PHONY: %
else
## rest of Makefile rules
endif

Compile multiple executables from multiple source directories to single bin directory using makefile

I'm trying to create a makefile for a suite of programs that I am working on. The programs are all written in fortran and the source files are contained in different directories. I can't seem how to figure out how to get things to work. My current sumfile is
#Compiler and compiler flag variables
FCOMP=/usr/local/bin/gfortran
F_FLAGS=-O2 -fbounds-check -Wall
F_FLAGSDB=-g -fbounds-check -Wall
#paths to libraries
COMMON_LIB=/usr/local/lib/libspc_common.a
SPICE_LIB=/usr/local/lib/spicelib.a
# Paths to directories
BIN_DIR=BIN
# Get file names of component source files
#get names of files in src1
FORT_FILES=$(wildcard ./SRC1/*.f)
#get names of files in src2
FORTFILES+=$(wildcard ./SRC2/*.f)
#get names of files in src3
FORTFILES+=$(wildcard ./SRC3/*.f)
#get file names for output
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
# make commands
# Set the default option to compile the library with optimization
default: all
# create all command
all: $(EXE_FILES)
#echo toolkit has been built with optimization
#If compiling for debugging replace the compiler flags to remove optimization and add debugging
debug: F_FLAGS=$(F_FLAGSDB)
#Run compiler with debugging flags
debug: $(EXE_FILES)
#echo toolkit has been built with debugging
# Compile all of the source files into executables
$(EXE_FILES): % : %.f
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$#
# install the library in /usr/local/lib
install:
cp -p $(BIN_DIR)* /usr/local/bin/toolkit/
# remove executable files for a clean build
clean:
rm $(BIN_DIR)*
The problem I am running into is that I get the following error when I try to run make:
make: *** No rule to make target `Display.f', needed by `Display'. Stop.
which I am assuming is because I have lost the directory that the source file comes from. Can someone help me here? I am totally stuck and don't know how to proceed.
In addition (this is more a general question about make), is there a way to tell make to recompile everything if the COMMON_LIB changes?
Thanks for your help!
Suppose your source files are
SRC1/alpha.f
SRC1/beta.f
SRC2/gamma.f
SRC3/delta.f
1) There is a flaw here:
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
This will produce
BINalpha BINbeta BINgamma BINdelta
when I think you intended
BIN/alpha BIN/beta BIN/gamma BIN/delta
A simple fix:
EXE_FILES=$(addprefix $(BIN_DIR)/,$(notdir $(patsubst %.f, % , $(FORTFILES))))
2) Now look at the static pattern rule:
$(EXE_FILES): % : %.f
...
So to build BIN/alpha, Make must first find BIN/alpha.f, which doesn't exist. To make it look for alpha.f, do this:
$(EXE_FILES): $(BIN_DIR)/% : %.f
...
3) How to find the sources?
You could do some delicate coding to help Make remember where it found alpha.f, but there's no need when we can use the vpath directive:
vpath %.f SRC1 SRC2 SRC3
4) One last look at that rule:
This command:
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$#
Will produce e.g. BIN/BIN/alpha, which is silly. A non-PHONY Make rule should produce a file whose name is the target of the rule. It prevents a lot of trouble.
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $#
A few further refinements may be possible, once you have this working perfectly.

Makefile to view files that has errors in absolute paths

I have the following setup for my project:
~/proj -> includes makefile and other stuff
~/proj/headers -> includes c header files
~/proj/source -> includes C source files
When executing make in the main tree folder ~/proj errors are show with file names like this:
"source1.c" error variable...etc
How is it possible to have make show the absolute paths of files in error. Something like this:
~/proj/source/source1.c" error variable etc...
This is an example of an error:
Dependencies for mem_init.c
Compiling mem_init.c
"mem_init.c", line 513: warning: implicit function declaration: init_mem (E_NO_IMPLICIT_DECL_ALLOWED)
cc: acomp failed for mem_init.c
It's not possible at all, because it's not make that's printing those errors: it's your compiler. What you want to be asking is how (or if) it's possible to have your compiler show the absolute paths in its error messages. And of course in order to ask that question you'll have to specify which compiler you're using.
It's possible that if you passed an absolute path of the source file on the command line to your compiler, that your compiler would use that same path in its error messages. That is, if you run cc -o foo.o foo.c your error messages will be relative to foo.c, but if you run cc -o foo.o /home/me/proj/source/foo.c your error messages will be relative to /home/me/proj/source/foo.c.
If that's true, then you can change your make rule to something like (if you're using GNU make of sufficiently new vintage):
%.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $# $(abspath $<)
or whatever.

Makefile.am - Manual target prerequisite + addprefix?

I have a autotool project where part of the source code is downloaded dynamically from the net (because of IP rights preventing direct redistribution) and then built.
I have a Makefile.am that works but I'm not happy about some of it's aspects.
Here it is:
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS = -fPIC -Wall ${SYMBOL_VISIBILITY}
LIBVERSION=0:0:0
REFSRC_PATH=refsrc
REFSRC_SRC=refsrc/dtx.c refsrc/globdefs.c refsrc/host.c refsrc/mathhalf.c refsrc/sp_enc.c refsrc/sp_rom.c refsrc/vad.c refsrc/err_conc.c refsrc/homing.c refsrc/mathdp31.c refsrc/sp_dec.c refsrc/sp_frm.c refsrc/sp_sfrm.c
${REFSRC_PATH}/.downloaded:
./fetch_sources.py "${REFSRC_PATH}"
for f in `ls -1 "${REFSRC_PATH}"/*.{c,h}`; do \
sed -i -e"s/round/round_l2s/" "$$f"; \
done
touch $#
${REFSRC_PATH}/dtx.c: ${REFSRC_PATH}/.downloaded
lib_LTLIBRARIES = libgsmhr.la
libgsmhr_la_SOURCES = libgsmhr.c $(REFSRC_SRC)
clean-local:
-rm -rf ${REFSRC_PATH}
So essentially, libgsmhr.c is my main wrapper, then I download the source code in a refsrc/ subdirectory and patch it a little.
First problem is that in REFSRC_SRC I would have loved to use a $(addprefix ...) instead of repeating refsrc/ in front of each .c file. But that doesn't seem to work and autoreconf complains a little.
Failure details (when removing the refsrc/ prefix from REFSRC_SRC= and using $(addprefix ${REFSRC_PATH}/, ${REFSRC_SRC}) on the dependency list):
bash$ autoreconf -i
libgsmhr/Makefile.am:19: addprefix ${REFSRC_PATH}/, ${REFSRC_SRC}: non-POSIX variable name
libgsmhr/Makefile.am:19: (probably a GNU make extension)
(configure works fine)
bash$ make
...
make[2]: Entering directory `/tmp/ram/gapk.build/libgsmhr'
CC libgsmhr.lo
CCLD libgsmhr.la
make[2]: Leaving directory `/tmp/ram/gapk.build/libgsmhr'
...
(So as you see it didn't include any of the downloaded .c files, didn't even download them at all. The compile works because libgsmhr.c is a stub that doesn't use the symbols in those file yet)
Second problem is this rule:
${REFSRC_PATH}/dtx.c: ${REFSRC_PATH}/.downloaded
I have to explicitely list the first file (dtx.c) instead of using a wildcard like:
${REFSRC_PATH}/%.c: ${REFSRC_PATH}/.downloaded
If I try to use the wildcard, then autoreconf complains and also it just doesn't work ... (pattern doesn't match somehow).
Failure detail:
bash$ autoreconf -i
libgsmhr/Makefile.am:16: `%'-style pattern rules are a GNU make extension
(configure works fine)
bash$ make
...
make[2]: *** No rule to make target `refsrc/dtx.c', needed by `dtx.lo'. Stop.
...
Sylvain
You seem to be writing a makefile in GNUMake style, but actually running some other version of Make. If it's not obvious what autoreconf is calling, you could insert a rule in the makefile:
dummy:
#echo using $(MAKE)
$(MAKE) -v
If this theory proves correct, you can either persuade autoconf to use GNUMake, or write for the version it's using.

Resources