| # Copyright 2015 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # Functions used to parse a package list file. |
| # |
| # A PACKAGES.TXT file has the following format: |
| # |
| # - Empty lines, and lines starting with a dash (#) are ignored. |
| # - Each line has several fields like <NAME>=<VALUE> |
| # - Valid <NAME>s and corresponding values are: |
| # |
| # URL=<url> |
| # Download URL for the source package. The package's |
| # basename and version number will be extracted from it. |
| # |
| # GIT=<url> |
| # GIT URL to be cloned and packed as a tarball in the |
| # archive directory. Package name will be <basename>-<revision>.tar.xz |
| # where <basename> is the GIT url basename, and <revision> is the |
| # branch or commit SHA1. |
| # |
| # SVN=<url> |
| # SVN URL to be checked out and packed as a tarball in the archive |
| # directory. Package name will be <basename>-<revision>.tar.xz |
| # where <basename> is the SVN url basename, and <revision> is the |
| # revision number after @. |
| # |
| # BASENAME=<name> |
| # Optional package base name. If not provided, the base name will |
| # be extracted from the URL/GIT/SVN value. |
| # |
| # BRANCH=<name> |
| # GIT branch name, only needed when GIT=<url> is also used, ignored |
| # otherwise. |
| # |
| # SHA1=<sha1> |
| # Optional SHA-1 hash for the source package. If URL=<url> is used, |
| # this is optional, and if present, the content of the downloaded |
| # package will be checked against this value. |
| # |
| # If GIT=<url> is used, this is the SHA1 of the list of files inside |
| # the tarball created by the downloader. The commit itself is |
| # specified through BRANCH=<name> |
| # |
| # SRCDIR=<subdir> |
| # Optional source sub-directory after extraction of the |
| # package. Normally, foo-bar-1.2.tar.gz extracts into |
| # a sub-directory named 'foo-bar-1.2', but there are a |
| # few exceptions where this is not the case. |
| # |
| # For example, when MesaLib-10.4.2.tar.gz is extracted, |
| # the 'Mesa-10.4.2' directory is created. SRCDIR=<subdir> |
| # is a way to override the default value derived from |
| # the package's full name. |
| # |
| # DSTDIR=<subdir> |
| # Optional destination sub-directory. In certain cases, it is |
| # necessary to rename the destination directory from something |
| # different from SRCDIR (e.g. Qt packages should all uncompress |
| # into the same source directory, but they come in tarballs that |
| # extract to separate directories like qtbase-XXX/ and qtsvg-XXX/. |
| # |
| # By setting a non-empty value here, the content of SRCDIR will be |
| # recursively copied into the DSTDIR sub-directory. This happens |
| # after all patches have been applied in SRCDIR. |
| # |
| # Usage: |
| # |
| # 1) Call 'package_list_parse_file /path/to/PACKAGES.TXT' to |
| # parse the package list file and record its content. |
| # |
| # 2) Use other package_list_get_XXX functions to retrieve |
| # information about a package. Each package is identified |
| # by its 'base name', which is the unversioned name of |
| # the package (e.g. 'zlib-2.1.8.tar.gz' has a base name |
| # of 'zlib'). |
| # |
| # 3) One can use 'package_list_get_packages' to retrieve a list |
| # of all the package base names. |
| |
| # Set to 1 to enable debugging this parser, 0 to disable. |
| _SHU_DEBUG_PARSER=0 |
| |
| if [ "$_SHU_DEBUG_PARSER" = "1" ]; then |
| _shu_parser_log () { |
| log "$@" |
| } |
| else |
| _shu_parser_log () { true; } |
| fi |
| |
| # Extract the version of a given package-name. Assumes the following format: |
| # <name>-<version><extension> |
| # |
| # Where <name> can contain hyphens (-) but not <version> or <extension>, |
| # and <extension> is one of the extensions known to package_file_strip_ext |
| # $1: Package name (e.g. 'zlib-1.2.8.tar.gz') |
| # Out: Package version number (e.g. '1.2.8') |
| _shu_package_name_extract_version () { |
| package_file_strip_ext "$1" | sed -e 's|.*-\([^-]*\)$|\1|g' |
| } |
| |
| # Extract the base name of a given package file. Assumes the same format as |
| # _shu_package_name_extract_basename. |
| # $1: Package name (e.g. 'zlib-1.2.8.tar.gz') |
| # Out: Package base name (e.g. 'zlib') |
| _shu_package_name_extract_basename () { |
| package_file_strip_ext "$1" | sed -e 's|^\(.*\)-[^-]*$|\1|g' |
| } |
| |
| # Return the name of a package without its archive suffix (.zip/.tar.gz/etc). |
| # $1: Package file path. |
| # Out: Package file path without zip/tarball extension. |
| package_file_strip_ext () { |
| case $1 in |
| *.zip) |
| printf %s "${1%.zip}" |
| ;; |
| *.tar.gz) |
| printf %s "${1%.tar.gz}" |
| ;; |
| *.tar.bz2) |
| printf %s "${1%.tar.bz2}" |
| ;; |
| *.tar.xz) |
| printf %s "${1%.tar.xz}" |
| ;; |
| *) |
| printf %s "$1" |
| esac |
| } |
| |
| # Set the value of a given package field. |
| # $1: Package index (e.g. '1') |
| # $2: Field name (e.g. 'URL') |
| # $3: Value |
| _shu_pkg_set_var () { |
| var_assign _SHU_PKG_${2}__${1} "$3" |
| } |
| |
| # Get the value of a given package field. |
| # $1: Package index (e.g. '1') |
| # $2: Field name (e.g. 'URL') |
| _shu_pkg_get_var () { |
| var_value _SHU_PKG_${2}__${1} |
| } |
| |
| # Find the index of a given package from its basename |
| # $1: Package basename (e.g. 'pkg-config') |
| # Out: index in _SHU_PKG_ lists (e.g. '1'), or '' if not found. |
| _shu_pkg_find_basename_index () { |
| local N=0 |
| while [ "$N" -lt "$_SHU_PKG_COUNT" ]; do |
| N=$(( $N + 1 )) |
| if [ "$(_shu_pkg_get_var $N BASENAME)" = "$1" ]; then |
| echo "$N" |
| return 0 |
| fi |
| done |
| } |
| |
| # Parse the package list file, and record its content. |
| # One can later use package_list_XXX functions to probe its content. |
| # |
| # $1: package list file. |
| package_list_parse_file () { |
| local PACKAGES="$1" |
| |
| _shu_parser_log "Trying to parse: $PACKAGES" |
| |
| # Small sanity check |
| if [ ! -f "$PACKAGES" ]; then |
| panic "Missing packages list file: $PACKAGES" |
| fi |
| |
| local PKG_BASENAME PKG_URL PKG_SHA1 PKG_PATCHES PKG_FILE PKG_VERSION |
| local PKG_LIST PKG_SRC_DIR PKG_GIT PKG_BRANCH |
| local OLD_IFS="$IFS" |
| local IFS="$OLD_IFS" |
| local COUNT=0 |
| local LINE_NUMBER=0 |
| local LINE |
| IFS=" |
| " |
| for LINE in $(cat "$1"); do |
| IFS=$OLD_IFS |
| LINE_NUMBER=$(( $LINE_NUMBER + 1 )) |
| _shu_parser_log "$LINE_NUMBER: LINE=[$LINE]" |
| PKG_URL= |
| PKG_GIT= |
| PKG_SVN= |
| PKG_BRANCH= |
| PKG_BASENAME= |
| PKG_SHA1= |
| PKG_FILE= |
| PKG_PATCHES= |
| PKG_VERSION= |
| PKG_SRC_DIR= |
| PKG_DST_DIR= |
| |
| # Skip empty lines, and comment lines that start with # |
| if [ -z "$LINE" -o "${LINE##\#}" != "${LINE}" ]; then |
| continue |
| fi |
| |
| local FIELD |
| for FIELD in $LINE; do |
| _shu_parser_log " FIELD=[$FIELD]" |
| case $FIELD in |
| SHA1=*) |
| PKG_SHA1=${FIELD#SHA1=} |
| ;; |
| URL=*) |
| PKG_URL=${FIELD#URL=} |
| ;; |
| BASENAME=*) |
| PKG_BASENAME=${FIELD##BASENAME=} |
| ;; |
| BRANCH=*) |
| PKG_BRANCH=${FIELD#BRANCH=} |
| ;; |
| GIT=*) |
| PKG_GIT=${FIELD#GIT=} |
| ;; |
| SVN=*) |
| PKG_SVN=${FIELD#SVN=} |
| ;; |
| PATCHES=*) |
| PKG_PATCHES=${FIELD#PATCHES=} |
| ;; |
| SRCDIR=*) |
| PKG_SRC_DIR=${FIELD#SRCDIR=} |
| ;; |
| DSTDIR=*) |
| PKG_DST_DIR=${FIELD#DSTDIR=} |
| ;; |
| *) |
| dump "WARNING: Unknown package field [$FIELD] on line $LINE_NUMBER: $1" |
| ;; |
| esac |
| done |
| |
| if [ "$PKG_URL" ]; then |
| if [ "$PKG_GIT" ]; then |
| panic "Cannot use both URL=<url> and GIT=<url> on line $LINE_NUMBER: $1" |
| fi |
| if [ "$PKG_SVN" ]; then |
| panic "Cannot use both URL=<url> and SVN=<url> on line $LINE_NUMBER: $1" |
| fi |
| PKG_FILE=$(basename "$PKG_URL") |
| if [ -z "$PKG_BASENAME" ]; then |
| PKG_BASENAME=$(_shu_package_name_extract_basename "$PKG_FILE") |
| fi |
| PKG_VERSION=$(_shu_package_name_extract_version "$PKG_FILE") |
| elif [ "$PKG_GIT" ]; then |
| if [ "$PKG_SVN" ]; then |
| panic "Cannot use both GIT=<url> and SVN=<url> on line $LINE_NUMBER: $1" |
| fi |
| if [ -z "$PKG_BRANCH" ]; then |
| panic "Missing BRANCH=<name> on line $LINE_NUMBER: $1" |
| fi |
| PKG_FILE=$(basename "$PKG_GIT") |
| PKG_FILE=${PKG_FILE%.git} # Remove any .git suffix. |
| if [ -z "$PKG_BASENAME" ]; then |
| PKG_BASENAME=$PKG_FILE |
| fi |
| PKG_FILE=$PKG_BASENAME-$PKG_BRANCH.tar.xz |
| PKG_VERSION=$PKG_BRANCH |
| elif [ "$PKG_SVN" ]; then |
| if [ -z "$PKG_BRANCH" ]; then |
| panic "Missing BRANCH=<name> on line $LINE_NUMBER: $1" |
| fi |
| PKG_FILE=$(basename "$PKG_SVN") |
| if [ -z "$PKG_BASENAME" ]; then |
| PKG_BASENAME=$PKG_FILE |
| fi |
| PKG_FILE=$PKG_BASENAME-$PKG_BRANCH.tar.xz |
| PKG_VERSION=$PKG_BRANCH |
| else |
| panic "Missing URL=<url>, GIT=<url> or SVN=<url> field in package list line $LINE_NUMBER: $1" |
| fi |
| |
| _shu_parser_log " BASENAME=$PKG_BASENAME FILE=$PKG_FILE" |
| if [ -z "$PKG_SRC_DIR" ]; then |
| PKG_SRC_DIR=$PKG_BASENAME-$PKG_VERSION |
| _shu_parser_log " SRC_DIR=$PKG_SRC_DIR" |
| fi |
| |
| if [ -z "$PKG_DST_DIR" ]; then |
| PKG_DST_DIR=$PKG_SRC_DIR |
| fi |
| _shu_parser_log " DST_DIR=$PKG_DST_DIR" |
| |
| # Save the package information now. |
| COUNT=$(( $COUNT + 1 )) |
| _shu_pkg_set_var $COUNT BASENAME "$PKG_BASENAME" |
| _shu_pkg_set_var $COUNT VERSION "$PKG_VERSION" |
| _shu_pkg_set_var $COUNT FILE "$PKG_FILE" |
| _shu_pkg_set_var $COUNT SRC_DIR "$PKG_SRC_DIR" |
| _shu_pkg_set_var $COUNT DST_DIR "$PKG_DST_DIR" |
| _shu_pkg_set_var $COUNT URL "$PKG_URL" |
| _shu_pkg_set_var $COUNT GIT "$PKG_GIT" |
| _shu_pkg_set_var $COUNT SVN "$PKG_SVN" |
| _shu_pkg_set_var $COUNT SHA1 "$PKG_SHA1" |
| _shu_pkg_set_var $COUNT PATCHES "$PKG_PATCHES" |
| |
| var_append PKG_LIST "$PKG_BASENAME" |
| done |
| |
| _SHU_PKG_COUNT=$COUNT |
| _SHU_PKG_LIST=$PKG_LIST |
| } |
| |
| |
| # Get the value of a named field for a packaged identified by basename. |
| # $1: Package basename (e.g. 'zlib') |
| # $2: Field name (e.g. 'URL') |
| # Out: field value, or empty if not defined. |
| _shu_package_list_get_field () { |
| local N |
| N=$(_shu_pkg_find_basename_index "$1") |
| if [ "$N" ]; then |
| _shu_pkg_get_var $N $2 |
| fi |
| } |
| |
| # Return the version of a given package. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'zlib') |
| # Out: package version (e.g. '1.2.8') |
| package_list_get_version () { |
| local N |
| N=$(_shu_pkg_find_basename_index "$1") |
| if [ "$N" ]; then |
| printf %s $(_shu_pkg_get_var $N VERSION) |
| fi |
| } |
| |
| # Return the full name of a given package. |
| # $1: unversioned and unsuffixed package prefix (e.g. 'zlib') |
| # Out: package full name (e.g. 'zlib-1.2.8') |
| package_list_get_full_name () { |
| local N |
| N=$(_shu_pkg_find_basename_index "$1") |
| if [ "$N" ]; then |
| printf %s $(_shu_pkg_get_var $N BASENAME)-$(_shu_pkg_get_var $N VERSION) |
| fi |
| } |
| |
| # Return the archive file name of a given package. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'zlib') |
| # Out: package tarball name (e.g. 'zlib-1.2.8.tar.gz') |
| package_list_get_filename () { |
| _shu_package_list_get_field "$1" FILE |
| } |
| |
| # Return the URL of a given package, if any. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'zlib') |
| # Out: package URL (e.g. 'ftp://someserver/somepath/zlib-1.2.8.tar.gz') |
| package_list_get_url () { |
| _shu_package_list_get_field "$1" URL |
| } |
| |
| # Return the git URL of a given package, if any. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'zlib') |
| # Out: package URL (e.g. 'git://git.qemu-project.org/dtc.git') |
| package_list_get_git_url () { |
| _shu_package_list_get_field "$1" GIT |
| } |
| |
| # Return the git SVM of a given package, if any. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'zlib') |
| # Out: package URL (e.g. 'svn://svn.project.org/trunk/something@version') |
| package_list_get_svn_url () { |
| _shu_package_list_get_field "$1" SVN |
| } |
| |
| package_list_get_git_branch () { |
| _shu_package_list_get_field "$1" BRANCH |
| } |
| |
| # Return the SHA1 of a given package, if any. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'zlib') |
| # Out: package SHA1 |
| package_list_get_sha1 () { |
| _shu_package_list_get_field "$1" SHA1 |
| } |
| |
| # Return the patches tarball of a given package, if any. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'glib') |
| # Out: package tarball name (e.g. 'glib-2.1.8-patches.tar.xz') |
| package_list_get_patches () { |
| _shu_package_list_get_field "$1" PATCHES |
| } |
| |
| # Return the source sub-directory name of a given package. |
| # $1: unversioned and un-suffixed package prefix (e.g. 'MesaLib') |
| # Out: source sub-directory (e.g. 'Mesa-10.4.2') |
| package_list_get_src_dir () { |
| _shu_package_list_get_field "$1" DST_DIR |
| } |
| |
| package_list_get_unpack_src_dir () { |
| _shu_package_list_get_field "$1" SRC_DIR |
| } |
| |
| # Return the list of all unversioned package names. |
| package_list_get_packages () { |
| printf %s "$_SHU_PKG_LIST" |
| } |
| |
| # Unpack and eventually patch a given source package. |
| # |
| # $1: unversioned and unsuffixed package name (e.g. 'zlib') |
| # $2: source archive directory. |
| # $3: destination directory. |
| package_list_unpack_and_patch () { |
| local PKG_NAME="$1" |
| local SRC_DIR="$2" |
| local DST_DIR="$3" |
| local PKG_VERSION PKG_PACKAGE PKG_PATCHES_DIR PKG_PATCHES_PACKAGE |
| local PKG_DIR PKG_DST_DIR PATCH PKG_FULLNAME |
| PKG_VERSION=$(package_list_get_version $PKG_NAME) |
| if [ -z "$PKG_VERSION" ]; then |
| panic "Cannot find version for package $PKG_NAME!" |
| fi |
| PKG_FULLNAME=$(package_list_get_full_name $PKG_NAME) |
| dump "Extracting $PKG_FULLNAME" |
| PKG_FILE=$(package_list_get_filename $PKG_NAME) |
| mkdir -p "$DST_DIR" && |
| unpack_archive "$SRC_DIR/$PKG_FILE" "$DST_DIR" || |
| panic "Could not unpack $PKG_FULLNAME" |
| PKG_DIR=$DST_DIR/$(package_list_get_unpack_src_dir $PKG_NAME) |
| if [ ! -d "$PKG_DIR" ]; then |
| panic "Missing extracted directory: $PKG_DIR" |
| fi |
| PKG_PATCHES_DIR=$PKG_FULLNAME-patches |
| PKG_PATCHES_FILE=$SRC_DIR/${PKG_PATCHES_DIR}.tar.xz |
| if [ -f "$PKG_PATCHES_FILE" ]; then |
| log "Patching $PKG_FULLNAME" |
| unpack_archive "$PKG_PATCHES_FILE" "$DST_DIR" |
| for PATCH in $(cd "$DST_DIR" && ls "$PKG_PATCHES_DIR"/*.patch); do |
| log "Applying patch: $PATCH" |
| (cd "$PKG_DIR" && run patch -p1 < "../$PATCH") || |
| panic "Could not apply $PATCH" |
| done |
| fi |
| PKG_DST_DIR=$DST_DIR/$(package_list_get_src_dir $PKG_NAME) |
| if [ "$PKG_DST_DIR" != "$PKG_DIR" ]; then |
| log "Copying sources from $PKG_DIR into $PKG_DST_DIR" |
| copy_directory "$PKG_DIR" "$PKG_DST_DIR" |
| fi |
| } |