From f015ed90ef10b6441ebea1eeea6b674292b2a409 Mon Sep 17 00:00:00 2001 From: deischen Date: Thu, 16 Mar 2006 15:12:26 +0000 Subject: Teach bsd.lib.mk to auto generate a version map file based on a set of symbol definitions (VERSION_DEF) and symbol mappings (SYMBOL_MAPS). Add an awk script to generate the version map. Suggested by: ru Helped by: ru Reviewed by: ru --- share/mk/bsd.lib.mk | 40 ++++++++++++ share/mk/version_gen.awk | 166 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 share/mk/version_gen.awk (limited to 'share') diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index c60c133..02f1d46 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -99,6 +99,46 @@ PO_FLAG=-pg all: objwarn +# Generate the version map given the version definitions +# and symbol maps. +.if !empty(VERSION_DEF) && !empty(SYMBOL_MAPS) +# Find the awk script that generates the version map. +VERSION_GEN?= version_gen.awk +VERSION_MAP?= Version.map + +# Compute the make's -m path. +_mpath= +_oarg= +.for _arg in ${.MAKEFLAGS} +.if ${_oarg} == "-m" +_mpath+= ${_arg} +.endif +_oarg= ${_arg} +.endfor +_mpath+= /usr/share/mk + +# Look up ${VERSION_GEN} in ${_mpath}. +_vgen= +.for path in ${_mpath} +.if empty(_vgen) +.if exists(${path}/${VERSION_GEN}) +_vgen= ${path}/${VERSION_GEN} +.endif +.endif +.endfor + +${VERSION_MAP}: + awk -v vfile=${VERSION_DEF} -f ${_vgen} ${SYMBOL_MAPS} \ + > ${.TARGET} +.endif # !empty(VERSION_DEF) && !empty(SYMBOL_MAPS) + +# Allow librararies to specify their own version map or have it +# automatically generated (see above). +.if !empty(VERSION_MAP) +${SHLIB_NAME}: ${VERSION_MAP} +LDFLAGS+= -Wl,--version-script=${VERSION_MAP} +.endif + .if defined(LIB) && !empty(LIB) || defined(SHLIB_NAME) OBJS+= ${SRCS:N*.h:R:S/$/.o/} .endif diff --git a/share/mk/version_gen.awk b/share/mk/version_gen.awk new file mode 100644 index 0000000..23c502c --- /dev/null +++ b/share/mk/version_gen.awk @@ -0,0 +1,166 @@ +# +# Copyright (C) 2006 Daniel M. Eischen. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# +# Make a list of all the library versions listed in the master file. +# +# versions[] - array indexed by version name, contains number +# of symbols (+ 1) found for each version. +# successors[] - array index by version name, contains successor +# version name. +# symbols[][] - array index by [version name, symbol index], contains +# names of symbols defined for each version. +# +BEGIN { + brackets = 0; + errors = 0; + version_count = 0; + current_version = ""; + stderr = "/dev/stderr"; + while (getline < vfile) { + # Strip comments. + sub("#.*$", "", $0); + + # Strip trailing spaces. + sub(" *$", "", $0); + + if (/^[ \t]*[a-zA-Z0-9._]+ *{/) { + brackets++; + symver = $1; + versions[symver] = 1; + successors[symver] = ""; + version_count++; + } + else if (/^[ \t]*} *[a-zA-Z0-9._]+ *;/) { + # Strip semicolon. + gsub(";", "", $2); + if (symver == "") + printf("Unmatched bracket.\n"); + else if (versions[$2] != 1) + printf("File %s: %s has unknown " \ + "successor %s\n", vfile, symver, $2); + else + successors[symver] = $2; + brackets--; + } + else if (/^[ \t]*};/) { + if (symver == "") + printf("File %s: Unmatched bracket.\n", + vfile) > stderr; + # No successor + brackets--; + } + else if (/^[ \t]*}/) { + printf("File %s: Missing ending semi-colon.\n", + vfile) > stderr; + } + else if (/^$/) + ; # Ignore blank lines. + else + printf("File %s: Unknown directive: %s\n", + vfile, $0) > stderr; + } + brackets = 0; +} + +/.*/ { + # Delete comments, preceding and trailing whitespace, then + # consume blank lines. + sub("#.*$", "", $0); + sub("^[ \t]+", "", $0); + sub("[ \t]+$", "", $0); + if ($0 == "") + next; +} + +/^[a-zA-Z0-9._]+ +{$/ { + # Strip bracket from version name. + sub("{", "", $1); + if (current_version != "") + printf("File %s, line %d: Illegal nesting detected.\n", + FILENAME, FNR) > stderr; + else if (versions[$1] == 0) { + printf("File %s, line %d: Undefined " \ + "library version %s\n", FILENAME, FNR, $1) > stderr; + # Remove this entry from the versions. + delete versions[$1]; + } + else + current_version = $1; + brackets++; + next; +} + +/^[a-zA-Z0-9._]+ *;$/ { + if (current_version != "") { + count = versions[current_version]; + versions[current_version]++; + symbols[current_version, count] = $1; + } + next; +} + +/^} *;$/ { + brackets--; + if (brackets < 0) { + printf("File %s, line %d: Unmatched bracket.\n", + FILENAME, FNR, $1) > stderr; + brackets = 0; # Reset + } + current_version = ""; + next; +} + + +/.*/ { + printf("File %s, line %d: Unknown directive: '%s'\n", + FILENAME, FNR, $0) > stderr; +} + +END { + for (v in versions) { + printf("\n"); + printf("%s {\n", v); + + # The version count is always one more that actual, + # so the loop ranges from 1 to n-1. + # + for (i = 1; i < versions[v]; i++) { + if (i == 1) + printf("global:\n"); + printf("\t%s\n", symbols[v, i]); + } + if (successors[v] == "") { + # This version succeeds no other version. + printf("local:\n"); + printf("\t*;\n"); + printf("};\n"); + } + else + printf("} %s;\n", successors[v]); + } +} -- cgit v1.1