From 176890c096bdc3847c9efffffe7fb25eb6351ee2 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 2 Jan 2020 21:03:55 +0000 Subject: Build config with boost-build pkg-config support --- pkg-config.jam | 485 --------------------------------------------------------- 1 file changed, 485 deletions(-) delete mode 100644 pkg-config.jam diff --git a/pkg-config.jam b/pkg-config.jam deleted file mode 100644 index 2efa9cf..0000000 --- a/pkg-config.jam +++ /dev/null @@ -1,485 +0,0 @@ -#| -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 <>. - -|# # 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 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: - -* ``: adds a `--define-variable` argument; -* ``: adds `--static` argument when `static`; -* ``: adds `--static` argument when `static`; -* ``: specifies package name (target name is used instead if the property - is not present); -* ``: 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 my_package <4 >=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: - * ``: sets `PKG_CONFIG_PATH` environment variable; - multiple occurences are allowed. - * ``: sets `PKG_CONFIG_LIBDIR` environment variable; - multiple occurences are allowed. - * ``: sets `PKG_CONFIG_ALLOW_SYSTEM_CFLAGS` - environment variable; multiple occurences are allowed. - * ``: sets `PKG_CONFIG_ALLOW_SYSTEM_LIBS` - environment variable; multiple occurences are allowed. - * ``: sets `PKG_CONFIG_SYSROOT_DIR` environment variable; - multiple occurences are allowed. - * ``: 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 <> 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 ] ; - 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 ] ; - 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 ] ; - 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 ] ; - local args = --define-variable=$(defines) ; - if [ $(property-set).get ] = 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 ] ; - 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 ] - { - 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 $(flags) ; - } - - local rule compile-flags ( config property-set : args * ) - { - local flags = [ pkg-config.run $(config) : --cflags $(args) ] ; - return $(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 += $(opt:G=) ; - case : libdir += $(opt:G=) ; - case : allow-system-cflags += $(opt:G=) ; - case : allow-system-libs += $(opt:G=) ; - case : sysroot += $(opt:G=) ; - case : 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 " - " 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 : : path/to/collection/A ; -using pkg-config : B : : 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 - A-os,A-arch:A - B-os,B-arch: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 `` -property in requirements: - -[source, jam] ----- -pkg-config.import mypackage : requirements @infer-name ; - -rule infer-name ( properties * ) -{ - local name = mypackage ; - local variant = [ property.select : $(properties) ] ; - if $(variant) = debug - { - name += -d ; - } - return $(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 `` property in -usage requirements: - ----- -mypackage = - [ pkg-config.import mypackage : usage-requirements @define_ns - ] ; - -rule extra-props ( properties * ) -{ - local ps = [ property-set.create $(properties) ] ; - local prefix = [ $(mypackage).variable name_prefix : $(ps) ] ; - prefix += [ $(mypackage).version $(ps) ] ; - return $(prefix:J=_) ; -} ----- - -|# # end::doc[] -- cgit v1.2.3