From: Michael Tremer Date: Sat, 5 Feb 2011 19:18:31 +0000 (+0100) Subject: build-essentials: Many other changes for the new pakfire build system. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=235217d273cf7ae9cce69e86459ed57215466254;p=ipfire-3.x.git build-essentials: Many other changes for the new pakfire build system. --- diff --git a/pkgs/core/build-essentials/build-essentials.nm b/pkgs/core/build-essentials/build-essentials.nm index 08c4ccbb6..a1d2d607a 100644 --- a/pkgs/core/build-essentials/build-essentials.nm +++ b/pkgs/core/build-essentials/build-essentials.nm @@ -27,6 +27,7 @@ include $(PKGROOT)/Include PKG_NAME = build-essentials PKG_VER = $(DISTRO_VERSION) PKG_REL = 2 +#PKG_ARCH = noarch PKG_MAINTAINER = Michael Tremer PKG_GROUP = Development/Tools @@ -47,12 +48,12 @@ STAGE_BUILD = # Nothing to do here define STAGE_INSTALL # Install the quality-agent and buildsystem header files. - -mkdir -pv $(BUILDROOT)/usr/bin - -mkdir -pv $(BUILDROOT)/usr/sbin - -mkdir -pv $(BUILDROOT)/usr/lib/buildsystem + -mkdir -pv $(BUILDROOT)/usr/{,s}bin + -mkdir -pv $(BUILDROOT)/usr/lib/buildsystem{,-tools} -mkdir -pv $(BUILDROOT)/usr/lib/quality-agent cp -vf buildsystem/* $(BUILDROOT)/usr/lib/buildsystem + cp -vf buildsystem-tools/* $(BUILDROOT)/usr/lib/buildsystem-tools cp -vf quality-agent/quality-agent $(BUILDROOT)/usr/sbin/ cp -vrf quality-agent/quality-agent.d/* \ @@ -61,11 +62,7 @@ define STAGE_INSTALL -mkdir -pv $(BUILDROOT)/etc/profile.d cp -vf buildsystem.sh $(BUILDROOT)/etc/profile.d/ - # Install chroot shell - cp -vf chroot-shell $(BUILDROOT)/usr/bin/chroot-shell - chmod -v 755 $(BUILDROOT)/usr/bin/chroot-shell - - # Install patch utility - cp -vf patch $(BUILDROOT)/usr/lib/buildsystem/patch - chmod -v 755 $(BUILDROOT)/usr/lib/buildsystem/patch + # Create symlink to chroot-shell + ln -svf ../lib/buildsystem-tools/chroot-shell \ + $(BUILDROOT)/usr/bin/chroot-shell endef diff --git a/pkgs/core/build-essentials/buildsystem-tools/chroot-shell b/pkgs/core/build-essentials/buildsystem-tools/chroot-shell new file mode 100755 index 000000000..0d4a61f20 --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/chroot-shell @@ -0,0 +1,24 @@ +#!/bin/bash + +cat </dev/null | wc -l)" = "0" ] +} + +function directory_remove_orphans() { + local basedir=${1} + + log DEBUG "Removing orphans in ${basedir}" + + local dir + for dir in ${ORPHAN_CANDIDATES}; do + dir="${basedir}/${dir}" + + [ -d "${dir}" ] || continue + + if dir_is_empty ${dir}; then + log DEBUG " Found orphaned directory: ${dir}" + rm -rf ${dir} + fi + done +} + diff --git a/pkgs/core/build-essentials/buildsystem-tools/functions-files b/pkgs/core/build-essentials/buildsystem-tools/functions-files new file mode 100644 index 000000000..41ce3be0c --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/functions-files @@ -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_shared_object ${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/pkgs/core/build-essentials/buildsystem-tools/functions-lists b/pkgs/core/build-essentials/buildsystem-tools/functions-lists new file mode 100644 index 000000000..d8152d487 --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/functions-lists @@ -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/pkgs/core/build-essentials/buildsystem-tools/functions-logging b/pkgs/core/build-essentials/buildsystem-tools/functions-logging new file mode 100644 index 000000000..4fd43edce --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/functions-logging @@ -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/pkgs/core/build-essentials/buildsystem-tools/functions-packager-find b/pkgs/core/build-essentials/buildsystem-tools/functions-packager-find new file mode 100644 index 000000000..bc97483cf --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/functions-packager-find @@ -0,0 +1,214 @@ +#!/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})" + + # Get provides, because packages should not depend on features they provide + # by themselves. + local provides=$(find_provides ${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 + listmatch ${require} ${provides} || 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})" + + listsort ${PKG_PROVIDES} ${sonames} ${others} +} + +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 + ${BASEDIR}/perl.prov $(find_perl_files $@) | sort -u +} + +function find_perl_requires() { + [ -x "/usr/bin/perl" ] || return 0 + ${BASEDIR}/perl.req $(find_perl_files $@) | sort -u +} + +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/pkgs/core/build-essentials/patch b/pkgs/core/build-essentials/buildsystem-tools/patch similarity index 100% rename from pkgs/core/build-essentials/patch rename to pkgs/core/build-essentials/buildsystem-tools/patch diff --git a/pkgs/core/build-essentials/buildsystem-tools/perl.prov b/pkgs/core/build-essentials/buildsystem-tools/perl.prov new file mode 100755 index 000000000..73bec513b --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/perl.prov @@ -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 . + +# 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 () { + + # 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/pkgs/core/build-essentials/buildsystem-tools/perl.req b/pkgs/core/build-essentials/buildsystem-tools/perl.req new file mode 100755 index 000000000..d0a1cd729 --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/perl.req @@ -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 . + +# 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 () { + + # skip the "= <<" block + + if ( ( m/^\s*\$(?:.*)\s*=\s*<<\s*(["'`])(.*)\1/) || + ( m/^\s*\$(.*)\s*=\s*<<(\w*)\s*;/) ) { + $tag = $2; + while () { + chomp; + ( $_ eq $tag ) && last; + } + $_ = ; + } + + # 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 () { + ( $_ =~ 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/pkgs/core/build-essentials/buildsystem-tools/py-compile b/pkgs/core/build-essentials/buildsystem-tools/py-compile new file mode 100755 index 000000000..66c33edfe --- /dev/null +++ b/pkgs/core/build-essentials/buildsystem-tools/py-compile @@ -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/pkgs/core/build-essentials/buildsystem/Constants b/pkgs/core/build-essentials/buildsystem/Constants index e882ad1b6..6eb6dfb2d 100644 --- a/pkgs/core/build-essentials/buildsystem/Constants +++ b/pkgs/core/build-essentials/buildsystem/Constants @@ -5,21 +5,18 @@ # ############################################################################### -# If we are running in a chroot, we map all directories to $(BASEDIR), otherwise -# BASEDIR will be the absolute path (for gathering information from the source -# packages) -ifeq "$(CHROOT)" "1" - BASEDIR = /usr/src -endif +BASEDIR = /build + +BUILD_TOOLS = /usr/lib/buildsystem-tools # Set default directories DIR_APP = $(DIR_SRC)/$(THISAPP) -DIR_DL = $(BASEDIR)/cache +DIR_DL = $(BASEDIR)/files DIR_PACKAGES = /usr/src/packages/$(PKG_ARCH) -DIR_PATCHES = $(DIR_SOURCE)/patches +DIR_PATCHES = $(BASEDIR)/patches DIR_SRC = /usr/src DIR_TMP = /tmp -DIR_SOURCE = $(CURDIR) +DIR_SOURCE = $(BASEDIR) DIR_TOOLS = $(BASEDIR)/tools # Directory where to search for object files @@ -27,7 +24,7 @@ VPATH = $(DIR_DL) # Paths to scripts DO_EXTRACT = tar xaf -DO_QUALITY_AGENT = $(DIR_TOOLS)/quality-agent +DO_QUALITY_AGENT = quality-agent ############################################################################### # @@ -36,11 +33,18 @@ DO_QUALITY_AGENT = $(DIR_TOOLS)/quality-agent ############################################################################### # Export CFLAGS + CXXFLAGS -export CFLAGS -export CXXFLAGS +GLOBAL_CFLAGS = -O2 -g -pipe -Wall -fexceptions --param=ssp-buffer-size=4 + +CFLAGS_i686 = -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables +CFLAGS_x86_64 = -m64 -mtune=generic + +export CFLAGS = $(GLOBAL_CFLAGS) $(CFLAGS_$(DISTRO_ARCH)) +export CXXFLAGS = $(CFLAGS) # Options that get passed to configure by default CONFIGURE_OPTIONS = \ + --host=$(DISTRO_MACHINE) \ + --build=$(DISTRO_MACHINE) \ --prefix=/usr ############################################################################### @@ -66,7 +70,7 @@ PKG_VARIABLES = \ PKG_MAINTAINER \ PKG_LICENSE \ PKG_PROVIDES \ - PKG_REL \ + PKG_RELEASE \ PKG_SUMMARY \ PKG_URL \ PKG_VER @@ -87,11 +91,13 @@ export BUILD_ID # # The actual package name (the name of the directory) -PKG_NAME_REAL = $(notdir $(CURDIR)) +PKG_NAME_REAL = $(notdir $(subst .nm,,$(firstword $(MAKEFILE_LIST)))) PKG_NAME = $(PKG_NAME_REAL) -# Set default epoch +# Set default epoch, release and arch PKG_EPOCH = 0 +PKG_RELEASE = $(PKG_REL).$(DISTRO_DISTTAG) +PKG_ARCH = $(DISTRO_ARCH) # Shortcut to package name + version THISAPP = $(PKG_NAME)-$(PKG_VER) @@ -124,7 +130,8 @@ PKG_PATCHES += \ $(foreach patch,$(wildcard $(DIR_PATCHES)/*.diff),$(notdir $(patch))) # Dynamic command that applies all patches -DO_PATCHES = cd $(DIR_APP) && $(DIR_TOOLS)/patch $(foreach patch,$(PKG_PATCHES),$(DIR_PATCHES)/$(patch)) +DO_PATCHES = cd $(DIR_APP) && $(BUILD_TOOLS)/patch \ + $(foreach patch,$(PKG_PATCHES),$(DIR_PATCHES)/$(patch)) # Get a list of files that are installed automatically PKG_DEFAULT_FILES = $(wildcard *.default) diff --git a/pkgs/core/build-essentials/buildsystem/Functions b/pkgs/core/build-essentials/buildsystem/Functions index 42cfa80fe..e2efad8d5 100644 --- a/pkgs/core/build-essentials/buildsystem/Functions +++ b/pkgs/core/build-essentials/buildsystem/Functions @@ -36,6 +36,19 @@ define DO_FILELIST @cd $(BUILDROOT) && find -ls endef +define DO_PACKAGE_VARIABLE + @echo $(if $($(1)-$(2)),$(1)="\"$(strip $($(1)-$(2)))\"",$(1)="\"$(strip $($(1)))\"") + +endef + +define DO_PACKAGE_INFO + @echo "PKG_NAME=\"$(1)\"" + $(foreach var,$(PKG_VARIABLES),$(call DO_PACKAGE_VARIABLE,$(var),$(1))) + + @echo + +endef + define __INSTALL_DEFAULT -mkdir -pv $(BUILDROOT)/etc/default cd $(DIR_APP) && cp -vf $(DIR_SOURCE)/$(1) $(BUILDROOT)/etc/default/$(subst .default,,$(notdir $(1))) @@ -67,7 +80,7 @@ define DO_INSTALL_PAM endef define DO_PYTHON_COMPILE - @find $(BUILDROOT) -name "*.py" | xargs $(DIR_TOOLS)/py-compile + @find $(BUILDROOT) -name "*.py" | xargs $(BUILD_TOOLS)/py-compile endef define DO_FIX_LIBTOOL diff --git a/pkgs/core/build-essentials/buildsystem/Targets b/pkgs/core/build-essentials/buildsystem/Targets index e969f3cd3..f9edd84ef 100644 --- a/pkgs/core/build-essentials/buildsystem/Targets +++ b/pkgs/core/build-essentials/buildsystem/Targets @@ -5,45 +5,51 @@ # ############################################################################### -.PHONY: info -info: - @echo "PKG_ARCH=\"$(PKG_ARCH)\"" +.PHONY: packageinfo +packageinfo: + $(foreach package,$(PKG_PACKAGES),$(call DO_PACKAGE_INFO,$(package))) + +.PHONY: buildinfo +buildinfo: + @echo "PKG_NAME=\"$(PKG_NAME_REAL)\"" + @echo "PKG_EPOCH=\"$(PKG_EPOCH)\"" + @echo "PKG_VER=\"$(PKG_VER)\"" + @echo "PKG_RELEASE=\"$(PKG_RELEASE)\"" + + @echo "PKG_ARCH=\"src\"" @echo "PKG_BUILD_DEPENDENCIES=\"$(PKG_BUILD_DEPS)\"" @echo "PKG_DEPENDENCIES=\"$(PKG_DEPS)\"" @echo "PKG_DESCRIPTION=\"$(strip $(PKG_DESCRIPTION))\"" - @echo "PKG_EPOCH=\"$(PKG_EPOCH)\"" @echo "PKG_GROUP=\"$(PKG_GROUP)\"" @echo "PKG_LICENSE=\"$(PKG_LICENSE)\"" @echo "PKG_MAINTAINER=\"$(PKG_MAINTAINER)\"" - @echo "PKG_NAME=\"$(PKG_NAME_REAL)\"" - @echo "PKG_OBJECTS=\"$(strip $(OBJECTS))\"" - @echo "PKG_PACKAGES=\"$(PKG_PACKAGES)\"" - @echo "PKG_PACKAGES_FILES=\"$(PKG_PACKAGES_FILES)\"" - @echo "PKG_PATCHES=\"$(PKG_PATCHES)\"" - @echo "PKG_VER=\"$(PKG_VER)\"" - @echo "PKG_REL=\"$(PKG_REL)\"" - @echo "PKG_SUMMARY=\"$(strip $(PKG_SUMMARY))\"" @echo "PKG_URL=\"$(PKG_URL)\"" - @echo "SOURCE_DIR=\"$(DIR_APP)\"" + + @echo "PKG_FILES=\"$(PKG_OBJECTS)\"" + @echo "PKG_BUILD_DEPS=\"$(PKG_BUILD_DEPS)\"" + + @echo "CFLAGS=\"$(CFLAGS)\"" + @echo "CXXFLAGS=\"$(CXXFLAGS)\"" $(OBJECTS): @echo "Object file \"$@\" is required." >&2 @exit 1 -.PHONY: build -build: $(STAGE_DONE) +.PHONY: package +package: $(STAGE_DONE) $(foreach package,$(call reverse,$(PKG_PACKAGES)),$(call DO_PACKAGE,$(package))) .PHONY: shell shell: $(OBJECTS) $(if $(STAGE_PREPARE),$(DO_PREPARE)) -prepare: +.PHONY: prepare +prepare: $(OBJECTS) $(if $(STAGE_PREPARE),$(DO_PREPARE)) -$(STAGE_DONE): $(OBJECTS) +.PHONY: build +build: $(OBJECTS) $(if $(STAGE_PREPARE),$(DO_PREPARE)) $(if $(STAGE_BUILD),$(DO_BUILD)) $(if $(STAGE_TEST),$(DO_TEST)) $(if $(STAGE_INSTALL),$(DO_INSTALL)) - @touch $@ diff --git a/pkgs/core/build-essentials/quality-agent/quality-agent.d/qa-include b/pkgs/core/build-essentials/quality-agent/quality-agent.d/qa-include index 4fe1c472b..284673388 100644 --- a/pkgs/core/build-essentials/quality-agent/quality-agent.d/qa-include +++ b/pkgs/core/build-essentials/quality-agent/quality-agent.d/qa-include @@ -1,7 +1,7 @@ #!/bin/bash # Include additional functions -. $(dirname ${0})/../common-functions +. /usr/lib/buildsystem-tools/common-functions function debug() { [ "${NAOKI_DEBUG}" = "1" ] || [ "${DEBUG}" = "1" ]