Test if files in another directory exist in makefile - makefile

How would one test for the existence of files with a certain extension (.cpp in this case) in a directory at a specified location which is several directories down from the location of the makefile? I would like to print(echo) a message out if they are found

Your question is ambiguous. You mean, inside a make recipe you want to perform this test? If so then just write the appropriate shell scripting to check for the existence of said files.
If you mean outside of any recipe, in the makefile itself, if you're using GNU make you can use the $(wildcard ...) function:
ifneq (,$(wildcard some/sub/directory/*.cpp))
$(info found some cpp files!)
endif

Related

Symbols ($(bindir), $(sysconfdir),...) unknown in (sub) Makefiles

I'm working with autotools for the first time, for a tool that's written in perl (SQLTeX), so only installation is required, no compilation.
The toplevel contains a simple Makefile.am:
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src man doc
EXTRA_DIST = README.md
.PHONY: all-am
all-am:
#echo "Done!"
If I create Makefile.am files in the sub-directories too, nothing seems to happen there so I just stick to Makefile. A snippet from src/Makefile (EDIT: this file is now renamed to Makefile.am):
SQLTeX: SQLTeX.pl
cat $^ | sed -e 's#{PERLDIR}#$(PL)#;s#{SYSCONFDIR}#$(sysconfdir)#' > $#
#chmod +x $#
The symbol PL is set as expect (defined in the same makefile), but sysconfdir is empty, although it is defined in the top-level Makefile generated by ./configure.
What am I doing wrong?
Thanks in advance!
What am I doing wrong?
Although the Autotools support, with some caveats, recursing into directories where you provide pre-built makefiles, you cannot expect those pre-built makefiles to be able to rely on autotools-provided variables such as the standard directory variables bindir and sysconfdir. Thus, although it is allowed to rely on hand-written makefiles in subdirectories, this is probably a false trail for you.
I recommend going back to this:
If I create Makefile.am files in the sub-directories too, nothing seems to happen there
and working out what's wrong. The Autotools definitely support generating recursive build systems, and one Makefile.am per directory is part of the usual approach to that. If it didn't work for you then my first guess would be that you forgot to list the extra makefiles in your AC_CONFIG_FILES list.
As an alternative, just because you have multiple directories does not mean that you need to use recursive make. It is quite possible to build such a project with the support of a single makefile, and the Autotools can help with such a makefile.

How to use GNU make to update files in all subdirectories containing a particular file?

In my project, I have a set of sub-directories that contain package.yaml files, for e.g.:
A/package.yaml
B/package.yaml
C/package.yaml
If I run hpack A/package.yaml, the file A/A.cabal is (re-)generated. The list of such directories can change over time, so I want to use GNU make to find all immediate sub-directories containing package.yaml files and generate the corresponding .cabal files using hpack.
I tried this based on another question, but it didn't work:
HPACK_FILES := $(wildcard */package.yaml)
PKG_DIRS := $(subst /,,$(dir $(HPACK_FILES)))
CABAL_FILES := $(addsuffix .cabal,$(join $(dir $(HPACK_FILES)),$(PKG_DIRS)))
test:
#echo $(CABAL_FILES)
update-cabal: $(CABAL_FILES)
%.cabal: package.yaml
hpack $<
However, make update-cabal says there's nothing to be done. make test however does output the right cabal files. How can I fix this?
Cheers!
The problem is this:
%.cabal: package.yaml
There is no file package.yaml. The files are named things like A/package.yaml. That is not the same thing.
Because the prerequisite doesn't exist, make decides that this pattern rule cannot match and so it goes looking for another rule that might be able to build the target. It doesn't find any rule that can build the target, so make says there's nothing to do because all the output files already exist.
Unfortunately what you want to do is not at all easy with make, because make is most comfortable with input and output files that are tied together by the filename with extensions, or similar. And in particular, it has a really hard time with relationships where the variable part is repeated more than once (as in, A/A.cabal where the A is repeated). There's no easy way to do that in make.
You'll have to use an advanced feature such as eval to do this. Something like:
# How to build a cabal file
%.cabal:
hpack $<
# Declare the prerequisites
$(foreach D,$(dir $(HPACK_FILES)),$(eval $D/$D.cabal: $D/package.yml))

gnu make, include path for `include` directives

Apart from the standard directories used by make to locate files loaded by include directives, is there any way to specify additional include paths within the makefile itself? I'm aware of the -I command-line GNU make option but I would like to know if there's any make variable to specify the same.
I suggested using the .INCLUDE_DIRS variable, but as pointed out in the comment below, that variable is read-only.
The only other way I can think of is to have a top-level file invoke the real makefile, and have the top level one update MAKEFLAGS:
# Top level -- Call it GNUmakefile?
INCLUDE_DIRS := first second third
MAKEFLAGS += $(foreach dir,$(INCLUDE_DIRS),--include-dir=$(dir))
.DEFAULT all:;$(MAKE) -f Makefile $(MAKECMDGOALS)
Then the real Makefile is invoked with the three directories in .INCLUDE_DIRS.

How to get makefile to depend on any files inside a folder

I have a simple makefile that I use to build some latex files. The syntax looks like this:
pdf: thesis.tex chapters/a.tex chapters/b.tex chapters/c.tex
latexmk -pdf -pdflatex="pdflatex thesis.tex
open:
open thesis.pdf
The files inside chapters folder can increase further with d.tex, e.tex and may even contain subfolders f\section1.tex, f\section2.tex etc.
I manually add all the requried tex files inside my thesis.tex like this which is not a problem.
\input{chapters/a.tex}
\input{chapters/b.tex}
\input{chapters/c.tex}
\input{chapters/d.tex}
\input{chapters/e.tex}
How can I get make target pdf to depend upon any file changes inside chapters and its subdirectories?
How do I write inter task dependency in makefile. If target open depends upon target pdf, how do I write it?
open: pdf will sort-of do what you want for your second question.
Though it would be better to not use the phony pdf target for this.
Instead have a thesis.pdf: target which depends on the right prerequisites and have both pdf: thesis.pdf and open: thesis.pdf targets.
For the first question you can either use something like:
SRCS := $(shell find chapters -name '*.tex')
or use from here:
rwildcard=$(strip $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)))
SRCS := $(call rwildcard,chapters,*.tex)
and then:
thesis.pdf: thesis.tex $(SRCS)
to use that variable as the prereq.
If you wanted to get even fancier you could write a script to pull out the actual filenames from the \input{} directives in thesis.tex and use that as your SRCS variable (but that's probably not worth the effort unless you know you will have other, unrelated, .tex files).

Make include in makefiles be relative to the file's location

Directly related to this question. How can I make the include directive in makefiles behave relatively to the location of the current script?
Assume that the current path is arbitrary and you have no control over it. Only the makefile location is known. Your makefile is not the root one - it's included. That's exactly how it is in Android NDK.
Is there a builtin variable with the current makefile's name? Can I strip filename away from it, leaving just the path? Using make 3.81 on Cygwin.
You can get the name of the makefile being currently processed from MAKEFILE_LIST builtin variable.
Given that the current makefile is the last one that has been included (in other words you didn't use another include directive since the beginning of the current script), the path to the script itself would be:
SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
Now you are able to include a script in the same directory as such (note an absence of slash, it has already been added by $(dir ...)):
include $(SELF_DIR)another.mk
Note: In GNU Make 3.80 there was no lastword builtin function. In that case you may implement it as follows replacing $(lastword ...) with $(call lastword,...):
lastword = $(if $(firstword $1),$(word $(words $1),$1))
Is there a builtin variable with the current makefile's name?
Yes, there is, use ${CURDIR}. This is the directory where top-level Makefile is located, so you don't need to strip anything from it.
http://www.gnu.org/software/make/manual/make.html#Recursion
I find that relative paths work (GNUMake 3.81), but if they don't for you, try this:
include $(abspath ../whatever)

Resources