Re: the *-config scripts



Martijn van Beers <martijn@earthling.net> writes:
> 
> I am hoping we can replace *-config with something like gnome-config
> and *Conf.sh scripts. I asked owen on irc if this was going to
> happen, and he said 'maybe, but I don't want to copy gnome-config
> blindly.'
> 
> So I'm sending this mail to start a discussion on what the requirements
> of the new g-config script would be.
> 

 - written in portable sh (joy!)
 - a way to check whether a package is installed and known about
 - a way to get the version of each package, and perhaps 
   support for checking that the version matches the desired
   version
 - a way to get the link flags of each package
 - a way to get the compile flags
 - should uniquify the flags (remove duplicates)
 - should support an env variable with a search path for the Conf.sh
   files (as with GNOME_LIBCONFIG_PATH)
 - implemented in the near future ;-)

James Henstridge did a thing called pkg-config which is a bit cleaner
than gnome-config, his Conf.sh equivalent looks like this:

 prefix=`gtk-config --prefix`

 REQUIRES="glib gdk gmodule" 
 CFLAGS="-I${prefix}/include"
 LIBS="-L${prefix}/lib -lgtk -lm"

The nice thing is the use of REQUIRES to implicitly drag in the
glib/gdk flags, instead of including those flags in LIBS.

I'll append James's script.

I would say this thing should ship in its own tarball, rather than
with glib, to ensure widest possible usage. With that in mind,
pkg-config or library-config are probably better names than g-config.

Havoc

#!/bin/sh

# All variables are prefixed with pc_ so that there is low likelyhood of
# conflicts with the .pc files.

IFS=":$IFS"

pc_prefix=/usr/local
pc_path=.:${pc_prefix}/share/pkgconfig:/usr/share/pkgconfig

if [ -n "$PC_INCLUDEPATH" ]; then
    pc_path="${PC_INCLUDEPATH}:$pc_path"
fi

trap 'echo "|$rev_pkgs|"; exit 1' 1 2 15

pc_help_msg="Usage: $0 [-I DIR] [--cflags] [--libs] [--expand] PKGS ...
Output link information for a combination of libraries
  -I DIR    Add a directory to the .pc file search path
  --cflags  show cflags to compile with
  --libs    show libraries to link with
  --expand  show expanded list of packages to link with
  PKGS      packages that your program needs to compile

.pc files are small shell scripts that define the variables REQUIRES, CFLAGS
and LIBS.  CFLAGS and LIBS are the cflags and libraries needed to compile
programs that use the library, and REQUIRES lists the packages that the
library requires."

#if the executable is called something like gtk-config, then add gtk to caps
pc_name_pkg=`basename $0 | sed 's/\(.*\)-config.*/\1/'`

pc_want_cflags=no
pc_want_libs=no
pc_want_expand=no
pc_prev=

# the capabilities we want ...
if [ "$pc_name_pkg" = pkg ]; then
    pc_caps=
else
    pc_caps="$pc_name_pkg"
fi

while [ $# -ne 0 ]; do
    pc_arg="$1"
    shift
    case "$pc_arg" in
	-*=*) pc_optarg=`echo $pc_arg | sed 's/[-_a-zA-Z0-9]*=//'` ;;
	*)    pc_optarg= ;;
    esac
    if [ -n "$pc_prev" ]; then
	if [ "$pc_pref" = pcpath ]; then
	    pc_path="$pc_arg:$pc_path"
	else
	    eval "$pc_prev=\$pc_arg"
	fi
	pc_prev=
	continue
    fi
    case "$pc_arg" in
	--help)
	    echo "$pc_help_msg"
	    exit 0 ;;
	--version)
	    echo "pkgconfig v0.0"
	    exit 0 ;;
	-I*) pc_path="`echo $pc_arg | sed 's/^-I//'`:$pc_path" ;;
        -I)   pc_prev=pcpath ;;
	--cflags) pc_want_cflags=yes ;;
	--libs)   pc_want_libs=yes ;;
	--expand) pc_want_expand=yes ;;
	-*)
	    echo "Unknown option: $pc_arg"
	    echo "$pc_help_msg"
	    exit 1 ;;
	*) pc_caps="$pc_caps $pc_arg" ;;
    esac
