# 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 # If GNAT_BUILDER looks like it will invoke Gnatmake, then make the default # value of GNATFLAGS compatible with Gnatmake. Otherwise make it suitable for # building multi-language projects with GPRbuild. ifeq ($(findstring gnatmake,${notdir ${lastword ${GNAT_BUILDER}}}),) GNATFLAGS ?= ${GNAT_BUILDER_FLAGS} \ -cargs:Ada ${ADAFLAGS} -cargs:C ${CFLAGS} \ -cargs:C++ ${CXXFLAGS} -cargs:Fortran ${FFLAGS} \ -largs ${LDFLAGS} else GNATFLAGS ?= ${GNAT_BUILDER_FLAGS} -cargs ${ADAFLAGS} -largs ${LDFLAGS} endif # (DESTDIR is also supported.) # # 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 directory project if there is one. It # becomes the Gnatprep symbols Directory_GPR and Directory_Project. 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 = 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. ifeq (${DESTDIR},) install_cp_flags = else install_cp_flags = --preserve=timestamps endif # 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: # ifneq (${origin configured_files},file) configured_files := ${basename ${wildcard *.in}} endif # configured_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. # # Compute the symbol definitions for Gnatprep, and some other data that the # rules need: # # Convey objdir and stagedir to Gnatprep. definitions = '-DObjdir="${objdir}"' '-DStagedir="${stagedir}"' # Convey the prefix variables too, although they're supposed to be unused when # the preprocessing is done with Make. definitions += '-DPrefix="${prefix}"' '-DExec_Prefix="${exec_prefix}"' # If a directory project is used, then make project files take the directory # variables from there. Otherwise convey the ones defined above. ifeq (${dirgpr},) definitions += '-DBindir="${bindir}"' '-DLibexecdir="${libexecdir}"' definitions += '-DIncludedir="${includedir}"' '-DLibdir="${libdir}"' else directory_project := ${basename ${notdir ${dirgpr}}} definitions += '-DDirectory_GPR="${dirgpr}"' definitions += '-DDirectory_Project=${directory_project}' definitions += '-DBindir=${directory_project}.Bindir' definitions += '-DLibexecdir=${directory_project}.Libexecdir' definitions += '-DIncludedir=${directory_project}.Includedir' definitions += '-DLibdir=${directory_project}.Libdir' endif # 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}} stage_any_GPRs = ${if ${usage_GPRs},stage_GPRs} 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. Arguments for the # builder may be appended. # # Make rules: # .SECONDEXPANSION: all: build %.gpr: %.gpr.in "${GNATPREP}" $< $@ ${definitions} configure: $${configured_files} %.gpr.phony_target: %.gpr configure ${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} ${configured_files}