summaryrefslogtreecommitdiff
path: root/tools/build/src/tools/quickbook.jam
blob: 6de2d42f84ef60bc118ca8c7e390eaa2edb10de2 (plain)
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
#
#   Copyright (c) 2005 Joćo Abecasis
#   Copyright (c) 2005 Vladimir Prus
#   Copyright (c) 2006 Rene Rivera
#
#   Distributed under the Boost Software License, Version 1.0. (See
#   accompanying file LICENSE_1_0.txt or copy at
#   http://www.boost.org/LICENSE_1_0.txt)
#

# This toolset defines a generator to translate QuickBook to BoostBook. It can
# be used to generate nice (!) user documentation in different formats
# (pdf/html/...), from a single text file with simple markup.
#
# The toolset defines the QUICKBOOK type (file extension 'qbk') and
# a QUICKBOOK to XML (BOOSTBOOK) generator.
#
#
#   ===========================================================================
#   Q & A
#   ===========================================================================
#
#   If you don't know what this is all about, some Q & A will hopefully get you
#   up to speed with QuickBook and this toolset.
#
#
#   What is QuickBook ?
#
#       QuickBook is a WikiWiki style documentation tool geared towards C++
#       documentation using simple rules and markup for simple formatting tasks.
#       QuickBook extends the WikiWiki concept. Like the WikiWiki, QuickBook
#       documents are simple text files. A single QuickBook document can
#       generate a fully linked set of nice HTML and PostScript/PDF documents
#       complete with images and syntax-colorized source code.
#
#
#   Where can I get QuickBook ?
#
#       Quickbook can be found in Boost's repository, under the tools/quickbook
#       directory it was added there on Jan 2005, some time after the release of
#       Boost v1.32.0 and has been an integral part of the Boost distribution
#       since v1.33.
#
#       Here's a link to the SVN repository:
#           https://svn.boost.org/svn/boost/trunk/tools/quickbook
#
#       And to QuickBook's QuickBook-generated docs:
#           http://www.boost.org/doc/libs/release/tools/quickbook/index.html
#
#
#   How do I use QuickBook and this toolset in my projects ?
#
#       The minimal example is:
#
#           using boostbook ;
#           import quickbook ;
#
#           boostbook my_docs : my_docs_source.qbk ;
#
#       where my_docs is a target name and my_docs_source.qbk is a QuickBook
#       file. The documentation format to be generated is determined by the
#       boostbook toolset. By default html documentation should be generated,
#       but you should check BoostBook's docs to be sure.
#
#
#   What do I need ?
#
#       You should start by setting up the BoostBook toolset. Please refer to
#       boostbook.jam and the BoostBook documentation for information on how to
#       do this.
#
#       A QuickBook executable is also needed. The toolset will generate this
#       executable if it can find the QuickBook sources. The following
#       directories will be searched:
#
#           BOOST_ROOT/tools/quickbook/
#           BOOST_BUILD_PATH/../../quickbook/
#
#       (BOOST_ROOT and BOOST_BUILD_PATH are environment variables)
#
#       If QuickBook sources are not found the toolset will then try to use
#       the shell command 'quickbook'.
#
#
#   How do I provide a custom QuickBook executable ?
#
#       You may put the following in your user-config.jam or site-config.jam:
#
#           using quickbook : /path/to/quickbook ;
#
#       or, if 'quickbook' can be found in your PATH,
#
#           using quickbook : quickbook ;
#
#
#   For convenience three alternatives are tried to get a QuickBook executable:
#
#       1.  If the user points us to the a QuickBook executable, that is used.
#
#       2.  Otherwise, we search for the QuickBook sources and compile QuickBook
#           using the default toolset.
#
#       3.  As a last resort, we rely on the shell for finding 'quickbook'.
#

import boostbook ;
import "class" : new ;
import feature ;
import generators ;
import toolset ;
import type ;
import scanner ;
import project ;
import targets ;
import build-system ;
import path ;
import common ;
import errors ;

# The one and only QUICKBOOK type!
type.register QUICKBOOK : qbk ;

