Building and Configuring LyX/Qt on Cygwin


This document is a summary of the steps to build and configure LyX on windows using the cygwin environment. This is not for the fainthearted or the impatient. I took me about a week to figure all the details (with the help of several people, including Georg Baum, Ruurd, Did Bar-David, and my wife Orith). But I use LyX a lot (on Linux up to now) so it was well worth the effort.
  1. Install cygwin, including X11
  2. Install gcc version 2.95.3 (get it here). This is NOT the version that comes with cygwin, which is currently 3.3.1. Versions 3.3.1 and 3.3.2 generate a few object files that do not link properly. The problem looks like a g++ bug, but I am not sure. 2.95.3 works fine.
  3. Install stlport. The version of the C++ standard libraries that comes with gcc 2.95.3 is defective (this is a known bug). Stlport is a complete C++ standard library.
  4. Install  Qt 3.x. I used 3.3.0, which is the most recent now, but older versions should work.  Configuring Qt is a bit tricky. The reason is that the Qt distribution comes with configuration files for many platforms, including cygwin on Windows. However, the prepackaged configuration is designed for a native build, not for an X11 build. Since the native-build files are not distributed with the free version of Qt, you can't use the preconfigured cygwin-g++ build. What you must do instead is modify the build files so that they force Qt to build an X11 library under cygwin.
    In addition to the X11 issue, there are two other issues under cygwin.  One is dynamic vs. static libraries. Cygwin uses an unusual naming scheme for dynamic libraries, a .dll.a  extension, which is unlike  the usual Unix/Linux naming scheme, which uses an .so  extension with a suffix that indicates a version. Qt expect the usual Unix naming convension, and as a consequence, I wasn't able to build a dynamic library. That is why the configuration setup below uses a -static flag. This is probably less of an issue under Windows since there aren't likely to be so many programs using Qt under cygwin simultenesouly. If you run many Qt programs at the same time, as you do when you use KDE under Linux, for example, then the dynamic library saves a lot of memory. If you only use Qt to run LyX, the difference is minor.
    The last significant issue is the set of modules that can or cannot be built. I disabled most of the Qt modules that I thought were not essential for LyX to reduce build problems. One module that proved particularly difficult is the network module. Cygwin is missing the DNS header files, so the network module cannot be built. The network module is also used intenally by some Qt tools, so their build breaks. This includes Qt Assistant. This does not interfere with LyX, but the Qt build is incomplete. This issue is the reason for the -DQT_NO_DNS flag.
    OK, here are the detailed instructions.
    1. use gcc-2 and g++-2 in mkspecs/cygwin-g++/qmake.def
    2. add -fnative-struct to CFLAGS in the same file. This ensures that the library links properly with LyX. Qt can be built without this flag, but not with lyx. Maybe deleting the option in both will also work, but is seems safer to use it.
    3. hardcode Q_WS_X11 and Q_OS_UNIX, to override the cygwin defaults in src/tools/qglobal.h. Add this after the Q_WS_* and Q_OS are set:
      #undef Q_WS_WIN32
      #undef Q_WS_WIN
      #undef Q_OS_WIN32
      #undef Q_OS_WIN64
      #undef Q_OS_WIN
      #define Q_WS_X11
      #define Q_OS_UNIX
    4. delete #include <windows.h> from mkspecs/cygwin-g++/qplatformdef.h.
    5. add dll.a to the allowed dll extensions in config.tests\x11\xfreetype.test. This is only necessary if you want to use Xft an freetype (highly recommended to get high-quality text display).
      EXTENSIONS="a so sl dll.a"
    6. cd to the Qt main library and invoke the following script, which configures the build. Change the paths below to where you installed freetype, if they are not in the default location.
      export QTDIR=$PWD
      ./configure -platform cygwin-g++ \
        -static \
        -freetype -xft -I/opt/freetype-2.1.5/include -L/opt/freetype-2.1.5/lib \
        -no-stl \
        -no-thread -no-nis -no-cups -no-largefile \
        -qt-zlib \
        -qt-gif  \
        -qt-imgfmt-png  -qt-libpng \
        -qt-imgfmt-jpeg -qt-libjpeg \
        -qt-imgfmt-mng  -qt-libmng \
        -no-g++-exceptions -no-exceptions \
        -disable-opengl -disable-sql -disable-network \
        -no-style-cde -no-style-motif -no-style-motifplus \
        -no-style-platinum -no-style-sgi \
        -no-sm \
        -DQT_NO_DNS
    7. Type "make". The build will break when Qt will try to build Qt Assistant, due to the DNS issue. But at this time the library has been successfully built. You can go to one of the example libraries, type make, and run the example (make sure X is running).
    8. That's it, Qt is ready.
  5. Now we build LyX. Basically, all you need is to configure the library propely.
    1. Before we can configure LyX, we have to fix the configure script a bit. After the line that defines the various possible Qt library names (-lqt, -lqt3, -lqt-mt, and so on), change the original definition of the variable LIBS to
      LIBS="$LIBS $libname -lX11 -lXext -lXrandr -lXrender -lXcursor"
      This is required because Qt is a static library that does not indicate which DLL's it needs.
    2. Run the following configure setup script, after changing the paths appropriately:
    3. ./configure \
      --prefix=/opt/lyx-1.3.3 \
      -with-frontend=qt \
      --with-qt-dir=/home/stoledo/qt-x11-free-3.3.0 \
      QTDIR=/home/stoledo/qt-x11-free-3.3.0 \
      CXX=g++-2 \
      CC=gcc-2 \
      CPP=cpp-2 \
      CXXFLAGS="-O -DCXX_GLOBAL_CSTD -nostdinc++ -fno-exceptions -ftemplate-depth-64 -I/home/stoledo/STLport-4.6.1/stlport" \
      LDFLAGS="-L/home/stoledo/STLport-4.6.1/lib -lstlport_cygwin -lm"
    4. Type "make". It will halt three times on minor syntactic errors (multiple definitions of symbols), once for std::i_forgot and twice for std::atoi. Just comment these out and restart. I am not sure whether this problem is due to g++ 2.95 vs g++ 3, or due to stlport.
    5. This is still not enough. The make process will also die when it will try to retrieve all the symbols from the Qt dll, which does not exist. When it does, just type make again.
    6. The make process will die again at the very end, when it tries to link lyx.exe. The link command in the makefile is flawed. Move to the src directory and issue the following link command:
      g++-2 -nostdlib -v \
      /usr/lib/crt0.o \
      -o lyx.exe  BufferView.o \
      BufferView_pimpl.o Bullet.o Chktex.o CutAndPaste.o DepTable.o \
      FloatList.o Floating.o FuncStatus.o InsetList.o LColor.o LaTeX.o \
      LaTeXFeatures.o LyXAction.o MenuBackend.o paragraph_funcs.o \
      ParagraphList.o ParagraphParameters.o Spacing.o TextCache.o Thesaurus.o \
      ToolbarDefaults.o boost.o boost-inst.o box.o buffer.o bufferlist.o \
      bufferparams.o bufferview_funcs.o chset.o converter.o counters.o debug.o encoding.o \
      exporter.o gettext.o factory.o funcrequest.o importer.o intl.o iterators.o kbmap.o \
      kbsequence.o language.o lastfiles.o lengthcommon.o lyx_cb.o lyx_main.o lyx_sty.o \
      lyxcursor.o lyxfont.o lyxfind.o lyxfunc.o lyxgluelength.o lyxlayout.o lyxlength.o \
      lyxlex.o lyxlex_pimpl.o lyxrc.o lyxrow.o lyxserver.o lyxtextclass.o \
      lyxtextclasslist.o lyxvc.o main.o paragraph.o paragraph_pimpl.o ispell.o pspell.o \
      sgml.o tabular.o tabular-old.o tabular_funcs.o tex-accent.o tex-strings.o texrow.o \
      text.o text2.o text3.o toc.o trans.o trans_mgr.o undo.o undo_funcs.o vc-backend.o \
      version.o vspace.o \
      mathed/.libs/libmathed.a \
      insets/.libs/libinsets.a \
      frontends/.libs/libfrontends.a \
      graphics/.libs/libgraphics.a \
      support/.libs/libsupport.a \
      ../boost/libs/regex/src/.libs/libboostregex.a \
      ../boost/libs/signals/src/.libs/libboostsignals.a \
      -L/home/stoledo/STLport-4.6.1/lib -lstlport_cygwin \
      .libs/libimp-cygintl-2.a .libs/libimp-cygiconv-2.a \
      -lSM -lICE \
      -L$QTDIR/lib -lqt \
      -L/opt/freetype-2.1.5/lib -lfreetype \
      -L/usr/X11R6/lib -lXft -lfontconfig -lXrender -lXrandr -lXcursor -lXext -lX11 -ldl \
      -lgcc \
      -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32
    7. Hopefully, that's it. Type "make install" and you should be all set.
  6. A few more details: I use the cygwin ghostscript and gv, but the native Win32 TeX package fpTeX, which comes as part of TeXLive 2003. LyX can use it very well. I had trouble with the cygwin teTeX.
  7. I had some problems with ImageMagick, the software that LyX uses to convert EPS and other graphic formats to bitmaps that it can display on the screen.  I had two versions installed, but non worked. One was the Win32 version, which called the Win32 GhostScript 8. It failed. I didn't test too much and installed instead the cygwin port, which uses the cygwin GhostScript, which is version 7. It was defective because it searched for its configuration files (with a .mgk suffix) in the wrong place. A symbolic link fixed that, but it still failed to convert EPS to PPM. A bit of testing showed that the problem was that LyX invokes it with a command that looks like convert -depth 8 eps:epsfilename.eps ppm:ppmfilename.ppm. For some reason, the eps: prefix causes convert.exe to add some binary junk to the EPS file, which causes GhostScript to fail. I finally fixed that by putting the following script in .lyx/scripts/convertDefault.sh:
    #! /bin/sh
    # The default converter if no other has been defined by the user from the
    # Conversion->Converter tab of the Preferences dialog.
    #
    # The user can also redefine this default converter, placing their
    # replacement in ~/.lyx/scripts
    #
    # converts an image from $1 to $2 format
    sourcefile="`echo $1 | sed 's/eps://'`" # this fixes the problem
    /opt/ImageMagick-5.5.7/bin/convert -depth 8 "$sourcefile" $2 # use your actual path
    if [ $? -ne 0 ]; then
        exit $?
    fi

    # It appears that convert succeeded, but we know better than to trust it ;-)
    # convert is passed strings in the form "FMT:FILENAME", so use the ':' to
    # delimit the two parts.
    FILE=`echo $2 | cut -d ':' -f 2`

    # FSTATUS == 0 is the file exists and == 1 if it does not.
    FSTATUS=0
    test -f $FILE || FSTATUS=1

    exit $FSTATUS
    This fixed it. Eventually, I installed ImageMagick from the sources, which resolved the configuration file problems. That is why I have the full path to convert in the script
  8. I think that this is it. Enjoy (I do).