done

# expand the packages list, so to satisfy dependencies ...
set - $pc_caps
pc_rev_pkgs=""
while [ $# -ne 0 ]; do
    pc_pkg="$1"
    shift

    if [ -z "$pc_pkg" ]; then
	# ash seems to count the space at the start of pc_caps as an extra
	# argument.  This catches that case.
	continue
    fi
    pc_rev_pkgs="$pc_pkg $pc_rev_pkgs"
    REQUIRES=""
    for pc_dir in $pc_path XXX; do
	if [ -f "${pc_dir}/${pc_pkg}.pc" ]; then
	    . ${pc_dir}/${pc_pkg}.pc
	    break
	fi
    done
    if [ "$pc_dir" = XXX ]; then
	echo "couldn't find information for package $pc_pkg." 1>&2
	exit 1
    fi
    if [ "x$REQUIRES" != x ]; then
	for pc_dep in $REQUIRES; do
	    case " $* " in
		*\ $pc_dep\ *) ;; # package occurs later in string
		*) set - $pc_dep $*;;
	    esac
	done
    fi
done

# now remove duplicate packages from the list (all but last duplicate) ...
pc_pkgs=""
pc_tmp="$pc_rev_pkgs"
pc_rev_pkgs=""
for pc_pkg in $pc_tmp; do
    case " $pc_pkgs " in
	*\ $pc_pkg\ *) ;;
	*) pc_pkgs="$pc_pkg $pc_pkgs"
	   rev_pkgs="$pc_rev_pkgs $pc_pkg";;
    esac
done

# from this point on, the list of packages should all exist, and be ordered
# print cflags if asked for ...
if [ "$pc_want_cflags" = yes ]; then
    pc_all_cflags=
    for pc_pkg in $pc_pkgs; do
	CFLAGS=""
	for pc_dir in $pc_path; do
	    if [ -f "${pc_dir}/${pc_pkg}.pc" ]; then
		. ${pc_dir}/${pc_pkg}.pc
		break
	    fi
	done
	pc_all_cflags="$pc_all_cflags $CFLAGS"
    done
    pc_cflags=
    for pc_flag in $pc_all_cflags; do
	case " $pc_cflags " in
	    *\ $pc_flag\ *) ;; # nothing
	    *)           pc_cflags="$pc_cflags $pc_flag" ;;
	esac
    done
    echo $pc_cflags
fi

# print libraries if asked for ...
if [ "$pc_want_libs" = yes ]; then
    pc_all_libs=
    for pc_pkg in $pc_pkgs; do
	LIBS=""
	for pc_dir in $pc_path; do
	    if [ -f "${pc_dir}/${pc_pkg}.pc" ]; then
		. ${pc_dir}/${pc_pkg}.pc
		break
	    fi
	done
	pc_all_libs="$pc_all_libs $LIBS"
    done
    # clean up duplicate flags.  Discard all but last occurence of -l* flags,
    # and all but first occurence of other flags
    set - $pc_all_libs
    pc_libs=
    while [ $# -ne 0 ]; do
	pc_lib=$1   # iterate over $1 ...
	shift
	case "$pc_lib" in
	    -l*)
		case " $* " in  #if multiple occurences, discard all but first
		    *\ $pc_lib\ *) ;;
		    *) pc_libs="$pc_libs $pc_lib" ;;
		esac ;;
	    *)
		case " $pc_libs " in # keep first occurence of other flags
		    *\ $pc_lib\ *) ;;
		    *) pc_libs="$pc_libs $pc_lib" ;;
		esac ;;
	esac
    done
    echo $pc_libs
fi

# list the expanded list of packages if asked for ...
if [ "$pc_want_expand" = yes ]; then
    echo $pc_pkgs
fi

exit 0




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]