Chapter 5. Implementation

5.1. RedHat 8.0 Sample

  1. Building the package

    Wine is configured the usual way (depending on your build environment). The "prefix" is chosen using your application placement policy (/usr/, /usr/X11R6/, /opt/wine/ or similar). The configuration files (wine.conf, wine.userreg, wine.systemreg) are targeted for /etc/wine/ (rationale: FHS 2.2, multiple readonly configuration files of a package).

    Example (split this into %build and %install section for rpm):

    CFLAGS=$RPM_OPT_FLAGS \
    ./configure --prefix=/usr/X11R6 --sysconfdir=/etc/wine/ --enable-dll
    make
    BR=$RPM_BUILD_ROOT
    make install prefix=$BR/usr/X11R6/ sysconfdir=$BR/etc/wine/
    install -d $BR/etc/wine/
    install -m 644 wine.ini $BR/etc/wine/wine.conf
    
    # Put all our dlls in a seperate directory. (this works only if
    # you have a buildroot)
    install -d $BR/usr/X11R6/lib/wine
    mv $BR/usr/X11R6/lib/lib* $BR/usr/X11R6/lib/wine/
    
    # the clipboard server is started on demand.
    install -m 755 dlls/x11drv/wineclipsrv $BR/usr/X11R6/bin/
    
    # The Wine server is needed.
    install -m 755 server/wineserver $BR/usr/X11R6/bin/
                  

    Here we unfortunately do need to create wineuser.reg and winesystem.reg from the Wine distributed winedefault.reg. This can be done using ./regedit once for one example user and then reusing his WINECONFDIR/user.reg and WINECONFDIR/system.reg files.

    FIXME: this needs to be done better

    install -m 644 wine.sytemreg $BR/etc/wine/
    install -m 644 wine.userreg $BR/etc/wine/
                  

    There are now a lot of libraries generated by the build process, so a seperate library directory should be used.

    install -d 755 $BR/usr/X11R6/lib/
    mv $BR/
                  

    You will need to package the files:

    $prefix/bin/wine, $prefix/bin/dosmod, $prefix/lib/wine/*
    $prefix/man/man1/wine.1, $prefix/include/wine/*,
    $prefix/bin/wineserver, $prefix/bin/wineclipsrv
    
    %config /etc/wine/*
    %doc ... choose from the toplevel directory and documentation/
                  

    The post-install script:

    if ! grep -q /usr/X11R6/lib/wine /etc/ld.so.conf; then
        echo "/usr/X11R6/lib/wine" >> /etc/ld.so.conf
    fi
    /sbin/ldconfig
                  

    The post-uninstall script:

    if [ "$1" = 0 ]; then
        perl -ni -e 'print unless m:/usr/X11R6/lib/wine:;' /etc/ld.so.conf
    fi
    /sbin/ldconfig
                  
  2. Creating a good default configuration file

    For the rationales of needing as less input from the user as possible arises the need for a very good configuration file. The one supplied with Wine is currently lacking. We need:

    • [Drive X]:

      • A for the floppy. Specify your distribution's default floppy mountpoint here.

        Path=/auto/floppy
                              
      • C for the C:\ directory. Here we use the user's home directory, for most applications do see C:\ as root-writeable directory of every windows installation and this basically is it in the UNIX-user context.

        Path=${HOME}
                              
      • R for the CD-Rom drive. Specify your distribution's default CD-ROM drives mountpoint here.

        Path=/auto/cdrom
                              
      • T for temporary storage. We do use /tmp/ (rationale: between process temporary data belongs to /tmp/, FHS 2.0)

      • W for the original Windows installation. This drive points to the windows\ subdirectory of the original windows installation. This avoids problems with renamed windows directories (as for instance lose95, win or sys\win95). During compile/package/install we leave this to be /, it has to be configured after the package install.

      • Z for the UNIX Root directory. This avoids any problems with "could not find drive for current directory" users occasionally complain about in the newsgroup and the irc channel. It also makes the whole directory structure browseable. The type of Z should be network, so applications expect it to be readonly.

        Path=/
                              
    • [wine]:

        Windows=c:\windows\ 		(the windows/ subdirectory in the user's
        				 home directory)
        System=c:\windows\system\	(the windows/system subdirectory in the user's
        				 home directory)
        Path=c:\windows;c:\windows\system;c:\windows\system32;w:\;w:\system;w:\system32;
        ; Using this trick we have in fact two windows installations in one, we
        ; get the stuff from the readonly installation and can write to our own.
        Temp=t:\			(the TEMP directory)
                        
    • [Tweak.Layout]

        WineLook=win95		(just the coolest look ;)
                        
    • Possibly modify the [spooler], [serialports] and [parallelports] sections.

      FIXME: possibly more, including printer stuff.

    Add this prepared configuration file to the package.

  3. Installing Wine for the system administrator

    Install the package using the usual packager rpm -i wine.rpm. You may edit /etc/wine/wine.conf, [Drive W], to point to a possible windows installation right after the install. That's it.

    Note that on Linux you should somehow try to add the unhide mount option (see man mount) to the CD-ROM entry in /etc/fstab during package install, as several stupid Windows programs mark some setup (!) files as hidden (ISO9660) on CD-ROMs, which will greatly confuse users as they won't find their setup files on the CD-ROMs as they were used on Windows systems when unhide is not set ;-\ And of course the setup program will complain that setup.ins or some other mess is missing... If you choose to do so, then please make this change verbose to the admin. Also make sure that the kernel you use includes the Joliet CD-ROM support, for the very same reasons as given above (no long filenames due to missing Joliet, files not found).

  4. Installing Wine for the user

    The user will need to run a setup script before the first invocation of Wine. This script should:

    • Copy /etc/wine/wine.conf for user modification.

    • Allow specification of the original windows installation to use (which modifies the copied wine.conf file).

    • Create the windows directory structure (c:\windows, c:\windows\system, c:\windows\Start Menu\Programs, c:\Program Files, c:\Desktop, etc.)

    • Symlink all .dll and .exe files from the original windows installation to the windows directory. Why? Some programs reference "%windowsdir%/file.dll" or "%systemdir%/file.dll" directly and fail if they are not present.

      This will give a huge number of symlinks, yes. However, if an installer later overwrites one of those files, it will overwrite the symlink (so that the file now lies in the windows/ subdirectory).

      FIXME: Not sure this is needed for all files.

    • On later invocation the script might want to compare regular files in the user's windows directories and in the global windows directories and replace same files by symlinks (to avoid diskspace problems).

5.1.1. Sample RedHat 8.0 .spec file for review purposes


%define DATE 20030115
Summary: A Windows 16/32 bit emulator.
Name: wine
Version: %{DATE}
Release: 1rh8winehq
Group: Applications/Emulators
License: LGPL
URL: http://www.winehq.com/
Source: ftp://metalab.unc.edu/pub/Linux/ALPHA/wine/development/Wine-%{version}.tar.bz2
Source1: wine.init
Patch: wine-%{version}-initial.patch
Patch1: wine-%{version}-kde2.patch
Patch2: wine-%{version}-winelauncher.patch
Patch3: wine-%{version}-defaultcfg.patch
Patch4: wine-%{version}-stabs+.patch
Buildroot: %{_tmppath}/%{name}-root
ExclusiveArch: %{ix86}
Prereq: shadow-utils
Conflicts: kdebase < 2.0
Requires: cups-libs >= 1.1.12
BuildRequires: docbook-utils, cups-devel >= 1.1.12, autoconf253, perl

%description
While Wine is usually thought of as a Windows(TM) emulator, the Wine
developers would prefer that users thought of Wine as a Windows
compatibility layer for UNIX. This package includes a program loader,
which allows unmodified Windows 3.1/95/NT binaries to run under Intel
Unixes. Wine does not require MS Windows, but it can use native system
.dll files if they are available.

%package devel
Summary: Wine development environment.
Group: System Environment/Libraries
Requires: wine = %{version}

%description devel
Header and include files for developing applications with the Wine
Windows(TM) emulation libraries.

%prep
%setup -q -n wine-%{version}
find . -type d -name CVS |xargs rm -rf
%patch -p1 -b .initial
%patch1 -p1 -b .kde2
%patch2 -p1 -b .wl
%patch3 -p1 -b .defcfg
%patch4 -p1 -b .stabs+

%build
export CFLAGS="$RPM_OPT_FLAGS"
autoconf || autoconf-2.53
%configure \
	--with-x \
	--libdir=%{_libdir}/wine \
	--includedir=%{_includedir}/wine \
	--sysconfdir=%{_sysconfdir}/wine

make depend
make
make -C documentation doc

%install
rm -rf $RPM_BUILD_ROOT

%makeinstall \
	includedir=%{?buildroot:%{buildroot}}%{_includedir}/wine \
	libdir=%{?buildroot:%{buildroot}}%{_libdir}/wine \
	sysconfdir=%{?buildroot:%{buildroot}}%{_sysconfdir}/wine \
	dlldir=%{?buildroot:%{buildroot}}%{_libdir}/wine/wine \
	LDCONFIG=/bin/true

for i in system "Start Menu/Programs/Startup" Profiles/Administrator Fonts \
         Desktop Favorites NetHood Recent SendTo ShellNew; do
	mkdir -p "$RPM_BUILD_ROOT%{_datadir}/wine-c/windows/$i"
done
mkdir -p "$RPM_BUILD_ROOT%{_datadir}/wine-c/My Documents"
mkdir -p "$RPM_BUILD_ROOT%{_datadir}/wine-c/Program Files/Common Files"

# Take care of wine and windows configuration files...
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/wine
mv documentation/samples/config documentation/samples/config.orig
sed "s/\"GraphicsDriver\" = .*/\"GraphicsDriver\" = \"ttydrv\"/" documentation/samples/config.orig |\
sed "s|\"Path\" = \"/c\"\$|\"Path\" = \"$RPM_BUILD_ROOT%{_datadir}/wine-c\"|" |\
sed "s|\"Path\" = \"\${HOME}\"$|\"Path\" = \"%{_builddir}/%{buildsubdir}\"|" -> documentation/samples/config
WINEPREFIX=%{_builddir}/%{buildsubdir}/documentation/samples programs/regedit/regedit winedefault.reg > /dev/null
# Wait until wineserver finishes and closes those files
sleep 5
install -c -m 0644 documentation/samples/system.reg $RPM_BUILD_ROOT%{_sysconfdir}/wine/system.reg
install -c -m 0644 documentation/samples/user.reg $RPM_BUILD_ROOT%{_sysconfdir}/wine/user.reg
install -c -m 0644 documentation/samples/userdef.reg $RPM_BUILD_ROOT%{_sysconfdir}/wine/userdef.reg
rm -f documentation/samples/system.reg
rm -f documentation/samples/user.reg
rm -f documentation/samples/userdef.reg

