|
1
|
# @synopsis: |
|
2
|
# |
|
3
|
# The 'cc-run' module provides a way to compile and run a bit of |
|
4
|
# code. This is not cross compilation friendly and is therefore |
|
5
|
# against autosetup's general philosophy, but is sometimes the only |
|
6
|
# way to perform a test. |
|
7
|
# |
|
8
|
|
|
9
|
use cc |
|
10
|
|
|
11
|
module-options {} |
|
12
|
|
|
13
|
# cc-run is based on cctest in cc.tcl. |
|
14
|
|
|
15
|
# @cc-run ?settings? |
|
16
|
# |
|
17
|
# Low level C/C++ program checker. Compiles, links, and runs a small |
|
18
|
# C/C++ program according to the arguments and returns 1 if OK, or 0 |
|
19
|
# if not. |
|
20
|
# |
|
21
|
# Supported settings are: |
|
22
|
# |
|
23
|
## -cflags cflags A list of flags to pass to the compiler |
|
24
|
## -includes list A list of includes, e.g. {stdlib.h stdio.h} |
|
25
|
## -declare code Code to declare before main() |
|
26
|
## -lang c|c++ Use the C (default) or C++ compiler |
|
27
|
## -libs liblist List of libraries to link, e.g. {-ldl -lm} |
|
28
|
## -code code Code to compile in the body of main() |
|
29
|
## -source code Compile a complete program. Ignore -includes, -declare and -code |
|
30
|
## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file] |
|
31
|
# |
|
32
|
# Unless -source or -sourcefile is specified, the C program looks like: |
|
33
|
# |
|
34
|
## #include <firstinclude> /* same for remaining includes in the list */ |
|
35
|
## |
|
36
|
## declare-code /* any code in -declare, verbatim */ |
|
37
|
## |
|
38
|
## int main(void) { |
|
39
|
## code /* any code in -code, verbatim */ |
|
40
|
## return 0; |
|
41
|
## } |
|
42
|
# |
|
43
|
# Any failures are recorded in 'config.log' |
|
44
|
# |
|
45
|
proc cc-run {args} { |
|
46
|
set src conftest__.c |
|
47
|
set tmp conftest__ |
|
48
|
|
|
49
|
# Easiest way to merge in the settings |
|
50
|
cc-with $args { |
|
51
|
array set opts [cc-get-settings] |
|
52
|
} |
|
53
|
|
|
54
|
if {[info exists opts(-sourcefile)]} { |
|
55
|
set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"] |
|
56
|
} |
|
57
|
if {[info exists opts(-source)]} { |
|
58
|
set lines $opts(-source) |
|
59
|
} else { |
|
60
|
foreach i $opts(-includes) { |
|
61
|
if {$opts(-code) ne "" && ![feature-checked $i]} { |
|
62
|
# Compiling real code with an unchecked header file |
|
63
|
# Quickly (and silently) check for it now |
|
64
|
|
|
65
|
# Remove all -includes from settings before checking |
|
66
|
set saveopts [cc-update-settings -includes {}] |
|
67
|
msg-quiet cc-check-includes $i |
|
68
|
cc-store-settings $saveopts |
|
69
|
} |
|
70
|
if {$opts(-code) eq "" || [have-feature $i]} { |
|
71
|
lappend source "#include <$i>" |
|
72
|
} |
|
73
|
} |
|
74
|
lappend source {*}$opts(-declare) |
|
75
|
lappend source "int main(void) {" |
|
76
|
lappend source $opts(-code) |
|
77
|
lappend source "return 0;" |
|
78
|
lappend source "}" |
|
79
|
|
|
80
|
set lines [join $source \n] |
|
81
|
} |
|
82
|
|
|
83
|
# Build the command line |
|
84
|
set cmdline {} |
|
85
|
lappend cmdline {*}[get-define CCACHE] |
|
86
|
switch -exact -- $opts(-lang) { |
|
87
|
c++ { |
|
88
|
lappend cmdline {*}[get-define CXX] {*}[get-define CXXFLAGS] |
|
89
|
} |
|
90
|
c { |
|
91
|
lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS] |
|
92
|
} |
|
93
|
default { |
|
94
|
autosetup-error "cc-run called with unknown language: $opts(-lang)" |
|
95
|
} |
|
96
|
} |
|
97
|
|
|
98
|
lappend cmdline {*}$opts(-cflags) |
|
99
|
|
|
100
|
switch -glob -- [get-define host] { |
|
101
|
*-*-darwin* { |
|
102
|
# Don't generate .dSYM directories |
|
103
|
lappend cmdline -gstabs |
|
104
|
} |
|
105
|
} |
|
106
|
lappend cmdline $src -o $tmp {*}$opts(-libs) |
|
107
|
|
|
108
|
# At this point we have the complete command line and the |
|
109
|
# complete source to be compiled. Get the result from cache if |
|
110
|
# we can |
|
111
|
if {[info exists ::cc_cache($cmdline,$lines)]} { |
|
112
|
msg-checking "(cached) " |
|
113
|
set ok $::cc_cache($cmdline,$lines) |
|
114
|
if {$::autosetup(debug)} { |
|
115
|
configlog "From cache (ok=$ok): [join $cmdline]" |
|
116
|
configlog "============" |
|
117
|
configlog $lines |
|
118
|
configlog "============" |
|
119
|
} |
|
120
|
return $ok |
|
121
|
} |
|
122
|
|
|
123
|
writefile $src $lines\n |
|
124
|
|
|
125
|
set ok 1 |
|
126
|
if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} { |
|
127
|
configlog "Failed: [join $cmdline]" |
|
128
|
configlog $result |
|
129
|
configlog "============" |
|
130
|
configlog "The failed code was:" |
|
131
|
configlog $lines |
|
132
|
configlog "============" |
|
133
|
set ok 0 |
|
134
|
} else { |
|
135
|
if {$::autosetup(debug)} { |
|
136
|
configlog "Compiled OK: [join $cmdline]" |
|
137
|
configlog "============" |
|
138
|
configlog $lines |
|
139
|
configlog "============" |
|
140
|
} |
|
141
|
if {[catch {exec-with-stderr ./$tmp} result errinfo]} { |
|
142
|
configlog "Failed: $tmp" |
|
143
|
configlog $result |
|
144
|
configlog "============" |
|
145
|
configlog "The failed code was:" |
|
146
|
configlog $lines |
|
147
|
configlog "============" |
|
148
|
set ok 0 |
|
149
|
} else { |
|
150
|
if {$::autosetup(debug)} { |
|
151
|
configlog "Ran OK: $tmp" |
|
152
|
configlog "============" |
|
153
|
configlog $lines |
|
154
|
configlog "============" |
|
155
|
} |
|
156
|
} |
|
157
|
} |
|
158
|
file delete $src |
|
159
|
file delete $tmp |
|
160
|
|
|
161
|
# cache it |
|
162
|
set ::cc_cache($cmdline,$lines) $ok |
|
163
|
|
|
164
|
return $ok |
|
165
|
} |
|
166
|
|