Build using sources from a duplicate tree - makefile

GNU Make 3.8.1
I am working on what is basically a plugin for a software product. The plugin is built in a subdirectory of the main product, so the directory structure looks something like:
product
product/src
product/plugin
product/plugin/myPlugin
where "myPlugin" is the name of the plugin I'm working on. What I would like to do, is be able to build myPlugin as well as another version of myPlugin, call it myPlugin-lite. This plugin would have the same sources as myPlugin, but use different flags and defines in the makefiles. The idea was to create a duplicate of the myPlugin tree structure, containing only myPlugin's makefiles, and have it build using the sources from myPlugin. So the directory structure would look like:
product
product/src
product/plugin
product/plugin/myPlugin
product/plugin/myPlugin-lite
myPlugin would build and create all its targets within its subdirectory, and myPlugin-lite would build and create all its targets within its subdirectory. I found a few solutions here: http://make.mad-scientist.net/papers/multi-architecture-builds/ and out of these options it seems like the symbolic links would be best, but it still doesn't feel like the "right" way to do this.
My question is, is this the best/simplest/most maintainable way to do this? If not what are the alternatives?

If the only thing you need from myPlugin is source files then this is exactly what VPATH and The vpath Directive are for.
4.5.1 VPATH: Search Path for All Prerequisites
The value of the make variable VPATH specifies a list of directories that make should search. Most often, the directories are expected to contain prerequisite files that are not in the current directory; however, make uses VPATH as a search list for both prerequisites and targets of rules.
Thus, if a file that is listed as a target or prerequisite does not exist in the current directory, make searches the directories listed in VPATH for a file with that name. If a file is found in one of them, that file may become the prerequisite (see below). Rules may then specify the names of files in the prerequisite list as if they all existed in the current directory. See Writing Recipes with Directory Search.
In the VPATH variable, directory names are separated by colons or blanks. The order in which directories are listed is the order followed by make in its search. (On MS-DOS and MS-Windows, semi-colons are used as separators of directory names in VPATH, since the colon can be used in the pathname itself, after the drive letter.)
For example,
VPATH = src:../headers
specifies a path containing two directories, src and ../headers, which make searches in that order.
With this value of VPATH, the following rule,
foo.o : foo.c
is interpreted as if it were written like this:
foo.o : src/foo.c
assuming the file foo.c does not exist in the current directory but is found in the directory src.
Also see How Not to Use VPATH from MadScientist for more discussion about what they aren't for. Though that's largely just a build-up for the multi-architecture-builds paper you already read.

Related

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))

How to create a rule to identify all the files with a .c extension on the included directories as a pre-requisite for a makefile rule?

If I have the rule, where OBJECTS_C is a list of object files with NO path:
$(OBJECTS_C): %.o: %.c
do stuff
how can I specify that the %.c file is supposed to match the same file stem, but the path can be anything?
Like suppose I have source/file1.c and source/dir1/file2.c
I want to modify the rule such that file1.o and file2.o are created on the current directory, regardless of where the source files are on the included directories.
You could use VPATH (as a variable or using the vpath directive) to add all the relevant directories to the list of directories searched for prerequisites.
(VPATH is for all prerequisites, vpath only for those matching the pattern it is given)
Here is the relevant documentation.
That said, beware of name conflicts : if you have src files that have the same name but are in different directories, you might experiment troubles. A better way would be to have your build tree reflects your source tree.

automake - target folder in source blocks executing destination

I am trying to understand a makefile from a project I am working on. It's using automake/autotools and contains this simple rule:
DEPS_SRC = $(shell cd $(srcdir); find . -name '*.ez')
DEPS = $(basename $(DEPS_SRC))
all : $(DEPS)
$(DEPS) : % : %.ez
$(UNZIP) -o $<
Say the directory structure is:
my-app/deps/
build/
When executing make my-app in the build folder the rule will basically unpack *.ez files located in the my-app/deps/ folder into build/my-app/deps/ folder.
I don't know if that's enough information to solve the problem that I am going to explain as I don't know enough about automake/autotools. Please ask if any additional information is needed.
The problem is that I noticed that having the unpacked directory in the source folder prevents make from unpacking the archive in the target folder. For example, given the following structure in the source folder:
my-app/deps/archive1.ez
my-app/deps/archive2.ez
my-app/deps/archive2/
make will only unpack archive1.ez in the build folder:
build/my-app/deps/archive1/
I would like to know if this is a bug in my makefile or a feature of automake. If the later, is there any workaround or setting or variable available to disable it?
This is primarily a GNU make question, not particularly specific to the Autotools. However, since the target system's make is of GNU's flavor (else none of this works), we can assume that the Makefile generated by configure uses GNU make's VPATH feature as part of its support for out-of-source (a.k.a. VPATH) builds such as the one you are performing.
The value of the VPATH variable that configure will have inserted into the Makefile is used as a search path for prerequisites that are not found relative to the build directory. The key point, however, is that it is also used as a search path for rule targets. That makes a certain amount of sense, especially for targets that are prerequisites of other rules.
In your case, however, that leads directly to the behavior you describe:
the default target depends on ./my-app/deps/archive2
resolving that name against the build directory does not produce a valid file name
before attempting to build that target, make looks in the directories listed in the VPATH, which, in your example case, will contain .. or an equivalent
make finds .././my-app/deps/archive2 in this VPATH search, and therefore determines that the specified target already exists, and does not need to be built
Thus, the behavior you observe is normal for GNU make, supposing the Makefile is constructed by Autoconf from an Automake-generated template.
is there any workaround or setting or variable available to disable it?
Do you really need one? If the archive file has already been unpacked in the source tree, then you can expect make to find its contents, too, via the VPATH. At least if the Makefile is well-prepared overall for for out-of-source builds.
But if you want to be certain to get the archive files unpacked in the build directory then you can specify that explicitly. This ought to do it:
DEPS_SRC = $(shell cd $(srcdir); find . -name '*.ez')
DEPS = $(basename $(DEPS_SRC))
LOCAL_DEPS = $(addprefix $(abs_builddir)/,$(DEPS))
all : $(LOCAL_DEPS)
$(LOCAL_DEPS) : $(abs_builddir)/% : %.ez
$(UNZIP) -o $<
That prefixes the name of each dependency with the absolute path to the build directory, and updates the rule for unzipping the archives to accommodate it. Targets with absolute paths such as that cannot be located in the VPATH.

