GNU PDF Library Hackers Guide: Updated For Version Trunk
GNU PDF Library Hackers Guide: Updated For Version Trunk
GNU PDF Library Hackers Guide: Updated For Version Trunk
This is the GNU PDF Library Hackers Guide, updated for libgnupdf version trunk. Copyright c 2008, 2011 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation License.
Table of Contents
1 2 3 4 Information for Newcomers . . . . . . . . . . . . . . . . . . . . 1 The build system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1 Third-party m4 macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Coding Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5.1 5.2 5.3 5.4 5.5 File Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inclusion of Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Testing for Preprocessor Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Spaces vs. Tabs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Naming Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.1 Public functions in a module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.2 Private functions in a module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.3 Platform specific functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6 Abstract Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.1 Implementation Files For ADTs . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.2 Data Structures For ADTs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.3 Access Functions For ADTs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.4 Opaque Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7 The layer header files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 13 13 13 13 14 14 14 14 15 15 15 17
6 7
Writing Documentation . . . . . . . . . . . . . . . . . . . . . . . 18
6.1 Generating pictures with ditaa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Sending Patches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
7.1 7.2 7.3 Documenting Your Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Generating a Bazaar Merge Directive . . . . . . . . . . . . . . . . . . . . . . . . . . Syntax Check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.1 Skipping syntax tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4 Patch Safety Dispatcher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.5 Sending your Patch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 19 19 20 20 21
ii
9 10
Cross-compiling libgnupdf for Windows under GNU/Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Updating the AUTHORS file . . . . . . . . . . . . . . . 33
Subscribing to the development mailing list GNU PDF developers communicate using the [email protected] mailing list. Most of the work in the development is discussed there, so you definitely want to subscribe to it if you are going to write some code. Goto the pdf-devel mailman web interface in http://lists.gnu.org/mailman/listinfo/pdf-dev and set up your subscription. Then, send a first email introducing yourself. There is another mailing list [email protected] that is used by the Flyspray installation to send change notifications of tasks. You can subscribe to this mailing list at http://lists.gnu.org/mailman/listinfo/pdf-tasks. Getting familiar with Savannah Savannah is the central point of development for GNU software. The GNU PDF project has a savannah project in http://savannah.gnu.org/projects/pdf Getting familiar with the library Take a look to the design of the library and the source code. The documents to look at are the GNU PDF Library Reference Guide (available in doc/gnupdf.texi) and the GNU PDF Library Architecture Manual (available in doc/gnupdf-arch.texi). There is useful information in the README-dev file located at the root of the source distribution. In particular the dependencies that you need to have installed in your system are detailed there.
1 2
http://bazaar-vcs.org http://doc.bazaar-vcs.org/bzr.dev/en/user-guide/index.html
If you have doubts about any aspect of the library or the implementation, just ask in pdf-devel. Getting familiar with the GNU standards The GNU PDF Library is a GNU package. That means we should follow the GNU Standards to ensure quality and compatibility with other parts of the GNU Operating System. You should be familiar with the GNU Coding Standards before to write code for the GNU PDF library. You can read it online in http://www.gnu.org/prep/standards. Getting familiar with our coding conventions Read our Hackers Guide (this very document) for several conventions we use when writing source code. Taking a task to work on Please read the documentation on tasks management in Chapter 4 [Tasks management], page 7. If you want to work in a NEXT task, please be sure to state your interest in the pdf-devel mailing list before. The developers in the pdf-devel mailing list can guide you towards the more convenient task for you to take and can give valuable advice about how to implement it. Signing papers The GNU PDF codebase is copyrighted by the Free Software Foundation. This is a way to strength the GPL. That means that we need you to sign papers before to be able to integrate your code in the distribution. There are several ways to get this done. Please ask in pdf-devel for the details. Sending patches for inclusion If you have written a patch you want to be included in GNU PDF, please send it to the pdf-devel mailing list. Your patch will be then discussed and maybe accepted.
3 Development procedures
The GNU PDF Library is composed by several layers. Each layer is in turn composed by several modules. The combination of the modules provide the functionality to layers. See undefined [Top], page undefined .
The development of the library involves the design of the overall architecture (determination of the layers that composes the library), the development of each layer and the design and implementation of system tests.
The development of each library layer involves the design of the overall architecture of the layer (determination of the modules that composes the layer), the development of each module and the design and implementation of subsystem tests.
The development of each module involves the design of the API offered by the module and the architectural details, the definition of development tasks needed to complete the implementation of the module and the design and implementation of unit tests.
4 Tasks management
This chapter contains information about the tasks management we use in the development of the GNU PDF Library.
The tasks pool contain a set of tasks that should be performed out by some agent. The pool do not contain all the tasks for the project: there is an approximation in the project plan. Instead there is a constant flow of tasks being introduced in the pool by originators and being consumed out by the developers. That means that when a task is performed by a developer it is pulled out of the pool and archived.
An archived task can be reactivated and inserted again in the tasks pool.
Figure 4.1: The tasks pool A task is attributed with a priority while it is into the tasks pool. The priority is a number between 1 (less priority) to 9 (higher priority). Some priority levels have names: 1 - Later 2 3 - Low 4 5 - Normal 6 7 - High 8 9 - Immediate
Note: The maintainer may change the priority of a task to avoid it to starve.
Note: A reactivated task gets a new priority number when it is reinserted into the tasks pool.
The maintainer The maintainer is the responsible of maintaining the tasks pool, introducing new tasks when needed and setting the priorities. The source of the tasks is either the project plan, bug reports or reactivated tasks.
Cron jobs running in gnupdf.org There are several cron jobs running in gnupdf.org that perform checks on a nightly build of the sources and executes the unit tests. These jobs can automatically generate new tasks to fix some problem (a high cyclomatic complexity in a module or a fail in a test case).
source project plan bug report test fail or bad software metric
10
Figure 4.2: Tasks workflow TODO NEXT STARTED The task has been started by a developer but it is not finished. DONE The task is archived and succesfully performed. The task is into the tasks pool but it not ready to be performed. The task is into the tasks pool and it is ready to be performed by a developer.
11
Note that a task may also be assigned to someone or unassigned: TODO and unassigned Dependency issues, no one in charge. TODO and assigned Dependency issues and someone showed interest. NEXT and unassigned Can be started, nobody interested. NEXT and assigned Someone is interested but cant work on it for personal issues. STARTED and assigned Someone is working on the task (no matter the time it takes)
Category
Priority Status
Summary
12
5 Coding Conventions
Like in any other GNU package, the code in the GNU PDF Library follows the coding conventions documented in the GNU Coding Standards. In this section we complement the guidelines of the GHM with some specific conventions that we follow in the development of the library. It is quite important to follow these guidelines to maintain a good level of coherence in the codebase.
13
#include <system-file-N.h> #include <lib-file-1.h> #include <lib-file-2.h> ... #include <lib-file-N.h> Note the empty lines separating the several blocks. In particular: Always include config.h, and do it in the first position. Never use the "foo.h" kind of inclusion. Use always <foo.h>. If some headers shall be included conditionally depending on the host platform, the macros PDF_HOST_* defined in config.h can be used. Those macros are set using autoheader.
14
pdf_MODULE-NAME_PART-NAME_... where part-name is the canonical name of that part of the module implementation (e.g. pdf_stm_filter_... where filter is the part name.
15
16
The mechanism is quite simple. Suppose that we want to publish an opaque ADT to the user: pdf_foo_t. A first approximation would be to mark the full definition of pdf_foo_t as public in the header file, like: /* -*- mode: C -** * File: pdf-foo.h ... */ ... /* BEGIN PUBLIC */ struct pdf_foo_s { int a; int b; }; typedef struct pdf_foo_s *pdf_foo_t; /* END PUBLIC */ ... Despite the user is not supposed to access the internal structure of pdf_foo_t, she can actually do it using the exported structure struct pdf_foo_s. An additional problem is that the user can allocate pdf_foo_s structs in the stack, and thus the binary compatibility would be break if the binary links with a more recent version of the library exporting more fields (like a third integer c). The solution to both problems is to export a opaque pointer: we simply do not export the details about the structure: /* -*- mode: C -** * File: pdf-foo.h ... */ ... /* BEGIN PUBLIC */ typedef struct pdf_foo_s *pdf_foo_t; /* END PUBLIC */ struct pdf_foo_s
17
18
6 Writing Documentation
This chapter contains some useful information on writing documentation in the GNU PDF project.
19
7 Sending Patches
This chapter contains some useful information to send patches to be integrated in the trunk.
20
21
22
Figure 8.1: Test types 1. Unit testing is performed in order to verify the low-level modules of the library. 2. Subsystem testing is performed in order to verify the combination of several subsystems. i.e. to test each library layer. 3. System testing is performed in order to verify the whole system. i.e. the GNU PDF Library. We use check1 to implement our testing infrastructure. Please read the check manual in order to become familiar with its concepts such as test suite, test case, etc. At some point we wrote a simple replacement for libcheck in Windows systems: nocheck (torture/unit/nocheck). The usage of the replacement is now deprecated, since the latest version of libcheck should support windows.
1
23
Figure 8.2: Unit Testing Architecture Test suites are used to collect unit tests for a given module. In turn each test suite contain a collection of test cases. Each test case identifies a function implemented in the module. Several tests can then be defined to test the function capabilities.
24
25
26
} END_TEST
/* * Provide this function to gather all the tests together. */ TCase* test_FUNCTION_NAME (void) { TCase* tc = tcase_create ("FUNCTION_NAME"); tcase_add_test(tc, FUNCTION_NAME_NNN); return tc; } Note the test_FUNCTION_NAME function. It is the function called by the test driver in order to perform all the tests implemented in the test file. Note also that the comments heading tests are written in a fixed format to allow the build-aux/generate-tsd.pl script to generate the bulk of the Test Specification Document from the comments.
27
28
exec "$progdir/$program" ${1+"$@"} and change it to something like: exec gdb --return-child-result --quiet --args "$progdir/$program" ${1+"$@"} Note that you need to repeat this change every time torture/unit/runtests is rebuilt by make. The second alternative is to run gdb on the real binary using: When debugging failing tests you may find it useful to set breakpoint to _fail_unless function: $ ( export CK FORK=no; make check ) # you can use make check FUNCTION=... as well ... (gdb) break fail unless Breakpoint 1 at 0x804ac44 (gdb) run ... Breakpoint 1, _fail_unless (result=1, file=0x80b2f94 "base/alloc/pdf-alloc.c", line=47, expr=0x80aac30 "Failure data == NULL occured") at check.c:237 237 send_loc_info (file, line); ... (gdb) list 232 void _fail_unless (int result, const char *file, 233 int line, const char *expr, ...) 234 { 235 const char *msg; 236 237 send_loc_info (file, line); 238 if (!result) { 239 va_list ap; 240 char buf[BUFSIZ]; 241 (gdb) break check.c:238 if (!result) Breakpoint 2 at 0xb7ea4a7c: file check.c, line 238. (gdb) delete 1 (gdb) continue Continuing. ... Breakpoint 2, _fail_unless (result=0, file=0x80a7ef8 "base/text/pdf-text-new-destroy.c", line=44, expr=0x80a7f1c "Assertion pdf_text_new (&newtext) == PDF_EBADCONTEXT failed") at check.c:238 238 if (!result) { (gdb) finish Run till exit from #0 _fail_unless (result=0, file=0x80a7ef8 "base/text/pdf-text-new-destroy.c", line=44, expr=0x80a7f1c "Assertion pdf_text_new (&newtext) == PDF_EBADCONTEXT failed")
29
at check.c:238 pdf_text_new_destroy_001 (_i=0) at base/text/pdf-text-new-destroy.c:46 46 END_TEST (gdb) list 41 { 42 pdf_text_t newtext = NULL; 43 44 fail_unless(pdf_text_new (&newtext) == PDF_EBADCONTEXT); 45 } 46 END_TEST 47 48 /* 49 * Test: pdf_text_new_destroy_002 50 * Description: (gdb) ...
30
If you are not on an usual disto, download mingw32 at http://sourceforge.net/projects/mingw MinGW Build Tool. You follow the README in order to install the package. You can go to http://mingw.org for more details: ... $ sh x86-mingw32-build.sh i686-mingw32 ... The dependencies After having downloaded the sources of the GNU PDF Library, you need to install the required libraries. Below is a list of the required libraries: zlib libpthread libuuid libgpg-error libgcrypt libcheck libjbig2dec libjpeg You need to create some directories in order to stock the mingw32 dependencies. $ mkdir $HOME/w32root $ mkdir $HOME/w32root/lib $ mkdir $HOME/w32root/include zlib Download zlib either the source or the binaries. In order to compile the source you have to follow to read the page available at http://www.crosscompile.org/static/pages/ZLib.html. The binaries are available at http://zlib.net/zlib125-dll.zip $ unzip path/to/zlib125-dll.zip $ mv include/* $HOME/w32root/include $ mv zlib1.dll $HOME/w32root/lib/libz.dll libpthreads There is a bug in mingw32-pthreads (Bug 599227). This bug affects the compilation of libcheck. You need to download the source of the fixed version. You have to log in the pthreads-win32 cvs. The password is anoncvs. Then, you download, compile and install.
31
$ $ $ $ $ $ libuuid
cvs -d :pserver:[email protected]:/cvs/pthreads-win32 login # anoncvs cvs -d :pserver:[email protected]:/cvs/pthreads-win32 checkout -D 2011 cd pthreads-w32-20110511 make CROSS=i586-mingw32msvc- clean GC cp pthread.h sched.h semaphore.h $HOME/mingw32/include/ cp pthreadGC2.dll $HOME/mingw32/lib/libpthread.dll
You can use precompiled libuuid binaries available in the following URL: http://mirror.vcu.edu/pub/windows/cygwin/release/util-linux/libuuid-devel/. So, steps for libuuid are: $ tar -jxf libuuid-devel-2.17.2-1.tar.bz2 $ cp -r usr/include/uuid $HOME/w32root/include $ cp -r usr/lib/libuuid.dll.a $HOME/w32root/lib
libgpg-error and libgcrypt Go to http://gnupg.org/download/index.en.html. You have to download: libgpg-error-1.10.tar.bz2 libgcrypt-1.4.6.tar.gz For libgpg-error-1.10 and libgcrypt-1.4.6, you have to note that the autogen.sh script recognizes build-w32 and set the prefix installation to $HOME/w32root. You cant modify this prefix. A typical compilation and installation would be: $ tar zxf path/to/libgpg-error-1.10.tar.gz $ cd libgpg-error-1.10 $ ./autogen.sh --build-w32 $ make $ make install $ tar zxf path/to/libgcrypt-1.4.6.tar.gz $ cd libgcrypt-1.4.6 $ ./autogen.sh --build-w32 $ make $ make install The libraries are installed in $HOME/w32root. libcheck You need the svn version of libcheck : $ svn co https://check.svn.sourceforge.net/svnroot/check/trunk check In order to compile, you need to type: $ cd check $ autoreconf --install $ ./configure --host=i586-mingw32msvc --prefix=$HOME/w32root $ make $ make install Download http://ghostscript.com/~giles/jbig2/jbig2dec/jbig2dec-0.11.tar.gz. Compile and install the library with the following commands. Note that due to http://bugs.ghostscript.com/show_bug.cgi?id=691784, youll need to generate the DLL manually.
libjbig2dec
32
$ ./configure --host=i586-mingw32msvc --prefix=$HOME/w32root $ make $ make install $ i586-mingw32msvc-gcc -shared -o .libs/libjbig2dec.dll jbig2.o jbig2_arith. jbig2_segment.o jbig2_page.o jbig2_symbol_dict.o jbig2_text.o jbig2_generic. jbig2_image.o jbig2_image_pbm.o jbig2_metadata.o $ cp .libs/libjbig2dec.dll $HOME/w32root/lib libjpeg Download libjpeg at http://www.ijg.org/files/jpegsrc.v8c.tar.gz. Compile and install the library with the following commands. $ cd jpeg-8c $ ./configure --host=i586-mingw32msvc --prefix=$HOME/w32root $ make $ make install
Compiling Now you can run in the GNU PDF trunk: $ sh autogen.sh $ ./configure --host=i586-mingw32msvc --with-zlib=$HOME/w32root --with-libche --with-libjpeg-prefix=$HOME/w32root --with-libuuid-prefix=$HOME/w32root $ make $ make install At the time of writing this documentation, there are some errors during make.
33