English | Japanese | German

# Unofficial OpenOffice Hacker's guide for 1.1

Building and hacking on OpenOffice.org (OO.o) entails climbing a fairly lengthy incline. Hopefully this document will make the learning curve somewhat steeper and more abrupt, and will give you a walking stick to help you out.

This document assumes that you'll be using a reasonably current Linux system, as a time saving feature. Real hackers use Free software, and don't have time to read about non-Free stuff.

We aim to answer at least the following questions:

- How do I build OO.o
- How do I go around a development iteration
- How do I debug it
- How do I send a patch

If you need help getting OO.o build, and you intend to hack on it, please join the mailing list here and ask questions there.

## 0. Contents

- 1. Getting OO.o
- 2. Building OO.o
- 3. Installing OO.o
- 4. Running OO.o
- 5. Hacking OO.o
- 6. Debugging OO.o
- 7. Contributing patches
- 8. Misc. tips
- 9. Useful Links
- 10. IFAQ
- 11. Working with us

This process is discussed in far more detail in the detailed build guide. We have however worked hard to make the process feasible for mere mortal programmers; and the easy description is what follows.

## 1. Getting OO.o

There are loads of competing versions of OO.o, and several choices of branch, with multiple outstanding patch sets. I recommend you build from CVS snapshots, that are known to build, and with patch sets against them that are known to apply. So to get the source do:

        export CVSROOT=':pserver:anonymous@anoncvs.gnome.org:/cvs/gnome'
        cvs login
        cvs -z3 checkout -r ooo-build-1-3 -P ooo-build

This will provide you with a copy of the ooo-build tree. If CVS scares you, you may be able to get a recent packaged version from here.

Note: You are going to need to download ~200Mb of compressed source, and have ~5Gb of space space to unpack and build it in.

## 2. Building OO.o

### 2.1. configure

The build process is pretty complicated; you have a choice of commands now; although running both won't actually hurt:

          ./autogen.sh # the CVS version
          ./configure  # the packaged version

This will guess which branch snapshot you want to build; if you have other ideas use the --with-tag option; eg.

    --with-tag=OOO_1_1_0

for a legacy branch.

### 2.2 download

By the time you've upgraded your system to the point that it has all the packages you need to start building OO.o (mozilla, recent libart etc. etc.) you're almost at the point that you can download the source. To do this, after a successful configure simply type:

    ./download

and wait.

### make

This is the taxing bit - type

    make

and don't forget to press enter. Quite possibly you want to log the output, so why not

    make 2>&1 | tee /tmp/log

.

## 3. Installing OO.o

The result of a perfect build is a perfect zipped install set located in

    build/$TAG/instsetoo/unxlngi4.pro/01/normal/

or similar. Then run the setup program from there to install using eg.

    /opt/OOInstall

to install to. It's possible to do this you'll need to first remove your

    ~/.sversionrc

file.

Having installed, you want to get in the mood for hacking by linking your build tree directly into the installed image, so by re-compiling a source sub-directory, you can simply re-run OO.o. This can get your build/test cycle down to a few tens of seconds. To do this do eg.

    linkoo /opt/OOInstall /opt/ooo-build/build/OOO_1_1_2

NB. see also the linkoo limitations.

## 4. Running OO.o

Now wander into

    /opt/OOInstall/program

and do:

    source ./env

this will setup your (bash) shell for running OO.o directly. Then simply

    soffice.bin

. This is better than running soffice, or a wrapper script since it's very easy to attach the debugger:

    gdb soffice.bin

.

Note: do not use

    ./soffice.bin

for reasons inscrutable this completely fails to work.

Note: you need to run the ooo-wrapper based OO.o before this, such that ~/.sversionrc is setup correctly first, otherwise running soffice.bin will throw you into the GUI setup tool. Just do a one-off

    oowriter

before you start.

## 5. Hacking OO.o

### 5.0. My first hack

So - we've built and run OO.o, and we want to prove to ourselves that it is in fact possible to hack on it. So in a new terminal do this:

          cd build/$TAG
          . ./LinuxIntelEnv.Set.sh
          cd vcl

Now have a hack at vcl/source/window/toolbox2.cxx; I suggest adding (eg.) an

    nPos = 0

anywhere before the m_aItems.insert in ToolBox::InsertItem( const ResId &rResId ...). Then save.

You're still in vcl/ yes ? then type 'build debug=true'; wait for the scrolling text to stop; (5 seconds?). Now re-run

    soffice -writer

