aboutsummaryrefslogtreecommitdiff
path: root/autosetup/local.tcl
blob: 73484e553f2800b4345b8a7272136dcd8a0c23af (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
global withinfo
global extdb

# Final determination of module status
dict set extdb status {}

# Returns 1 if the extension has the attribute
proc ext-has {ext attr} {
    expr {$attr in [dict get $::extdb attrs $ext]}
}

# Returns an entry from the extension 'info' table, or $default otherwise
proc ext-get {ext key {default {}}} {
    if {[dict exists $::extdb info $ext $key]} {
        return [dict get $::extdb info $ext $key]
    } else {
        return $default
    }
}

# Set the status of the extension to the given value, and returns the value
proc ext-set-status {ext value} {
    dict set ::extdb status $ext $value
    return $value
}

# Returns the status of the extension, or ? if unknown
proc ext-get-status {ext} {
    if {[dict exists $::extdb status $ext]} {
        return [dict get $::extdb status $ext]
    }
    return ?
}

proc check-extension-status {ext required {asmodule 0}} {
    global withinfo

    set status [ext-get-status $ext]

    if {$ext in $withinfo(without)} {
        # Disabled without further ado
        msg-result "Extension $ext...disabled"
        return [ext-set-status $ext n]
    }

    if {$status in {m y n}} {
        return $status
    }

    # required is "required" if this extension *must* be enabled
    # required is "wanted" if it is not fatal for this extension
    # not to be enabled

    array set depinfo {m 0 y 0 n 0}

    # Stash the current value of LIBS
    set LIBS [get-define LIBS]

    set use_pkgconfig 0
    set pkgconfig [ext-get $ext pkg-config]
    if {$pkgconfig ne ""} {
        # pkg-config support is optional, so explicitly initialise it here
        if {[pkg-config-init 0]} {
            # Check for at least one set of alternates
            foreach pinfo [split $pkgconfig |] {
                set ok 1
                set pkgs {}
                foreach pkg [split $pinfo ,] {
                    set args [lassign $pkg pkgname]
                    set pkg [string trim $pkg]
                    set optional 0
                    if {[string match {*[*]} $pkg]} {
                        # This package is optional
                        set optional 1
                        set pkg [string range $pkg 0 end-1]
                    }
                    if {![pkg-config $pkg {*}$args]} {
                        if {!$optional} {
                            set ok 0
                            break
                        }
                    } else {
                        lappend pkgs $pkg
                    }
                }
                if {$ok} {
                    set use_pkgconfig 1
                    break
                }
            }
        }
    }
    if {!$use_pkgconfig} {
        # Check direct dependencies
        if [ext-get $ext check 1] {
            # "check" conditions are met
        } else {
            # not met
            incr depinfo(n)
        }
    }

    # asmodule=1 means that the parent is a module so
    # any automatically selected dependencies should also be modules
    if {$asmodule == 0 && $ext in $withinfo(mod)} {
        set asmodule 1
    }

    if {$asmodule} {
        # This is a module, so ignore LIBS
        # LDLIBS_$ext will contain the appropriate libs for this module
        define LIBS $LIBS
    }

    if {$depinfo(n) == 0} {
        # Now extension dependencies
        foreach i [ext-get $ext dep] {
            set status [check-extension-status $i $required $asmodule]
            #puts "$ext: dep $i $required => $status"
            incr depinfo($status)
            if {$depinfo(n)} {
                break
            }
        }
    }

    #parray depinfo

    if {$depinfo(n)} {
        msg-checking "Extension $ext..."
        if {$required eq "required"} {
            user-error "dependencies not met"
        }
        msg-result "disabled (dependencies)"
        return [ext-set-status $ext n]
    }

    # Selected as a module directly or because of a parent dependency?
    if {$asmodule} {
        if {[ext-has $ext tcl]} {
            # Easy, a Tcl module
            msg-result "Extension $ext...tcl"
        } elseif {[ext-has $ext static]} {
            user-error "Extension $ext can't be a module"
        } else {
            msg-result "Extension $ext...module"
            if {$use_pkgconfig} {
                add-pkgconfig-deps $ext $pkgs $asmodule
            } else {
                foreach i [ext-get $ext libdep] {
                    define-append LDLIBS_$ext [get-define $i ""]
                }
            }
        }
        return [ext-set-status $ext m]
    }

    # Selected as a static extension?
    if {[ext-has $ext shared]} {
        user-error "Extension $ext can only be selected as a module"
    } elseif {$ext in $withinfo(ext) || $required eq "$required"} {
        msg-result "Extension $ext...enabled"
    } elseif {$ext in $withinfo(maybe)} {
        msg-result "Extension $ext...enabled (default)"
    } else {
        # Could be selected, but isn't (yet)
        return [ext-set-status $ext x]
    }
    if {$use_pkgconfig} {
        add-pkgconfig-deps $ext $pkgs $asmodule
    } else {
        foreach i [ext-get $ext libdep] {
            define-append LDLIBS [get-define $i ""]
        }
    }
    return [ext-set-status $ext y]
}

# Add dependencies for a pkg-config module to the extension
proc add-pkgconfig-deps {ext pkgs asmodule} {
    foreach pkg $pkgs {
        if {$asmodule} {
            define-append LDLIBS_$ext [pkg-config-get $pkg LIBS]
        } else {
            define-append LDLIBS [pkg-config-get $pkg LIBS]
        }
        define-append LDFLAGS [pkg-config-get $pkg LDFLAGS]
        define-append AS_CFLAGS [pkg-config-get $pkg CFLAGS]
        define-append PKG_CONFIG_REQUIRES $pkg
    }
}

# Examines the user options (the $withinfo array)
# and the extension database ($extdb) to determine
# what is selected, and in what way.
#
# If $allextmod is 1, extensions that would normally be disabled
# are enabled as modules if their prerequisites are met
#
# The results are available via ext-get-status
# And a dictionary is returned containing four keys:
#   static-c     extensions which are static C
#   static-tcl   extensions which are static Tcl
#   module-c     extensions which are C modules
#   module-tcl   extensions which are Tcl modules
proc check-extensions {allextmod} {
    global extdb withinfo

    # Check valid extension names
    foreach i [concat $withinfo(ext) $withinfo(mod)] {
        if {![dict exists $extdb attrs $i]} {
            user-error "Unknown extension: $i"
        }
    }

    set extlist [lsort [dict keys [dict get $extdb attrs]]]

    set withinfo(maybe) {}
    set withinfo(maybemod) {}

    # Now work out the default status. We have.
    # normal case: include !off, !optional if possible
    # --without=default: only include always
	foreach i $extlist {
		if {$withinfo(nodefault)} {
			if {[ext-has $i always]} {
				lappend withinfo(maybe) $i
			}
			continue
		}
		if {[ext-has $i off]} {
			if {$allextmod} {
				lappend withinfo(maybemod) $i
			}
			continue
		}
		if {[ext-has $i optional] && !$withinfo(optional)} {
			if {$allextmod} {
				lappend withinfo(maybemod) $i
			}
			continue
		}
		lappend withinfo(maybe) $i
    }

    foreach i $extlist {
        define LDLIBS_$i ""
    }

    foreach i [concat $withinfo(ext) $withinfo(mod)] {
        check-extension-status $i required
    }
    foreach i $withinfo(maybe) {
        check-extension-status $i wanted
    }
    foreach i $withinfo(maybemod) {
        check-extension-status $i wanted 1
    }

    array set extinfo {static-c {} static-tcl {} module-c {} module-tcl {}}

    foreach i $extlist {
        set status [ext-get-status $i]
        set tcl [ext-has $i tcl]
        switch $status,$tcl {
            y,1 {
                define jim_ext_$i
                lappend extinfo(static-tcl) $i
            }
            y,0 {
                define jim_ext_$i
                lappend extinfo(static-c) $i
                # If there are any static C++ extensions, jimsh must be linked using
                # the C++ compiler
                if {[ext-has $i cpp]} {
                    define HAVE_CXX_EXTENSIONS
                }
            }
            m,1 { lappend extinfo(module-tcl) $i }
            m,0 { lappend extinfo(module-c) $i }
        }
    }
    return [array get extinfo]
}