sed "s|\"Path\" = \"/c\"\$|\"Path\" = \"%{_datadir}/wine-c\"|" documentation/samples/config.orig > documentation/samples/config.rh
install -c -m 0644 documentation/samples/config.rh $RPM_BUILD_ROOT%{_sysconfdir}/wine/wine.conf
rm -f documentation/samples/config
rm -f documentation/samples/config.rh
mv documentation/samples/config.orig documentation/samples/config

# Install link to windows applications replacements
ln -sf %{_libdir}/wine/notepad.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/notepad.exe
ln -sf %{_libdir}/wine/regedit.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/regedit.exe
ln -sf %{_libdir}/wine/rundll32.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/rundll32.exe
ln -sf %{_libdir}/wine/wcmd.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/cmd.exe
ln -sf %{_libdir}/wine/control.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/control.exe
ln -sf %{_libdir}/wine/winhelp.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/help.exe
ln -sf %{_libdir}/wine/notepad.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/notepad.exe
ln -sf %{_libdir}/wine/progman.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/progman.exe
ln -sf %{_libdir}/wine/regsvr32.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/regsvr32.exe
ln -sf %{_libdir}/wine/winemine.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/winmine.exe
ln -sf %{_libdir}/wine/winver.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/winver.exe
ln -sf %{_libdir}/wine/uninstaller.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/uninstaller.exe
ln -sf %{_libdir}/wine/winhelp.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/winhelp.exe
ln -sf %{_libdir}/wine/winhelp.exe.so $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/winhlp32.exe