. You should notice the effect.

Note: this assumes you have carefully followed the previous steps, particularly the linkoo in Section 3.

Note: for day to day hacking you want to just run 'build' inside the source tree. Do not run 'make' in the toplevel

    ooo-build/

directory or you will (most likely) trash any changes you've made, and get depressed. It makes sense to keep an out-of line copy of

    build/OOO_1_1_2

somewhere else see here for help relocating the build.

### 5.1. Read the Fine manual

With the power of C++ comes the ability to shoot yourself in the foot all the more easily; (and implicitly), cf. Holub, Rules for C and C++ programming, McGraw-Hill, 95.

The best way to prepare yourself for battle is to read the OpenOffice coding guidelines here, and for the easily confused c'tor / d'tor is short for constructor / destructor.

### 5.2. Sending patches

It is seldom clear which module a patch resides in in bugzilla. A quick way to try and work this out is to do:

    cvs status <somefile> | head

This should give a 'Repository Revision:' line, with a path, the 2nd fragment of this is the project name.

### 5.3 Hacking the installer

Since the installer image deletes the (runnable) temporary setup image in `/tmp/sv001.tmp`, you have to stop it doing that. To do so, run setup / install with the -dontdeletetemp option.

### 5.4. Hacking other bits

Having got a working install, the best way to add your hacks is to symlink `program/libfoo641li.so` to the version you just built — most likely in `foo/unxlngi4.pro/lib/`, then re-run the suite and your changes should be incorporated.

For example; say you want to hack 'sal' the System Abstraction Layer and you've installed OOO_STABLE_1 into /opt/OOInstall you need to do:

    cd /opt/OOInstall/program
    mkdir backup
    mv libsal.so.3.0.1 backup
    ln -s /opt/OpenOffice/OOO_STABLE_1/sal/unxlngi4.pro/lib/libsal.so.3.0.1 .

### 5.5. Understanding D' make (man)

While the build system is in similar to may other systems, it is also perhaps slightly different. The overview is that each module is built, and then the results are delivered into the solver. Each module builds against the headers in the solver. Thus there are a few intricacies.

- build — this perl script solenv/bin/build.pl is used in conjunction with prj/build.lst to ensure that every module that is needed is built first.

  build then un-winds internal module dependencies, and builds each module with a chdir, dmake pair.

- deliver — this perl script solenv/bin/deliver.pl installs headers, and libraries (etc.) into the solver, as informed by prj/d.lst. Crucially deliver ensures that the date stamp on any file that is installed to the solver is the same as that in the module's directory. This ensures, that (particularly for headers) that there is no dependency cascade triggering re-builds in other modules.

#### 5.5.1 Standard directories

There are various standard directories and files in most of the modules that make up OO.o, here are some of the more useful:

- prj
  - build.lst — this lists directories to be made, '^#' comments are allowed, the order of the list is immaterial see detail, it is dictates build's operation.
  - d.lst — this file describes the deliver process, see detail.
- util — typically the util directory is charged with glueing together the sub-libraries for each sub-module into a single large library, adding system library dependencies, building GUI resource files etc. All the work is described in makefile.mk, this is usually the last directory to be built in a project.
- inc — public headers are typically separated into an 'inc' directory, these will be installed into the solver by the 'deliver' phase (using prj/d.lst)

There are also various file types that are (or are not) interesting:

- makefile.rc — these are ~all redundant, and can safely be ignored.
- makefile.mk — these in contrast are the 'dmake' files, that are used to build each source directory.

#### 5.5.2 build.lst

On first view build.lst looks scary:

    vc      vcl : nas freetype psprint rsc sot ucbhelper unotools sysui NULL
    vc      vcl                      usr1   -       all     vc_mkout NULL
    vc      vcl\source\unotypes      nmake  -       all     vc_unot NULL
    vc      vcl\source\glyphs        nmake  -       all     vc_glyphs vc_unot NULL

so we need to try and un-pack what's going on here, which is in fact not as odd as it might seem at first glance. Firstly lists are terminated by the 'NULL' string. Every line is prefixed by a shortcut which is irrelevant.

