Thursday, January 21, 2010

Compiling HPLIP in Windows using Cygwin

Windows drivers for the HP Color LaserJet 2840 All-in-One Printer are a bloated piece of garbage. Scanning over the network doesn't work, and downloadable drivers only offer printing support for 64-bit versions of Windows. The potentially decent Windows driver alternatives may be to only use the all-in-one for printing or connect the printer via USB to a computer running Windows 7.

Via HPLIP (HP Linux Imaging and Printing), Hewlett-Packard provides Linux drivers for many HP printers and all-in-one devices. The 2840 is fully supported. These drivers consist of applications and dynamically linked libraries which can work in Cygwin in Windows The process of compiling them is not straightforward, but it's certainly not impossible. Here I will concisely describe how to compile a lite version of HPLIP with scanning and printing support.

First, note the dependencies that are listed in the manual installation page. Some of these, (such as gcc, libjpeg and libcrypto) are standard Cygwin packages. They can simply be installed via the setup program. That is the easy part. The next step is compiling the dependencies. The following instructions list the important points (such as problems and workarounds) and omit the obvious things (such as running make and "make install"). They place everything under /opt/hplip, to keep things tidy and somewhat portable.

Net-SNMP 5.5

HPLIP seems to only require a stripped-down version of Net-SNMP; basically only the library is needed. Compiling only the needed parts simplifies things and avoids some issues:

./configure --prefix=/opt/hplip --disable-agent --disable-applications --with-perl-modules=no --disable-embedded-perl

The entire agent subdirectory is not needed; remove it from SUBDIRS in the generated top level Makefile.

Windows DLLs can't have undefined symbols, and because of this libtool normally requires a -no-undefined switch to build shared libraries in Windows. In in the Cygwin section of func_mode_link () in libtool uncomment the allow_undefined=no line and comment out the yes line. Note comments explaining the issue.

CUPS (1.4.2)

Even the network scanner driver depends on CUPS. Fortunately, CUPS is easy to compile. The only problem is that the rules for generating shared libraries are for Unix only. One could add Cygwin-specific rules or set up the project for Automake and Libtool, but it's far simpler to just disable shared libraries:

LIBS=-lz ./configure --prefix=/opt/hplip --disable-shared --with-cups-group=None

After CUPS is installed, create an administration password with "lppasswd -g admin -a root" and change AuthType to BasicDigest in /opt/hplip/etc/cups/cupsd.conf. The administration interface is at http://localhost:631/ and https://localhost:631/. Note that you don't need to let cupsd through your Windows firewall to access the administration interface on localhost.

SANE (sane-backends-1.0.20)

This is easiest to build. I simply configured it using:

./configure --prefix=/opt/hplip --with-group=None --disable-ipv6

When attempting to run "saned -d" before, I got "invalid fd in set, attempting to re-bind" errors. I think disabling IPv6 fixed that. In any case, I don't need IPv6.

While building tools/sane-desc, I got missing include file errors the first time. Surprisingly, retrying fixed that error.

HPLIP (3.9.12)

If you get a .run file, you can get a .tar.gz by starting with the 0x1F byte after the shell script. The contents of the resulting tar.gz are not all in one directory, like with most software. That means you need to create a new directory, change to it and extract there. You can also download a .tar.gz from HP. At this point you definitely need the dependencies, so add /opt/hplip/bin to the path and use CPPFLAGS and LDFLAGS:

CPPFLAGS=-I/opt/hplip/include LDFLAGS=-L/opt/hplip/lib LIBS="-lssl -lz" ./configure --prefix=/opt/hplip --enable-hpijs-only-build=no --enable-hpijs-install=no --enable-gui-build=no --enable-dbus-build=no --enable-cups-drv-install=yes --with-cupsbackenddir=/opt/hplip/lib/cups/backend --with-cupsfilterdir=/opt/hplip/lib/cups/filter --enable-qt4=no --enable-lite-build

After this, the generated libtool again needs to be fixed. Under the "libtool link mode" comment, uncomment "allow_undefined=no" and comment out "allow_undefined=yes". In prnt/hpcups/ErnieFilter.cpp, ensure that math.h is included; remove the conditional around the include.

