diff options
author | Martin Mares <mj@ucw.cz> | 2022-10-30 16:26:43 +0100 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 2022-10-30 16:26:43 +0100 |
commit | de53aa4fd7777a2602882bb7d4304e0b2ad6bc6f (patch) | |
tree | 57fb2a63be351b71bde8c4f73600adc3b99cee01 | |
parent | 637ad022fcc53da9ef84d11f9772bcb02c0d02ea (diff) | |
parent | 59cb656889fe77f062b7391160188b70bf60c7b2 (diff) | |
download | pciutils-de53aa4fd7777a2602882bb7d4304e0b2ad6bc6f.tar.gz |
Merge remote-tracking branch 'pali/win32-dll'
-rw-r--r-- | Makefile | 72 | ||||
-rw-r--r-- | lib/Makefile | 26 | ||||
-rwxr-xr-x | lib/configure | 20 | ||||
-rw-r--r-- | lib/dllrsrc.rc.in | 35 | ||||
-rw-r--r-- | lib/filter.c | 4 | ||||
-rw-r--r-- | lib/internal.h | 17 | ||||
-rw-r--r-- | lib/libpci.ver | 7 | ||||
-rwxr-xr-x | lib/ver2def.pl | 47 |
8 files changed, 200 insertions, 28 deletions
@@ -29,7 +29,7 @@ HWDB= # ABI version suffix in the name of the shared library # (as we use proper symbol versioning, this seldom needs changing) -ABI_VERSION=.3 +ABI_VERSION=3 # Installation directories PREFIX=/usr/local @@ -53,6 +53,8 @@ CC=cc endif AR=$(CROSS_COMPILE)ar RANLIB=$(CROSS_COMPILE)ranlib +DLLTOOL=$(CROSS_COMPILE)dlltool +WINDRES=$(CROSS_COMPILE)windres # Base name of the library (overridden on NetBSD, which has its own libpci) LIBNAME=libpci @@ -64,9 +66,9 @@ PCIINC_INS=lib/config.h lib/header.h lib/pci.h lib/types.h export -all: lib/$(PCILIB) lspci$(EXEEXT) setpci$(EXEEXT) example$(EXEEXT) lspci.8 setpci.8 pcilib.7 pci.ids.5 update-pciids update-pciids.8 $(PCI_IDS) +all: lib/$(PCIIMPLIB) lspci$(EXEEXT) setpci$(EXEEXT) example$(EXEEXT) lspci.8 setpci.8 pcilib.7 pci.ids.5 update-pciids update-pciids.8 $(PCI_IDS) -lib/$(PCILIB): $(PCIINC) force +lib/$(PCIIMPLIB): $(PCIINC) force $(MAKE) -C lib all force: @@ -80,8 +82,8 @@ PCIINC+=compat/getopt.h COMMON+=compat/getopt.o endif -lspci$(EXEEXT): lspci.o ls-vpd.o ls-caps.o ls-caps-vendor.o ls-ecaps.o ls-kernel.o ls-tree.o ls-map.o $(COMMON) lib/$(PCILIB) -setpci$(EXEEXT): setpci.o $(COMMON) lib/$(PCILIB) +lspci$(EXEEXT): lspci.o ls-vpd.o ls-caps.o ls-caps-vendor.o ls-ecaps.o ls-kernel.o ls-tree.o ls-map.o $(COMMON) lib/$(PCIIMPLIB) +setpci$(EXEEXT): setpci.o $(COMMON) lib/$(PCIIMPLIB) LSPCIINC=lspci.h pciutils.h $(PCIINC) lspci.o: lspci.c $(LSPCIINC) @@ -100,11 +102,11 @@ lspci$(EXEEXT): LDLIBS+=$(LIBKMOD_LIBS) ls-kernel.o: CFLAGS+=$(LIBKMOD_CFLAGS) update-pciids: update-pciids.sh - sed <$< >$@ "s@^DEST=.*@DEST=$(IDSDIR)/$(PCI_IDS)@;s@^PCI_COMPRESSED_IDS=.*@PCI_COMPRESSED_IDS=$(PCI_COMPRESSED_IDS)@" + sed <$< >$@ "s@^DEST=.*@DEST=$(if $(IDSDIR),$(IDSDIR)/,)$(PCI_IDS)@;s@^PCI_COMPRESSED_IDS=.*@PCI_COMPRESSED_IDS=$(PCI_COMPRESSED_IDS)@" chmod +x $@ # The example of use of libpci -example$(EXEEXT): example.o lib/$(PCILIB) +example$(EXEEXT): example.o lib/$(PCIIMPLIB) example.o: example.c $(PCIINC) %$(EXEEXT): %.o @@ -123,26 +125,30 @@ TAGS: clean: rm -f `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core -o -name "*.orig"` - rm -f update-pciids lspci$(EXEEXT) setpci$(EXEEXT) example$(EXEEXT) lib/config.* *.[578] pci.ids.gz lib/*.pc lib/*.so lib/*.so.* tags + rm -f update-pciids lspci$(EXEEXT) setpci$(EXEEXT) example$(EXEEXT) lib/config.* *.[578] pci.ids.gz lib/*.pc lib/*.so lib/*.so.* lib/*.dll lib/*.def lib/dllrsrc.rc tags rm -rf maint/dist distclean: clean install: all # -c is ignored on Linux, but required on FreeBSD - $(DIRINSTALL) -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(IDSDIR) $(DESTDIR)$(MANDIR)/man8 $(DESTDIR)$(MANDIR)/man7 $(DESTDIR)/$(MANDIR)/man5 + $(DIRINSTALL) -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(IDSDIR) $(DESTDIR)$(MANDIR)/man8 $(DESTDIR)$(MANDIR)/man7 $(DESTDIR)$(MANDIR)/man5 $(INSTALL) -c -m 755 $(STRIP) lspci$(EXEEXT) $(DESTDIR)$(LSPCIDIR) $(INSTALL) -c -m 755 $(STRIP) setpci$(EXEEXT) $(DESTDIR)$(SBINDIR) $(INSTALL) -c -m 755 update-pciids $(DESTDIR)$(SBINDIR) +ifneq ($(IDSDIR),) $(INSTALL) -c -m 644 $(PCI_IDS) $(DESTDIR)$(IDSDIR) +else + $(INSTALL) -c -m 644 $(PCI_IDS) $(DESTDIR)$(SBINDIR) +endif $(INSTALL) -c -m 644 lspci.8 setpci.8 update-pciids.8 $(DESTDIR)$(MANDIR)/man8 $(INSTALL) -c -m 644 pcilib.7 $(DESTDIR)$(MANDIR)/man7 $(INSTALL) -c -m 644 pci.ids.5 $(DESTDIR)$(MANDIR)/man5 ifeq ($(SHARED),yes) ifeq ($(LIBEXT),dylib) - ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME)$(ABI_VERSION).$(LIBEXT) -else - ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT)$(ABI_VERSION) + ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(ABI_VERSION).$(LIBEXT) +else ifeq ($(LIBEXT),so) + ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT).$(ABI_VERSION) endif endif @@ -152,37 +158,65 @@ endif install-pcilib: lib/$(PCILIB) $(DIRINSTALL) -m 755 $(DESTDIR)$(LIBDIR) +ifeq ($(SHARED)_$(LIBEXT),yes_dll) +# DLL library must have executable flag on disk and be placed in same directory as where are EXE files + $(DIRINSTALL) -m 755 $(DESTDIR)$(SBINDIR) + $(INSTALL) -c -m 755 lib/$(PCILIB) $(DESTDIR)$(SBINDIR) +else $(INSTALL) -c -m 644 lib/$(PCILIB) $(DESTDIR)$(LIBDIR) +endif install-lib: $(PCIINC_INS) install-pcilib $(DIRINSTALL) -m 755 $(DESTDIR)$(INCDIR)/pci $(DESTDIR)$(PKGCFDIR) $(INSTALL) -c -m 644 $(PCIINC_INS) $(DESTDIR)$(INCDIR)/pci $(INSTALL) -c -m 644 lib/$(PCILIBPC) $(DESTDIR)$(PKGCFDIR) +ifneq ($(PCIIMPLIB),$(PCILIB)) + $(INSTALL) -c -m 644 lib/$(PCIIMPLIB) $(DESTDIR)$(LIBDIR) +endif +ifneq ($(PCIIMPDEF),) + $(INSTALL) -c -m 644 lib/$(PCIIMPDEF) $(DESTDIR)$(LIBDIR) +endif ifeq ($(SHARED),yes) ifeq ($(LIBEXT),dylib) - ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME)$(ABI_VERSION).$(LIBEXT) - ln -sf $(LIBNAME)$(ABI_VERSION).$(LIBEXT) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT) -else - ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT)$(ABI_VERSION) - ln -sf $(LIBNAME).$(LIBEXT)$(ABI_VERSION) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT) + ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(ABI_VERSION).$(LIBEXT) + ln -sf $(LIBNAME).$(ABI_VERSION).$(LIBEXT) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT) +else ifeq ($(LIBEXT),so) + ln -sf $(PCILIB) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT).$(ABI_VERSION) + ln -sf $(LIBNAME).$(LIBEXT).$(ABI_VERSION) $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT) endif endif uninstall: all rm -f $(DESTDIR)$(SBINDIR)/lspci$(EXEEXT) $(DESTDIR)$(SBINDIR)/setpci$(EXEEXT) $(DESTDIR)$(SBINDIR)/update-pciids +ifneq ($(IDSDIR),) rm -f $(DESTDIR)$(IDSDIR)/$(PCI_IDS) +else + rm -f $(DESTDIR)$(SBINDIR)/$(PCI_IDS) +endif rm -f $(DESTDIR)$(MANDIR)/man8/lspci.8 $(DESTDIR)$(MANDIR)/man8/setpci.8 $(DESTDIR)$(MANDIR)/man8/update-pciids.8 rm -f $(DESTDIR)$(MANDIR)/man7/pcilib.7 rm -f $(DESTDIR)$(MANDIR)/man5/pci.ids.5 +ifeq ($(SHARED)_$(LIBEXT),yes_dll) + rm -f $(DESTDIR)$(SBINDIR)/$(PCILIB) +else rm -f $(DESTDIR)$(LIBDIR)/$(PCILIB) +endif rm -f $(DESTDIR)$(PKGCFDIR)/$(PCILIBPC) rm -f $(addprefix $(DESTDIR)$(INCDIR)/pci/,$(notdir $(PCIINC_INS))) +ifneq ($(PCIIMPLIB),$(PCILIB)) + rm -f $(DESTDIR)$(LIBDIR)/$(PCIIMPLIB) +endif +ifneq ($(PCIIMPDEF),) + rm -f $(DESTDIR)$(LIBDIR)/$(PCIIMPDEF) +endif ifeq ($(SHARED),yes) +ifneq ($(LIBEXT),dll) rm -f $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT) ifeq ($(LIBEXT),dylib) - rm -f $(DESTDIR)$(LIBDIR)/$(LIBNAME)$(ABI_VERSION).$(LIBEXT) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(ABI_VERSION).$(LIBEXT) else - rm -f $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT)$(ABI_VERSION) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBNAME).$(LIBEXT).$(ABI_VERSION) +endif endif endif diff --git a/lib/Makefile b/lib/Makefile index 400c32d..13c2a19 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -71,13 +71,29 @@ $(PCILIB): $(addsuffix .o,$(OBJS)) $(AR) rcs $@ $^ $(RANLIB) $@ else +ifeq ($(LIBEXT),dll) +all: $(PCIIMPDEF) $(PCIIMPLIB) +build.def: $(PCIIMPDEF) +$(PCIIMPDEF): libpci.ver ver2def.pl + perl ver2def.pl libpci.ver $(PCILIB) build.def $(PCIIMPDEF) +$(PCIIMPLIB): $(PCIIMPDEF) + $(DLLTOOL) --input-def $< --output-lib $@ +comma := , +dllrsrc.rc: dllrsrc.rc.in + sed <$< >$@ -e 's,@PCILIB_VERSION@,$(PCILIB_VERSION),' \ + -e 's,@PCILIB_VERSION_WINRC@,$(subst .,\$(comma),$(PCILIB_VERSION).0),' \ + -e 's,@PCILIB@,$(PCILIB),' \ + -e 's,@DEBUG_BUILD@,$(if $(findstring -g,$(CFLAGS)),1,0),' +dllrsrc.o: dllrsrc.rc + $(WINDRES) --input=$< --output=$@ --input-format=rc --output-format=coff +OBJS += dllrsrc +endif CFLAGS += -fPIC -fvisibility=hidden $(PCILIB): $(addsuffix .o,$(OBJS)) - ifdef PCI_HAVE_PM_DARWIN_DEVICE - $(CC) -shared $(LDFLAGS) $(SONAME) -Wl,-install_name,$(LIBDIR)/$(PCILIB) -o $@ $^ $(LIB_LDLIBS) - else - $(CC) -shared $(LDFLAGS) $(SONAME) -Wl,--version-script=libpci.ver -o $@ $^ $(LIB_LDLIBS) - endif + $(CC) -shared $(CFLAGS) $(LDFLAGS) $(PCILIB_LDFLAGS) -o $@ $^ $(LIB_LDLIBS) +ifeq ($(LIBEXT),dll) +$(PCILIB): build.def +endif endif $(PCILIBPC): libpci.pc.in diff --git a/lib/configure b/lib/configure index 7585bfe..f5c2c0d 100755 --- a/lib/configure +++ b/lib/configure @@ -166,6 +166,7 @@ case $sys in fi ;; esac EXEEXT=.exe + LIBEXT=dll ;; beos|haiku) case $cpu in @@ -291,6 +292,8 @@ if [ "$SHARED" = no ] ; then else if [ "$LIBEXT" = so ]; then echo >>$m 'PCILIB=$(LIBNAME).$(LIBEXT).$(VERSION)' + elif [ "$LIBEXT" = dll ]; then + echo >>$m 'PCILIB=$(LIBNAME)$(ABI_VERSION).$(LIBEXT)' else echo >>$m 'PCILIB=$(LIBNAME).$(VERSION).$(LIBEXT)' fi @@ -298,11 +301,24 @@ else echo >>$m 'LDLIBS=' echo >>$m 'LIB_LDLIBS=$(WITH_LIBS)' echo >>$c '#define PCI_SHARED_LIB' - if [ "$SHARED" = yes -a "$LIBEXT" = so ]; then - echo >>$m 'SONAME=-Wl,-soname,$(LIBNAME).$(LIBEXT)$(ABI_VERSION)' + if [ "$LIBEXT" = so ]; then + echo >>$m 'PCILIB_LDFLAGS+=-Wl,-soname,$(LIBNAME).$(LIBEXT).$(ABI_VERSION)' + echo >>$m 'PCILIB_LDFLAGS+=-Wl,--version-script=libpci.ver' + elif [ "$LIBEXT" = dylib ]; then + echo >>$m 'PCILIB_LDFLAGS+=-Wl,-install_name,$(LIBDIR)/$(PCILIB)' + elif [ "$LIBEXT" = dll ]; then + echo >>$m 'PCIIMPDEF=$(LIBNAME)$(ABI_VERSION).def' + # GCC's -fvisibility=hidden is broken for Windows targets, use -Wl,--exclude-all-symbols instead (supported since GNU LD 2.21) + echo >>$m 'PCILIB_LDFLAGS+=-Wl,--exclude-all-symbols' fi fi echo >>$m 'PCILIBPC=$(LIBNAME).pc' +if [ "$SHARED" != no ] && [ "$LIBEXT" = dll ]; then + echo >>$m 'PCIIMPLIB=$(PCILIB).a' +else + echo >>$m 'PCIIMPLIB=$(PCILIB)' +fi + echo >>$c "#define PCILIB_VERSION \"$VERSION\"" sed '/"/{s/^#define \([^ ]*\) "\(.*\)"$/\1=\2/;p;d;};s/^#define \(.*\)/\1=1/' <$c >>$m diff --git a/lib/dllrsrc.rc.in b/lib/dllrsrc.rc.in new file mode 100644 index 0000000..519772b --- /dev/null +++ b/lib/dllrsrc.rc.in @@ -0,0 +1,35 @@ +#include <windows.h> +VS_VERSION_INFO VERSIONINFO +FILEVERSION @PCILIB_VERSION_WINRC@ +PRODUCTVERSION @PCILIB_VERSION_WINRC@ +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#if @DEBUG_BUILD@ +FILEFLAGS VS_FF_DEBUG +#else +FILEFLAGS 0 +#endif +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + /* + * GNU windres seems that converts 7-bit ASCII strings to UTF-16, + * so specify UNICODE/UTF-16 encoding (0x04B0) for these strings. + */ + BLOCK "040904B0" /* Default U.S. English language, UNICODE/UTF-16 codepage */ + BEGIN + VALUE "FileDescription", "libpci" + VALUE "FileVersion", "@PCILIB_VERSION@" + VALUE "InternalName", "@PCILIB@" + VALUE "OriginalFilename", "@PCILIB@" + VALUE "ProductName", "pciutils" + VALUE "ProductVersion", "@PCILIB_VERSION@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x004B0 /* Default U.S. English language, UNICODE/UTF-16 codepage */ + END +END diff --git a/lib/filter.c b/lib/filter.c index d025a96..7038451 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -204,13 +204,13 @@ pci_filter_match_v38(struct pci_filter *f, struct pci_dev *d) } if (f->device_class >= 0) { - pci_fill_info(d, PCI_FILL_CLASS); + pci_fill_info_v38(d, PCI_FILL_CLASS); if ((f->device_class ^ d->device_class) & f->device_class_mask) return 0; } if (f->prog_if >= 0) { - pci_fill_info(d, PCI_FILL_CLASS_EXT); + pci_fill_info_v38(d, PCI_FILL_CLASS_EXT); if (f->prog_if != d->prog_if) return 0; } diff --git a/lib/internal.h b/lib/internal.h index 0a5dce4..11cf5a6 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -21,8 +21,15 @@ #else #define STATIC_ALIAS(_decl, _for) #define DEFINE_ALIAS(_decl, _for) extern _decl __attribute__((alias(#_for))) +#ifdef _WIN32 +/* GCC does not support asm .symver directive for Windows targets, so define new external global function symbol as alias to internal symbol */ +#define SYMBOL_VERSION(_int, _ext) asm(".globl\t" PCI_STRINGIFY(__MINGW_USYMBOL(_ext)) "\n\t" \ + ".def\t" PCI_STRINGIFY(__MINGW_USYMBOL(_ext)) ";\t.scl\t2;\t.type\t32;\t.endef\n\t" \ + ".set\t" PCI_STRINGIFY(__MINGW_USYMBOL(_ext)) "," PCI_STRINGIFY(__MINGW_USYMBOL(_int))) +#else #define SYMBOL_VERSION(_int, _ext) asm(".symver " #_int "," #_ext) #endif +#endif #else #define VERSIONED_ABI #define STATIC_ALIAS(_decl, _for) _decl { return _for; } @@ -33,6 +40,16 @@ #include "pci.h" #include "sysdep.h" +/* Old 32-bit-only versions of MinGW32 do not define __MINGW_USYMBOL macro */ +#ifdef __MINGW32__ +#ifndef __MINGW_USYMBOL +#define __MINGW_USYMBOL(sym) _##sym +#endif +#endif + +#define _PCI_STRINGIFY(x) #x +#define PCI_STRINGIFY(x) _PCI_STRINGIFY(x) + struct pci_methods { char *name; char *help; diff --git a/lib/libpci.ver b/lib/libpci.ver index bd5ae23..33ee024 100644 --- a/lib/libpci.ver +++ b/lib/libpci.ver @@ -4,6 +4,13 @@ * Visibility declarations in the source take precedence over this script, * so we can boldly declare pci_* as public and still keep the internal * functions properly hidden. + * + * To preserve compatibility of Windows DLL file, always add new symbol at + * the end of file and never change order of symbols nor version sections. + * On Windows the last referenced version of the symbol is the default one. + + * For PE/COFF targets this file is processed by ver2def.pl script and not + * by GNU LD linker like for ELF targets. */ LIBPCI_3.0 { diff --git a/lib/ver2def.pl b/lib/ver2def.pl new file mode 100755 index 0000000..18231bc --- /dev/null +++ b/lib/ver2def.pl @@ -0,0 +1,47 @@ +#!/usr/bin/perl +use strict; +use warnings; +die "Usage: $0 script.ver dllname build.def import.def\n" if @ARGV != 4; +my ($verfile, $dllname, $builddef, $importdef) = @ARGV; +open my $verfh, '<', $verfile or die "Cannot open input file $verfile: $!\n"; +my $input = join '', <$verfh>; +close $verfh; +my @syms; +my (%cnt, %last, %ords); +$input =~ s/\/\*.*?\*\///sg; # Remove C comments +while ($input =~ m/(\S+)\s*\{((?:[^\{\}]|\{(?2)\})+)\}\s*;/sg) { # Split {...} + my ($ver, $block) = ($1, $2); + while ($block =~ s/(\S+)\s*:((?:[^\{\}:]|\{(?2)\})+)$//sg) { # Split section: + my ($section, $syms) = ($1, $2); + next if $section ne 'global'; + $syms =~ s/\s+//g; + foreach (split /;\s*/, $syms) { # Split symbols + $cnt{$_}++; + $last{$_} = $ver; + push @syms, [$_, $ver]; + } + } +} +open my $importfh, '>', $importdef or die "Cannot open output file $importdef: $!\n"; +open my $buildfh, '>', $builddef or die "Cannot open output file $builddef: $!\n"; +print $importfh "LIBRARY \"$dllname\"\n"; +print $importfh "EXPORTS\n"; +print $buildfh "EXPORTS\n"; +my $ord = 1; +foreach (@syms) { + my ($sym, $ver) = @{$_}; + print $importfh "\"$sym\@$ver\" \@$ord\n"; + if ($last{$sym} ne $ver) { + print $buildfh "\"$sym\@$ver\" \@$ord\n"; + } else { + $ords{$sym} = $ord; + print $buildfh "\"$sym\@$ver\" = " . (($cnt{$sym} > 1) ? "\"$sym\@\@$ver\"" : $sym) . " \@$ord\n" + } + $ord++; +} +# GNU dlltool has broken calculation of ordinals for aliased symbols, so specify ordinals explicitly +# GNU LD prior 2.21 has broken handling of symbols with dot character +# Operator == for defining symbol alias is supported since GNU dlltool 2.21 +print $importfh "$_ \@$ords{$_} == \"$_\@$last{$_}\"\n" foreach sort keys %last; +close $importfh; +close $buildfh; |