- First active line contains a ':', this describes the fact that this project (vcl) depends on these other modules 'nas', 'freetype', 'psprint' etc. to be built first. This is for inter-project dependencies.
- Then we have a redundant line 'usr1' [ for fun ? ], in fact only lines containing the magic string 'nmake' are valid after this.
- The next lines describe internal project directory dependencies and look like:

      [shortcut] [path to dir to build] nmake - [flags] [unique-name] [deps...] NULL
      vc           vcl\source\glyphs    nmake -   all     vc_glyphs   vc_unot   NULL

  shortcut is not used; flags determines which platforms this builds on; usually single char platform codes: 'dnpum' 'u' being Unix. The higher up the system, the more stuff is flagged 'all'.

  unique-name this is a magic name, used by other lines to describe an internal dependency. deps... any number of names of other directories in this file, that must be built before this one.

So we see in the vcl case that vcl\source\unotypes (vc_unot) has to be built before vcl\source\glyphs (vc_glyphs). It is important to understand that the order of the list is ~immaterial, and instead of a simple ordered list, we have a more complex internal dependency system — this contrasts with most other make systems.

There is also documentation here on it.

#### 5.5.3 d.lst

The syntax of d.lst is more comprehensible than build.lst, it omits some default actions, such as copying build.lst into inc/<module>/build.lst.

A line is of the form:

    [action]: [arguments]
    mkdir:    %_DEST%\inc%_EXT%\external

where if '[action]:' is omitted, it defaults to the 'copy' action. Typical actions are copy, mkdir, touch, hedabu, dos and linklib.

