
		Notes on building X.Org for OpenBSD X hackers


This document presents some techniques that can be useful for people
wanting to hack the XF4 tree. It assumes some basic knowledge of the
OpenBSD build system, as described in the release(8) manual page.

o Source tree
  -----------

The XF4 directory has several sub-directories :

- distrib: the data files used by the make release process
- extras:  some extra X application(s) not included anywhere else
- xc-old:  a partial XFree86 3.3.6 source tree, used to build the
           XFree86 3.3.6 servers on i386 and mac68k.
- xc:      the X.Org 6.8.1 source tree, augmented with some OpenBSD
	   additions (xlock, fvwm, wm2, the wsfb module, the usb
	   tablet input driver). 

o Shadow trees
  ------------

Always use a shadow tree to build X, especially on multiple
architectures.

Let's assume XF4 is in /source/XF4, and you want to setup the build
shadow tree in /obj/XF4 do:

       mkdir -p /obj/XF4
       cd /obj/XF4
       lndir /source/XF4

Don't forget to update the shadow tree each time something gets added
in /source/XF4.

There is a script to remove dead links from the shadow tree when stuff
gets removed from /source/XF4: xc/config/util/cleanlinks.sh (to be
run from the top of the shadow tree).

o Makefile targets
  ----------------

There are two ways to build X in OpenBSD either from XF4 or from
XF4/xc.

The Makefile in XF4 is added by OpenBSD to provide a set of high-level
targets compatibles with the rest of the OpenBSD build environment.

all, compile: cleans the tree and restart a full compilation. Can be run
	as a non root user.
install: installs programs and manual pages to ${DESTDIR}. DESTDIR
         defaults to /. Needs to be run as root.
build:	 execute 'make compile and make install in sequence'. This
	 target knows about the SUDO variable in /etc/mk.conf. So it
	 can be run as a non root user if SUDO is set.
release: installs programs and manual pages to ${DESTDIR} and builds a
         set of distribution tar balls in ${RELEASEDIR}. Both DESTDIR
         and RELEASEDIR should be set. Any existing X files will be
         removed from DESTDIR first.
clean:   removes produced object files, but not Makefiles
distclean: removes every produced file.


If you start from the xc directory, you'll need to use the make
targets, as defined by X:

World: cleans the tree and starts a full build. This is the only safe
       way to start if the tree was not built before.
Everything: regenerates all Makefiles and rebuild without cleaning
            (dependencies are supposed to be good enough, which is not
            always true; so if something goes wrong after a make
            Everything, try a make World)
clean: removes produces files, but not Makefiles. Note that after a
       make clean, 'make includes ; make depend' are needed before a
       'make'.
distclean: removes every produced file. a 'make World' from the xc
           directory is the only safe way to restart a build after
           that.
Makefile:  rebuild the Makefile in the current directory
Makefiles: rebuild Makefiles in all sub-directories. (recursive)
includes:  rebuild files and links needed for the build (recursive)
depend:    generate make dependencies (recursive)
all:       rebuild things (default target, recursive)
install:   install programs (recursive, should be run as root)
install.man: install manual pages (recursive, should be run as root)

In xc/programs/Xserver, there's a special target 'load<Server>' to
just relink the specified X server. For instance to relink the 'Xorg'
server, use 'make loadXorg', to relink the Xnest server use 'make
loadXnest' and so on...

o How to build something with debug information?
  ----------------------------------------------

The /usr/X11R6/bin/makeg command calls make with proper arguments to
build object files and executables with -g.
It's not reasonable to use it on the whole tree, except on modern
machines with more than 512MB of RAM, because it will take gigabytes
of disk space and hundreds of megabytes of memory.

Use it in selected directories after a regular build by doing:

    make clean
    make includes
    make depend
    makeg

in the directory(ies) in which you need debugging information.

If you did that in a subdirectory of the Xserver, finish by relinking
the X server:

    make loadXorg

in xc/programs/Xserver.

o How to get a core file out of the X server?
  -------------------------------------------

Several things are needed:

1) set kern.nosuidcoredump=0 in /etc/sysctl.conf
2) put 

        Option  "NoTrapSignals" "true"

   in the "ServerFlags" section of /etc/X11/xorg.conf. If such a section 
   doesn't exist, it can be added as follow:

   Section "ServerFlags"
        Option  "NoTrapSignals" "true"
   EndSection

   anywhere in the configuration file. 

3) start the X server as root, with the -keepPriv option. A regular
   user is not allowed to use this option. If you use xdm, you can add
   the option in /etc/X11/xdm/Xservers. If you want to use startx, you
   need to run it as root, like this:

   startx -- /usr/X11R6/bin/X -keepPriv

Now the X server will dump core when catching a fatal signal. But it
will also not be able to restore the text mode on exit. So be prepared
to log in remotely (serial terminal or ssh) to reboot your machine or
to restart X.