for i in shell.dll shell32.dll winsock.dll wnsock32.dll; do
	touch $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system/$i
done
touch $RPM_BUILD_ROOT%{_datadir}/wine-c/autoexec.bat
touch $RPM_BUILD_ROOT%{_datadir}/wine-c/config.sys
touch $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/win.ini
install -c -m 0644 documentation/samples/system.ini $RPM_BUILD_ROOT%{_datadir}/wine-c/windows/system.ini

cat >RedHat <<EOF
Wine directory structure used in Red Hat Linux:
===============================================

%{_datadir}/wine-c is the root directory (aka C: drive) wine looks for
by default. It contains (empty) C:\windows and C:\windows\system
directories, needed to operate Wine without an existing Windows installation.

If you want to use Wine with an existing Windows installation that is mounted,
for example, in /mnt/windows-c, edit /etc/wine.conf to say

[Drive C]
Path=/mnt/windows-c
Type=hd
Label=Whatever
Filesystem=win95

instead of the defaults set by installation.

If you do this, you can safely remove %{_datadir}/wine-c.
(Alternatively, just mount your Windows partition to %{_datadir}/wine-c.)
EOF

# Allow users to launch Windows programs by just clicking on the .exe file...
mkdir -p $RPM_BUILD_ROOT%{_initrddir}
install -c -m 755 %SOURCE1 $RPM_BUILD_ROOT%{_initrddir}/wine