The 'hedabu' action is particularly interesting, inasmuch that it cosmetically re-formats the header to shrink it on install (otherwise it's much like the copy action).

During the action, various macro variables are expanded some of which are:

- %__SRC% — distribution directory name eg. unxlngi4.pro
- %_DEST% — absolute path into solver eg. /opt/OpenOffice/OOO_STABLE_1/solver/641/unxlngi4.pro
- %_EXT% — (unusual) way of having minor updates eg. 641.1, typically used to version every base sub-directory.

Typically then, if indeed you need to add a rule (cf. implicit directory copies), it will be of the form:

    ..\%__SRC%\inc\sal\*.h %_DEST%\inc%_EXT%\sal\*.h

NB. relative paths are relative to the 'prj/' directory.

### 5.6 fast iteration

There are lots of ways to go round a development iteration; the best way is to use linkoo to symlink the libraries from the install set directly into your build tree. Then you can simply re-build a sub-directory eg.

    vcl

by running

    build

and re-run soffice.bin.

### 5.7 Can I get a `char *`, please?

Just barely. OO.o has at least six string wrappers, although the C implementations are of little interest:

- `rtl_String` — sal/inc/rtl/string.h
  "Normal" string plus reference counting. `rtlstring->buffer` is useful, as is `rtlstring->length`. This string has already been converted to a particular character set; see sal/inc/rtl/textenc.h — the only interesting cases are `RTL_TEXTENCODING_UTF8` and perhaps `RTL_TEXTENCODING_ASCII_US` for real luddites. Feel free to treat `rtlstring->buffer` as your beloved `char *`.

- `OString` — sal/inc/rtl/string.hxx
  Simply a rtl_String wrapped inside a `class`; you can use `ostring.pData` to get at the rtl_String (it's public). `OString` has reasonably useful methods for if you need them.

- `rtl_uString` — sal/inc/rtl/ustring.h
  "Normal" Unicode string, similar to rtl_String, and refcounted as well. However, this one always comes in UCS-2 encoding, presumably to be compatible with Java's questionable choices.

- `OUString` — sal/inc/rtl/ustring.hxx
  An rtl_uString wrapped inside a `class`. This is what most of the OO.o code uses to pass strings around.

- `String` — tools/inc/string.hxx
  This is an obsolete string class, aliased to 'UniString'. It has a number of limitations such as An rtl_uString wrapped inside a `class`. This is what most of the OO.o code uses to pass strings around.

Since real men use `char *` strings encoded in UTF-8; to use any system API such as 'printf' you need to extract a char * from a `OUString` use this:

    static char *
    gimme_utf8_please (const rtl::OUString &oustring)
    {
    	rtl::OString ostring;

    	ostring = ::rtl::OUStringToOString (oustring, RTL_TEXTENCODING_UTF8);
            return strdup (ostring.pData->buffer);
    }

And the reverse:

    static rtl::OUString
    complicate_things_into_ucs2_please (const char *utf8_string)
    {
    	rtl::OString ostring;

            ostring = rtl::OString (utf8_string);
    	return rtl::OStringToOUString (ostring, RTL_TEXTENCODING_UTF8);
    }

If you just want to programattically print out a string for debugging purposes you probably want to see this.

#### 5.7.2. Examining strings from GDB

We have already seen that OO.o does not use humble `char *` strings. If you thought this was painful enough when writing code, wait until you have to debug it. Here's how to get at your strings from gdb/dbx which don't natively handle unicode.

- from cvs branch cws_srx645_ooo112fix1 onwards you can use

      (gdb) print dbg_dump(sWhatEver)

  to print the contents of a UniString/ByteString/rtl::OUString/rtl::OString regardless of the type when debugging C++ code. See issue 17295 for details.

Alternatively if this support isn't in your version of OOo yet then...

- rtl_String: just poke at it
- String: — note, the decl' of this uses the macro 'UniString' to confuse readers of tools/inc/string.hxx. Luckily programattically we can transparently cast a String to an OUString.
- OString: p str->pData
- OUString, rtl_uString: (great tip from Kevin Hendricks) The quickest and best way to dump the string is to do:

            p *theString; # grab the length (2nd field)
            x/<length>s theString->buffer

  eg. for a 20 character string we want

      x/20s theString->buffer

  . This should print the string as an array of shorts with ASCII char values nicely in a column. To programatically print a OUString (or String) you need:

      ::rtl::OString tmpStr = OUStringToOString (MyOUString, RTL_TEXTENCODING_UTF8);
      fprintf (stderr, "String is '%s'\n", tmpStr.getStr());

#### 5.8. Linkoo Limitations

Linkoo while very powerful has a number of limitations imposed by the way OO.o is put together. There are 2 sorts of problem:

- Strange link behavior - ie. if you symlink the library it follows the link at runtime and ends up highly confused.
  - soffice.bin - this has to be copied from desktop/unxlngi4.pro/bin/soffice each time you go around a devel cycle; otherwise debugging gets confused.
  - libcfgmgr2.so - this has to be copied from configmgr/unxlngi4.pro/lib each time, otherwise the config cannot be loaded.
- Odd internal library construction
  - File filters have detection code; eg. sc/source/ui/app/sclib.cxx (ScDLL::DetectFilter) that is compiled to static libraries, installed then linked into libwrp in desktop/source/offwrp. To re-build in 'sc' run:

        build && deliver

    then in desktop/source/offwrp run:

        touch wrapper.cxx && dmake.

## 6. Debugging OO.o

This section assumes use of gdb, from the console.

### 6.1. Building with debugging symbols

OO.o includes a way to add debugging code in per module, via the `build debug=true` command in each module. Unfortunately this is not recommended to run for the whole project, and in addition to including vital debugging symbols it also includes scads of assertions, churning warnings, and various other checks.

Thus if you want debugging symbols for everything, you have to hack several makefiles to add debugging symbols, [ NB. this makes the OO binaries ~1Gb small and the full build tree ~8Gb so beware ], apply this patch:

    --- solenv/inc/unxlngi4.mk
    +++ solenv/inc/unxlngi4.mk
    @@ -92,18 +92,18 @@ cc=gcc
     # do not use standard header search paths
     # if installed elsewhere
     .IF "$(BUILD_SOSL)"!=""
    -CFLAGS=
    +CFLAGS=-g
     .ENDIF
     CFLAGS+=-fmessage-length=0 -c $(INCLUDE)
     # flags for the C++ Compiler
    -CFLAGSCC= -pipe -mcpu=pentiumpro
    +CFLAGSCC= -g -pipe -mcpu=pentiumpro
     # Flags for enabling exception handling
     CFLAGSEXCEPTIONS=-fexceptions -fno-enforce-eh-specs
     # Flags for disabling exception handling
     CFLAGS_NO_EXCEPTIONS=-fno-exceptions

     # -fpermissive should be removed as soon as possible
    -CFLAGSCXX= -pipe -mcpu=pentiumpro -fno-for-scope -fpermissive -fno-rtti
    +CFLAGSCXX= -g -pipe -mcpu=pentiumpro -fno-for-scope -fpermissive -fno-rtti

     # HACK: enable Hamburg developers to build on glibc-2.2 machines but compile vs. glibc-2.1 headers
     .IF "$(BUILD_SOSL)"==""

Of course, without debugging symbols gdb becomes even more useless. To apply the patch cut and paste the above to /tmp/foo and in the base directory:

    patch -p0 < /tmp/foo

### 6.2. Setting breakpoints

Due to the general level of brokenness in gdb, it's most likely that setting a breakpoint before running is unlikely to work; thus the best scheme is to:

    gdb ./soffice
    break main
    run # don't forget the arguments here
    # ... traps in main ...
    break osl_readFile
    continue

Of course, this is never going to work if the code is implemented in a library that is dlopened later, which accounts for the vast majority of OO code. Thus, you need to trap the code loading and then put the breakpoint in. To do that whack a breakpoint in osl_psz_loadModule, and suffer.

Alternatively if you can instrument the code, it's pretty easy to add #include <signal.h> and then put a raise (SIGSTOP); somewhere in the code which will trap out in the debugger.

### 6.3. Starting at the beginning

We start in 'main' with a sal wrapper, that calls vcl/source/app/svmain.cxx (SVMain). It invokes Main on pSVData->mpApp; but pSVData is an in-line local. To debug this use the pImplSVData global variable. eg:

          p pImplSVData->maAppData

This 'Main' method is typically: desktop/source/app/app.cxx (Main).

### 6.4. Examining strings

The humble char * (that gdb can natively display) is eschewed in the object world by wrapping it with innumerable different classes that gdb doesn't understand. Worse, in many cases it is extremely difficult even to print the string — one consequence of the appalling decision to go with ucs-2 encoding. There are also both mutable and immutable string classes.

Please read section 5.7.2 to see how strings work in OO.o and to get some debugging tips.

### 6.5 Getting the build order right

The build dependencies of the modules are clearly crucial to getting a clean build. When you type 'build' in a module, first build examines prj/build.list, eg. neon/prj/build.lst:

    xh      neon  :  soltools external expat NULL

this specifies that 'soltools', 'external' and 'expat' have to be satisfactorily built and delivered before neon can be built. Occasionally these rules get broken, and people don't notice for a while.

### 6.6 It crashes, but only in gdb

What fun — you symlinked desktop/unxlngi4.pro/bin/soffice to soffice.bin in your install tree didn't you. That works fine if you just run it, but it seems gdb unpacks the symlink and passes a fully qualified path as argv[0], which defeats the hunting for the binary in the path, so it assigns the program base path as /opt/OpenOffice/OOO_STABLE_1/desktop/unxlngi4.pro/bin and starts looking for (eg. applicat.rdb) in there. Of course when it fails to find any setup information, it silently crashes somewhere else yards away from the original problem.

### 6.7 It crashes, but doesn't crash

For various reasons signal handlers are trapped and life can get rather confusing; thus it's best for builders to apply something like this:

    --- sal/osl/unx/signal.c
    +++ sal/osl/unx/signal.c
    @@ -188,6 +188,8 @@ static sal_Bool InitSignal()
                 bSetILLHandler = sal_True;
            }

    +       bSetSEGVHandler = bSetWINCHHandler = bSetILLHandler = bDoHardKill = sal_False;
    +
            SignalListMutex = osl_createMutex();

            act.sa_handler = SignalHandlerFunction;

NB. trailing space.

### 6.8 I can't find the code from the trace

Some methods, are described as having a special linkage, such that they can be used in callbacks; these typically have a prefix: 'LinkStub', so search for the latter part of the identifier in a freetext search. eg.

          IMPL_LINK( Window, ImplHandlePaintHdl, void*, EMPTYARG )

builds the 'LinkStubImplHandlePaintHdl' method.

### 6.9 How can I re-build just the files I see in the trace

Often when you run gdb on a non-debugging build, you can't afford to wait, and re-compile (eg.) all of oowriter. Thus we have created a small perl helper, with which you can cut and paste method / class names you are interested in from the stack, and it'll touch just files containing those strings — for easier re-build. Here is a typical debugging workflow:

        gdb ./soffice.bin
        ...
        bt
    #0  0x40b4e0a1 in kill () from /lib/libc.so.6
    #1  0x409acfe6 in raise () from /lib/libpthread.so.0
    #2  0x447bcdbd in SfxMedium::DownLoad(Link const&) () from ./libsfx641li.so
    #3  0x447be151 in SfxMedium::SfxMedium(String const&, unsigned short, unsigned char, SfxFilter const*, SfxItemSet*) ()
       from ./libsfx641li.so
    #4  0x448339d3 in getCppuType(com::sun::star::uno::Reference const*) () from ./libsfx641li.so
    ...
        quit
        cd base/OOO_STABLE_1/sfx2
        ootouch SfxMedium
        build debug=true

Thus, all files referencing / implementing anything with SfxMedium will be touched, and hence rebuilt with debugging symbols.

### 6.10 How can I re-build all the files in one source directory

If you want to recompile the code in just your current directory, you can use the killobj dmake target to remove the object files:

        dmake killobj
        dmake

### 6.11 It always crashes in sal_XErrorHdl

You are a victim of asynchronous X error reporting;

    export SAL_SYNCHRONIZE=1

will make all the X traffic synchronous, and report the error by the method that caused it, it'll also make OO.o far slower, and the timing different.

### 6.12 It silently fails to load my word file

Caolan suggests: put breakpoints in ww8par.cxx top and tail of SwWW8ImplReader::LoadDoc, and confirm that the document gets as far as the import filter.

A handy human place to put a breakpoint is in SwWW8ImplReader::ReadPlainChars, you can see chunks of text as they are read in. Alternatively SwWW8ImplReader::AppendTxtNode as each paragraph is inserted.

### 6.13 How do I use the debug console ?

So OO.o contains some hefty debugging infrastructure; pictured here. Unfortunately enabling it is not altogether trivial. Firstly - none of it is built into a product build; so we need to go to re-build some core parts of OO.o as non-product builds; and then we need to re-run linkoo to link those new builds into our set.

First create a debug Environment file; I call it LinuxIntelEnv.Set.debug:

    TMPFILE=~/.Env.Set.debug

    # Purge .pro bits
    sed 's/\.pro//g' LinuxIntelEnv.Set.sh > $TMPFILE
    . $TMPFILE
    rm $TMPFILE

    # Clobber product parts
    unset PRODUCT PROSWITCH PROFULLSWITCH

Now do

    source ./LinuxIntelEnv.Set.debug

, this sets up your environment for a non-product build.

cd vcl; build dbgutil=true --all linkoo

Now - just run OO.o, and when it's in full-flow, press <Alt>-<Shift>-<Control> 'D' in that order; this should popup a debugging options window. The debugging options are subsequently saved to the .dbgsv.init file for the next run; you can control the location of that with:

    export DBGSV_INIT=$(HOME)/.dbgsv.init

eg. it is (unfortunately) a binary file.

### 6.14 Excel Interop debugging

This is fairly easy; edit sc/source/filter/inc/biffdump.hxx, define EXC_INCL_DUMPER to 1, and re-build 'sc'. Also, copy sc/source/filter/excel/biffrecdumper.ini to ~. Then run

    soffice.bin foo.xls

and you should get a foo.txt with the debug data in it. If you get nothing, you need to find/apply sc-biffdump.diff from here.

## 7. Contributing patches

### 7.1. Diff style

Always use unified diffs 'cvs -z3 diff -u', since they are the most readable, (and sensible) types of diff to read and apply.

### 7.2. Some interaction

It tends to be a good idea to work out how best to implement your fix, and/or discuss it with a developer or two before hand. Some of the best ways to do this are to post to dev@openoffice.org or lurk on IRC at `irc.freenode.net` on the `#OpenOffice.org` channel. IRC is an awfully poor communication medium, but better than no communication. See here to unwind who is whom.

### 7.3. ooo-build patch creation

See here for more information on our patching infrastructure.

### 7.4 filing bugs

See here for a sane / hackers interface to OpenOffice's IssueZilla.

Since we can often extract the owner of a module by checking for the ADMIN_FILE_OWNER tag; there is a little tool in ooo-build: bin/owner <file-name> that helps you find out who to E-mail / interact with about a given module; it's worth assigning very specifically located bugs to that person.

## 8. Misc. tips

### 8.1. Getting an OO.o CVS account

This is the process for getting CVS accounts for the up-stream CVS server, ooo-build accounts are handled differently. To see how the issue raising process works see eg. issue #7270. Having got the account setup, you need to tunnel to the secure CVS server something like:

    ssh -f -2 -P -L 2401:localhost:2401 tunnel@openoffice.org sleep 1400 < /dev/null > /dev/null

Then you need to change your CVSROOT to point at your local machine, since this is the endpoint of the tunnel:

    :pserver:mmeeks@localhost:/cvs

Your account name and password - will be the same as you use for filing bugs etc. in the SourceCast system. Login, and ... you'll soon notice that you'll need to migrate your CVS settings to the new server, to do this without wasting B/W with duplicate checkouts do:

    bin/re-root /path/to/checkout ":pserver:<account-name-here>@localhost:/cvs"

Of course, to commit anything, you'll need various project priviliges - and to battle the bureaucracy.

### 8.2 Using patch / diff

Patch/diff are a wonderful tools, however people often provide data that confuses them in a messy and difficult to un-tangle sort of a way. Here are some hints on untangling the mess:

- If at all unsure, run patch with --dry-run first, this will appear to do the patching action, but not actually do it [ this can give bogus results with compound inter-depending patches, but is extremely useful ].
- Mostly use patch -p0; 0 signifies the number of path elements to strip from the beginning of the file path the diff points at.
- When you mess up, and have 1/2 of the patch applied and want to revert to clean, either remove the files and cvs update, or re-patch with the '-R' option, to reverse the effect.
- Sometimes using diff between modules with lots of whitespace changes makes the patch hard to read; the '-w' flag to (cvs) diff makes this easier.

### 8.3 Make clean

Just use dmake clean in the toplevel directory. In pre HEAD versions there was no 'clean' target so instead you had to do something (what dmake clean does now) like:

    find -name 'unxlngi4.pro' -exec rm -Rf {} \;

### 8.4 CVS setup

In order to make efficient use of bandwidth, generate sensible diffs by default, and follow the trend, you need this in your ~/.cvsrc.

    cvs -z3 -q
    diff -upN
    update -dP
    checkout -P
    status -v

### 8.5. Adding header files to the build

Adding header files to the OO.o build is notoriously clunky. To add header files under external/, make sure you list them in external/prj/d.lst so that they get copied under the solver/641/unxlngi4.pro/inc/external directory when building.

### 8.6. Finding where to hack

Often there is some GUI element used near the thing you're trying to locate / fix. So, find some sufficiently unusual string and search for it in LXR's text search; this should reveal an identifier related to that string; eg. SID_AUTOFORMAT, or FN_NUM_BULLET_ON. Having obtained that, do a new text search for that string, and you'll find the usage [ or a chained define to something else ]. For eg. menus/toolbar buttons the functionality is usually in a case statement eg. case SID_AUTOFORMAT: ...

## 9. Useful links

### 9.1. www.OpenOffice.org

While much of the initial openoffice.org structure seems not to be orientated towards hackers, there is much useful documentation if you dig for it.

For OO.o news, and a distinctive perspective on OO.o see ooodocs.org.

Other related pages are: OOODIa Gtk+ Dictionary installer. OOExtras provides extra templates, macros, and clip art. Quickstart applet for GNOME (and KDE). Dictionaries & Docs from Kevin Hendricks.

### 9.2. Patch archives

While productising various releases of OpenOffice, different projects have come up with (quite huge) patch sets against OO.o. Mercifully they are starting to get folded back in at a greater rate, so no patches should be necessary to HEAD to build it, similarly many have got into OOO_STABLE_1. It may be necessary to use some/all of these nevertheless.

- Ximian's OO.o patches and build tools / snapshots are all available as packages; or as patches.
- Debian's helpful OO.o page, with patches. And also Debian CVS.
- Mandrake's OO.o patch archive.
- FreeBSD's OO.o port patches.
- Red Hat's .spec file (based on Mandrake's) is also worth a read, from their SRPM.
- People wanting to localize OO.o should study these patches from Pavel Janik.