o Where to set variables?
  -----------------------

Most imake configuration files set variables only if they were not
previously set in host.def.  So, when hacking on X, you can modify the
vast majority of imake's configuration variables in
xc/config/cf/host.def.

Only some of them require direct modification in
xc/config/cf/OpenBSD.cf or other files under xc/config/cf.

Once you're happy with a change, you can reflect it in the file where
the default value is set, or in OpenBSD.cf if the change is specific
to OpenBSD.

xc/config/cf/README has an almost complete list of configuration
variables and rules for imake.

o Building a X server only
  ------------------------

One of the most common configuration hacking is to build only a
statically linked Xorg server without spending time in all the rest.

Use the following host.def file:

---Cut here---
#define InstallEmptyHostDef

#define BuildServersOnly	YES

/*
 * you may also restrict the drivers that are built by editing and
 * uncommenting the line below
 */
/* #define XF86CardDrivers		neomagic */

#define UsbMouseSupport			NO
#define DoLoadableServer		NO
#define XnestServer			NO
#define XVirtualFramebufferServer	NO
#define XprtServer 			NO
#define BuildGlxExt			NO
#define BuildGLXLibrary			NO
#define BuildGLULibrary         	NO
#define BuildRenderLibrary		NO
#define BuildXprint                     NO
#define BuildLBX			NO
#define BuildType1			NO
#define BuildFreeType			NO
#define BuildXTrueType			NO
#define BuildSpeedo			NO
#define	BuildFonts			NO
#define BuildXFree86ConfigTools		NO
---Cut here---

The host.def file is supposed to be in xc/config/cf during
build. There are several ways to achieve that:

- if you're using the Makefile in XF4 copy it to
  xc/programs/Xserver/hw/xfree86/etc/bindist/OpenBSD-xxxx, where xxx
  is the X.Org name for your architecture. It will be copied into
  place in the first stages of 'make compile'
- if you're using the xc Makefile, you should put it directly into
  xc/config/cf in the shadow tree. This allows you to have several
  shadow trees with different host.def.

o Partial builds
  --------------

Apart of the ServersOnly build described above, it's pretty hard to
build only parts of the tree, without having first built everything,
since many parts depend on each other, and recursive make cannot
handle this at all.

Please be patient and (re)build X from the top of the tree as much as
possible. Trying to be smarter will considerably augment the risk of
things getting out of sync and make you lose time.

Whenever you want to rebuild something in a particular directory
without touching the rest, use the following sequence:

make clean
make Makefile
make Makefiles
make includes
make depend
make

No, there is no built-in target to handle this. As mentioned above, a
particular X server can be re-linked by running:

make load<Server>

in xc/programs/Xserver.

If you decide to rebuild an X server with DoLoadableServer NO, you
need to make clean/Makefile/etc. in lib/font before going to
programs/Xserver.

o About OpenBSD.cf
  ----------------

xc/config/cf/OpenBSD.cf holds most of the OpenBSD specific imake
configuration for OpenBSD. It has basically 2 parts:

- a general section defining stuff for all OpenBSD architectures
- several architecture-dependent sections, ended by some defaults
  for all architectures.

The general section defines things about the libc and kernel features,
as well as about the build environment.

The architecture specific sections can be used to customize the X
server build and some of the above features that need special
treatments.

Since host.def is read once before OpenBSD.cf, settings that can be
overridden in host.def are encapsulated in

  #ifndef HasFeature
  #  define HasFeature   YES or NO
  #endif

