27.04.2015 13:37, Paolo Bonzini пишет:
> 
> 
> On 27/04/2015 11:44, Michael Tokarev wrote:
>> Currently we link individual object files from libcacard
>> to qemu-system binaries, this way (from Makefile.objs):
>>
>> libcacard-y += libcacard/cac.o libcacard/event.o
>> libcacard-y += libcacard/vcard.o libcacard/vreader.o
>> ...
>> common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
>>
>> Why can't we use the actual library, and just add the
>> linker flag, -Ilibcacard -lcacard?
> 
> Because that would require people to use "libtool --mode=execute gdb" to
> debug qemu.  This is not a problem for me, but I know that some people
> on the list are allergic to the GNU build tools.
> 
> I would be okay for this, and I would also be okay with making libcacard
> standalone.  Making it standalone would also bypass the problem of
> verbose debugging command lines.  You've already done most of the work
> with your patches to stop using libqemuutil.a.  As a small step in that
> direction, I've sent a patch to remove use of qemu-common.h.
> 
> Somebody has to write some Autoconf/Automake and package it up, I guess.

Ok.  I wrote small configure script (just a simple shell script,
no auto*tools, since the configuration of it is stright-forward,
we just need to check libglib and libnss versions using pkg-config
and check if libtool works) and a small Makefile for libcacard.

Now the question is what to do with it?  How to make it external
and where to put it?  What to use for its version?  How to migrate
to its usage in qemu?

I propose to put it in a separate git repository on qemu project
site and remove it from qemu source, since it is definitely not a
hard requiriment to have smartcard support.  Or maybe we can keep
it for a release in qemu source, adding it as a submodule, with
a tweak to be able to use external lib instead of embedded copy
if external is available.

Thanks,

/mjt
#! /bin/sh

# defaults
cc=cc
cross_prefix=
shared=

prefix=/usr/local
exec_prefix='${prefix}'
bindir='${exec_prefix}/bin'
libdir='${exec_prefix}/lib'
includedir='${prefix}/include'

