summaryrefslogtreecommitdiff
path: root/libs/predef/check/predef.jam
blob: 0638703a0558682ca667ff6504da4bb315dd0d91 (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
# Copyright Rene Rivera 2015
# 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)

# Defines rules that provide requirements based on checking
# conditions using Boost Predef definitions and version numbers.

import modules ;
import project ;
import feature ;
import string ;
import toolset ;
import modules ;
import path ;

# Create a project for our targets.
project.extension predef check ;

# Feature to pass check expressions to check programs.
feature.feature predef-expression : : free ;

# Check programs. Each needs to be compiled for different languages
# even though they are all the same source code.
local rule check_target ( language : ext )
{
    # Need to use absolute paths because we don't know the
    # context of the invocation which affects where the paths
    # originate from.
    local predef_jam
        = [ modules.binding $(__name__) ] ;
        local source_path
            = $(predef_jam:D)/predef_check_as_$(language).$(ext) ;
        local include_path
            = $(predef_jam:D)/../include ;
        _check_exe_($(language)) = [
            exe predef_check_as_$(language)
                : $(source_path)
                : <include>$(include_path) ] ;
    explicit predef_check_as_$(language) ;
}
check_target c : c ;
check_target cpp : cpp ;
check_target objc : m ;
check_target objcpp : mm ;

# Checks the expressions and when used evaluates to the true-properties
# if the expressions are all true. Otherwise evaluates to the
# false-properties.
rule check ( expressions + : language ? : true-properties * : false-properties * )
{
    # Default to C++ on the check context.
    language ?= cpp ;
    
    local project_target = [ project.target $(__name__) ] ;
	project.push-current $(project_target) ;
    local result ;
    for expression in $(expressions)
    {
        # The check program to use.
        local exe_target = [ $(_check_exe_($(language))).name ] ;
        exe_target = /check/predef//$(exe_target) ;
        
        # Create the check run if we don't have one yet.
        local key = [ MD5 $(language)::$(expression) ] ;
        if ! ( $(key) in $(_checks_) )
        {
            _checks_ += $(key) ;
            make
                $(key).txt :
                $(exe_target) :
                @$(__name__).predef_check_action :
                <predef-expression>$(expression) ;
            explicit
                $(key).txt ;
        }
        
        local check_target = [ check-target-builds
            /check/predef//$(key).txt $(expression)
            : $(true-properties)
            : $(false-properties) ] ;
        
        result += $(check_target) ;
    }
	project.pop-current ;
    return $(result) ;
}

# Checks the expressions and when used evaluates to <build>no
# if the expressions are all false. Otherwise evaluates to the
# nothing.
rule require ( expressions + : language ? )
{
    return [ check $(expressions) : $(language) : : <build>no ] ;
}

rule predef_check_action ( targets + : sources + : props * )
{
    PREDEF_CHECK_EXPRESSION on $(targets)
        = [ feature.get-values <predef-expression> : $(props) ] ;
}

actions predef_check_action bind PREDEF_CHECK_EXPRESSION
{
    $(>) "$(PREDEF_CHECK_EXPRESSION)" > $(<)
}