constructions. If you need to override a setting that doesn't have this
protection, you will need to change OpenBSD.cf (Well, this is not
really required, but let's say it so for now).

Note that all imake defines should have a value (YES/NO or something
else). Putting just

#define HasFeature

is equivalent to:

#define HasFeature NO

which is generally not what you want.

o Other tricks about OpenBSD.cf
  ------------------------------

- Most of the server build configuration is controlled by xorg.cf,
  which is included last in most architecture dependent
  sections. Before including this file, variables are set to OpenBSD
  specific values to control its actions.
  Some old servers still use xf86.rules or even no external file to
  configure their X server. I'd recommend that they switch to the use of
  xorg.cf.

- Building the libraries is handled on OpenBSD 2.9 and later by
  OpenBSDLib.rules. This file has a set of rules that apply to both
  a.out and ELF libraries and don't suffer from common mistakes made
  on ELF architectures by other systems.

o What to do when make detects an error in a generated Makefile?
  --------------------------------------------------------------

A common problem that arises when hacking imake configuration files is
that imake can generate incorrect Makefiles, leadings to errors in
'make'. The easiest to recover is to fix the problem in the Imakefile
or in the files in xc/config/cf/ and to re-generate the faulty
Makefile with:

    make -f Makefile.bak Makefile

But this will not always work, especially if Makefile.bak is bad too.

*Don't* use just 'xmkmf' to generate the Makefiles in the X
tree. xmkmf uses the installed X from /usr/X11R6 instead of the
in-tree files. You should pass 2 arguments to xmkmf: the relative path
from the current dir to the top of the source (i.e. the xc directory)
and the relative path from the top to the current directory.

For instance, to rebuild the Makefile in xc/programs/Xserver if you've
lost both Makefile and Makefile.bak, use

    xmkmf ../.. programs/Xserver


o A small explanation on how imake works
  --------------------------------------

Most of this is taken more or less verbatim from the imake(1) manual
page. Please read it for more details.

Imake takes an Imakefile as input and produces a Makefile, with the
help of configuration files.  It is really just a wrapper to call the
C preprocessor on the Imakefile with the correct option. But imake
itself is generally not called directly either. It's called by the way
of the 'xmkmf' script or from the rules in a (I)makefile.

imake starts by generating a file containing three lines:

    #define IMAKE_TEMPLATE "Imake.tmpl"
    #define INCLUDE_IMAKEFILE <Imakefile>
    #include IMAKE_TEMPLATE

and calls cpp on it, passing all -D and -I options from imake to cpp.
Imake.tmpl is the template Makefile and it will include all other
needed configuration files.

In imake configuration files, you'll find two kinds of things:
definition of cpp macros and actual make variable definitions or
rules.

This is the actual tree of included files, in order for OpenBSD:

Imake.tmpl
  Imake.cf
  site.def
    host.def
    xf86site.def
  OpenBSD.cf
    xorg.cf
      xf86.rules
    OpenBSDLib.rules
  site.def
    host.def
  Imake.rules
  X11.rules
  X11.tmpl
    bsdLib.tmpl
  Imakefile
    Threads.tmpl
    Libray.tmpl
    Server.tmpl
      xorg.tmpl
    ServerLib.tmpl

Note that host.def is included twice, before and after OpenBSD.cf. The
first time 'BeforeVendorCf' is YES and the second time 'AfterVendorCf'
is YES.

The Imakefile can include other configuration files. Imakefiles
building a library will include Library.tmpl. Imakefiles building
server parts will include either Server.tmpl or ServerLib.tmpl.  An
Imakefile to build a regular program doesn't normally need to include
anything else.

o Writing Imakefiles
  ------------------

Imakefiles are very close in philosophy to BSD make Makefiles. You
only need to specify source and object files in the Imakefile and
the rest of the Makefile will be added from the configuration files by
imake.

It's better to use one directory per program or library to build. It
will make Imakefiles simpler to write.

If the application has only one source file, the Imakefile can be real
simple. The SimpleProgramTarget() macro takes care of everything. You
just need to specify libraries and library dependencies with the
DEPLIBS and LOCAL_LIBRARIES make variables. This is for instance the
Imakefile for xev:

---Cut here---
        DEPLIBS = $(DEPXONLYLIB)
LOCAL_LIBRARIES = $(XONLYLIB)

SimpleProgramTarget(xev)
---Cut Here---

For more complex programs, define SRCS and OBJS to the list of source
and object files, and use the ComplexProgramTarget() macro to specify
the name of the executable and manual page to install. See
xc/programs/xlogo/Imakefile for an example.

The following make variables alter the behavior of the compilation
rules:

DEFINES holds extra -D and -U options to pass to CPP
INCLUDES holds extra -I options to pass to CPP

DEPLIBS holds the list of library dependencies (ie libraries on which
the executable depends, in a form suitable for a dependencies line).
LOCAL_LIBRARIES holds the list of libraries to link into the
executable. Under OpenBSD *don't* rely on implicit intra-library
dependencies to omit libraries that are required by others.

The following macros or make variables are useful to describe the most
commonly used X libraries:

$(DEPXONLYLIB), $(XONLYLIB): libX11 alone
$(DEPXLIB), $(XLIB):	     libX11 and X extension lib
$(DEPXTOOLLIB), $(XTOOLLIB): libXt and its dependencies (libSM,
			     libICE) but without libX11.
$(DEPXPMLIB), $(XPMLIB):     libXpm alone.

XawClientDepLibs, XawClientLibs:    libXaw and all its dependencies (libXmu,
				    libXt, libSM, libICE, libXpm, libX11,
				    libXext)
XmuuClientDepLibs, XmuuClientLib:   libXmuu and all its dependencies
				    (libX11 and libXext)


To build a library, define the SRCS and OBJS make variables and
include <Library.tmpl>. The following macros control the produced
library:

LibName	:	the name of the library
DoSharedLib:	build a shared lib?
SoRev:		shared lib version
LibHeaders:	install $(HEADERS) in /usr/X11R6/include ?
IncSubdir:	subdir of /usr/X11R6/include to install $(HEADERS) to.

-- 
$Id: README,v 1.18 2005/08/16 20:39:22 matthieu Exp $