## 10. (Infrequently) FAQ

So no-one ever asked me these, I just made them up to astro-turf a bit (safer, wipe-clean, more durable questions).

### 10.1. Why do branches like 'mws_srx644' have odd numbers in them ?

By consulting various oracles, entrails etc. it transpires that in theory this number increments weekly, there being weekly freezes and hence solvers, development environments. However - in recent time the process of solidifying a single build for wider release, has taken longer than a week — creating a quandary, and a mixed alphanumeric release tag. The 'mws' stands for 'Master Workspace'.

### 10.2. Why does the build require Java ?

Essentially it seems there are a lot of XML files involved in component registration, and various other services. It turns out that using Java is just an easy way to get this manipulation done simply. Also, Java can be used nicely at run-time if it's on the machine.

But from tag SRC680_m44 onwards there is an alternative python script included to address the issue of processing these XML files used for registration, so it should be possible to build versions after that date without java, though your milage may vary as the default build is with java.

### 10.3. Why is [t]csh so broken ?

This is rather inscrutable; some particularly curious brokenness would be the way piping commands on stdin is crucially different to inputting them from the tty thus:

    echo 'echo #define DLL_NAME "libsch641li.so" >./foo.hxx' | /bin/tcsh -s

fails to do anything whereas typing the same thing into the shell works just fine. Even more oddly:

    tcsh -fc 'echo #define DLL_NAME "libsch641li.so" >./foo.hxx'

