diff options
Diffstat (limited to 'comfignat.mk')
-rw-r--r-- | comfignat.mk | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/comfignat.mk b/comfignat.mk new file mode 100644 index 0000000..e64eab6 --- /dev/null +++ b/comfignat.mk @@ -0,0 +1,371 @@ +# Comfignat makefile foundation for configuring and building GNAT projects +# Copyright 2013 B. Persson, Bjorn@Rombobeorn.se +# +# This material is provided as is, with absolutely no warranty expressed +# or implied. Any use is at your own risk. +# +# Permission is hereby granted to use or copy this makefile +# for any purpose, provided the above notices are retained on all copies. +# Permission to modify the code and to distribute modified code is granted, +# provided the above notices are retained, and a notice that the code was +# modified is included with the above copyright notice. + + +# This file contains generic Make code. It is designed to be included by other +# makefiles, called containing makefiles, which add information specific to the +# project at hand. Builds are controlled by GNAT project files which import the +# abstract project Comfignat and use the directory variables it defines. For +# libraries there shall also be usage projects to be installed on the target +# system. Usage projects and the Comfignat project will be preprocessed with +# Gnatprep. (Build projects may also be preprocessed.) +# +# If a directory project is provided, then the project files will get the +# directory variables from there, otherwise the Make variables will be used. +# +# This file may not work with other Make clones than GNU Make. (Reusable Make +# code is pretty much impossible to write without advanced Make features.) If +# Make cannot be used for whatever reason, then it's not too difficult to run +# the project files through Gnatprep manually. + + +# +# Program-name variables and the usual options variables are picked up from the +# environment or the command line: +# + +GNATPREP ?= gnatprep +GNAT_BUILDER ?= gprbuild + +GNATFLAGS ?= ${if ${findstring gnatmake, \ + ${notdir ${call mung,${GNAT_BUILDER}}}}, \ + ${GNAT_BUILDER_FLAGS} \ + -cargs ${ADAFLAGS} \ + -bargs ${GNATBINDFLAGS} \ + -largs ${GNATLINKFLAGS} ${LDFLAGS}, \ + ${GNAT_BUILDER_FLAGS} \ + -cargs:Ada ${ADAFLAGS} \ + -cargs:C ${CPPFLAGS} ${CFLAGS} \ + -cargs:C++ ${CPPFLAGS} ${CXXFLAGS} \ + -cargs:Fortran ${FFLAGS} \ + -bargs ${GNATBINDFLAGS} \ + -largs ${LDFLAGS}} + +# (DESTDIR is also supported.) + +# Containing makefiles may assign default values to the options variables +# GNAT_BUILDER_FLAGS, ADAFLAGS, CFLAGS, CXXFLAGS, FFLAGS, GNATBINDFLAGS, +# GNATLINKFLAGS and LDFLAGS if they are undefined in the environment, but +# should expect that users and distributions may override those defaults. + + +# +# These variables should be overridden on the command line as needed, but will +# not be picked up from the environment: +# + +dirgpr = +# dirgpr should be the filename of the target system's directory project if +# there is one. Project files will be configured to use the directory project, +# and the Gnatprep symbols Directory_GPR and Directory_Project will be derived +# from dirgpr. + +prefix = /usr/local +exec_prefix = ${prefix} +bindir = ${exec_prefix}/bin +libexecdir = ${exec_prefix}/libexec +datarootdir = ${prefix}/share +datadir = ${datarootdir} +sysconfdir = ${prefix}/etc +localstatedir = ${prefix}/var +includedir = ${prefix}/include +libdir = ${exec_prefix}/lib +gprdir = ${datarootdir}/gpr +localedir = ${datarootdir}/locale +mandir = ${datarootdir}/man +infodir = ${datarootdir}/info +# These are the directories where different kinds of files will be installed on +# the target system. Some of these directory variables aren't used in this file +# but may be needed in containing makefiles. + +builddir = ${CURDIR}/build +objdir = ${builddir}/obj +stagedir = ${builddir}/stage +# 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. + +# Containing makefiles should avoid modifying the directory variables. Users +# should be able to rely on these defaults. + +relocatable_package = false +# If relocatable_package is true, then directory variables in project files +# will be configured with relative pathnames so that the installed directory +# tree as a whole can be moved to another location in the filesystem without +# breaking the project files. +# dirgpr takes precedence over relocatable_package. + +install_cp_flags = ${if ${DESTDIR},--preserve=timestamps,} +# Timestamps are preserved when installation is done to a staging directory. +# This matters for files that aren't generated during the build but copied from +# the source tree. Timestamps are not preserved when installation is done +# directly to the target system, because that would change the timestamps of +# existing directories. + + +# +# Containing makefiles should assign or append to these variables as needed: +# + +configuration_variables += \ + GNATPREP GNAT_BUILDER GNAT_BUILDER_FLAGS ADAFLAGS CPPFLAGS CFLAGS CXXFLAGS \ + FFLAGS GNATBINDFLAGS GNATLINKFLAGS LDFLAGS GNATFLAGS DESTDIR \ + dirgpr prefix exec_prefix bindir libexecdir datarootdir datadir sysconfdir \ + localstatedir includedir libdir gprdir localedir mandir infodir builddir \ + objdir stagedir relocatable_package install_cp_flags +# configuration_variables is a list of variables that can be saved in the +# persistent configuration with "make configure". Containing makefiles may +# append additional variable names. + +ifneq (${origin preprocessed_files},file) + preprocessed_files := ${basename ${wildcard *.in}} +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. + +ifneq (${origin build_GPRs},file) + build_GPRs := +endif +# build_GPRs shall name one or more project files for building the software. +# These project files will be used when "make" or "make build" is invoked. + +ifneq (${origin usage_GPRs},file) + usage_GPRs := +endif +# If the build produces libraries, then usage_GPRs shall name the project files +# that other projects should import to link to the libraries. These project +# files will be installed to the target system. + +ifneq (${origin options},file) + options := +endif +# options may be assigned a list of variable names. Those variables may be +# overridden on the command line, and will be defined as Gnatprep symbols. +# Their values must be "true" or "false". +# The containing makefile should assign a default value to each variable unless +# it shall be mandatory to always set the option on the command line. + +ifneq (${origin Gnatprep_definitions},file) + Gnatprep_definitions := +endif +# Any text assigned to Gnatprep_definitions will be included in the Gnatprep +# command line. It may be used for additional symbol definitions. + + +# +# Containing makefiles may use this command variable: +# + +build_GPR = "${GNAT_BUILDER}" -P ${firstword ${filter %.gpr,$^}} -p \ + ${GNATFLAGS} -margs +# build_GPR is a command for use in recipies. It performs a build controlled by +# the first project file among the rule's prerequisites. +# Containing makefiles may append additional arguments for the builder, but +# should ensure that any arguments that aren't essential for the build to work +# can be overridden from the command line. Global default values for optional +# arguments should be set in the options variables instead. + + +# +# Read the configuration file if there is one: +# + +-include comfignat_configuration.mk + + +# +# Compute the symbol definitions for Gnatprep, and some other data that the +# rules need: +# + +nil = +space_sub = _Comfignat_magic_protective_space_character_substitute_ +percent_sub = _Comfignat_magic_protective_percent_character_substitute_ +mung = ${subst %,${percent_sub},${subst ${nil} ,${space_sub},${1}}} +unmung = ${subst ${percent_sub},%,${subst ${space_sub}, ,${1}}} +# mung and unmung are used to prevent Make from interpreting space and percent +# characters in strings. + +# Convey objdir and stagedir to Gnatprep. +directories := '-DObjdir="${objdir}"' '-DStagedir="${stagedir}"' +# directories is simply expanded as this reduces redundant processing and the +# directory variables are not to be modified after this point. + +ifneq (${dirgpr},) + + # A directory project is used, so make project files take the directory + # variables from there. + + directory_project := ${basename ${notdir ${dirgpr}}} + directories += '-DDirectory_GPR="${dirgpr}"' + directories += '-DDirectory_Project=${directory_project}' + directories += '-DPrefix="${prefix}"' + directories += '-DExec_Prefix="${exec_prefix}"' + directories += '-DBindir=${directory_project}.Bindir' + directories += '-DLibexecdir=${directory_project}.Libexecdir' + directories += '-DIncludedir=${directory_project}.Includedir' + directories += '-DLibdir=${directory_project}.Libdir' + +else ifeq (${relocatable_package},true) + + # Make project files use directory names relative to gprdir. + + relativize = ${if ${filter ${2}%,${1}}, \ + ${3}${1:${2}%=%}, \ + ${call relativize,${1},${dir ${2:%/=%}},${3}../}} + # relativize is the recursive algorithm that converts an absolute pathname + # into a relative one. + # Parameters: + # 1: an absolute pathname to convert to relative + # 2: the absolute base pathname, being shortened until it's a prefix of 1 + # 3: a growing series of "../" to lead the relative pathname with + # If 2 is a prefix of 1, then return 3 concatenated with the part of 1 that + # differs from 2. Otherwise delete the last element of 2, add one level of + # "../" to 3, and repeat. + # Within relativize all pathnames have one trailing slash so that only whole + # directory names will match. Otherwise "/usr/lib" could match "/usr/lib64" + # for example. + + prep = ${subst //,/,${abspath ${call mung,${1}}}/} + # prep prepares a pathname for use as a parameter to relativize. + # · Protect space and percent characters from interpretation by Make. + # · Normalize the pathname, eliminating ".", ".." and "//". + # · Append a slash. + # · If the input was "/", then it is now "//". Change that back to "/". + + relative_to_gprdir = \ + ${or ${call unmung,${patsubst %/,%,${call relativize \ + ,${call prep,${1}} \ + ,${call prep,${gprdir}},}}},.} + # relative_to_gprdir converts an absolute pathname into a pathname relative + # to gprdir. What it actually does is to prepare the input to relativize and + # fix up its output. + # · Prepare the input pathname with prep. + # · Prepare gprdir with prep. + # · Call relativize with the input for parameter 1, gprdir for 2, and an + # empty string for 3. + # · Strip the result of surrounding spaces and the trailing slash. + # · Reverse the protection of space and percent characters. + # · If the result is an empty string, then return "." instead. + + directories += '-DBase="${gprdir}"' + directories += '-DPrefix="${call relative_to_gprdir,${prefix}}"' + directories += '-DExec_Prefix="${call relative_to_gprdir,${exec_prefix}}"' + directories += '-DBindir="${call relative_to_gprdir,${bindir}}"' + directories += '-DLibexecdir="${call relative_to_gprdir,${libexecdir}}"' + directories += '-DIncludedir="${call relative_to_gprdir,${includedir}}"' + directories += '-DLibdir="${call relative_to_gprdir,${libdir}}"' + +else ifeq (${relocatable_package},false) + + # Convey the directory variables unmodified to project files. + + directories += '-DPrefix="${prefix}"' + directories += '-DExec_Prefix="${exec_prefix}"' + directories += '-DBindir="${bindir}"' + directories += '-DLibexecdir="${libexecdir}"' + directories += '-DIncludedir="${includedir}"' + directories += '-DLibdir="${libdir}"' + +else + ${error relocatable_package must be "true" or "false".} +endif + +definitions = ${directories} +# definitions is recursively expanded so that the options referenced below may +# be defined in containing makefiles after the inclusion of this file. + +# Convey boolean options to Gnatprep. +definitions += \ + ${foreach option,${options}, \ + ${if ${and ${filter-out environment,${origin ${option}}}, \ + ${filter 1,${words ${${option}}}}, \ + ${filter true false,${${option}}}}, \ + -D${option}=${${option}}, \ + ${error ${option} must be "true" or "false".}}} +# For each variable listed in options, check that it didn't come from the +# environment (to prevent accidents), that its value is a single word, and that +# that word is either "true" or "false". If so, append a symbol definition; +# otherwise complain and stop. + +# Convey any additional symbols that the containing makefile has defined. +definitions += ${Gnatprep_definitions} + +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 recipie 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. + + +# +# Make rules: +# + +.SECONDEXPANSION: + +all: build + +configure:: + @( ${foreach variable,${configuration_variables}, \ + ${if ${or ${findstring command line, \ + ${origin ${variable}}}, \ + ${filter true,${${variable}_is_configured}}}, \ + echo '${variable} = ${value ${variable}}'; \ + echo '${variable}_is_configured = true';}} \ + ) > comfignat_configuration.mk +# 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. A variable is considered previously +# configured if there is another variable with "_is_configured" appended to its +# name and a value of "true", and such a variable is also written for each +# configured variable. It is therefore possible to delete a variable V from the +# configuration by running "make configure V_is_configured=false". + +%.gpr: %.gpr.in + "${GNATPREP}" $< $@ ${definitions} + +preprocess: $${preprocessed_files} + +%.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 "${stagedir}${gprdir}" + cp -p ${usage_GPRs} "${stagedir}${gprdir}" +.PHONY: stage_GPRs + +build: $${build_targets} $${stage_any_GPRs} + +${stagedir}: + @${MAKE} build --no-print-directory +# "make install" straight out of a source package triggers a build, but if +# something has been built then "make install" doesn't rebuild anything, just +# copies the built files to their destination. + +install: ${stagedir} + mkdir -p "${DESTDIR}/" + cp -RPf ${install_cp_flags} "${stagedir}"/* "${DESTDIR}/" +.PHONY: install + +clean:: + rm -Rf ${builddir} ${preprocessed_files} + +unconfigure:: + rm -f comfignat_configuration.mk + +distclean: clean unconfigure |