1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<title>Raptor RDF Syntax Library - Upgrading to the Raptor V2 API</title>
</head>
<body>
<h1>Raptor RDF Syntax Library - Upgrading to the Raptor V2 API</h1>
<p>Raptor V2 is a major new version of the Raptor V1 API with many
cleanups and changes that include adding, removing and re-ordering
parameters, adding and removing return types as well as renaming the
functions.
</p>
<p>The headers and libraries install to different places or names so
that Raptor V1 and Raptor V2 can both be present (including headers)
on the same system without clashing. However, if you do try linking
the same binary with both libraries, the symbols will clash and the
program will fail in mysterious ways if it runs at all. There are
only two installed files that overlap - the <code>rapper</code>
utility and it's manual page.
</p>
<h2>Configuration and compiling changes</h2>
<p>Raptor V2 uses <code>pkg-config(1)</code> to provide the compile
and link parameters whereas Raptor V1 supports that as well as a
script <code>raptor-config</code>. The recommended linking approach
is now as follows:
</p>
<pre>
cc -o prog prog.c `pkg-config raptor2 --cflags` `pkg-config raptor2 --libs`
</pre>
<p>Shown here as a compile in link all in one line but you typically
split that into two stages.
</p>
<pre>
cc -c `pkg-config raptor2 --cflags` raptor-module.c
...
cc -o prog raptor-module.c ... other modules ... `pkg-config raptor2 --libs`
</pre>
<h2>Code changes</h2>
<p>There are significant API changes, which are described in the
<a href="RELEASE.html">Release Notes</a> in long summary form with
some background to why, in the <a href="ChangeLog">ChangeLog</a> in
very long form. The reference manual contains
<a href="https://librdf.org/raptor/api/raptor-changes.html">a section</a>
describing what was added, deleted, renamed and otherwise changed for
both the functions exported from the library, as well as the
typedefs and enum values.
</p>
<p>There is no fully automatic way to handle updating the code
however there is a perl script provided in the docs directory that
renames what it can, and otherwise inserts a WARNING comment near
code that needs manual updating. This cannot be automated in some
places such as when the fields of the raptor_statement object were
replaced with raptor_term pointers. The script is used like
<code>perl docs/upgrade-script.pl</code> <em>source files</em> for example</p>
<pre>
$ perl docs/upgrade-script.pl prog.c
</pre>
<p>and then edit the file prog.c and search for <code>WARNING:</code>
for any places that manual editing is needed.
</p>
<h2>Handling Raptor V1 or Raptor V2 in the same code</h2>
<p>If you need to handle both APIs in the same codebase as
alternatives, it is recommended that you use the following approach.
</p>
<p>
Create an application <code>#define</code> that records the choice of
which API you want to use. You can do this triggered on whichever
<code>raptor.h</code> is in the include path by <code>#ifdef
RAPTOR_V2_AVAILABLE</code> but that may be dangerous if both
libraries and headers are present. A better choice is an application
specific define that is determined by a configuration step.
</p>
<p>Once the choice is made, it is recommended you convert the
code to the Raptor V2 API and then add backwards-compatible macros
for the changed functions:
</p>
<pre>
#ifdef APP_WANTS_RAPTOR_V2
/* nop */
#else
#define raptor_v2_function(arg1, arg2, arg3) raptor_v1_function(arg2, arg3)
#endif
</pre>
<p>Where the code cannot be done by simple expansion such as use of
<code>raptor_init()</code> and <code>raptor_finish()</code> in V1
that are replaced by the functions around the world object in V2, use
an <code>#ifdef</code> that provides the two code paths.
</p>
<p><a href="https://librdf.org/rasqal/">rasqal</a>
in GIT (will be 0.9.20) uses this approach.
</p>
<p>Another approach if the Raptor V1 code is in a separate module /
source file is to copy it and make a V2 version and then choose the
file to use at configure or build time.
</p>
<p><a href="https://librdf.org/">librdf</a> 1.0.11 uses this approach.
</p>
<p>Either way, basing the interface on the V2 APIs makes it clear
what to remove when V1 is no longer supported.
</p>
<h2>Packaging recommendations for distributors</h2>
<p>Since Raptor V2 probably needs to be installed in parallel with V1
for some time, at least for the different libraries and headers, both
need to be packaged such that no files clash.
</p>
<p>There are, however, two files that are shared after a 'make install':
<code>rapper(1)</code> and <code>rapper.1</code> the manual page.
</p>
<p>For packaging systems that split the installation into multiple
packages (libraries, headers, docs, debug files), these two files
should be in a package of their own that replace and conflict with
the earlier files. (This is what I have done with the Debian
packages raptor-utils and raptor2-utils). For packaging systems that
do not use multiple packages, you will have to either leave these
files out of the V2 package or migrate them from the V1 package to
the V2 package using dependencies to ensure there are no conflicts.
</p>
<p>The advantage of making the V2 version of rapper is that it means
the command-line utility under the well known name uses the latest
Raptor code.
</p>
<hr />
<p>Copyright 2010-2023 <a href="https://www.dajobe.org/">Dave Beckett</a></p>
</body>
</html>
|