does do the right thing. See also csh.

### 10.4. I just tried to re-locate the build, why doesn't it work ?

The simple answer is: you need to run

    relocate /path/to/new/build

; another more complex answer is:

Well, assuming you have re-configured things (LinuxIntelEnv.Set will need paths tweaking too — and re-importing to your shell) — then it's most likely down to the ubiquitous non-relative paths, coded in lots of generated / built files, particularly '.dpc*' (dependency) files. Try:

    find -name '*.dpc*' -exec rm {} \;

The stlport does some really broken things, so you will also need to edit the 'stl_gcc.h' inside the solver/, and replace the two path instances there (see inc/stl/config/stl_gcc.h).

### 10.5 CVS says 'Fatal Error aborting. [acc] no such user', why ?

While of course it's possible that your user name is not registered; often this just means your ~/.cvspass got lost and/or that you haven't logged in. cvs login, and repeat the command.

### 10.6 What does '.pro' in 'unxlngi4.pro' mean ?

Product — isn't it obvious ?

### 10.7 What does OpenOffice really look like ?

Today I found a photograph of it on my system, so I stuck it in here:

### 10.8 How do I take a screenshot of OO.o ?

OOo does some very odd things with X resources, thus some conventional screenshot apps fail to take accurate shots. ImageMagick's 'import' however does a good job; use:

    import foo.png