After "make install" copy data/models/models.dat to /opt/hplip/share/hplip/data/models/models.dat, or maybe move the whole data directory. Also, move /opt/hplip/lib/bin/cygsane-hpaio-1.dll to /opt/hplip/lib/sane/. Then, add a hpaio line to /opt/hplip/etc/sane.d/dll.conf. You can comment out all the other lines in that dll.conf and remove /etc/sane.d and the dll.conf file found there. The only file that remains outside of /opt/hplip is /etc/hp/hplip.conf. That path is hard-coded into several hplip files.

Finally, it's time to configure CUPS. You can create a URI for your printer by probing it with hp-mkuri. For example "hp-mkuri -i" would give you something like hp:/net/HP_Color_LaserJet_2840?ip= if successful. When adding a printer, choose HPLIP and enter that URI. You can find your PPD file in /opt/hplip/share/ppd/HP/ and with the 2840, CUPS can retrieve settings from the printer (it just takes a while). At that point, you can print a test page.

At this point, scanning should work. Scanning from the command line via scanimage does not need saned running because it uses the backend directly. The output goes to standard output, so be sure to redirect it. Scanning from a GUI is possible via xsane-win32 and there even TWAIN frontends for SANE. Note that although saned is designed to run under inetd, it can be run temporarily via "/opt/hplib/sbin/saned -d".

The HPLIP GUI is not available and faxing isn't supported. The LyX instructions for compiling Qt in Cygwin seem promising, but I may not work on that anytime soon because I don't need the fax features and I expect the GUI would be bloated.


Stephen said...

hi, any chance you could please post your binary for hplip/win32? It'd be a great help, I'm not a programmer and I've love to be able to use xsane in Windows as well as Linux.

Anonymous said...

Hi, Boris!
Today I spent again many hours to get that plastic monster HP CLJ2840 working! No chance! In the network are 7 PCs and this horror-machine works on 6 - connected with SILEX USB device server. Using this, scanning and printig is possible over tcp/ip. With the PC #7 it doesn't work.

I'm very gladfull for your blog. I hope, I can compile this...

Thank you for your howto! This will prevent me to kick the printer off the window. Never again HP all in one printer!

Kind regards from Austria!


mitroko said...

How did u get cups dlls?
Every time i build cups, i get only "a" files, not cygwin "dll"'s.
That's why i'm symlinked libcups*.a to a libcups*.dll.a to get hplip configure return positive result.
What version of gcc did you use and version of other stuff?
hplip 3.11.3a
cups 1.4.6
sane-backends 1.0.22

Did you ever get the
prnt/cupsext/cupsext.c:198: error: initializer element is not constant
prnt/cupsext/cupsext.c:198: error: (near initialization for `printer_Type.ob_type')
prnt/cupsext/cupsext.c:885: error: initializer element is not constant
prnt/cupsext/cupsext.c:885: error: (near initialization for `job_Type.ob_type')
make: *** [cupsext_la-cupsext.lo] Error 1?

Boris Gjenero said...

CUPS uses libtool to build libraries. In Windows, libtool requires the -no-undefined switch to build DLLs. (This is because unlike Unix shared libraries, Windows DLLs can't have undefined symbols. CUPS doesn't have an issue with undefined symbols, so the only problem is lack of that switch.) To get DLLs to build, either pass -no-undefined to libtool or patch the libtool created by configure so it doesn't require -no-undefined to create DLLs.

I used cups-1.4.2, and I didn't have any problems compiling it. I also used net-snmp-5.5, hplip-3.9.12 and sane-backends-1.0.20.

Dhananjay AM said...

It's been a month I am trying to compile sanebackeneds 1.0.23, cups and net-snmp with cygwin on windows but no success so far.when I look into config.log,It shows, "conftest.c:16:28: fatal error: ac_nonexistent.h: No such file or directory
compilation terminated." don't know how to set it up.Could you please help me make saned work on windows?Thanks a lot in advance.