# <quickbook-binary> shell command to run QuickBook
# <quickbook-binary-dependencies> targets to build QuickBook from sources.
feature.feature <quickbook-binary> : : free ;
feature.feature <quickbook-binary-dependencies> : : free dependency ;
feature.feature <quickbook-define> : : free ;
feature.feature <quickbook-indent> : : free ;
feature.feature <quickbook-line-width> : : free ;


# quickbook-binary-generator handles generation of the QuickBook executable, by
# marking it as a dependency for QuickBook docs.
#
# If the user supplied the QuickBook command that will be used.
#
# Otherwise we search some sensible places for the QuickBook sources and compile
# from scratch using the default toolset.
#
# As a last resort we rely on the shell to find 'quickbook'.
#
class quickbook-binary-generator : generator
{
    import modules path targets quickbook ;

    rule run ( project name ? : property-set : sources * : multiple ? )
    {
        quickbook.freeze-config ;
        # QuickBook invocation command and dependencies.
        local quickbook-binary = [ modules.peek quickbook : .quickbook-binary ] ;
        local quickbook-binary-dependencies ;

        if ! $(quickbook-binary)
        {
            # If the QuickBook source directory was found, mark its main target
            # as a dependency for the current project. Otherwise, try to find
            # 'quickbook' in user's PATH
            local quickbook-dir = [ modules.peek quickbook : .quickbook-dir ] ;
            if $(quickbook-dir)
            {
                # Get the main-target in QuickBook directory.
                local quickbook-main-target = [ targets.resolve-reference $(quickbook-dir) : $(project) ] ;

                # The first element are actual targets, the second are
                # properties found in target-id. We do not care about these
                # since we have passed the id ourselves.
                quickbook-main-target =
                    [ $(quickbook-main-target[1]).main-target quickbook ] ;

                quickbook-binary-dependencies =
                    [ $(quickbook-main-target).generate [ $(property-set).propagated ] ] ;

                # Ignore usage-requirements returned as first element.
                quickbook-binary-dependencies = $(quickbook-binary-dependencies[2-]) ;

                # Some toolsets generate extra targets (e.g. RSP). We must mark
                # all targets as dependencies for the project, but we will only
                # use the EXE target for quickbook-to-boostbook translation.
                for local target in $(quickbook-binary-dependencies)
                {
                    if [ $(target).type ] = EXE
                    {
                        quickbook-binary = 
                            [ path.native 
                                [ path.join
                                    [ $(target).path ]
                                    [ $(target).name ]
                                ]
                            ] ;
                    }
                }
            }
        }

        # Add $(quickbook-binary-dependencies) as a dependency of the current
        # project and set it as the <quickbook-binary> feature for the
        # quickbook-to-boostbook rule, below.
        property-set = [ $(property-set).add-raw
            <dependency>$(quickbook-binary-dependencies)
            <quickbook-binary>$(quickbook-binary)
            <quickbook-binary-dependencies>$(quickbook-binary-dependencies)
        ] ;

        return [ generator.run $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
    }
}


# Define a scanner for tracking QBK include dependencies.
#
class qbk-scanner : common-scanner
{
    rule pattern ( )
    {
        return "\\[[ ]*include[ ]+([^]]+)\\]" 
        "\\[[ ]*include:[a-zA-Z0-9_]+[ ]+([^]]+)\\]" 
        "\\[[ ]*import[ ]+([^]]+)\\]" ;
    }
}


scanner.register qbk-scanner : include ;

type.set-scanner QUICKBOOK : qbk-scanner ;


# Initialization of toolset.
#
# Parameters:
#   command ?    -> path to QuickBook executable.
#
# When command is not supplied toolset will search for QuickBook directory and
# compile the executable from source. If that fails we still search the path for
# 'quickbook'.
#
rule init (
        command ?   # path to the QuickBook executable.
    )
{
    if $(command)
    {
        if $(.config-frozen)
        {
            errors.user-error "quickbook: configuration cannot be changed after it has been used." ;
        }
        .command = $(command) ;
    }
}

rule freeze-config ( )
{
    if ! $(.config-frozen)
    {
        .config-frozen = true ;

        # QuickBook invocation command and dependencies.

        .quickbook-binary = $(.command) ;

        if $(.quickbook-binary)
        {
            # Use user-supplied command.
            .quickbook-binary = [ common.get-invocation-command quickbook : quickbook : $(.quickbook-binary) ] ;
        }
        else
        {
            # Search for QuickBook sources in sensible places, like
            #   $(BOOST_ROOT)/tools/quickbook
            #   $(BOOST_BUILD_PATH)/../../quickbook

            # And build quickbook executable from sources.

            local boost-root = [ modules.peek : BOOST_ROOT ] ;
            local boost-build-path = [ build-system.location ] ;

            if $(boost-root)
            {
                .quickbook-dir += [ path.join $(boost-root) tools ] ;
            }

            if $(boost-build-path)
            {
                .quickbook-dir += $(boost-build-path)/../.. ;
            }

            .quickbook-dir = [ path.glob $(.quickbook-dir) : quickbook ] ;

            # If the QuickBook source directory was found, mark its main target
            # as a dependency for the current project. Otherwise, try to find
            # 'quickbook' in user's PATH
            if $(.quickbook-dir)
            {
                .quickbook-dir = [ path.make $(.quickbook-dir[1]) ] ;
            }
            else
            {
                ECHO "QuickBook warning: The path to the quickbook executable was" ;
                ECHO "  not provided. Additionally, couldn't find QuickBook" ;
                ECHO "  sources searching in" ;
                ECHO "    * BOOST_ROOT/tools/quickbook" ;
                ECHO "    * BOOST_BUILD_PATH/../../quickbook" ;
                ECHO "  Will now try to find a precompiled executable by searching" ;
                ECHO "  the PATH for 'quickbook'." ;
                ECHO "  To disable this warning in the future, or to completely" ;
                ECHO "  avoid compilation of quickbook, you can explicitly set the" ;
                ECHO "  path to a quickbook executable command in user-config.jam" ;
                ECHO "  or site-config.jam with the call" ;
                ECHO "    using quickbook : /path/to/quickbook ;" ;

                # As a last resort, search for 'quickbook' command in path. Note
                # that even if the 'quickbook' command is not found,
                # get-invocation-command will still return 'quickbook' and might
                # generate an error while generating the virtual-target.

                .quickbook-binary = [ common.get-invocation-command quickbook : quickbook ] ;
            }
        }
    }
}


generators.register [ new quickbook-binary-generator quickbook.quickbook-to-boostbook : QUICKBOOK : XML ] ;


# <quickbook-binary> shell command to run QuickBook
# <quickbook-binary-dependencies> targets to build QuickBook from sources.
toolset.flags quickbook.quickbook-to-boostbook QB-COMMAND      <quickbook-binary> ;
toolset.flags quickbook.quickbook-to-boostbook QB-DEPENDENCIES <quickbook-binary-dependencies> ;
toolset.flags quickbook.quickbook-to-boostbook INCLUDES        <include> ;
toolset.flags quickbook.quickbook-to-boostbook QB-DEFINES      <quickbook-define> ;
toolset.flags quickbook.quickbook-to-boostbook QB-INDENT       <quickbook-indent> ;
toolset.flags quickbook.quickbook-to-boostbook QB-LINE-WIDTH   <quickbook-line-width> ;


rule quickbook-to-boostbook ( target : source : properties * )
{
    # Signal dependency of quickbook sources on <quickbook-binary-dependencies>
    # upon invocation of quickbook-to-boostbook.
    DEPENDS $(target) : [ on $(target) return $(QB-DEPENDENCIES) ] ;
}


actions quickbook-to-boostbook
{
    "$(QB-COMMAND)" -I"$(INCLUDES)" -D"$(QB-DEFINES)" --indent="$(QB-INDENT)" --linewidth="$(QB-LINE-WIDTH)" --output-file="$(1)" "$(2)"
}


# Declare a main target to convert a quickbook source into a boostbook XML file.
#
rule to-boostbook ( target-name : sources * : requirements * : default-build * )
{ 
  local project = [ project.current ] ;
    
  targets.main-target-alternative 
    [ new typed-target $(target-name) : $(project) : XML
        : [ targets.main-target-sources $(sources) : $(target-name) ] 
        : [ targets.main-target-requirements $(requirements) : $(project) ]
        : [ targets.main-target-default-build $(default-build) : $(project) ] 
    ] ;
}