Patchwork [RFC] Feature autodetection during compilation

login
register
about
Submitter Carl-Daniel Hailfinger
Date 2012-11-20 22:50:16
Message ID <50AC0928.5010000@gmx.net>
Download mbox | patch
Permalink /patch/3794/
State Superseded
Headers show

Comments

Carl-Daniel Hailfinger - 2012-11-20 22:50:16
Am 20.11.2012 12:44 schrieb Kyösti Mälkki:
> On Mon, 2012-11-19 at 01:15 +0100, Carl-Daniel Hailfinger wrote:
>> We enable programmer compilation based on the following criteria:
>> - Default off unless explicitly enabled (dediprog)
>> - Default on unless explicitly disabled (dummy)
>> - Default on if technically possible on target machine (linux_spi)
>> - Default on if the required libs+headers are available (ft2232_spi)
>>
>> The last criterion is what causes pains to no end, at least with the
>> current Makefile infrastructure. Yes, we (I) can maintain it, but in the
>> long run we either need a separate configure script (which may or may
>> not work in all envorinments where GNU make works, especially exotic
>> platforms like Windows), or we switch to something like CMake (which
>> doesn't have the required features in ancient versions AFAIK), or we use
>> two chained Makefiles (which would not meet my definition of "fun").
>> Now why is the last criterion such a PITA? All other criteria have a
>> hard fail/success test, i.e. if a required lib/header is missing, we
>> stop compilation. However, this criterion has a soft fail/success test,
>> i.e. if you enable a feature and the required libraries/headers are
>> missing, the feature simply will be silently disabled. That sort of
>> violates the principle of least surprise, and it's the reason why our
>> current Makefile uses nasty tricks with external files to avoid
>> reloading itself.
>>
>> I would like to switch ft2232_spi to "Default on if technically possible
>> on target machine" and spit out an improved error message in case the
>> headers are missing.
> I would say people don't have libftdi-dev installed by default. Moving
> ft2232_spi (and the not-yet merged usbblaster_spi) to that "default on
> if technically possible" -class would mean compile without extra options
> will fail on a platform for which libftdi is available. Did I understand
> this right?

Yes.


> Switching to default "off" would affect less users and IMO would be
> better choice if there is no easy fix. I don't quite see why the 4th
> option is so troublesome in the first place, but haven't studied the
> makefile that close. Maybe it does something backwards?

Yes, it does something backwards (it uses external helper files to avoid
re-running make or having a separate configure step), and I'm probably
the only developer left who dares change anything in the Makefile. If we
ever switch to an explicit "./configure" before running "make", quite a
lot of this stuff will be easier. However, writing a portable configure
script (which works even for cross-compilation and on Windows) is
something which is really hard, and nobody has ever tried.

Anyway, here is a first draft of what I'm trying to do (keep compilation
autodetection for library/environment quirks, but change libftdi
autodetection into a hard requirement with a good error message).
The test programs are unchanged, they just had to be moved around a bit.

Tested on current openSUSE Linux, needs tests pretty much everywhere
else (*BSD, Linux 2.4 (Debian Woody), Linux 2.6.18 or older (Debian
Etch), MinGW).

If you test on *BSD/DOS/MinGW, please try the following make invocation
besides standard make:
make CONFIG_INTERNAL=no CONFIG_SERPROG=no CONFIG_NIC3COM=no
CONFIG_GFXNVIDIA=no CONFIG_SATASII=no CONFIG_FT2232_SPI=no
CONFIG_DRKAISER=no CONFIG_NICREALTEK=no CONFIG_NICINTEL_SPI=no
CONFIG_OGP_SPI=no CONFIG_SATAMV=no CONFIG_NICINTEL=no CONFIG_PONY_SPI=no
CONFIG_LINUX_SPI=no CONFIG_BUSPIRATE_SPI=no CONFIG_RAYER_SPI=yes

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>

Patch

Index: flashrom-Makefile_harddependencies/hwaccess.h
===================================================================
--- flashrom-Makefile_harddependencies/hwaccess.h	(Revision 1623)
+++ flashrom-Makefile_harddependencies/hwaccess.h	(Arbeitskopie)
@@ -167,7 +167,7 @@ 
 #define le_to_cpu32 cpu_to_le32
 #define le_to_cpu64 cpu_to_le64
 
