From 2bf0dfd6a04f5dfb9798cabbd56fc49863b64172 Mon Sep 17 00:00:00 2001 From: Björn Persson Date: Sat, 13 Jul 2013 23:56:04 +0200 Subject: Redesigned the handling of relative pathnames. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit · Directory variables for embedding and for installation were separated. · Directory variables for embedding are now available in project Comfignat. · Relative pathnames are now relative to gprdir or bindir in different places. · Options are conveyed to build project files as external variables. · Gnatprep_definitions is now Gnatprep_arguments. · preprocess_file and builder_arguments were added. --- comfignat.mk | 334 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 205 insertions(+), 129 deletions(-) (limited to 'comfignat.mk') diff --git a/comfignat.mk b/comfignat.mk index 49da99f..d24a262 100644 --- a/comfignat.mk +++ b/comfignat.mk @@ -82,27 +82,29 @@ relocatable_package = false 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 -statedir = ${localstatedir}/lib -cachedir = ${localstatedir}/cache -logdir = ${localstatedir}/log -runtimedir = /run -lockdir = ${runtimedir}/lock -includedir = ${prefix}/include -libdir = ${exec_prefix}/lib -gprdir = ${datarootdir}/gpr -localedir = ${datarootdir}/locale -mandir = ${datarootdir}/man -infodir = ${datarootdir}/info -miscdocdir = ${datarootdir}/doc -# 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. +# These variables are used in constructing the default values of the directory +# variables below. + +bindir = ${exec_prefix}/bin +libexecdir = ${exec_prefix}/libexec +datadir = ${datarootdir} +sysconfdir = ${prefix}/etc +statedir = ${localstatedir}/lib +cachedir = ${localstatedir}/cache +logdir = ${localstatedir}/log +includedir = ${prefix}/include +libdir = ${exec_prefix}/lib +gprdir = ${datarootdir}/gpr +localedir = ${datarootdir}/locale +mandir = ${datarootdir}/man +infodir = ${datarootdir}/info +miscdocdir = ${datarootdir}/doc +runtimedir = /run +lockdir = ${runtimedir}/lock +# These are the directories where different kinds of files will be located on +# the target system. builddir = ${CURDIR}/build objdir = ${builddir}/obj @@ -114,7 +116,7 @@ stagedir = ${builddir}/stage # Containing makefiles should avoid modifying the directory variables. Users # should be able to rely on these defaults. -install_cp_flags = ${if ${DESTDIR},--preserve=timestamps,} +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 @@ -134,20 +136,20 @@ endif # append additional filenames to it. ifneq (${origin build_GPRs},file) - build_GPRs := + 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 := + 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 := + 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. @@ -155,21 +157,30 @@ endif # 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 := +ifneq (${origin Gnatprep_arguments},file) + Gnatprep_arguments = endif -# Any text assigned to Gnatprep_definitions will be included in the Gnatprep +# Any text assigned to Gnatprep_arguments will be included in the Gnatprep # command line. It may be used for additional symbol definitions. +ifneq (${origin builder_arguments},file) + builder_arguments = +endif +# Any text assigned to builder_arguments will be included in the GPRbuild or +# Gnatmake command line. It may be used for external variables for project +# files or other arguments that are essential for the build to work. Global +# default values for optional arguments should be set in the options variables +# instead. + configuration_variables += \ GNATPREP GNAT_BUILDER \ GNAT_BUILDER_FLAGS ADAFLAGS CPPFLAGS CFLAGS CXXFLAGS FFLAGS GNATBINDFLAGS \ GNATLINKFLAGS LDFLAGS GNATFLAGS \ DESTDIR \ dirgpr relocatable_package \ - prefix exec_prefix bindir libexecdir datarootdir datadir sysconfdir \ - localstatedir statedir cachedir logdir runtimedir lockdir includedir libdir \ - gprdir localedir mandir infodir miscdocdir \ + prefix exec_prefix datarootdir localstatedir \ + bindir libexecdir datadir sysconfdir statedir cachedir logdir includedir \ + libdir gprdir localedir mandir infodir miscdocdir runtimedir lockdir \ builddir objdir stagedir \ install_cp_flags \ ${options} @@ -179,17 +190,38 @@ configuration_variables += \ # -# Containing makefiles may use this command variable: +# Containing makefiles may use these variables in their rules: # +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 = \ + ${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 \ - ${GNATFLAGS} -margs + ${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 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. # @@ -200,8 +232,8 @@ build_GPR = "${GNAT_BUILDER}" -P ${firstword ${filter %.gpr,$^}} -p \ # -# Compute the symbol definitions for Gnatprep, and some other data that the -# rules need: +# Compute symbol definitions for Gnatprep, external variable assignments for +# build projects, and some other data that the rules need: # nil = @@ -212,110 +244,151 @@ 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. +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 = \ + ${or ${call unmung,${patsubst %/,%,${call relativize \ + ,${call prep,${1}} \ + ,${call prep,${2}},}}},.} +# relative_to converts an absolute pathname into a relative one. What it +# actually does is to prepare the input to relativize and fix up its output. +# Parameters: +# 1: an absolute pathname to convert to relative +# 2: the absolute base pathname that 1 shall be made relative to +# Processing: +# · Prepare the two input pathnames with prep. +# · Call relativize with the prepared pathnames for parameters 1 and 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. + +maybe_relative_to = \ + ${if ${or ${filter-out 1,${words ${relocatable_package}}}, \ + ${filter-out true false,${relocatable_package}}}, \ + ${error relocatable_package must be "true" or "false"} \ + ,${if ${filter true,${relocatable_package}} \ + ,${call relative_to,${1},${2}},${1}}} +# maybe_relative_to converts an absolute pathname into a relative one if a +# relocatable package is desired. +# Parameters: +# 1: an absolute pathname to convert to relative +# 2: the absolute base pathname that 1 may be made relative to +# First check that the value of relocatable_package is a single word and that +# that word is either "true" or "false". Complain and stop if that isn't so. +# Then, if relocatable_package is "true", let relative_to convert the pathname, +# otherwise return parameter 1 unchanged. + +embed_pathname = ${call maybe_relative_to,${1},${bindir}} +# embed_pathname converts an absolute pathname into the right form for +# inclusion in a program, which means that it is made relative to bindir if a +# relocatable package is desired. + +usage_pathname = ${call maybe_relative_to,${1},${gprdir}} +# usage_pathname converts an absolute pathname into the right form for +# 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 the builder-irrelevant directory variables, making them available to +# build projects for inclusion in binaries. Make most of the pathnames relative +# if a relocatable package is desired. +all_directories += '-DDatadir="${call embed_pathname,${datadir}}"' +all_directories += '-DSysconfdir="${call embed_pathname,${sysconfdir}}"' +all_directories += '-DStatedir="${call embed_pathname,${statedir}}"' +all_directories += '-DCachedir="${call embed_pathname,${cachedir}}"' +all_directories += '-DLogdir="${call embed_pathname,${logdir}}"' +all_directories += '-DGPRdir="${call embed_pathname,${gprdir}}"' +all_directories += '-DLocaledir="${call embed_pathname,${localedir}}"' +all_directories += '-DMandir="${call embed_pathname,${mandir}}"' +all_directories += '-DInfodir="${call embed_pathname,${infodir}}"' +all_directories += '-DMiscdocdir="${call embed_pathname,${miscdocdir}}"' +all_directories += '-DRuntimedir="${runtimedir}"' +all_directories += '-DLockdir="${lockdir}"' +# runtimedir and lockdir belong to the operating system and are used for +# communication between subsystems. It wouldn't make sense for an application +# to have its own runtimedir. Therefore these variables are always absolute +# pathnames. + +ifeq (${dirgpr},) + + # No directories project was provided, so convey even the builder-relevant + # directory variables to comfignat.gpr, and convey the usage-relevant ones + # to usage projects in the form that usage projects need. + + all_directories += '-DBindir="${call embed_pathname,${bindir}}"' + all_directories += '-DLibexecdir="${call embed_pathname,${libexecdir}}"' + all_directories += '-DIncludedir="${call embed_pathname,${includedir}}"' + all_directories += '-DLibdir="${call embed_pathname,${libdir}}"' + + all_directories += '-DStage_Bindir="${stage_bindir}"' + all_directories += '-DStage_Libexecdir="${stage_libexecdir}"' + all_directories += '-DStage_Includedir="${stage_includedir}"' + all_directories += '-DStage_Libdir="${stage_libdir}"' + + usage_directories = '-DIncludedir="${call usage_pathname,${includedir}}"' \ + '-DLibdir="${call usage_pathname,${libdir}}"' -ifneq (${dirgpr},) +else - # A directories project is used, so make project files take the directory - # variables from there. + # A directories project is used, so make project files take the builder- + # relevant directory variables from there. directories_project := ${basename ${notdir ${dirgpr}}} - directories += '-DDirectories_GPR="${dirgpr}"' - directories += '-DDirectories_Project=${directories_project}' - directories += '-DPrefix="${prefix}"' - directories += '-DExec_Prefix="${exec_prefix}"' - directories += '-DBindir=${directories_project}.Bindir' - directories += '-DLibexecdir=${directories_project}.Libexecdir' - directories += '-DIncludedir=${directories_project}.Includedir' - directories += '-DLibdir=${directories_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 + all_directories += '-DDirectories_GPR="${dirgpr}"' + all_directories += '-DDirectories_Project=${directories_project}' + all_directories += '-DBindir=${directories_project}.Bindir' + all_directories += '-DLibexecdir=${directories_project}.Libexecdir' + all_directories += '-DIncludedir=${directories_project}.Includedir' + all_directories += '-DLibdir=${directories_project}.Libdir' -definitions = ${directories} -# definitions is recursively expanded so that the options referenced below may -# be defined in containing makefiles after the inclusion of this file. + usage_directories = '-DDirectories_GPR="${dirgpr}"' \ + '-DIncludedir=${directories_project}.Includedir' \ + '-DLibdir=${directories_project}.Libdir' -# Convey boolean options to Gnatprep. -definitions += \ +endif + +option_values = \ ${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".}}} + ${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; +# that word is either "true" or "false". If so, output a name/value pair; # otherwise complain and stop. -# Convey any additional symbols that the containing makefile has defined. -definitions += ${Gnatprep_definitions} +# Convey boolean options to Gnatprep. +options_preprocessing = ${addprefix -D,${option_values}} + +# Convey boolean options to build projects. +options_building = ${addprefix -X,${option_values}} build_targets = ${addsuffix .phony_target,${build_GPRs}} # A phony target is defined for each build project, and the job of determining @@ -350,8 +423,11 @@ configure:: # configured variable. It is therefore possible to delete a variable V from the # configuration by running "make configure V_is_configured=false". +comfignat.gpr: comfignat.gpr.gp + "${GNATPREP}" $< $@ -DInvoked_By_Makefile ${all_directories} + %.gpr: %.gpr.gp - "${GNATPREP}" $< $@ ${definitions} + ${preprocess_file} preprocess: $${preprocessed_files} @@ -361,8 +437,8 @@ preprocess: $${preprocessed_files} # 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}" + mkdir -p "${stage_gprdir}" + cp -p ${usage_GPRs} "${stage_gprdir}" .PHONY: stage_GPRs build: $${build_targets} $${stage_any_GPRs} -- cgit v1.2.3