]> git.ipfire.org Git - pakfire.git/commitdiff
Import buildsystem-tools from build-essentials.
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 29 Aug 2011 16:19:04 +0000 (18:19 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 29 Aug 2011 16:19:04 +0000 (18:19 +0200)
19 files changed:
po/pakfire.pot
setup.py
tools/buildsystem-tools/chroot-shell [new file with mode: 0755]
tools/buildsystem-tools/cleanup [new file with mode: 0755]
tools/buildsystem-tools/common-functions [new file with mode: 0644]
tools/buildsystem-tools/dependency-tracker [new file with mode: 0755]
tools/buildsystem-tools/functions-common [new file with mode: 0644]
tools/buildsystem-tools/functions-constants [new file with mode: 0644]
tools/buildsystem-tools/functions-directories [new file with mode: 0644]
tools/buildsystem-tools/functions-files [new file with mode: 0644]
tools/buildsystem-tools/functions-lists [new file with mode: 0644]
tools/buildsystem-tools/functions-logging [new file with mode: 0644]
tools/buildsystem-tools/functions-packager-find [new file with mode: 0644]
tools/buildsystem-tools/perl.prov [new file with mode: 0644]
tools/buildsystem-tools/perl.req [new file with mode: 0644]
tools/buildsystem-tools/pkg-config.prov [new file with mode: 0755]
tools/buildsystem-tools/pkg-config.req [new file with mode: 0755]
tools/buildsystem-tools/py-compile [new file with mode: 0755]
tools/buildsystem-tools/stripper [new file with mode: 0755]

index c1e7940712ec0ab474fe70632b54b97df25a633e..2f6c0805c29882a693362aaa12b7065571ac0e24 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-08-29 17:25+0200\n"
+"POT-Creation-Date: 2011-08-29 18:18+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
index af1114ac58260f6c9f867e2db60b484dd87c81ce..d1dda81efbfdd7e459f24f0066d96cd3f5505921 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -38,6 +38,8 @@ setup(
                ("lib/pakfire", ["tools/quality-agent/quality-agent",]),
                ("lib/quality-agent", [os.path.join("tools/quality-agent/quality-agent.d", f) \
                        for f in os.listdir("tools/quality-agent/quality-agent.d")]),
+               ("lib/buildsystem-tools", [os.path.join("tools/buildsystem-tools", f) \
+                       for f in os.listdir("tools/buildsystem-tools")]),
        ],
        ext_modules = [
                Extension("pakfire._pakfire", _pakfire_module_files,
diff --git a/tools/buildsystem-tools/chroot-shell b/tools/buildsystem-tools/chroot-shell
new file mode 100755 (executable)
index 0000000..0d4a61f
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+cat <<EOF
+
+       You are now dropped to a chrooted shell of the package's environment.
+
+       The sources have been extracted to /build and maybe there are files left
+       from a last (broken) build. Nothing of that content will be saved after
+       you left the shell.
+
+       You can leave the environment by typing "exit" or Ctrl-D.
+
+EOF
+
+# Setting nice environment
+export PS1="pakfire-chroot \w> "
+
+# Change to directory the user will most likely work in
+if [ -z "${SOURCE_DIR}" ]; then
+       SOURCE_DIR="/build"
+fi
+cd "${SOURCE_DIR}"
+
+exec /bin/bash --login
diff --git a/tools/buildsystem-tools/cleanup b/tools/buildsystem-tools/cleanup
new file mode 100755 (executable)
index 0000000..49e7c1b
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+dirname=$(dirname ${0})
+
+. ${dirname}/common-functions
+
+directory_remove_orphans $@
diff --git a/tools/buildsystem-tools/common-functions b/tools/buildsystem-tools/common-functions
new file mode 100644 (file)
index 0000000..4c44a58
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# Simply import all files from this directory that
+# begin with functions-*.
+
+BASEDIR=$(dirname ${BASH_SOURCE[0]})
+
+for file in ${BASEDIR}/functions-*; do
+       # Avoid infinite loop when importing this file again
+       [ "$(basename ${file})" = "functions-common" ] && continue
+
+       . ${file}
+done
+
diff --git a/tools/buildsystem-tools/dependency-tracker b/tools/buildsystem-tools/dependency-tracker
new file mode 100755 (executable)
index 0000000..8bdb839
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+dirname=$(dirname ${0})
+
+. ${dirname}/common-functions
+
+args=${1}
+
+if [ -n "${2}" ]; then
+       args=${2}
+fi
+
+provides=$(find_provides ${args})
+requires=""
+for require in $(find_requires ${args}); do
+       listmatch ${require} ${provides} || requires="${requires} ${require}"
+done
+
+if [ -n "${PKG_PREREQUIRES}" ]; then
+       echo "prerequires=\"/bin/sh ${PKG_PREREQUIRES}\""
+fi
+echo "requires=\"${requires}\""
+echo "provides=\"${provides}\""
+echo "conflicts=\"${PKG_CONFLICTS}\""
+echo "obsoletes=\"${PKG_OBSOLETES}\""
+
+exit 0
diff --git a/tools/buildsystem-tools/functions-common b/tools/buildsystem-tools/functions-common
new file mode 100644 (file)
index 0000000..4c44a58
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# Simply import all files from this directory that
+# begin with functions-*.
+
+BASEDIR=$(dirname ${BASH_SOURCE[0]})
+
+for file in ${BASEDIR}/functions-*; do
+       # Avoid infinite loop when importing this file again
+       [ "$(basename ${file})" = "functions-common" ] && continue
+
+       . ${file}
+done
+
diff --git a/tools/buildsystem-tools/functions-constants b/tools/buildsystem-tools/functions-constants
new file mode 100644 (file)
index 0000000..80256f9
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# Debugging mode for these scripts
+DEBUG=0
+
+# Interpreters that should not be found by find_interpreters()
+INTERPRETERS_TO_BE_SKIPPED="/usr/bin/env"
+
+# Some path constants...
+LIBRARY_PATHS="/lib /usr/lib /libexec /usr/libexec"
+BINARY_PATHS="${LIBRARY_PATHS} /bin /sbin /usr/bin /usr/sbin"
+
+# List of directories that could probably empty and are removed automatically
+# so they won't appear in any package.
+ORPHAN_CANDIDATES="${BINARY_PATHS} /usr /usr/include /usr/share"
+for i in $(seq 0 9); do
+       ORPHAN_CANDIDATES="${ORPHAN_CANDIDATES} /usr/share/man/man${i}"
+done
+ORPHAN_CANDIDATES="${ORPHAN_CANDIDATES} /usr/lib/pkgconfig"
+ORPHAN_CANDIDATES="${ORPHAN_CANDIDATES} /usr/lib/python*"
+
diff --git a/tools/buildsystem-tools/functions-directories b/tools/buildsystem-tools/functions-directories
new file mode 100644 (file)
index 0000000..700321c
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+function dir_is_empty() {
+       [ "$(ls -A $@ 2>/dev/null | wc -l)" = "0" ]
+}
+
+function directory_remove_orphans() {
+       if [ "${QUALITY_AGENT_NO_DIRECTORY_PRUNE}" = "yes" ]; then
+               return
+       fi
+
+       local basedir=${1}
+
+       log DEBUG "Removing orphans in ${basedir}"
+
+       local dir
+       local dir_pattern
+       for dir_pattern in ${ORPHAN_CANDIDATES}; do
+               dir=$(echo ${basedir}/${dir_pattern})
+
+               for dir in ${dir}; do
+                       echo "DIR ${dir}" >&2
+                       [ -d "${dir}" ] || continue
+
+                       if dir_is_empty ${dir}; then
+                               log DEBUG "  Found orphaned directory: ${dir}"
+                               rm -rf ${dir}
+                       fi
+               done
+       done
+}
+
diff --git a/tools/buildsystem-tools/functions-files b/tools/buildsystem-tools/functions-files
new file mode 100644 (file)
index 0000000..05920c8
--- /dev/null
@@ -0,0 +1,195 @@
+#!/bin/bash
+
+# Check if a file is an ELF binary
+#
+function file_is_elf() {
+       local file=${1}
+
+       file "${file}" | grep -q "ELF"
+}
+
+# Check if a file is a script.
+#   If the first line starts with #! this is sufficient.
+#
+function file_is_script() {
+       local file=${1}
+
+       local first_line=$(head -n1 ${file})
+
+       [ "${first_line:0:2}" = "#!" ]
+}
+
+# Get the interpreter of a file.
+#
+function file_get_interpreter() {
+       local file=${1}
+
+       if file_is_elf ${file}; then
+               _file_get_elf_interpreter ${file}
+       elif file_is_script ${file}; then
+               _file_get_script_interpreter ${file}
+       fi
+}
+
+# Hidden function that gets the interpreter from an ELF file.
+#
+function _file_get_elf_interpreter() {
+       local file=${1}
+
+       readelf -l ${file} | grep "program interpreter" | \
+               tr -d "]" | awk '{ print $NF }'
+}
+
+# Hidden fucntion that gets the interpreter from a script file.
+#
+function _file_get_script_interpreter() {
+       local file=${1}
+
+       # If the file is not executeable, no interpreter will be needed
+       [ -x "${file}" ] || return
+
+       local first_line=$(head -n1 ${file})
+
+       first_line="${first_line:2:${#first_line}}"
+
+       # Choose the first argument and strip any parameters if available
+       local interpreter
+       for interpreter in ${first_line}; do
+               echo "${interpreter}"
+               return
+       done
+}
+
+# Check if a file is statically linked.
+#
+function file_is_static() {
+       local file=${1}
+
+       file ${file} | grep -q "statically linked"
+}
+
+# Get NEEDED from a file.
+#
+function file_get_needed() {
+       local file=${1}
+
+       readelf -d ${file} | grep NEEDED | \
+               tr -d "[]" | awk '{ print $NF }'
+}
+
+# Get RPATH from a file.
+#
+function file_get_rpath() {
+       local file=${1}
+
+       readelf -d ${file} | grep RPATH | \
+               tr -d "[]" | awk '{ print $NF }'
+}
+
+# Get SONAME from a file.
+#
+function file_get_soname() {
+       local file=${1}
+
+       local file_basename=$(basename ${file})
+       if [ "${file_basename:0:3}" = "ld-" ]; then
+               log DEBUG "Don't return a SONAME for linkers: ${file}"
+               return
+       fi
+
+       readelf -d ${file} | grep SONAME | \
+               tr -d "[]" | awk '{ print $NF }'
+}
+
+# Check if a file is a shared object.
+#
+function file_is_shared_object() {
+       local file=${1}
+
+       file ${file} | grep -q "shared object"
+}
+
+# Check if a file has the canary.
+#
+function file_has_canary() {
+       local file=${1}
+
+       readelf -s ${file} | grep -q "__stack_chk_fail"
+}
+
+# Check if a file has an executeable stack.
+#
+function file_has_execstack() {
+       local file=${1}
+
+       readelf -h ${file} | grep -qE "Type:[[:space:]]*EXEC"
+}
+
+# Check if a file has NX.
+#
+function file_has_nx() {
+       local file=${1}
+
+       readelf -l ${file} | grep "GNU_STACK" | grep -q "RWE"
+       [ $? != 0 ]
+}
+
+# Check if a file is partly RELRO.
+#
+function file_is_relro_partly() {
+       local file=${1}
+
+       readelf -l ${file} | grep -q "GNU_RELRO"
+}
+
+# Check if a file is fully RELRO.
+#
+function file_is_relro_full() {
+       local file=${1}
+
+       if file_is_relro_partly ${file}; then
+               readelf -d ${file} | grep -q "BIND_NOW"
+               return $?
+       fi
+       return 1
+}
+
+# Find all ELF files.
+#
+function find_elf_files() {
+       local dir
+       local dirs
+       local prefix
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --prefix=*)
+                               prefix="${1#--prefix=}/"
+                               ;;
+                       *)
+                               dirs="${dirs} ${1}"
+                               ;;
+               esac
+               shift
+       done
+
+       local file
+       local files
+
+       for dir in ${dirs}; do
+               dir="${prefix}${dir}"
+               for file in $(find ${dir} -type f 2>/dev/null); do
+                       if file_is_elf ${file} && ! file_is_static ${file}; then
+                               files="${files} ${file}"
+                       fi
+               done
+       done
+
+       echo ${files}
+}
+
+function filter_startfiles() {
+       local file=${1}
+
+       grep -qE "crt[1in]\.o$" <<<${file}
+}
diff --git a/tools/buildsystem-tools/functions-lists b/tools/buildsystem-tools/functions-lists
new file mode 100644 (file)
index 0000000..d8152d4
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+function listsort() {
+       local item
+       for item in $@; do
+               echo "${item}"
+       done | sort -u | tr "\n" " "
+}
+
+function listmatch() {
+       local arg=${1}
+       shift
+
+       local item
+       for item in $@; do
+               if [ "${arg}" = "${item}" ]; then
+                       return 0
+               fi
+       done
+       return 1
+}
+
+function sort_by_length() {
+       local c
+       local i
+       for i in $@; do
+               echo "$(wc -c <<<${i}) ${i}"
+       done | sort -n -r | while read c i; do
+               echo "${i}"
+       done
+}
diff --git a/tools/buildsystem-tools/functions-logging b/tools/buildsystem-tools/functions-logging
new file mode 100644 (file)
index 0000000..4fd43ed
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+function log() {
+       local level=${1}
+       shift
+
+       if [ "${level}" = "DEBUG" ] && [ "${DEBUG}" != "1" ]; then
+               return
+       fi
+
+       printf " %1s | %s\n" "${level:0:1}" "$@" >&2
+}
diff --git a/tools/buildsystem-tools/functions-packager-find b/tools/buildsystem-tools/functions-packager-find
new file mode 100644 (file)
index 0000000..1b488d9
--- /dev/null
@@ -0,0 +1,237 @@
+#!/bin/bash
+
+# A function that finds needed libraries and interpreters.
+#
+function find_requires() {
+       local dir
+       local dirs=$@
+
+       # Find interpreters of all files in the dirs and skip those we provide
+       # ourself.
+       local interpreter
+       local interpreters
+       for interpreter in $(find_interpreters ${dirs}); do
+               local found=0
+               for dir in ${dirs}; do
+                       if [ -e "${dir}/${interpreter}" ]; then
+                               found=1
+                               break
+                       fi
+               done
+
+               [ "${found}" = "0" ] && interpreters="${interpreters} ${interpreter}"
+       done
+
+       # Find NEEDED libs and add them to a list if they are not provided by any
+       # other file in dirs.
+       local neededs
+       for file in $(find_elf_files ${dirs}); do
+               for needed in $(file_get_needed ${file}); do
+                       neededs="${neededs} ${needed}"
+               done
+       done
+
+       # Find all symlink destinations
+       local links=$(find_symlink_destinations ${dirs})
+
+       # Others
+       local others=$(find_python_requires ${dirs})
+       others="${others} $(find_weak_symbols_requires ${dirs})"
+       others="${others} $(find_perl_requires ${dirs})"
+       others="${others} $(find_pkgconfig_requires ${dirs})"
+
+       # Return a sorted and unique(!) list
+       local require
+       local requires
+       for require in $(listsort ${PKG_DEPS} ${interpreters} ${neededs} ${links} ${others}); do
+               [ "${require:0:3}" = "ld-" ] && continue
+
+               if [ -n "${PKG_REQUIRES_FILTER}" ]; then
+                       grep -qE "${PKG_REQUIRES_FILTER}" <<< "${require}" && continue
+               fi
+
+               requires="${requires} ${require}"
+       done
+
+       echo ${requires}
+}
+
+function find_provides() {
+       local dirs=$@
+
+       local file
+       local sonames
+       for file in $(find_elf_files ${dirs}); do
+               sonames="${sonames} $(file_get_soname ${file})"
+       done
+       sonames=$(listsort ${sonames})
+
+       # Others
+       local others=$(find_python_provides ${dirs})
+       others="${others} $(find_weak_symbols_provides ${dirs})"
+       others="${others} $(find_perl_provides ${dirs})"
+       others="${others} $(find_pkgconfig_provides ${dirs})"
+
+       local provide
+       local provides
+       for provide in $(listsort ${PKG_PROVIDES} ${sonames} ${others}); do
+               if [ -n "${PKG_PROVIDES_FILTER}" ]; then
+                       grep -qE "${PKG_PROVIDES_FILTER}" <<< "${provide}" && continue
+               fi
+
+               provides="${provides} ${provide}"
+       done
+
+       echo ${provides}
+}
+
+function find_interpreters() {
+       local dirs=$@
+
+       log DEBUG "Searching for interpreters in ${dirs}"
+
+       local file
+       local interpreter
+       local interpreters
+       for file in $(find ${dirs} -type f 2>/dev/null); do
+               # Get interpreter information from file.
+               interpreter=$(file_get_interpreter ${file})
+
+               # Skip the file silently if the result was empty.
+               [ -z "${interpreter}" ] && continue
+
+               # Skip invalid interpreters that don't start with a slash.
+               if [ "${interpreter:0:1}" != "/" ]; then
+                       log WARNING "Skipping invalid interpreter \"${interpreter}\" from \"${file}\"."
+                       continue
+               fi
+
+               if ! listmatch ${interpreter} ${INTERPRETERS_TO_BE_SKIPPED}; then
+                       interpreters="${interpreters} ${interpreter}"
+               fi
+       done
+
+       interpreters=$(listsort ${interpreters})
+
+       log DEBUG "find_interpreters ${dirs}: ${interpreters}"
+
+       echo "${interpreters}"
+}
+
+# Find the destinations of all symlinks and adds a dependency for that.
+#
+function find_symlink_destinations() {
+        local dir=$@
+
+        local link
+        local links
+        for link in $(find ${dir} -type l 2>/dev/null); do
+                link="$(readlink -m ${link})"
+                [ -e "${link}" ] && continue
+
+                link="${link#${dir}}"
+                links="${links} ${link}"
+        done
+
+        echo ${links}
+}
+
+function find_python_provides() {
+       local dir=${1}
+
+       local file
+       for file in $(find ${dir}/usr/bin/python* 2>/dev/null); do
+               file=$(basename ${file})
+               file=${file#python}
+
+               if [ -n "${file}" ]; then
+                       echo "python-api=${file}"
+               fi
+       done
+}
+
+function find_python_requires() {
+       local dir=${1}
+
+       local file
+       for file in $(find ${dir}/usr/lib -maxdepth 1 2>/dev/null); do
+               file=$(basename ${file})
+
+               if [ "${file:0:6}" = "python" ]; then
+                       file=${file#python}
+
+                       if [ -n "${file}" ]; then
+                               echo "python-api=${file}"
+                       fi
+               fi
+       done
+}
+
+function find_perl_files() {
+       local extension
+       for extension in pm pl; do
+               find $@ -name "*.${extension}" 2>/dev/null
+       done
+}
+
+function find_perl_provides() {
+       [ -x "/usr/bin/perl" ] || return 0
+       perl ${BASEDIR}/perl.prov $(find_perl_files $@) | sort -u
+}
+
+function find_perl_requires() {
+       [ -x "/usr/bin/perl" ] || return 0
+       perl ${BASEDIR}/perl.req $(find_perl_files $@) | sort -u
+}
+
+function find_pkgconfig_provides() {
+       [ -x "/usr/bin/pkg-config" ] || return 0
+       find $@ | ${BASEDIR}/pkg-config.prov
+}
+
+function find_pkgconfig_requires() {
+       [ -x "/usr/bin/pkg-config" ] || return 0
+       find $@ | ${BASEDIR}/pkg-config.req
+}
+
+function find_weak_symbols_provides() {
+       local dirs=$@
+
+       local file
+       local soname
+       local symbol
+       for file in $(find_elf_files ${dirs}); do
+               soname=$(file_get_soname ${file})
+               [ -z "${soname}" ] && continue
+
+               for symbol in $(objdump -p ${file} | grep -E "^[0-9]+" | awk '{ print $4 }'); do
+                       [ "${symbol}" = "${soname}" ] && continue
+                       [ "${symbol}" = "GLIBC_PRIVATE" ] && continue
+
+                       echo "${soname}(${symbol})"
+               done
+       done | sort -u
+}
+
+function find_weak_symbols_requires() {
+       local dirs=$@
+
+       local file
+       for file in $(find_elf_files ${dirs}); do
+           objdump -p ${file} | awk 'BEGIN { START=0; LIBNAME=""; }
+                       /^$/ { START=0; }
+                       /^Dynamic Section:$/ { START=1; }
+                       (START==1) && /NEEDED/ {
+                               print $2;
+                       }
+                       (START==2) && /^[A-Za-z]/ { START=3; }
+                       /^Version References:$/ { START=2; }
+                       (START==2) && /required from/ {
+                           sub(/:/, "", $3);
+                           LIBNAME=$3;
+                       }
+                       (START==2) && (LIBNAME!="") && ($4!="") && (($4~/^GLIBC_*/) || ($4~/^GCC_*/)) {
+                           print LIBNAME "(" $4 ")";
+                       }'
+       done | grep -v "GLIBC_PRIVATE" | sort -u
+}
diff --git a/tools/buildsystem-tools/perl.prov b/tools/buildsystem-tools/perl.prov
new file mode 100644 (file)
index 0000000..73bec51
--- /dev/null
@@ -0,0 +1,199 @@
+#!/usr/bin/perl
+
+# RPM (and it's source code) is covered under two separate licenses.
+
+# The entire code base may be distributed under the terms of the GNU
+# General Public License (GPL), which appears immediately below.
+# Alternatively, all of the source code in the lib subdirectory of the
+# RPM source code distribution as well as any code derived from that
+# code may instead be distributed under the GNU Library General Public
+# License (LGPL), at the choice of the distributor. The complete text
+# of the LGPL appears at the bottom of this file.
+
+# This alternative is allowed to enable applications to be linked
+# against the RPM library (commonly called librpm) without forcing
+# such applications to be distributed under the GPL.
+
+# Any questions regarding the licensing of RPM should be addressed to
+# Erik Troan <ewt@redhat.com>.
+
+# a simple script to print the proper name for perl libraries.
+
+# To save development time I do not parse the perl grammmar but
+# instead just lex it looking for what I want.  I take special care to
+# ignore comments and pod's.
+
+# it would be much better if perl could tell us the proper name of a
+# given script.
+
+# The filenames to scan are either passed on the command line or if
+# that is empty they are passed via stdin.
+
+# If there are lines in the file which match the pattern
+#      (m/^\s*\$VERSION\s*=\s+/)
+# then these are taken to be the version numbers of the modules.
+# Special care is taken with a few known idioms for specifying version
+# numbers of files under rcs/cvs control.
+
+# If there are strings in the file which match the pattern
+#     m/^\s*\$RPM_Provides\s*=\s*["'](.*)['"]/i
+# then these are treated as additional names which are provided by the
+# file and are printed as well.
+
+# I plan to rewrite this in C so that perl is not required by RPM at
+# build time.
+
+# by Ken Estes Mail.com kestes@staff.mail.com
+
+if ("@ARGV") {
+  foreach (@ARGV) {
+    process_file($_);
+  }
+} else {
+
+  # notice we are passed a list of filenames NOT as common in unix the
+  # contents of the file.
+
+  foreach (<>) {
+    process_file($_);
+  }
+}
+
+
+foreach $module (sort keys %require) {
+  if (length($require{$module}) == 0) {
+    print "perl($module)\n";
+  } else {
+
+    # I am not using rpm3.0 so I do not want spaces arround my
+    # operators. Also I will need to change the processing of the
+    # $RPM_* variable when I upgrade.
+
+    print "perl($module)=$require{$module}\n";
+  }
+}
+
+exit 0;
+
+
+
+sub process_file {
+
+  my ($file) = @_;
+  chomp $file;
+  
+  open(FILE, "<$file") || return;
+
+  my ($package, $version, $incomment, $inover) = ();
+
+  while (<FILE>) {
+    
+    # skip the documentation
+
+    # we should not need to have item in this if statement (it
+    # properly belongs in the over/back section) but people do not
+    # read the perldoc.
+
+    if (m/^=(head[1-4]|pod|item)/) {
+      $incomment = 1;
+    }
+
+    if (m/^=(cut)/) {
+      $incomment = 0;
+      $inover = 0;
+    }
+    
+    if (m/^=(over)/) {
+      $inover = 1;
+    }
+
+    if (m/^=(back)/) {
+      $inover = 0;
+    }
+
+    if ($incomment || $inover) {
+       next;
+    }
+    
+    # skip the data section
+    if (m/^__(DATA|END)__$/) {
+      last;
+    }
+
+    # not everyone puts the package name of the file as the first
+    # package name so we report all namespaces except some common
+    # false positives as if they were provided packages (really ugly).
+
+    if (m/^\s*package\s+([_:a-zA-Z0-9]+)\s*;/) {
+      $package=$1;
+      undef $version;
+      if ($package eq 'main') {
+        undef $package;
+      } else {
+        # If $package already exists in the $require hash, it means
+        # the package definition is broken up over multiple blocks.
+        # In that case, don't stomp a previous $VERSION we might have
+        # found.  (See BZ#214496.)
+        $require{$package}=undef unless (exists $require{$package});
+      }
+    }
+
+    # after we found the package name take the first assignment to
+    # $VERSION as the version number. Exporter requires that the
+    # variable be called VERSION so we are safe.
+
+    # here are examples of VERSION lines from the perl distribution
+
+    #FindBin.pm:$VERSION = $VERSION = sprintf("%d.%02d", q$Revision: 1.9 $ =~ /(\d+)\.(\d+)/);
+    #ExtUtils/Install.pm:$VERSION = substr q$Revision: 1.9 $, 10;
+    #CGI/Apache.pm:$VERSION = (qw$Revision: 1.9 $)[1];
+    #DynaLoader.pm:$VERSION = $VERSION = "1.03";     # avoid typo warning
+    #General.pm:$Config::General::VERSION = 2.33;
+    # 
+    # or with the new "our" pragma you could (read will) see:
+    #
+    #    our $VERSION = '1.00'
+    if (($package) && (m/^\s*(our\s+)?\$(\Q$package\E::)?VERSION\s*=\s+/)) {
+
+      # first see if the version string contains the string
+      # '$Revision' this often causes bizzare strings and is the most
+      # common method of non static numbering.
+
+      if (m/(\$Revision: (\d+[.0-9]+))/) {
+       $version= $2; 
+      } elsif (m/[\'\"]?(\d+[.0-9]+)[\'\"]?/) {
+       
+       # look for a static number hard coded in the script
+       
+       $version= $1; 
+      }
+      $require{$package}=$version;
+    }
+  
+    # Allow someone to have a variable that defines virtual packages
+    # The variable is called $RPM_Provides.  It must be scoped with 
+    # "our", but not "local" or "my" (just would not make sense). 
+    # 
+    # For instance:
+    #  
+    #     $RPM_Provides = "blah bleah"
+    # 
+    # Will generate provides for "blah" and "bleah".
+    #
+    # Each keyword can appear multiple times.  Don't
+    #  bother with datastructures to store these strings,
+    #  if we need to print it print it now.
+       
+    if ( m/^\s*(our\s+)?\$RPM_Provides\s*=\s*["'](.*)['"]/i) {
+      foreach $_ (split(/\s+/, $2)) {
+       print "$_\n";
+      }
+    }
+
+  }
+
+  close(FILE) ||
+    die("$0: Could not close file: '$file' : $!\n");
+
+  return ;
+}
diff --git a/tools/buildsystem-tools/perl.req b/tools/buildsystem-tools/perl.req
new file mode 100644 (file)
index 0000000..d0a1cd7
--- /dev/null
@@ -0,0 +1,249 @@
+#!/usr/bin/perl
+
+# RPM (and its source code) is covered under two separate licenses. 
+
+# The entire code base may be distributed under the terms of the GNU
+# General Public License (GPL), which appears immediately below.
+# Alternatively, all of the source code in the lib subdirectory of the
+# RPM source code distribution as well as any code derived from that
+# code may instead be distributed under the GNU Library General Public
+# License (LGPL), at the choice of the distributor. The complete text
+# of the LGPL appears at the bottom of this file.
+
+# This alternatively is allowed to enable applications to be linked
+# against the RPM library (commonly called librpm) without forcing
+# such applications to be distributed under the GPL.
+
+# Any questions regarding the licensing of RPM should be addressed to
+# Erik Troan <ewt@redhat.com>.
+
+# a simple makedepend like script for perl.
+# To save development time I do not parse the perl grammmar but
+# instead just lex it looking for what I want.  I take special care to
+# ignore comments and pod's.
+
+# It would be much better if perl could tell us the dependencies of a
+# given script.
+
+# The filenames to scan are either passed on the command line or if
+# that is empty they are passed via stdin.
+
+# If there are strings in the file which match the pattern
+#     m/^\s*\$RPM_Requires\s*=\s*["'](.*)['"]/i
+# then these are treated as additional names which are required by the
+# file and are printed as well.
+
+# I plan to rewrite this in C so that perl is not required by RPM at
+# build time.
+
+# by Ken Estes Mail.com kestes@staff.mail.com
+
+if ("@ARGV") {
+  foreach (@ARGV) {
+    process_file($_);
+  }
+} else {
+  
+  # notice we are passed a list of filenames NOT as common in unix the
+  # contents of the file.
+  
+  foreach (<>) {
+    process_file($_);
+  }
+}
+
+
+foreach $module (sort keys %require) {
+  if (length($require{$module}) == 0) {
+    print "perl($module)\n";
+  } else {
+
+    # I am not using rpm3.0 so I do not want spaces around my
+    # operators. Also I will need to change the processing of the
+    # $RPM_* variable when I upgrade.
+
+    print "perl($module)>=$require{$module}\n";
+  }
+}
+
+exit 0;
+
+
+
+sub process_file {
+  
+  my ($file) = @_;
+  chomp $file;
+  
+  open(FILE, "<$file") || return;
+  
+  while (<FILE>) {
+    
+    # skip the "= <<" block
+
+    if ( ( m/^\s*\$(?:.*)\s*=\s*<<\s*(["'`])(.*)\1/) ||
+         ( m/^\s*\$(.*)\s*=\s*<<(\w*)\s*;/) ) {
+      $tag = $2;
+      while (<FILE>) {
+        chomp;
+        ( $_ eq $tag ) && last;
+      }
+      $_ = <FILE>;
+    }
+
+    # skip q{} quoted sections - just hope we don't have curly brackets
+    # within the quote, nor an escaped hash mark that isn't a comment
+    # marker, such as occurs right here. Draw the line somewhere.
+    if ( m/^.*\Wq[qxwr]?\s*([\{\(\[#|\/])[^})\]#|\/]*$/ && ! m/^\s*(require|use)\s/ ) {
+      $tag = $1;
+      $tag =~ tr/{\(\[\#|\//})]#|\//;
+      while (<FILE>) {
+        ( $_ =~ m/\}/ ) && last;
+      }
+    }
+
+    # skip the documentation
+
+    # we should not need to have item in this if statement (it
+    # properly belongs in the over/back section) but people do not
+    # read the perldoc.
+
+    if ( (m/^=(head[1-4]|pod|item)/) .. (m/^=(cut)/) ) {
+      next;
+    }
+
+    if ( (m/^=(over)/) .. (m/^=(back)/) ) {
+      next;
+    }
+    
+    # skip the data section
+    if (m/^__(DATA|END)__$/) {
+      last;
+    }
+
+    # Each keyword can appear multiple times.  Don't
+    #  bother with datastructures to store these strings,
+    #  if we need to print it print it now.
+    #
+       # Again allow for "our".
+    if ( m/^\s*(our\s+)?\$RPM_Requires\s*=\s*["'](.*)['"]/i) {
+      foreach $_ (split(/\s+/, $2)) {
+       print "$_\n";
+      }
+    }
+
+    if ( 
+
+# ouch could be in a eval, perhaps we do not want these since we catch
+# an exception they must not be required
+
+#   eval { require Term::ReadLine } or die $@;
+#   eval "require Term::Rendezvous;" or die $@;
+#   eval { require Carp } if defined $^S; # If error/warning during compilation,
+
+
+       (m/^(\s*)         # we hope the inclusion starts the line
+        (require|use)\s+(?!\{)     # do not want 'do {' loops
+        # quotes around name are always legal
+        [\'\"]?([^\;\ \'\"\t]*)[\'\"]?[\t\;\ ]
+        # the syntax for 'use' allows version requirements
+        \s*([.0-9]*)
+        /x)
+       ) {
+      my ($whitespace, $statement, $module, $version) = ($1, $2, $3,$4);
+
+      # we only consider require statements that are flush against
+      # the left edge. any other require statements give too many
+      # false positives, as they are usually inside of an if statement
+      # as a fallback module or a rarely used option
+
+      ($whitespace ne "" && $statement eq "require") && next;
+
+      # if there is some interpolation of variables just skip this
+      # dependency, we do not want
+      #        do "$ENV{LOGDIR}/$rcfile";
+   
+      ($module =~ m/\$/) && next;
+
+      # skip if the phrase was "use of" -- shows up in gimp-perl, et al.
+      next if $module eq 'of';
+
+      # if the module ends in a comma we probaly caught some
+      # documentation of the form 'check stuff,\n do stuff, clean
+      # stuff.' there are several of these in the perl distribution
+
+      ($module  =~ m/[,>]$/) && next;
+
+      # if the module name starts in a dot it is not a module name.
+      # Is this necessary?  Please give me an example if you turn this
+      # back on.
+
+      #      ($module =~ m/^\./) && next;
+
+      # if the module ends with .pm strip it to leave only basename.
+      # starts with /, which means its an absolute path to a file
+      if ($module =~ m(^/)) {
+        print "$module\n";
+        next;
+      }
+
+      # sometimes people do use POSIX qw(foo), or use POSIX(qw(foo)) etc.
+      # we can strip qw.*$, as well as (.*$:
+      $module =~ s/qw.*$//;
+      $module =~ s/\(.*$//;
+
+      $module =~ s/\.pm$//;
+
+      # some perl programmers write 'require URI/URL;' when 
+      # they mean 'require URI::URL;'
+
+      $module =~ s/\//::/;
+
+      # trim off trailing parentheses if any.  Sometimes people pass
+      # the module an empty list.
+
+      $module =~ s/\(\s*\)$//;
+
+      if ( $module =~ m/^v?([0-9._]+)$/ ) {
+      # if module is a number then both require and use interpret that
+      # to mean that a particular version of perl is specified
+
+      my $ver=$1;
+      if ($ver =~ /5.00/) {
+        print "perl>=0:$ver\n";
+        next;
+      }
+      else {
+        print "perl>=1:$ver\n";
+        next;
+      }
+
+      };
+
+      # ph files do not use the package name inside the file.
+      # perlmodlib documentation says:
+      
+      #       the .ph files made by h2ph will probably end up as
+      #       extension modules made by h2xs.
+      
+      # so do not expend much effort on these.
+
+
+      # there is no easy way to find out if a file named systeminfo.ph
+      # will be included with the name sys/systeminfo.ph so only use the
+      # basename of *.ph files
+
+      ($module  =~ m/\.ph$/) && next;
+
+      $require{$module}=$version;
+      $line{$module}=$_;
+    }
+    
+  }
+
+  close(FILE) ||
+    die("$0: Could not close file: '$file' : $!\n");
+  
+  return ; 
+}
diff --git a/tools/buildsystem-tools/pkg-config.prov b/tools/buildsystem-tools/pkg-config.prov
new file mode 100755 (executable)
index 0000000..2ef9b3c
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/bash
+pkgconfig=${1:-/usr/bin/pkg-config}
+test -x $pkgconfig || exit 0
+while read filename ; do
+case "${filename}" in
+*.pc)
+       # Assume that this file doesn't contain useful information.
+       needs_pkgconfig=false
+       # Query the dependencies of the package.
+       $pkgconfig --print-provides "$filename" 2> /dev/null | while read n r v ; do
+               # We have a dependency.  Make a note that we need the pkgconfig
+               # tool for this package.
+               echo "pkgconfig($n)$r$v"
+               needs_pkgconfig=true
+       done
+       # The dependency on the pkgconfig package itself.
+       if $needs_pkgconfig ; then
+               echo pkgconfig
+       fi
+       ;;
+esac
+done
diff --git a/tools/buildsystem-tools/pkg-config.req b/tools/buildsystem-tools/pkg-config.req
new file mode 100755 (executable)
index 0000000..edb8bce
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+pkgconfig=${1:-/usr/bin/pkg-config}
+test -x $pkgconfig || exit 0
+while read filename ; do
+case "${filename}" in
+*.pc)
+       $pkgconfig --print-requires "$filename" 2> /dev/null | while read n r v ; do
+               echo "pkgconfig($n)$r$v"
+       done
+esac
+done
diff --git a/tools/buildsystem-tools/py-compile b/tools/buildsystem-tools/py-compile
new file mode 100755 (executable)
index 0000000..66c33ed
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+PYTHON=$(which python 2>/dev/null)
+
+if [ -z "${PYTHON}" ]; then
+       # Python is not present. Fail silently.
+       exit 0
+fi
+
+files=""
+for i in $*; do
+       if [ -e ${i}c ] && [ -e ${i}o ]; then
+               continue # all files we want are already there
+       fi
+       files="$files $i"
+done
+
+if [ -z "${files}" ]; then
+       # No files need to be proceeded.
+       exit 0
+fi
+
+$PYTHON -c "
+import sys, os, string, py_compile
+
+files = '''$files'''
+print 'Byte-compiling python modules...'
+for file in string.split(files):
+    if not os.path.exists(file) or not (len(file) >= 3 and file[-3:] == '.py'):
+        continue
+    print file,
+    sys.stdout.flush()
+    py_compile.compile(file)
+print" || exit $?
+
+# this will fail for python < 1.5, but that doesn't matter ...
+$PYTHON -O -c "
+import sys, os, string, py_compile
+
+files = '''$files'''
+print 'Byte-compiling python modules (optimised versions) ...'
+for file in string.split(files):
+    if not os.path.exists(file) or not (len(file) >= 3 and file[-3:] == '.py'):
+        continue
+    print file,
+    sys.stdout.flush()
+    py_compile.compile(file)
+print" 2>/dev/null || :
diff --git a/tools/buildsystem-tools/stripper b/tools/buildsystem-tools/stripper
new file mode 100755 (executable)
index 0000000..b35d72e
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# Based on RedHat's brp-strip*.
+
+BUILDROOT=${1}
+
+for f in `find ${BUILDROOT} -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \) -exec file {} \; | \
+               grep -v "^${BUILDROOT}/\?usr/lib/debug"  | \
+               grep -v ' shared object,' | \
+               sed -n -e 's/^\(.*\):[  ]*ELF.*, not stripped/\1/p'`; do
+
+       # Strip ELF binaries
+       strip -g "$f" || :
+
+       note="-R .note"
+       if objdump -h $f | grep '^[     ]*[0-9]*[       ]*.note[        ]' -A 1 | \
+               grep ALLOC >/dev/null; then
+               note=
+       fi
+       strip -R .comment $note "$f" || :
+done
+
+# Strip ELF shared objects
+# Please note we don't restrict our search to executable files because
+# our libraries are not (should not be, at least) +x.
+for f in `find ${BUILDROOT} -type f -a -exec file {} \; | \
+        grep -v "^${BUILDROOT}/\?usr/lib/debug"  | \
+       grep ' shared object,' | \
+       sed -n -e 's/^\(.*\):[  ]*ELF.*, not stripped/\1/p'`; do
+       strip --strip-unneeded "$f"
+done