portable shared libraries

Giorgos Keramidas keramida at ceid.upatras.gr
Tue Nov 9 17:10:56 EET 2010


On Tue, 09 Nov 2010 16:35:20 +0200, Antonis Christofides <anthony at itia.ntua.gr> wrote:
> Κάνω τα πρώτα μου βήματα σε autoconf/automake/libtool προσπαθώντας να
> φτιάξω ένα C shared library που να τρέχει και σε linux και σε windows.
> Σε Windows χρησιμοποιώ MinGW+MSYS. Είμαι σε καλό δρόμο, αλλά έχω
> ορισμένα προβληματάκια:
>
> 1. Δεν μου τρέχει σε Windows. Νομίζω ότι μπερδεύει αυτά τα cdecl,
> stdcall κλπ.
>
> 2. Το Makefile.am περιέχει τη γραμμή "lib_LTLIBRARIES =
> libdickinson.la". Ενώ όμως το όνομα libdickinson.so που προκύπτει
> είναι πράγματι αυτό που θέλω για το linux, εντούτοις σε Windows θα
> ήθελα dickinson.dll.
>
> 3. Χρησιμοποιώ την strdup, που υπάρχει σε linux αλλά δεν υπάρχει σε
> Windows. Αν βάλω τη δικιά μου υλοποίηση μέσα σε κάποιο source file,
> τότε χτυπάει ο compiler όταν κομπιλάρω σε linux.
>
> 4. make install δουλεύει σε linux, αλλά δεν έχω καταλάβει τι κάνει σε
> windows. Βάζει τα αρχεία στο "/usr/local/lib", που είναι κάποια
> directory του msys.
>
> Υπάρχει κάποιος τρόπος να τα αντιμετωπίσω αυτά, ή τα windows δεν
> πολυπαίζουν με autoconf; Και τι ενδείκνυται; Να χρησιμοποιήσω autoconf
> για τα γιουνιξοειδή και κάποια χακιά στα windows;

Το mingw δεν είναι ακριβώς "windows" περιβάλλον.  Γι αυτό και έχεις τα
εξής προβλήματα:

  * Οι βιβλιοθήκες σου χρησιμοποιούν τον UNIX-specific τρόπο
    ονοματολογίας (συγκεκριμένα, η default τιμή του LT_MODULE_EXT macro
    είναι "so" κι όχι "dll").

  * Το default installation prefix είναι ορισμένο ως "/usr/local" και
    από αυτό ορίζονται τα $(bindir), $(datadir) ... κι όλα τα άλλα
    "Installation Directory Variables" από το manual του autoconf.

Γι αυτό το πρόβλημα δε μπορώ να σε βοηθήσω, γιατί δεν έχω ασχοληθεί ποτέ
με DLL-based development σε Windows.

Για το πρόβλημα συμβατότητας με την strdup() μπορείς να κάνεις αυτό που
έκανα εγώ σε παλιότερα autotools-based projects: να φτιάξεις μια δική
σου *static* library με όνομα libcompat.la η οποία θα παρέχει όσες
"compatibility" υλοποιήσεις χρειάζεσαι από ότι σου λείπει.

Στο configure.ac σου μπορείς να ελέγξεις αν υπάρχει η strdup() στο
σύστημα π.χ. με:

    AC_CHECK_FUNCTIONS([strdup])

Στο υπόλοιπο project μπορείς να προσθέσεις μια "libcompat" library, ως
κεντρικό μέρος από library functions που χρειάζεσαι αλλά μπορεί για τον
ένα ή τον άλλο λόγο να μην είναι διαθέσιμες στο build ή target host.

Στο Makefile.am της libcompat.la μπορείς να προσθέσεις ένα header file
που δε στήνεται κατά τη διάρκεια του "make install" με:

    ## libcompat/Makefile.am contents:

    HDRS =       libcompat.h \
                 compat/strdup.h
    SRCS =       strdup.c

    noinst_HEADERS =     $(HDRS)

    noinst_LT_LIBRARIES = libcompat.la

    libcompat_la_SOURCES = $(SRCS) $(HDRS)
    libcompat_la_LDFLAGS = -static

Η σημαντική επιλογή εδώ είναι:

  * Το -static libtool option, για να γίνεται statically link κάθε
    symbol σε όποιο μέρος του υπόλοιπου project χρησιμοποιεί την
    libcompat.la library)

  * Το noinst_ prefix στα variables που ορίζουν header files και
    sources, για να μη στήνονται τα "compatibility hacks" ως μέρος από
    το τελικό "προϊόν" στο $prefix directory.

Στο ίδιο το libcompat.h header file μπορείς να έχεις κανόνες όπως:

    /* If the system doesn't have its own strdup() function provide our own. */
    #ifndef HAVE_STRDUP
    #include "compat/strdup.h"
    #endif

Στο function-specific libcompat/compat/strdup.h header file μπορείς να
έχεις κάτι σαν:

    #ifndef LIBCOMPAT_STRDUP_H_INCLUDED
    #define LIBCOMPAT_STRDUP_H_INCLUDED 1

    /* If the system doesn't have an strdup() function provide our own. */
    #ifndef HAVE_STRDUP
    extern char *strdup(const char *s);
    #endif  /* !HAVE_STRDUP */

    #endif  /* !LIBCOMPAT_STRDUP_H_INCLUDED */

Ακόμα και το ίδιο το source της strdup() μπορεί να είναι conditionally
empty με βάση την τιμή του HAVE_STRDUP στο αρχείο libcompat/strdup.c:

    /* If the system doesn't have an strdup() function provide our own. */
    #ifndef HAVE_STRDUP

    #include <stddef.h>
    #include <stdlib.h>
    #include <string.h>

    /*
     * Copied from FreeBSD 'src/lib/libc/string/strdup.c'.
     * The normal FreeBSD libc license terms apply; see
     * http://cvsweb.freebsd.org/src/lib/libc/string/strdup.c
     */
    char *
    strdup(const char *str)
    {
        size_t len;
        char *copy;

        len = strlen(str) + 1;
        if ((copy = malloc(len)) == NULL)
           return (NULL);
        memcpy(copy, str, len);
        return (copy);
    }

    #endif  /* !HAVE_STRDUP */

Με αυτό τον τρόπο μπορείς να έχεις μια "source-tree library" που δε
στήνεται στο $prefix directory, και (ανάλογα με τα checks που έγιναν από
το `configure' script σου) εξάγει σε όποιον κάνει link μαζί της ένα σετ
από stub functions που υλοποιούν ότι "λείπει" από το target σύστημα.



More information about the Linux-greek-users mailing list