-#if NEED_PCI == 1
+#if (NEED_PCI == 1) || (NEED_IOPORT_ACCESS == 1)
 #if defined (__i386__) || defined (__x86_64__)
 
 #define __FLASHROM_HAVE_OUTB__ 1
Index: flashrom-Makefile_harddependencies/Makefile
===================================================================
--- flashrom-Makefile_harddependencies/Makefile	(Revision 1623)
+++ flashrom-Makefile_harddependencies/Makefile	(Arbeitskopie)
@@ -103,28 +103,28 @@ 
 LIBS += ../libgetopt/libgetopt.a
 # Bus Pirate, Serprog and PonyProg are not supported under DOS (missing serial support).
 ifeq ($(CONFIG_BUSPIRATE_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_BUSPIRATE_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_BUSPIRATE_SPI
 else
 override CONFIG_BUSPIRATE_SPI = no
 endif
 ifeq ($(CONFIG_SERPROG), yes)
-UNSUPPORTED_FEATURES += CONFIG_SERPROG=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_SERPROG
 else
 override CONFIG_SERPROG = no
 endif
 ifeq ($(CONFIG_PONY_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_PONY_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_PONY_SPI
 else
 override CONFIG_PONY_SPI = no
 endif
 # Dediprog and FT2232 are not supported under DOS (missing USB support).
 ifeq ($(CONFIG_DEDIPROG), yes)
-UNSUPPORTED_FEATURES += CONFIG_DEDIPROG=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_DEDIPROG
 else
 override CONFIG_DEDIPROG = no
 endif
 ifeq ($(CONFIG_FT2232_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_FT2232_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_FT2232_SPI
 else
 override CONFIG_FT2232_SPI = no
 endif
@@ -140,73 +140,73 @@ 
 LDFLAGS += -L/usr/local/lib
 # Serprog is not supported under Windows/MinGW (missing sockets support).
 ifeq ($(CONFIG_SERPROG), yes)
-UNSUPPORTED_FEATURES += CONFIG_SERPROG=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_SERPROG
 else
 override CONFIG_SERPROG = no
 endif
 # For now we disable all PCI-based programmers on Windows/MinGW (no libpci).
 ifeq ($(CONFIG_INTERNAL), yes)
-UNSUPPORTED_FEATURES += CONFIG_INTERNAL=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_INTERNAL
 else
 override CONFIG_INTERNAL = no
 endif
 ifeq ($(CONFIG_RAYER_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_RAYER_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_RAYER_SPI
 else
 override CONFIG_RAYER_SPI = no
 endif
 ifeq ($(CONFIG_NIC3COM), yes)
-UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NIC3COM
 else
 override CONFIG_NIC3COM = no
 endif
 ifeq ($(CONFIG_GFXNVIDIA), yes)
-UNSUPPORTED_FEATURES += CONFIG_GFXNVIDIA=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_GFXNVIDIA
 else
 override CONFIG_GFXNVIDIA = no
 endif
 ifeq ($(CONFIG_SATASII), yes)
-UNSUPPORTED_FEATURES += CONFIG_SATASII=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_SATASII
 else
 override CONFIG_SATASII = no
 endif
 ifeq ($(CONFIG_ATAHPT), yes)
-UNSUPPORTED_FEATURES += CONFIG_ATAHPT=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_ATAHPT
 else
 override CONFIG_ATAHPT = no
 endif
 ifeq ($(CONFIG_DRKAISER), yes)
-UNSUPPORTED_FEATURES += CONFIG_DRKAISER=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_DRKAISER
 else
 override CONFIG_DRKAISER = no
 endif
 ifeq ($(CONFIG_NICREALTEK), yes)
-UNSUPPORTED_FEATURES += CONFIG_NICREALTEK=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NICREALTEK
 else
 override CONFIG_NICREALTEK = no
 endif
 ifeq ($(CONFIG_NICNATSEMI), yes)
-UNSUPPORTED_FEATURES += CONFIG_NICNATSEMI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NICNATSEMI
 else
 override CONFIG_NICNATSEMI = no
 endif
 ifeq ($(CONFIG_NICINTEL), yes)
-UNSUPPORTED_FEATURES += CONFIG_NICINTEL=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NICINTEL
 else
 override CONFIG_NICINTEL = no
 endif
 ifeq ($(CONFIG_NICINTEL_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_NICINTEL_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NICINTEL_SPI
 else
 override CONFIG_NICINTEL_SPI = no
 endif
 ifeq ($(CONFIG_OGP_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_OGP_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_OGP_SPI
 else
 override CONFIG_OGP_SPI = no
 endif
 ifeq ($(CONFIG_SATAMV), yes)
-UNSUPPORTED_FEATURES += CONFIG_SATAMV=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_SATAMV
 else
 override CONFIG_SATAMV = no
 endif
@@ -215,28 +215,28 @@ 
 ifeq ($(TARGET_OS), libpayload)
 FLASHROM_CFLAGS += -DSTANDALONE
 ifeq ($(CONFIG_DUMMY), yes)
-UNSUPPORTED_FEATURES += CONFIG_DUMMY=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_DUMMY
 else
 override CONFIG_DUMMY = no
 endif
 ifeq ($(CONFIG_BUSPIRATE_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_BUSPIRATE_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_BUSPIRATE_SPI
 else
 override CONFIG_BUSPIRATE_SPI = no
 endif
 ifeq ($(CONFIG_SERPROG), yes)
-UNSUPPORTED_FEATURES += CONFIG_SERPROG=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_SERPROG
 else
 override CONFIG_SERPROG = no
 endif
 # Dediprog and FT2232 are not supported with libpayload (missing libusb support)
 ifeq ($(CONFIG_DEDIPROG), yes)
-UNSUPPORTED_FEATURES += CONFIG_DEDIPROG=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_DEDIPROG
 else
 override CONFIG_DEDIPROG = no
 endif
 ifeq ($(CONFIG_FT2232_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_FT2232_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_FT2232_SPI
 else
 override CONFIG_FT2232_SPI = no
 endif
@@ -244,7 +244,7 @@ 
 
 ifneq ($(TARGET_OS), Linux)
 ifeq ($(CONFIG_LINUX_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_LINUX_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_LINUX_SPI
 else
 override CONFIG_LINUX_SPI = no
 endif
@@ -260,32 +260,32 @@ 
 # Right now this means the drivers below only work on x86.
 ifneq ($(ARCH), x86)
 ifeq ($(CONFIG_NIC3COM), yes)
-UNSUPPORTED_FEATURES += CONFIG_NIC3COM=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NIC3COM
 else
 override CONFIG_NIC3COM = no
 endif
 ifeq ($(CONFIG_NICREALTEK), yes)
-UNSUPPORTED_FEATURES += CONFIG_NICREALTEK=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NICREALTEK
 else
 override CONFIG_NICREALTEK = no
 endif
 ifeq ($(CONFIG_NICNATSEMI), yes)
-UNSUPPORTED_FEATURES += CONFIG_NICNATSEMI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_NICNATSEMI
 else
 override CONFIG_NICNATSEMI = no
 endif
 ifeq ($(CONFIG_RAYER_SPI), yes)
-UNSUPPORTED_FEATURES += CONFIG_RAYER_SPI=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_RAYER_SPI
 else
 override CONFIG_RAYER_SPI = no
 endif
 ifeq ($(CONFIG_ATAHPT), yes)
-UNSUPPORTED_FEATURES += CONFIG_ATAHPT=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_ATAHPT
 else
 override CONFIG_ATAHPT = no
 endif
 ifeq ($(CONFIG_SATAMV), yes)
-UNSUPPORTED_FEATURES += CONFIG_SATAMV=yes
+UNSUPPORTED_TARGET_FEATURES += CONFIG_SATAMV
 else
 override CONFIG_SATAMV = no
 endif
@@ -421,27 +421,26 @@ 
 PROGRAMMER_OBJS += ichspi.o ich_descriptors.o
 else
 endif
-NEED_PCI := yes
+NEED_PCI += CONFIG_INTERNAL
 endif
 
 ifeq ($(CONFIG_SERPROG), yes)
 FEATURE_CFLAGS += -D'CONFIG_SERPROG=1'
 PROGRAMMER_OBJS += serprog.o
-NEED_SERIAL := yes
-NEED_NET := yes
+NEED_SERIAL += CONFIG_SERPROG
+NEED_NET += CONFIG_SERPROG
 endif
 
 ifeq ($(CONFIG_RAYER_SPI), yes)
 FEATURE_CFLAGS += -D'CONFIG_RAYER_SPI=1'
 PROGRAMMER_OBJS += rayer_spi.o
-# Actually, NEED_PCI is wrong. NEED_IOPORT_ACCESS would be more correct.
-NEED_PCI := yes
+NEED_IOPORT_ACCESS += CONFIG_RAYER_SPI
 endif
 
 ifeq ($(CONFIG_PONY_SPI), yes)
 FEATURE_CFLAGS += -D'CONFIG_PONY_SPI=1'
 PROGRAMMER_OBJS += pony_spi.o
-NEED_SERIAL := yes
+NEED_SERIAL += CONFIG_PONY_SPI
 endif
 
 ifeq ($(CONFIG_BITBANG_SPI), yes)
@@ -452,36 +451,32 @@ 
 ifeq ($(CONFIG_NIC3COM), yes)
 FEATURE_CFLAGS += -D'CONFIG_NIC3COM=1'
 PROGRAMMER_OBJS += nic3com.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_NIC3COM
 endif
 
 ifeq ($(CONFIG_GFXNVIDIA), yes)
 FEATURE_CFLAGS += -D'CONFIG_GFXNVIDIA=1'
 PROGRAMMER_OBJS += gfxnvidia.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_GFXNVIDIA
 endif
 
 ifeq ($(CONFIG_SATASII), yes)
 FEATURE_CFLAGS += -D'CONFIG_SATASII=1'
 PROGRAMMER_OBJS += satasii.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_SATASII
 endif
 
 ifeq ($(CONFIG_ATAHPT), yes)
 FEATURE_CFLAGS += -D'CONFIG_ATAHPT=1'
 PROGRAMMER_OBJS += atahpt.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_ATAHPT
 endif
 
 ifeq ($(CONFIG_FT2232_SPI), yes)
-FTDILIBS := $(shell pkg-config --libs libftdi 2>/dev/null || printf "%s" "-lftdi -lusb")
-# This is a totally ugly hack.
-FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-D'CONFIG_FT2232_SPI=1'")
+FEATURE_CFLAGS += -D'CONFIG_FT2232_SPI=1'
 FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FT232H := yes" .features && printf "%s" "-D'HAVE_FT232H=1'")
-FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "$(FTDILIBS)")
 PROGRAMMER_OBJS += ft2232_spi.o
-# We can't set NEED_USB here because that would transform libftdi auto-enabling
-# into a hard requirement for libusb, defeating the purpose of auto-enabling.
+NEED_FTDI += CONFIG_FT2232_SPI
 endif
 
 ifeq ($(CONFIG_DUMMY), yes)
@@ -492,55 +487,55 @@ 
 ifeq ($(CONFIG_DRKAISER), yes)
 FEATURE_CFLAGS += -D'CONFIG_DRKAISER=1'
 PROGRAMMER_OBJS += drkaiser.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_DRKAISER
 endif
 
 ifeq ($(CONFIG_NICREALTEK), yes)
 FEATURE_CFLAGS += -D'CONFIG_NICREALTEK=1'
 PROGRAMMER_OBJS += nicrealtek.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_NICREALTEK
 endif
 
 ifeq ($(CONFIG_NICNATSEMI), yes)
 FEATURE_CFLAGS += -D'CONFIG_NICNATSEMI=1'
 PROGRAMMER_OBJS += nicnatsemi.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_NICNATSEMI
 endif
 
 ifeq ($(CONFIG_NICINTEL), yes)
 FEATURE_CFLAGS += -D'CONFIG_NICINTEL=1'
 PROGRAMMER_OBJS += nicintel.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_NICINTEL
 endif
 
 ifeq ($(CONFIG_NICINTEL_SPI), yes)
 FEATURE_CFLAGS += -D'CONFIG_NICINTEL_SPI=1'
 PROGRAMMER_OBJS += nicintel_spi.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_NICINTEL_SPI
 endif
 
 ifeq ($(CONFIG_OGP_SPI), yes)
 FEATURE_CFLAGS += -D'CONFIG_OGP_SPI=1'
 PROGRAMMER_OBJS += ogp_spi.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_OGP_SPI
 endif
 
 ifeq ($(CONFIG_BUSPIRATE_SPI), yes)
 FEATURE_CFLAGS += -D'CONFIG_BUSPIRATE_SPI=1'
 PROGRAMMER_OBJS += buspirate_spi.o
-NEED_SERIAL := yes
+NEED_SERIAL += CONFIG_BUSPIRATE_SPI
 endif
 
 ifeq ($(CONFIG_DEDIPROG), yes)
 FEATURE_CFLAGS += -D'CONFIG_DEDIPROG=1'
 PROGRAMMER_OBJS += dediprog.o
-NEED_USB := yes
+NEED_USB += CONFIG_DEDIPROG
 endif
 
 ifeq ($(CONFIG_SATAMV), yes)
 FEATURE_CFLAGS += -D'CONFIG_SATAMV=1'
 PROGRAMMER_OBJS += satamv.o
-NEED_PCI := yes
+NEED_PCI += CONFIG_SATAMV
 endif
 
 ifeq ($(CONFIG_LINUX_SPI), yes)
@@ -549,17 +544,17 @@ 
 PROGRAMMER_OBJS += linux_spi.o
 endif
 
-ifeq ($(NEED_SERIAL), yes)
+ifneq ($(NEED_SERIAL), )
 LIB_OBJS += serial.o
 endif
 
-ifeq ($(NEED_NET), yes)
+ifneq ($(NEED_NET), )
 ifeq ($(TARGET_OS), SunOS)
 LIBS += -lsocket
 endif
 endif
 
-ifeq ($(NEED_PCI), yes)
+ifneq ($(NEED_PCI), )
 CHECK_LIBPCI = yes
 FEATURE_CFLAGS += -D'NEED_PCI=1'
 PROGRAMMER_OBJS += pcidev.o physmap.o hwaccess.o
@@ -589,12 +584,23 @@ 
 endif
 endif
 
-ifeq ($(NEED_USB), yes)
+ifneq ($(NEED_USB), )
 CHECK_LIBUSB0 = yes
 FEATURE_CFLAGS += -D'NEED_USB=1'
 USBLIBS := $(shell pkg-config --libs libusb 2>/dev/null || printf "%s" "-lusb")
 endif
 
+ifneq ($(NEED_FTDI), )
+CHECK_LIBFTDI = yes
+FEATURE_CFLAGS += -D'NEED_FTDI=1'
+FTDILIBS := $(shell pkg-config --libs libftdi 2>/dev/null || libftdi-config --libs 2>/dev/null || printf "%s" "-lftdi")
+endif
+
+ifneq ($(NEED_IOPORT_ACCESS), )
+FEATURE_CFLAGS += -D'NEED_IOPORT_ACCESS=1'
+PROGRAMMER_OBJS += hwaccess.o
+endif
+
 ifeq ($(CONFIG_PRINT_WIKI), yes)
 FEATURE_CFLAGS += -D'CONFIG_PRINT_WIKI=1'
 CLI_OBJS += print_wiki.o
@@ -614,7 +620,7 @@ 
 endif
 
 $(PROGRAM)$(EXEC_SUFFIX): $(OBJS)
-	$(CC) $(LDFLAGS) -o $(PROGRAM)$(EXEC_SUFFIX) $(OBJS) $(FEATURE_LIBS) $(LIBS) $(PCILIBS) $(USBLIBS)
+	$(CC) $(LDFLAGS) -o $(PROGRAM)$(EXEC_SUFFIX) $(OBJS) $(FEATURE_LIBS) $(LIBS) $(PCILIBS) $(USBLIBS) $(FTDILIBS)
 
 libflashrom.a: $(LIBFLASHROM_OBJS)
 	$(AR) rcs $@ $^
@@ -699,6 +705,37 @@ 
 endef
 export LIBUSB0_TEST
 
+define FTDI_TEST
+#include <ftdi.h>
+struct ftdi_context *ftdic = NULL;
+int main(int argc, char **argv)
+{
+	(void) argc;
+	(void) argv;
+	return ftdi_init(ftdic);
+}
+endef
+export FTDI_TEST
+
+define FTDI_232H_TEST
+#include <ftdi.h>
+enum ftdi_chip_type type = TYPE_232H;
+endef
+export FTDI_232H_TEST
+
+define LINUX_SPI_TEST
+#include <linux/types.h>
+#include <linux/spi/spidev.h>
+
+int main(int argc, char **argv)
+{
+	(void) argc;
+	(void) argv;
+	return 0;
+}
+endef
+export LINUX_SPI_TEST
+
 hwlibs: compiler
 	@printf "" > .libdeps
 ifeq ($(CHECK_LIBPCI), yes)
@@ -706,16 +743,18 @@ 
 	@echo "$$LIBPCI_TEST" > .test.c
 	@$(CC) -c $(CPPFLAGS) $(CFLAGS) .test.c -o .test.o >/dev/null &&		\
 		echo "found." || ( echo "not found."; echo;			\
-		echo "Please install libpci headers (package pciutils-devel).";	\
+		echo "Please install libpci headers (package pciutils-devel)";	\
+		echo "or disable the following features: $(NEED_PCI)";		\
 		echo "See README for more information."; echo;			\
 		rm -f .test.c .test.o; exit 1)
 	@printf "Checking if libpci is present and sufficient... "
-	@$(CC) $(LDFLAGS) .test.o -o .test$(EXEC_SUFFIX) $(PCILIBS) >/dev/null &&		\
+	@$(CC) $(LDFLAGS) .test.o -o .test$(EXEC_SUFFIX) $(PCILIBS) $(LIBS) >/dev/null &&		\
 		echo "yes." || ( echo "no.";							\
 		printf "Checking if libz+libpci are present and sufficient...";	\
-		$(CC) $(LDFLAGS) .test.o -o .test$(EXEC_SUFFIX) $(PCILIBS) -lz >/dev/null &&	\
+		$(CC) $(LDFLAGS) .test.o -o .test$(EXEC_SUFFIX) $(PCILIBS) -lz $(LIBS) >/dev/null &&	\
 		( echo "yes."; echo "NEEDLIBZ := yes" > .libdeps ) || ( echo "no."; echo;	\
-		echo "Please install libpci (package pciutils) and/or libz.";			\
+		echo "Please install libpci (package pciutils) and/or libz";			\
+		echo "or disable the following features: $(NEED_PCI)";		\
 		echo "See README for more information."; echo;				\
 		rm -f .test.c .test.o .test$(EXEC_SUFFIX); exit 1) )
 	@rm -f .test.c .test.o .test$(EXEC_SUFFIX)
@@ -725,17 +764,39 @@ 
 	@echo "$$LIBUSB0_TEST" > .test.c
 	@$(CC) -c $(CPPFLAGS) $(CFLAGS) .test.c -o .test.o >/dev/null &&		\
 		echo "found." || ( echo "not found."; echo;				\
-		echo "Please install libusb-0.1 headers or libusb-compat headers.";	\
+		echo "Please install libusb-0.1 headers or libusb-compat headers";	\
+		echo "or disable the following features: $(NEED_USB)";		\
 		echo "See README for more information."; echo;				\
 		rm -f .test.c .test.o; exit 1)
 	@printf "Checking if libusb-0.1 is usable... "
-	@$(CC) $(LDFLAGS) .test.o -o .test$(EXEC_SUFFIX) $(USBLIBS) >/dev/null &&	\
+	@$(CC) $(LDFLAGS) .test.o -o .test$(EXEC_SUFFIX) $(USBLIBS) $(LIBS) >/dev/null &&	\
 		echo "yes." || ( echo "no.";						\
-		echo "Please install libusb-0.1 or libusb-compat.";			\
+		echo "Please install libusb-0.1 or libusb-compat";			\
+		echo "or disable the following features: $(NEED_USB)";		\
 		echo "See README for more information."; echo;				\
 		rm -f .test.c .test.o .test$(EXEC_SUFFIX); exit 1)
 	@rm -f .test.c .test.o .test$(EXEC_SUFFIX)
 endif
+ifeq ($(CHECK_LIBFTDI), yes)
+	@printf "Checking for libftdi support... "
+	@echo "$$FTDI_TEST" > .test.c
+	@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .test.c -o .test$(EXEC_SUFFIX) $(FTDILIBS) $(LIBS) >/dev/null &&	\
+		echo "found." || ( echo "not found."; echo;				\
+		echo "Please install libftdi headers";	\
+		echo "or disable the following features: $(NEED_FTDI)";		\
+		echo "See README for more information."; echo;				\
+		rm -f .test.c .test.o; exit 1)
+endif
+ifeq ($(CONFIG_LINUX_SPI), yes)
+	@printf "Checking for Linux kernel SPI headers... "
+	@echo "$$LINUX_SPI_TEST" > .test.c
+	@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .test.c -o .test$(EXEC_SUFFIX) >/dev/null &&	\
+		echo "found." || ( echo "not found."; echo;					\
+		echo "Please install Linux kernel SPI headers (linux/spi/spidev.h, part of recent glibc)";	\
+		echo "or disable the following features: CONFIG_LINUX_SPI";		\
+		echo "See README for more information."; echo;			\
+		rm -f .test.c .test.o; exit 1)
+endif
 
 .features: features
 
@@ -748,29 +809,11 @@ 
 	@echo "You have to enable at least one programmer driver!"
 	@false
 endif
-ifneq ($(UNSUPPORTED_FEATURES), )
-	@echo "The following features are unavailable on your machine: $(UNSUPPORTED_FEATURES)"
+ifneq ($(UNSUPPORTED_TARGET_FEATURES), )
+	@echo "The following features are unavailable on the target machine: $(UNSUPPORTED_TARGET_FEATURES)"
 	@false
 endif
 
-define FTDI_TEST
-#include <ftdi.h>
-struct ftdi_context *ftdic = NULL;
-int main(int argc, char **argv)
-{
-	(void) argc;
-	(void) argv;
-	return ftdi_init(ftdic);
-}
-endef
-export FTDI_TEST
-
-define FTDI_232H_TEST
-#include <ftdi.h>
-enum ftdi_chip_type type = TYPE_232H;
-endef
-export FTDI_232H_TEST
-
 define UTSNAME_TEST
 #include <sys/utsname.h>
 struct utsname osinfo;
@@ -784,40 +827,15 @@ 
 endef
 export UTSNAME_TEST
 
-define LINUX_SPI_TEST
-#include <linux/types.h>
-#include <linux/spi/spidev.h>
-
-int main(int argc, char **argv)
-{
-	(void) argc;
-	(void) argv;
-	return 0;
-}
-endef
-export LINUX_SPI_TEST
-
 features: compiler
 	@echo "FEATURES := yes" > .features.tmp
 ifeq ($(CONFIG_FT2232_SPI), yes)
-	@printf "Checking for FTDI support... "
-	@echo "$$FTDI_TEST" > .featuretest.c
-	@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest$(EXEC_SUFFIX) $(FTDILIBS) $(LIBS) >/dev/null 2>&1 &&	\
-		( echo "found."; echo "FTDISUPPORT := yes" >> .features.tmp ) ||	\
-		( echo "not found."; echo "FTDISUPPORT := no" >> .features.tmp )
 	@printf "Checking for FT232H support in libftdi... "
 	@echo "$$FTDI_232H_TEST" >> .featuretest.c
 	@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest$(EXEC_SUFFIX) $(FTDILIBS) $(LIBS) >/dev/null 2>&1 &&	\
 		( echo "found."; echo "FT232H := yes" >> .features.tmp ) ||	\
 		( echo "not found."; echo "FT232H := no" >> .features.tmp )
 endif
-ifeq ($(CONFIG_LINUX_SPI), yes)
-	@printf "Checking if Linux SPI headers are present... "
-	@echo "$$LINUX_SPI_TEST" > .featuretest.c
-	@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest$(EXEC_SUFFIX) >/dev/null 2>&1 &&	\
-		( echo "yes."; echo "LINUX_SPI_SUPPORT := yes" >> .features.tmp ) ||	\
-		( echo "no."; echo "LINUX_SPI_SUPPORT := no" >> .features.tmp )
-endif
 	@printf "Checking for utsname support... "
 	@echo "$$UTSNAME_TEST" > .featuretest.c
 	@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest$(EXEC_SUFFIX) >/dev/null 2>&1 &&	\