from the console, or

    sleep 2; import -window root foo.png

instead. NB. unless you want your world to look tiny, you need to turn large toolbar icons first.

### 10.9 I tried to build with gcc on a prefix with BUILD in it why does it break ?

This is due to some very serious crack smoking going on in stlport. Essentially, there is some nasty header overriding, and they want to be able to fallback to the previous header (with the same name) - thus they have to hard-code the paths. To save doing that in lots of places, they use a #define, the #define has macro expansion done on it. Thus if your gcc prefix contains an element which is a macro - you're stuffed:

stlport config header:

    #define _STLP_NATIVE_INCLUDE_PATH \
            /home/michael/ximian-desktop/ooo/BUILD/ooo/include/c++/3.2.2

stlport helpful macros:

    # define _STLP_MAKE_HEADER(path, header) <path/header>
    # define _STLP_NATIVE_CPP_C_HEADER(header)  \
            _STLP_MAKE_HEADER(_STLP_NATIVE_INCLUDE_PATH,header)

and finally stlport cunning native include:

    #include _STLP_NATIVE_CPP_C_HEADER(foo)

Net result:

          g++ ... -DBUILD=7663 ...
          ...
    from /home/michael/ximian-desktop/ooo/BUILD/ooo/OOO_1_0_2/xml2cmp/source/xcd/main.cxx:62:
    /home/michael/ximian-desktop/ooo/BUILD/ooo/OOO_1_0_2/solver/641/unxlngi4.pro/inc/stl/cstddef:35:46:
    /home/michael/ximian-desktop/ooo/7663/ooo/include/c++/3.2.2/cstddef: No such file or directory

### 10.10 What are the UNO component XML descriptions for ?

Not much; worth installing, but currently highly under-used.

### 10.11 Why does the code look so ugly?

The authors must be using a really strange editor. It thinks tab stops are on every fourth column. Of course, the files come out ugly in Unix editors which know that tabs are eight characters wide.

If you happen to use a Real Editor, we have some pink glasses to sell to you. Paste the contents of http://ooo.ximian.com/emacs.el into your `.emacs`, or load it with a line like this: `(load "/path/to/that/file.el")`. Don't forget to adapt `my-openoffice-path-regexp` to your needs.

Henceforth emacs will use 4-column tabs for your OOo source files. (And use C++-Mode for `sdi`-, `hrc`-, and `src`-files.)

## 11. Working with us

See the About ooo-build document.

If you have more hacking tips, corrections, a grip of correct spelling etc. please do mail me, at michael.meeks@novell.com.