Rombobjörn

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Persson <bjorn@rombobjörn.se>2013-08-01 18:25:26 +0200
committerBjörn Persson <bjorn@rombobjörn.se>2013-08-01 18:25:26 +0200
commit46d272892e2bb070e694e36cc9a9e58988032094 (patch)
treed66986b1e3c9956aeb0b747864410f50f802c130
parentc000eadddcaf1a2628cc54015690a2abd3f5dc1e (diff)
Added support for separate build directories and for usage projects in subdirectories.
-rw-r--r--comfignat.gpr.gp9
-rw-r--r--comfignat.mk205
2 files changed, 150 insertions, 64 deletions
diff --git a/comfignat.gpr.gp b/comfignat.gpr.gp
index d5bcd78..3b0c950 100644
--- a/comfignat.gpr.gp
+++ b/comfignat.gpr.gp
@@ -204,11 +204,18 @@ abstract project Comfignat is
-- generated files are placed.
--
+ -- Various generated files are kept in Builddir.
+ #if Builddir'Defined then
+ Builddir := $Builddir;
+ #else
+ Builddir := ".";
+ #end if;
+
-- Intermediate files produced during the build shall be kept in Objdir.
#if Objdir'Defined then
Objdir := $Objdir;
#else
- Objdir := "build";
+ Objdir := Builddir & "/obj";
#end if;
#if Directories_Project'Defined then
diff --git a/comfignat.mk b/comfignat.mk
index e90c9fb..5c5e62a 100644
--- a/comfignat.mk
+++ b/comfignat.mk
@@ -106,9 +106,10 @@ lockdir = ${runtimedir}/lock
# These are the directories where different kinds of files will be located on
# the target system.
-builddir = ${CURDIR}/build
+builddir = ${CURDIR}
objdir = ${builddir}/obj
stagedir = ${builddir}/stage
+# builddir is the build directory, which may be separate from the source tree.
# Intermediate files produced during the build are kept in objdir. Files to be
# installed are written to stagedir, and then copied to their destination in
# the installation step.
@@ -125,15 +126,52 @@ install_cp_flags = ${if ${DESTDIR},--preserve=timestamps}
#
-# Containing makefiles should assign or append to these variables as needed:
+# Containing makefiles may use these variables in their rules, but nothing
+# should modify them:
#
-ifneq (${origin preprocessed_files},file)
- preprocessed_files := ${basename ${wildcard *.gp}}
-endif
-# preprocessed_files is a list of files to be produced in the preprocessing
-# step at the beginning of the build. Containing makefiles may override it or
-# append additional filenames to it.
+srcdir := ${abspath ${dir ${lastword ${MAKEFILE_LIST}}}}
+# srcdir is the root of the source tree, computed as the directory part of the
+# last pathname in MAKEFILE_LIST – which is this file since there is no include
+# directive above this point.
+
+stage_bindir = ${stagedir}${bindir}
+stage_libexecdir = ${stagedir}${libexecdir}
+stage_datadir = ${stagedir}${datadir}
+stage_sysconfdir = ${stagedir}${sysconfdir}
+stage_statedir = ${stagedir}${statedir}
+stage_cachedir = ${stagedir}${cachedir}
+stage_logdir = ${stagedir}${logdir}
+stage_includedir = ${stagedir}${includedir}
+stage_libdir = ${stagedir}${libdir}
+stage_gprdir = ${stagedir}${gprdir}
+stage_localedir = ${stagedir}${localedir}
+stage_mandir = ${stagedir}${mandir}
+stage_infodir = ${stagedir}${infodir}
+stage_miscdocdir = ${stagedir}${miscdocdir}
+# These are the directories where different kinds of files to be installed are
+# written during the build.
+
+preprocess_file = "${GNATPREP}" ${firstword ${filter %.gp,$^}} $@ \
+ ${options_preprocessing} ${Gnatprep_arguments} \
+ ${if ${filter ${notdir $@},${notdir ${usage_GPRs}}}, \
+ ${usage_directories}, \
+ '-DSrcdir="${srcdir}"'}
+# preprocess_file is a command for use in recipes. It runs the first .gp file
+# among the rule's prerequisites through Gnatprep to produce the target. If the
+# target is a usage project, then the usage-relevant directory variables are
+# conveyed to it as Gnatprep symbols. Otherwise srcdir is conveyed.
+
+build_GPR = "${GNAT_BUILDER}" -P ${firstword ${filter %.gpr,$^}} \
+ -aP${srcdir} -aP${builddir} -p \
+ ${options_building} ${builder_arguments} ${GNATFLAGS}
+# build_GPR is a command for use in recipes. It performs a build controlled by
+# the first project file among the rule's prerequisites.
+
+
+#
+# Containing makefiles should assign or append to these variables as needed:
+#
ifneq (${origin build_GPRs},file)
build_GPRs =
@@ -148,6 +186,18 @@ endif
# that other projects should import to link to the libraries. These project
# files will be installed to the target system.
+ifneq (${origin preprocessed_files},file)
+ preprocessed_files = \
+ ${filter-out ${notdir ${usage_GPRs}}, \
+ ${basename ${notdir ${wildcard ${srcdir}/*.gp}}}}
+endif
+# preprocessed_files is a list of files to be produced in the preprocessing
+# step at the beginning of the build. Containing makefiles may override it or
+# append additional filenames to it.
+# The files are assumed to be needed during the build. The default list is all
+# the .gp files in srcdir except for usage projects, minus the .gp suffix. This
+# includes comfignat.gpr.
+
ifneq (${origin options},file)
options =
endif
@@ -172,6 +222,9 @@ endif
# default values for optional arguments should be set in the options variables
# instead.
+VPATH += ${srcdir} ${builddir}
+# VPATH is a list of directories that Make should search for prerequisites.
+
configuration_variables += \
GNATPREP GNAT_BUILDER \
GNAT_BUILDER_FLAGS ADAFLAGS CPPFLAGS CFLAGS CXXFLAGS FFLAGS GNATBINDFLAGS \
@@ -181,7 +234,7 @@ configuration_variables += \
prefix exec_prefix datarootdir localstatedir \
bindir libexecdir datadir sysconfdir statedir cachedir logdir includedir \
libdir gprdir localedir mandir infodir miscdocdir runtimedir lockdir \
- builddir objdir stagedir \
+ objdir stagedir \
install_cp_flags \
${options}
# configuration_variables is a list of variables that can be saved in the
@@ -190,50 +243,41 @@ configuration_variables += \
#
-# Containing makefiles may use these variables in their rules:
+# Read the configuration file if there is one:
#
-stage_bindir = ${stagedir}${bindir}
-stage_libexecdir = ${stagedir}${libexecdir}
-stage_datadir = ${stagedir}${datadir}
-stage_sysconfdir = ${stagedir}${sysconfdir}
-stage_statedir = ${stagedir}${statedir}
-stage_cachedir = ${stagedir}${cachedir}
-stage_logdir = ${stagedir}${logdir}
-stage_includedir = ${stagedir}${includedir}
-stage_libdir = ${stagedir}${libdir}
-stage_gprdir = ${stagedir}${gprdir}
-stage_localedir = ${stagedir}${localedir}
-stage_mandir = ${stagedir}${mandir}
-stage_infodir = ${stagedir}${infodir}
-stage_miscdocdir = ${stagedir}${miscdocdir}
-# These are the directories where different kinds of files to be installed are
-# written during the build.
+configuration = ${builddir}/comfignat_configuration.mk
-preprocess_file = \
- ${if ${filter-out 1,${words $^}}, \
- ${error preprocess_file takes 1 prerequisite but $@ has ${words $^}}, \
- "${GNATPREP}" $< $@ ${options_preprocessing} ${Gnatprep_arguments} \
- ${if ${filter $@,${usage_GPRs}},${usage_directories}}}
-# preprocess_file is a command for use in recipes. It runs the rule's single
-# prerequisite through Gnatprep to produce the target.
-
-build_GPR = "${GNAT_BUILDER}" -P ${firstword ${filter %.gpr,$^}} -p \
- ${options_building} ${builder_arguments} ${GNATFLAGS}
-# build_GPR is a command for use in recipes. It performs a build controlled by
-# the first project file among the rule's prerequisites.
+-include ${configuration}
#
-# Read the configuration file if there is one:
+# Ensure that builddir, objdir and stagedir are absolute pathnames:
#
--include comfignat_configuration.mk
+ifeq (${origin builddir},command line)
+ override builddir := ${abspath ${builddir}}
+endif
+ifeq (${origin objdir},command line)
+ override objdir := ${abspath ${objdir}}
+ objdir_is_configured = true
+endif
+ifeq (${origin stagedir},command line)
+ override stagedir := ${abspath ${stagedir}}
+ stagedir_is_configured = true
+endif
+# These pathnames need to be absolute in project files, because a pathname
+# relative to a project file can be wrong when a separate build directory is
+# used and project files are both in srcdir and in builddir. objdir and
+# stagedir also need to be absolute in the configuration file because the
+# working directory might change between Make invocations.
+# Once modified the variables are no longer of command line origin, so they are
+# marked as configured so that "make configure" will save them.
#
-# Compute symbol definitions for Gnatprep, external variable assignments for
-# build projects, and some other data that the rules need:
+# Compute symbol definitions for Gnatprep and external variable assignments for
+# build projects:
#
nil =
@@ -311,8 +355,9 @@ usage_pathname = ${call maybe_relative_to,${1},${gprdir}}
# inclusion in a usage project, which means that it is made relative to gprdir
# if a relocatable package is desired.
-# Convey objdir and stagedir to comfignat.gpr.
-all_directories = '-DObjdir="${objdir}"' '-DStagedir="${stagedir}"'
+# Convey builddir, objdir and stagedir to comfignat.gpr.
+all_directories = '-DBuilddir="${builddir}"' '-DObjdir="${objdir}"' \
+ '-DStagedir="${stagedir}"'
# Convey the builder-irrelevant directory variables, making them available to
# build projects for inclusion in binaries. Make most of the pathnames relative
@@ -391,13 +436,26 @@ options_preprocessing = ${addprefix -D,${option_values}}
# Convey boolean options to build projects.
options_building = ${addprefix -X,${option_values}}
+
+#
+# Some other data that the rules below need:
+#
+
+delegation_command := @$${MAKE} --file=${abspath ${firstword ${MAKEFILE_LIST}}}\
+ --include-dir=${srcdir} --no-print-directory
+# delegation_command is the Make command line that delegating makefiles in
+# separate build directories use to delegate commands to the main makefile. The
+# first pathname in MAKEFILE_LIST is the main makefile.
+
build_targets = ${addsuffix .phony_target,${build_GPRs}}
# A phony target is defined for each build project, and the job of determining
# whether the project needs rebuilding is delegated to the builder.
-stage_any_GPRs = ${if ${usage_GPRs},stage_GPRs}
-# The recipe for the target stage_GPRs breaks if usage_GPRs is empty, so it's
-# included as a prerequisite of build only if there are some usage projects.
+staged_usage_GPRs = ${addprefix ${stage_gprdir}/,${usage_GPRs}}
+preprocessed_files_in_builddir = ${addprefix ${builddir}/,${preprocessed_files}}
+# When usage projects are preprocessed they are written to stage_gprdir. Other
+# preprocessed files are assumed to be needed during the build and are written
+# to builddir.
#
@@ -406,9 +464,27 @@ stage_any_GPRs = ${if ${usage_GPRs},stage_GPRs}
.SECONDEXPANSION:
-default: build
-
-configure::
+Comfignat_default_goal: build
+
+${builddir} ${stage_gprdir}:
+ mkdir -p $@
+
+${builddir}/Makefile: | ${builddir}
+ @echo 'Writing $@.'
+ @( echo 'Comfignat_default_goal: force ; ${delegation_command}'; \
+ echo '%: force ; ${delegation_command} $$@'; \
+ echo 'force: ;'; \
+ echo 'Makefile: ;' \
+ ) > $@
+# This rule generates a delegating makefile in a separate build directory. The
+# generated makefile delegates all commands to the main makefile. The default
+# rule invokes the main makefile without a specified goal, triggering the main
+# makefile's default goal. A match-anything rule forwards any specified goals
+# to the main makefile. An empty recipe for "Makefile" prevents Make from using
+# the match-anything rule to update the makefile.
+
+configure:: ${builddir}/Makefile
+ @echo "Writing ${configuration}."
@( ${foreach variable,${configuration_variables}, \
${if ${or ${findstring command line, \
${origin ${variable}}}, \
@@ -417,7 +493,8 @@ configure::
echo 'override ${variable} = ${value ${variable}}'; \
echo 'endif'; \
echo '${variable}_is_configured = true';}} \
- ) > comfignat_configuration.mk
+ true \
+ ) > "${configuration}"
# Out of the variables listed in configuration_variables, all that were
# overridden on the command line, and all that were previously configured, are
# written to the configuration file. Configured values override defaults
@@ -428,25 +505,27 @@ configure::
# therefore possible to delete a variable V from the configuration by running
# "make configure V_is_configured=false".
-comfignat.gpr: comfignat.gpr.gp
+${builddir}/comfignat.gpr: comfignat.gpr.gp | ${builddir}
"${GNATPREP}" $< $@ -DInvoked_By_Makefile ${all_directories}
-%.gpr: %.gpr.gp
+${builddir}/%: %.gp | ${builddir}
${preprocess_file}
-preprocess: $${preprocessed_files}
+${stage_gprdir}/%: %.gp | ${stage_gprdir}
+ ${preprocess_file}
+
+${stage_gprdir}/%: % | ${stage_gprdir}
+ cp -p $< $@
+
+preprocess: $${preprocessed_files_in_builddir}
%.gpr.phony_target: %.gpr preprocess
${build_GPR}
# Instead of tracking dependencies between project files, this rule simply
-# requires that all preprocessing is done before any project is built.
-
-stage_GPRs: $${usage_GPRs}
- mkdir -p "${stage_gprdir}"
- cp -p ${usage_GPRs} "${stage_gprdir}"
-.PHONY: stage_GPRs
+# requires that all preprocessing of files that are needed during the build is
+# done before any project is built.
-build: $${build_targets} $${stage_any_GPRs}
+build: $${build_targets} $${staged_usage_GPRs}
${stagedir}:
@${MAKE} build --no-print-directory
@@ -460,9 +539,9 @@ install: ${stagedir}
.PHONY: install
clean::
- rm -Rf ${builddir} ${preprocessed_files}
+ rm -Rf "${objdir}" "${stagedir}" ${preprocessed_files_in_builddir}
unconfigure::
- rm -f comfignat_configuration.mk
+ rm -f "${configuration}"
distclean: clean unconfigure