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