for opt in "$@"; do

  optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`

  case "$opt" in
  --cross-prefix=*) cross_prefix="$optarg" ;;
  --enable-shared) shared=yes ;;
  --disable-shared) shared=no ;;

  --prefix=*) prefix="$optarg" ;;
  --exec-prefix=*) exec_prefix="$optarg" ;;
  --libdir=*) libdir="$optarg" ;;
  --includedir=*) includedir="$optarg" ;;
  --libexecdir=*|\
  --mandir=*|\
  --datadir=*|\
  --docdir=*|\
  --sysconfdir=*|\
  --localstatedir=*|\
  --sbindir=*|\
  --sharedstatedir=*|\
  --oldincludedir=*|\
  --datarootdir=*|\
  --infodir=*|\
  --localedir=*|\
  --htmldir=*|\
  --dvidir=*|\
  --pdfdir=*|\
  --psdir=*)
    ;; # These autoconf switches are silently ignored
  --help)
    cat <<EOF
Usage: ./configure [options]
Options (defaults shown in brackets):
 --help                 print this help and exit
 --cross-prefix=PFX     use PFX for compile tools
 --prefix=PFX           install data in PFX [$prefix]
 --exec-prefix=EPFX     install binaries in EPFX [$exec_prefix]
 --bindir=BINDIR        install binaries in BINDIR [$bindir]
 --libdir=LIBDIR        install libraries in LIBDIR [$libdir]
 --includedir=INCDIR    install includesin INCDIR [$includedir]
 --disable-shared, --enable-shared
                        disable or enable shared library build
                        (a working libtool is needed for shared)
Environment variables:
 CC, CFLAGS     the C compiler [$cc]
 LD, LDFLAGS    linker [\$CC]
 PKG_CONFIG     pkg-config
 LIBTOOL        libtool
 AR             ar (the archiver)
EOF
    exit 0;;

  *) echo "E: unknown option \`$opt'" >&2; exit 1 ;;
  esac

done

# Preferred compiler
if [ -z "${CC}${cross_prefix}" ]; then
  CC="$cc"
else
  : ${CC:-${cross_prefix}gcc}
fi
: ${LD:='${CC}'}
: ${LIBTOOL:=${cross_prefix}libtool}
: ${PKG_CONFIG:=${cross_prefix}pkg-config}

cleanup() {
  rm -f conftest.* libconftest.la
}
cleanup
rm -f config.log
exec 3>config.log

error() {
  echo "E: $*" >&2
  echo "E: $*" >&3
  cleanup
  exit 1
}
warning() {
  echo "W: $*" >&2
  echo "W: $*" >&3
}

has() {
  type "$1" >/dev/null 2>&1
}

pkg_config() {
  # Run pkg-config, capturing its output to the log
  echo "== running: $PKG_CONFIG $@" >&3
  $PKG_CONFIG "$@" >&3 2>&1
}

if ! has $PKG_CONFIG ; then
  error "pkg-config binary $PKG_CONFIG not found"
fi

glib=glib-2.0
min_glib_ver=2.22
if ! pkg_config --atleast-version=$min_glib_ver $glib ; then
  error "required glib-$min_glib_ver not found"
fi
GLIB_CFLAGS=`$PKG_CONFIG --cflags $glib`
GLIB_LIBS=`$PKG_CONFIG --libs $glib`

# check for smartcard support
if ! pkg_config --atleast-version=3.12.8 nss ; then
  error "NSS package not found"
fi
NSS_CFLAGS=`$PKG_CONFIG --cflags nss`
NSS_LIBS=`$PKG_CONFIG --libs nss`

do_libtool() {
  tmp=$1; shift
  # Run the compiler under libtool, capturing its output to the log.
  echo "$LIBTOOL $tmp --tag=CC $CC $@" >&3
  $LIBTOOL $tmp --tag=CC $CC "$@" >&3 2>&1
}

if [ "$shared" = no ]; then
  LIBTOOL=
else
  cat > conftest.c <<EOF
void *f(unsigned char *buf, int len);
void *g(unsigned char *buf, int len);
void *f(unsigned char *buf, int len) { return (void*)0L; }
void *g(unsigned char *buf, int len) { return f(buf, len); }
EOF
  if do_libtool --mode=compile $CFLAGS -c -fPIE -DPIE -o conftest.lo conftest.c 
&& \
     do_libtool --mode=link $LDFLAGS -o libconftest.la conftest.lo
  then
    :
  elif [ "$shared" = yes ]; then
     error "libtool can not be used, can not build shared libraries"
  else
    warning "disabling shared library support, no working libtool found"
    LIBTOOL=
  fi
fi

cleanup

cat >Makefile.tmp - Makefile.in <<EOF || exit 1
# Makefile for libcacard
# @configure_output@

prefix = $prefix
exec_prefix = $exec_prefix
bindir = $bindir
libdir = $libdir
includedir = $includedir

CC = $CC
CFLAGS = $CFLAGS
LD = $LD
LDFLAGS = $LDFLAGS
LIBTOOL = $LIBTOOL
AR = ${AR:-${cross_prefix}ar}
RANLIB = ${RANLIB:-${cross_prefix}ranlib}

INSTALL = install
SED = sed

GLIB_CFLAGS = $GLIB_CFLAGS
GLIB_LIBS = $GLIB_LIBS
NSS_CFLAGS = $NSS_CFLAGS
NSS_LIBS = $NSS_LIBS

# end configuration section
EOF

mv Makefile.tmp Makefile
/*
 * GLIB Compatibility Functions
 *
 * Copyright IBM, Corp. 2013
 *
 * Authors:
 *  Anthony Liguori   <aligu...@us.ibm.com>
 *  Michael Tokarev   <m...@tls.msk.ru>
 *  Paolo Bonzini     <pbonz...@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

#ifndef QEMU_GLIB_COMPAT_H
#define QEMU_GLIB_COMPAT_H

#include <glib.h>

#if !GLIB_CHECK_VERSION(2, 31, 0)
/* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate
 * GStaticMutex, but it didn't work with condition variables).
 *
 * Our implementation uses GOnce to fake a static implementation that does
 * not require separate initialization.
 * We need to rename the types to avoid passing our CompatGMutex/CompatGCond
 * by mistake to a function that expects GMutex/GCond.  However, for ease
 * of use we keep the GLib function names.  GLib uses macros for the
 * implementation, we use inline functions instead and undefine the macros.
 */

typedef struct CompatGMutex {
    GOnce once;
} CompatGMutex;

typedef struct CompatGCond {
    GOnce once;
} CompatGCond;

static inline gpointer do_g_mutex_new(gpointer unused)
{
    return (gpointer) g_mutex_new();
}

static inline void g_mutex_init(CompatGMutex *mutex)
{
    mutex->once = (GOnce) G_ONCE_INIT;
}

static inline void g_mutex_clear(CompatGMutex *mutex)
{
    g_assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
    if (mutex->once.retval) {
        g_mutex_free((GMutex *) mutex->once.retval);
    }
    mutex->once = (GOnce) G_ONCE_INIT;
}

static inline void (g_mutex_lock)(CompatGMutex *mutex)
{
    g_once(&mutex->once, do_g_mutex_new, NULL);
    g_mutex_lock((GMutex *) mutex->once.retval);
}
#undef g_mutex_lock

static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex)
{
    g_once(&mutex->once, do_g_mutex_new, NULL);
    return g_mutex_trylock((GMutex *) mutex->once.retval);
}
#undef g_mutex_trylock


static inline void (g_mutex_unlock)(CompatGMutex *mutex)
{
    g_mutex_unlock((GMutex *) mutex->once.retval);
}
#undef g_mutex_unlock

static inline gpointer do_g_cond_new(gpointer unused)
{
    return (gpointer) g_cond_new();
}

static inline void g_cond_init(CompatGCond *cond)
{
    cond->once = (GOnce) G_ONCE_INIT;
}

static inline void g_cond_clear(CompatGCond *cond)
{
    g_assert(cond->once.status != G_ONCE_STATUS_PROGRESS);
    if (cond->once.retval) {
        g_cond_free((GCond *) cond->once.retval);
    }
    cond->once = (GOnce) G_ONCE_INIT;
}

static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex)
{
    g_assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
    g_once(&cond->once, do_g_cond_new, NULL);
    g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval);
}
#undef g_cond_wait

static inline void (g_cond_broadcast)(CompatGCond *cond)
{
    g_once(&cond->once, do_g_cond_new, NULL);
    g_cond_broadcast((GCond *) cond->once.retval);
}
#undef g_cond_broadcast

static inline void (g_cond_signal)(CompatGCond *cond)
{
    g_once(&cond->once, do_g_cond_new, NULL);
    g_cond_signal((GCond *) cond->once.retval);
}
#undef g_cond_signal


/* before 2.31 there was no g_thread_new() */
static inline GThread *g_thread_new(const char *name,
                                    GThreadFunc func, gpointer data)
{
    GThread *thread = g_thread_create(func, data, TRUE, NULL);
    if (!thread) {
        g_error("creating thread");
    }
    return thread;
}
#else
#define CompatGMutex GMutex
#define CompatGCond GCond
#endif /* glib 2.31 */

#endif
# Makefile for libcacard

libcacard_includedir = ${includedir}/cacard

libcacard_SRCS = cac.c event.c vcard.c vreader.c \
 vcard_emul_nss.c vcard_emul_type.c card_7816.c \
 vcardt.c

all: vscclient

.SUFFIXES:
.SUFFIXES: .c .o .lo

COMPILE := ${CC} ${CFLAGS} ${GLIB_CFLAGS} ${NSS_CFLAGS}
LINK := ${LD} ${LDFLAGS}

.c.o:
        ${COMPILE} -c -o $@ $<

ifneq (${LIBTOOL},)
# shared library build
LT := ${LIBTOOL} --tag=CC

.c.lo:
        ${LT} --mode=compile ${COMPILE} -c -o $@ $<

LTA := la
libcacard.la: ${libcacard_SRCS:.c=.lo}
        ${LT} --mode=link ${LINK} -rpath ${libdir} -export-symbols 
libcacard.syms -o $@ $^ ${GLIB_LIBS} ${NSS_LIBS}
vscclient: vscclient.o libcacard.la
        ${LT} --mode=link ${LINK} -o $@ vscclient.o libcacard.la ${GLIB_LIBS}
LT_INSTALL := ${LT} --mode=install ${INSTALL}

else
# static build

LTA := a
libcacard.a: ${libcacard_SRCS:.c=.o}
        ${AR} rv $@ $^
        ${RANLIB} $@
vscclient: vscclient.o libcacard.a
        ${LINK} -o $@ vscclient.o -L. -lcacard ${GLIB_LIBS} ${NSS_LIBS}
LT_INSTALL := ${INSTALL}

endif

install: libcacard.${LTA} vscclient
        mkdir -p '${DESTDIR}${libdir}' '${DESTDIR}${libdir}/pkgconfig' 
'${DESTDIR}${libcacard_includedir}' '${DESTDIR}${bindir}'
        ${LT_INSTALL} libcacard.${LTA} '${DESTDIR}${libdir}'
        ${LT_INSTALL} vscclient '${DESTDIR}${bindir}/vscclient'
        ${SED} \
         -e 's|@LIBDIR@|${libdir}|' \
         -e 's|@INCLUDEDIR@|${libcacard_includedir}|' \
         -e 's|@VERSION@|${VERSION}|' \
         -e 's|@PREFIX@|${prefix}|' \
         libcacard.pc.in > '${DESTDIR}${libdir}/pkgconfig'/libcacard.pc

clean:
        rm -f *.o *.lo libcacard.a libcacard.la vscclient config.log
        rm -rf .libs
distclean: clean
        rm -f Makefile

Reply via email to