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