%clean
rm -rf $RPM_BUILD_ROOT

%pre
/usr/sbin/groupadd -g 66 -r wine &>/dev/null || :

%post
if ! grep -q "^/usr/lib/wine$" /etc/ld.so.conf; then
	echo "/usr/lib/wine" >>/etc/ld.so.conf
fi
/sbin/ldconfig
/sbin/chkconfig --add wine
/sbin/chkconfig --level 2345 wine on
/sbin/service wine start &>/dev/null || :

%preun
if test "$1" = "0"; then
	/sbin/chkconfig --del wine
fi

%postun
if test "$1" = "0"; then
	perl -pi -e "s,^/usr/lib/wine$,,g" /etc/ld.so.conf
	/usr/sbin/groupdel wine &>/dev/null || :
fi
/sbin/ldconfig

%files
%defattr(-,root,root)
%attr(0775, root, wine) %dir %{_datadir}/wine-c
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/system
%attr(0775, root, wine) %dir "%{_datadir}/wine-c/windows/Start Menu"
%attr(0775, root, wine) %dir "%{_datadir}/wine-c/windows/Start Menu/Programs"
%attr(0775, root, wine) %dir "%{_datadir}/wine-c/windows/Start Menu/Programs/Startup"
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/Profiles
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/Profiles/Administrator
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/Fonts
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/Desktop
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/Favorites
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/NetHood
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/Recent
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/SendTo
%attr(0775, root, wine) %dir %{_datadir}/wine-c/windows/ShellNew
%attr(0775, root, wine) %dir "%{_datadir}/wine-c/My Documents"
%attr(0775, root, wine) %dir "%{_datadir}/wine-c/Program Files"
%attr(0775, root, wine) %dir "%{_datadir}/wine-c/Program Files/Common Files"
%{_libdir}/wine
%{_bindir}/*
%{_mandir}/man?/*
%{_datadir}/wine-c/windows/system/*.dll
%{_datadir}/wine-c/windows/*.exe
%config %{_datadir}/wine-c/autoexec.bat
%config %{_datadir}/wine-c/config.sys
%attr(0664, root, wine) %config %{_datadir}/wine-c/windows/win.ini
%attr(0664, root, wine) %config %{_datadir}/wine-c/windows/system.ini
%config %{_sysconfdir}/wine/*
%config %{_initrddir}/*
%doc ANNOUNCE BUGS COPYING.LIB ChangeLog DEVELOPERS-HINTS LICENSE LICENSE.OLD README VERSION
%doc AUTHORS RedHat
%doc documentation/ChangeLog.OLD documentation/HOWTO-winelib documentation/README.fr
%doc documentation/wine-devel documentation/wine-user documentation/winelib-user documentation/samples

%files devel
%defattr(-,root,root)
%{_includedir}/*