Makefile to compile Fortran source files in different directories

Here is my problem: I have been using Java for many years and enjoy having many directories separating different areas of the code. For my current project I am writing Fortran code, which should compile under Windows and Unix/Linux. For Windows, I am using Eclipse/Photran with MinGW/gfortran tools to set up Makefiles.
Here is the desired project structure (deep nesting tree-like Java-like would be even nicer)
dir1/src/*.f95
dir1/make/Makefile_lib1.any
dir1/make/Makefile_lib1.win
dir1/make/Makefile_lib1.unix
dir2/src/*.f
dir2/make/Makefile_lib2.any
dir2/make/Makefile_lib2.win
dir2/make/Makefile_lib2.unix
...
dir_main/src/*.f or *.f95
dir_main/make/Makefile_main.any
dir_main/make/Makefile_main.win
dir_main/make/Makefile_main.unix
I would like to call make Makefile_main.unix, which would set up any Unix-specific variables and then include Makefile_main.any, Makefile_lib1.any, ...
(similar for making on Windows)
I got to the stage where I can see all source files in a given directory, e.g.
SRCS := $(wildcard $(SRC_DIR)/*.$(SRC_EXT))
Now I am struggling with how to make all dependencies as in Fortran 95 each source generates *.o and *.mod.
Is there a way to switch between directories when compiling so that all targets/dependencies do not have dir-path in their names? Note that I am calling make from some other service directory where the Eclipse project lives. Any suggestions how to proceed?
I really do not want to do the usual Fortran style of having just one directory with
all the mess together with the code.
There are two major strategies you can take.
You can place a makefile in each subdirectory and have it support targets like all, clean etc, then use recursive make invocations from the top-level makefile to make the same target (e.g. all) in every subdirectory.
Alternatively, you can handle it all in one make invocation, without recursing, but then you'll have to work with relative paths containing subdirectory names. Personally I don't see a problem with it, and I've maintained a system of makefiles based on this approach.
Here is what you can do in your case, assuming that SRC is set correctly to the list of relative paths to every source you need to compile.
# This replaces the SRC_EXT suffix with .o in each filename
OBJ = $(SRC:%.$(SRC_EXT)=%.o)
$(BINARY_NAME): $(OBJ)
...link command...
%.o: %.$(SRC_EXT)
...compile command...

(Auto)make dependency across multiple makefiles

I am wondering if this is possible at all. Here is the situation:
My project uses automake to build its targets. The top-directory contains the usual configure.ac and Makefile.am. Amongst others, the Makefile.am contains a SUBDIRS variable listing the subdirectories, important for my question is the doc and include directory. The include directory's makefile looks like:
nobase_include_HEADERS = <lot-of-headers>
so it basically installs the headers. The makefile in doc is supposed to generate html documentation out of those files:
doxygen-stamp: Doxyfile
$(DOXYGEN) $<
echo "timestamp for Doxyfile" > $#
all-local: doxygen-stamp
Everything works fine so far, but if I change any of the headers in include the documentation is still up-to-date - because I did not list them as dependencies. What I would like to have is to have a doxygen-stamp-target that is rebuilt once the headers change without again listing all headers as dependencies. Is that possible and if it is, how?
In this case, using a single Makefile would be hinted at — though you can split it up by using the automake include instruction (also see section 7.3 "An alternative approach to subdirectories" of the am manual). Therefore:
#can't use nobase_
include_HEADERS = include/foo.h include/bar.h
doc/doxygen-stamp: ${include_HEADERS}
I think if you make doxygen-stamp also depend on '$(top_srcdir)/include/*.h' (or .hpp or whatever) it will rebuild when doxygen-stamp is out of date relative to any .h file in the include directory.
doxygen-stamp: Doxyfile $(top_srcdir)/include/*.h

Resources