diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2019-06-30 20:49:52 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2019-06-30 20:49:52 +0100 | 
| commit | d18570cff5c55458df8e6931304126bfa97d56a6 (patch) | |
| tree | 6e4177a5abe65be8841e30ab4e8696e98407147c | |
| parent | Fix link error (diff) | |
| download | icespider-d18570cff5c55458df8e6931304126bfa97d56a6.tar.bz2 icespider-d18570cff5c55458df8e6931304126bfa97d56a6.tar.xz icespider-d18570cff5c55458df8e6931304126bfa97d56a6.zip | |
Get glibmm and xml++ flags from pkg-configicespider-0.6.1.1
| -rw-r--r-- | Jamroot.jam | 43 | ||||
| -rw-r--r-- | pkg-config.jam | 485 | 
2 files changed, 489 insertions, 39 deletions
| diff --git a/Jamroot.jam b/Jamroot.jam index 8b18b94..7451996 100644 --- a/Jamroot.jam +++ b/Jamroot.jam @@ -2,6 +2,8 @@ import os ;  import slice ;  using gcc : : [ os.environ CXX ] ; +using pkg-config ; +import pkg-config ;  variant coverage : debug ; @@ -26,43 +28,6 @@ project  build-project icespider ; -# Some useful aliases - -lib xml++-3.0 ; -lib xml2 ; -lib glibmm-2.4 ; -lib gobject-2.0 ; -lib glib-2.0 ; -lib sigc-2.0 ; - -alias libxmlpp : : : : -	<include>/usr/include/libxml++-3.0 -	<include>/usr/lib/libxml++-3.0/include -	<include>/usr/include/libxml2 -	<include>/usr/include/glibmm-2.4 -	<include>/usr/lib/glibmm-2.4/include -	<include>/usr/include/glib-2.0 -	<include>/usr/lib/glib-2.0/include -	<include>/usr/include/sigc++-2.0 -	<include>/usr/lib/sigc++-2.0/include -	<library>xml++-3.0 -	<library>xml2 -	<library>glibmm-2.4 -	<library>gobject-2.0 -	<library>glib-2.0 -	<library>sigc-2.0 -	; - -alias glibmm : : : : -	<include>/usr/include/glibmm-2.4 -	<include>/usr/lib/glibmm-2.4/include -	<include>/usr/include/glib-2.0 -	<include>/usr/lib/glib-2.0/include -	<include>/usr/include/sigc++-2.0 -	<include>/usr/lib/sigc++-2.0/include -	<library>glibmm-2.4 -	<library>gobject-2.0 -	<library>glib-2.0 -	<library>sigc-2.0 -	; +pkg-config.import libxmlpp : : <name>libxml++-3.0 ; +pkg-config.import glibmm : : <name>glibmm-2.4 ; diff --git a/pkg-config.jam b/pkg-config.jam new file mode 100644 index 0000000..2efa9cf --- /dev/null +++ b/pkg-config.jam @@ -0,0 +1,485 @@ +#| +Copyright 2019 Dmitry Arkhipov +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) +|# + + +import "class" : new ; +import common ; +import errors ; +import feature ; +import os ; +import param ; +import project ; +import regex ; +import sequence ; +import string ; +import targets ; + + +#| tag::doc[] + += pkg-config +The *pkg-config* program is used to retrieve information about installed +libraries in the system. It retrieves information about packages from special +metadata files. These files are named after the package, and have a `.pc` +extension. The package name specified to *pkg-config* is defined to be the name +of the metadata file, minus the `.pc` extension. + +|# # end::doc[] + + +#| tag::doc[] + +== Feature: `pkg-config` + +Selects one of the initialized `pkg-config` configurations. This feature is +`propagated` to dependencies. Its use is dicussed in +section <<pkg-config-init>>. + +|# # end::doc[] + +feature.feature pkg-config : : propagated ; + + +#| tag::doc[] + +== Feature: `pkg-config-define` + +This `free` feature adds a variable assignment to pkg-config invocation. For +example, + +[source, jam] +---- +pkg-config.import mypackage : requirements <pkg-config-define>key=value ; +---- + +is equivalent to invoking on the comand line + +[source, shell] +---- +pkg-config --define-variable=key=value mypackage ; +---- + +|# # end::doc[] + +feature.feature pkg-config-define : : free ; + + +#| tag::doc[] + +== Rule: `import` + +Main target rule that imports a *pkg-config* package. When its consumer targets +are built, *pkg-config* command will be invoked with arguments that depend on +current property set. The features that have an effect are: + +* `<pkg-config-define>`: adds a `--define-variable` argument; +* `<link>`: adds `--static` argument when `<link>static`; +* `<link>`: adds `--static` argument when `<link>static`; +* `<name>`: specifies package name (target name is used instead if the property +    is not present); +* `<version>`: specifies package version range, can be used multiple times and +    should be a dot-separated sequence of numbers optionally prefixed with `=`, +    `<`, `>`, `<=` or `>=`. + +Example: + +[source, jam] +---- +pkg-config.import my-package +    : requirements <name>my_package <version><4 <version>>=3.1 ; +---- + +|# # end::doc[] + + +rule import +    ( target-name +    : sources * +    : requirements * +    : default-build * +    : usage-requirements * +    ) +{ +    param.handle-named-params +        sources requirements default-build usage-requirements ; +    targets.create-metatarget pkg-config-target +        : [ project.current ] +        : $(target-name) +        : $(sources) +        : $(requirements) +        : $(default-build) +        : $(usage-requirements) +        ; +} + + +#| tag::doc[] + +== Initialization [[ pkg-config-init ]] + +To use the `pkg-config` tool you need to declare it in a configuration file +with the `using` rule: + +[source, jam] +---- +using pkg-config : [config] : [command] ... : [ options ] ... ; +---- + + +* `config`: the name of initialized configuration. The name can be omitted, in +    which case the configuration will become the default one. +* `command`: the command, with any extra arguments, to execute. If no command +    is given, first `PKG_CONFIG` environment variable is checked, and if its +    empty the string `pkg-config` is used. +* `options`: options that modify `pkg-config` behavior. Allowed options are: +    * `<path>`: sets `PKG_CONFIG_PATH` environment variable; +        multiple occurences are allowed. +    * `<libdir>`: sets `PKG_CONFIG_LIBDIR` environment variable; +        multiple occurences are allowed. +    * `<allow-system-cflags>`: sets `PKG_CONFIG_ALLOW_SYSTEM_CFLAGS` +        environment variable; multiple occurences are allowed. +    * `<allow-system-libs>`: sets `PKG_CONFIG_ALLOW_SYSTEM_LIBS` +        environment variable; multiple occurences are allowed. +    * `<sysroot>`: sets `PKG_CONFIG_SYSROOT_DIR` environment variable; +        multiple occurences are allowed. +    * `<variable>`: adds a variable definition argument to command invocation; +        multiple occurences are allowed. + +|# # end::doc[] + +rule init ( config ? : command * : options * ) +{ +    config ?= [ default-config ] ; + +    local tool = [ os.environ PKG_CONFIG ] ; +    tool ?= pkg-config ; +    command = +        [ common.get-invocation-command pkg-config : $(tool) : $(command) ] ; + +    configure $(config) : $(command) : $(options) ; +    $(.configs).use $(config) ; +} + + +rule run ( config ? : args * ) +{ +    config ?= [ default-config ] ; + +    local command = [ $(.configs).get $(config) : command ] ; +    command = "$(command) $(args:J= )" ; + +    local output = [ SHELL "$(command)" : exit-status ] ; +    if 0 != $(output[2]) +    { +      errors.error "pkg-config: command '$(command)' resulted in error:" +          [ common.newline-char ] $(output[1]) ; +    } + +    local ws = [ string.whitespace ] ; +    output = [ regex.split $(output[1]) "[$(ws)]" ] ; +    return [ sequence.filter non-empty : $(output) ] ; +} + + +#| tag::doc[] + +== Class `pkg-config-target` + +[source, jam] +---- +class pkg-config-target : alias-target-class { +    rule construct ( name : sources * : property-set ) +    rule version ( property-set ) +    rule variable ( name : property-set ) +} +---- + +The class of objects returned by `import` rule. The objects themselves could be +useful in situations that require more complicated logic for consuming a +package. See <<pkg-config-tips>> for examples. + +. `rule construct ( name : sources * : property-set )` +  Overrides `alias-target.construct`. + +. `rule version ( property-set )` +  Returns the package's version, in the context of `property-set`. + +. `rule variable ( name : property-set )` +  Returns the value of variable `name` in the package, in the context of +  `property-set`. + + +|# # end::doc[] + +class pkg-config-target : alias-target-class +{ +    import pkg-config ; +    import regex ; + +    rule construct ( name : sources * : property-set ) +    { +        local config = [ $(property-set).get <pkg-config> ] ; +        local args = [ common-arguments $(name) : $(property-set) ] ; +        return +            [ property-set.create +              [ compile-flags $(config) $(property-set) : $(args) ] +              [ link-flags $(config) $(property-set) : $(args) ] +            ] ; +    } + +    rule version ( property-set ) +    { +        local config = [ $(property-set).get <pkg-config> ] ; +        local args = [ common-arguments [ name ] : $(property-set) ] ; +        local version = [ pkg-config.run $(config) : --modversion $(args) ] ; +        return [ regex.split $(version) "\\." ] ; +    } + +    rule variable ( name : property-set ) +    { +        local config = [ $(property-set).get <pkg-config> ] ; +        local args = [ common-arguments [ name ] : $(property-set) ] ; +        return [ pkg-config.run $(config) : --variable=$(name) $(args) ] ; +    } + +    local rule common-arguments ( name : property-set ) +    { +        local defines = [ $(property-set).get <pkg-config-define> ] ; +        local args = --define-variable=$(defines) ; +        if [ $(property-set).get <link> ] = static +        { +            args += --static ; +        } +        return $(args) [ get-package-request $(property-set) $(name) ] ; +    } + +    local rule get-package-request ( property-set name ) +    { +        local pkg-name = [ $(property-set).get <name> ] ; +        pkg-name ?= $(name) ; +        if $(pkg-name[2]) +        { +            errors.error "multiple package names were specified for target " +                "'$(name)': $(pkg-name)" ; +        } + +        local versions ; +        for local version in [ $(property-set).get <version> ] +        { +            local match = [ MATCH "^(<=)(.*)" : $(version) ] ; +            match ?= [ MATCH "^(>=)(.*)" : $(version) ] ; +            match ?= [ MATCH "^([><=])(.*)" : $(version) ] ; +            if $(match) +            { +                version = " $(match:J= )" ; +            } +            else +            { +                version = " = $(version)" ; +            } +            versions += $(version) ; +        } +        versions ?= "" ; + +        return "'$(pkg-name)"$(versions)"'" ; +    } + +    local rule link-flags ( config property-set : args * ) +    { +        local flags = [ pkg-config.run $(config) : --libs $(args) ] ; +        return <linkflags>$(flags) ; +    } + +    local rule compile-flags ( config property-set : args * ) +    { +        local flags = [ pkg-config.run $(config) : --cflags $(args) ] ; +        return <cflags>$(flags) ; +    } +} + + +local rule default-config ( ) +{ +    return default ; +} + + +local rule configure ( config : command + : options * ) +{ +    $(.configs).register $(config) ; + +    local path ; +    local libdir ; +    local allow-system-cflags ; +    local allow-system-libs ; +    local sysroot ; +    local defines ; +    for local opt in $(options) +    { +        switch $(opt:G) +        { +            case <path> : path += $(opt:G=) ; +            case <libdir> : libdir += $(opt:G=) ; +            case <allow-system-cflags> : allow-system-cflags += $(opt:G=) ; +            case <allow-system-libs> : allow-system-libs += $(opt:G=) ; +            case <sysroot> : sysroot += $(opt:G=) ; +            case <variable> : defines += $(opt:G=) ; +            case * : +                errors.error "pkg-config: invalid property '$(opt)' was " +                    "specified for configuration '$(config)'." ; +        } +    } + +    for local opt in allow-system-cflags allow-system-libs +    { +        if ! $($(opt)) in "on" off +        { +            errors.error "pkg-config: invalid value '$($(opt))' was specified " +                "for option <$(opt)> of configuration '$(config)'." +                [ common.newline-char ] "Available values are 'on' and 'off'" ; +        } +    } + +    if $(sysroot[2]) +    { +        errors.error "pkg-config: several values were specified for option " +            "<sysroot> of configuration '$(config)'." +            [ common.newline-char ] "Only one value is allowed." ; +    } + +    local sep = [ os.path-separator ] ; +    path = [ envar-set-command PKG_CONFIG_PATH : $(path:J=$(sep)) ] ; +    libdir = [ envar-set-command PKG_CONFIG_LIBDIR : $(libdir:J=$(sep)) ] ; +    sysroot = [ envar-set-command PKG_CONFIG_SYSROOT_DIR : $(sysroot) ] ; +    allow-cflags = +        [ envar-set-command PKG_CONFIG_ALLOW_SYSTEM_CFLAGS +        : $(allow-cflags) +        : 1 +        ] ; +    allow-libs = +        [ envar-set-command PKG_CONFIG_ALLOW_SYSTEM_LIBS +        : $(allow-libs) +        : 1 +        ] ; + +    command += --print-errors --errors-to-stdout --define-variable=$(defines) ; +    $(.configs).set $(config) +        : command +        : "$(path)$(libdir)$(sysroot)$(allow-cflags)$(allow-libs)$(command:J= )" +        ; + +    feature.extend pkg-config : $(config) ; +} + + +local rule envar-set-command ( envar : value * : implied-value * ) +{ +    if $(value) +    { +        if $(implied-value) +        { +            value = $(implied-value) ; +        } +        return [ common.path-variable-setting-command $(envar) : $(value) ] ; +    } +    else +    { +        return "" ; +    } +} + + +local rule non-empty ( string ) +{ +    if $(string) != "" { return true ; } +} + + +.configs = [ new configurations ] ; + + +#| tag::doc[] + +== Tips [[pkg-config-tips]] + + +=== Using several configurations + +Suppose, you have 2 collections of `.pc` files: one for platform A, and another +for platform B. You can initialize 2 configurations of `pkg-config` tool each +corresponding to specific collection: + +[source, jam] +---- +using pkg-config : A : : <libdir>path/to/collection/A ; +using pkg-config : B : : <libdir>path/to/collection/B ; +---- + +Then, you can specify that builds for platform A should use configuration A, +while builds for B should use configuration B: + +[source, jam] +---- +project +    : requirements +      <target-os>A-os,<architecture>A-arch:<pkg-config>A +      <target-os>B-os,<architecture>B-arch:<pkg-config>B +    ; +---- + +Thanks to the fact, that `project-config`, `user-config` and `site-config` +modules are parents of jamroot module, you can put it in any of those files.o + + +=== Choosing the package name based on the property set + +Since a file for a package should be named after the package suffixed with +`.pc`, some projects came up with naming schemes in order to allow simultaneous +installation of several major versions or build variants. In order to pick the +specific name corresponding to the build request you can use `<conditional>` +property in requirements: + +[source, jam] +---- +pkg-config.import mypackage : requirements <conditional>@infer-name ; + +rule infer-name ( properties * ) +{ +    local name = mypackage ; +    local variant = [ property.select <variant> : $(properties) ] ; +    if $(variant) = debug +    { +      name += -d ; +    } +    return <name>$(name) ; +} +---- + +The `common.format-name` rule can be very useful in this situation. + + +=== Modify usage requirements based on package version or variable + +Sometimes you need to apply some logic based on package's version or a +variable that it defines. For that you can use `<conditional>` property in +usage requirements: + +---- +mypackage = +  [ pkg-config.import mypackage : usage-requirements <conditional>@define_ns +  ] ; + +rule extra-props ( properties * ) +{ +    local ps = [ property-set.create $(properties) ] ; +    local prefix = [ $(mypackage).variable name_prefix : $(ps) ] ; +    prefix += [ $(mypackage).version $(ps) ] ; +    return <define>$(prefix:J=_) ; +} +---- + +|# # end::doc[] | 
