future.exp revision 1.8
1# Copyright 2004-2019 Free Software Foundation, Inc.
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16load_lib libgloss.exp
17
18# FIXME:brobecker/2004-03-31:
19# The following functions should eventually be part of dejagnu. Even after
20# these functions becomes available in dejagnu, we will keep for a while
21# a copy here in order to avoid increasing the dejagnu version
22# requirement.
23
24proc gdb_find_gnatmake {} {
25    global tool_root_dir
26
27    set root "$tool_root_dir/gcc"
28    set GM ""
29
30    if ![is_remote host] {
31        set file [lookfor_file $root gnatmake]
32        if { $file != "" } {
33            set GM "$file -I$root/ada/rts --GCC=$root/xgcc --GNATBIND=$root/gnatbind --GNATLINK=$root/gnatlink -cargs -B$root -largs --GCC=$root/xgcc -margs";
34        }
35    }
36
37    if {$GM == ""} {
38        set GM [transform gnatmake]
39    }
40
41    return $GM
42}
43
44proc gdb_find_gdc {} {
45    global tool_root_dir
46    print "Tool Root: $tool_root_dir"
47
48    if {![is_remote host]} {
49	set file [lookfor_file $tool_root_dir gdc]
50	if { $file == "" } {
51	    set file [lookfor_file $tool_root_dir gcc/gdc]
52	}
53	if { $file != "" } {
54	    set CC "$file -B[file dirname $file]/"
55	} else {
56	    set CC [transform gdc]
57	}
58    } else {
59	set CC [transform gdc]
60    }
61    print "CC: $CC"
62    return $CC
63}
64
65proc gdb_find_gfortran {} {
66    global tool_root_dir
67
68    if {![is_remote host]} {
69	set file [lookfor_file $tool_root_dir gfortran]
70	if { $file == "" } {
71	    set file [lookfor_file $tool_root_dir gcc/gfortran]
72	}
73	if { $file != "" } {
74	    set CC "$file -B[file dirname $file]/"
75	} else {
76	    set CC [transform gfortran]
77	}
78    } else {
79	set CC [transform gfortran]
80    }
81    return $CC
82}
83
84proc gdb_find_go {} {
85    global tool_root_dir
86
87    set GO ""
88
89    if {![is_remote host]} {
90	set file [lookfor_file $tool_root_dir gccgo]
91	if { $file != "" } {
92	    set root [file dirname $file]
93	    set GO "$file -B$root/gcc/"
94	}
95    }
96
97    if { $GO == "" } {
98	set GO [transform gccgo]
99    }
100
101    return $GO
102}
103
104proc gdb_find_go_linker {} {
105    return [find_go]
106}
107
108proc gdb_find_rustc {} {
109    global tool_root_dir
110    if {![is_remote host]} {
111	set rustc [lookfor_file $tool_root_dir rustc]
112	if {$rustc == ""} {
113	    set rustc rustc
114	}
115    } else {
116	set rustc ""
117    }
118    if {$rustc != ""} {
119	append rustc " --color never"
120    }
121    return $rustc
122}
123
124proc gdb_find_ldd {} {
125    global LDD_FOR_TARGET
126    if [info exists LDD_FOR_TARGET] {
127	set ldd $LDD_FOR_TARGET
128    } else {
129	set ldd "ldd"
130    }
131    return $ldd
132}
133
134proc gdb_find_objcopy {} {
135    global OBJCOPY_FOR_TARGET
136    if [info exists OBJCOPY_FOR_TARGET] {
137	set objcopy $OBJCOPY_FOR_TARGET
138    } else {
139	set objcopy [transform objcopy]
140    }
141    return $objcopy
142}
143
144# find target objdump
145proc gdb_find_objdump {} {
146    global OBJDUMP_FOR_TARGET
147    if [info exists OBJDUMP_FOR_TARGET] {
148	set objdump $OBJDUMP_FOR_TARGET
149    } else {
150	set objdump [transform objdump]
151    }
152    return $objdump
153}
154
155proc gdb_find_readelf {} {
156    global READELF_FOR_TARGET
157    if [info exists READELF_FOR_TARGET] {
158	set readelf $READELF_FOR_TARGET
159    } else {
160	set readelf [transform readelf]
161    }
162    return $readelf
163}
164
165proc gdb_default_target_compile {source destfile type options} {
166    global target_triplet
167    global tool_root_dir
168    global CFLAGS_FOR_TARGET
169    global compiler_flags
170
171    if { $destfile == "" && $type != "preprocess" && $type != "none" } {
172	error "Must supply an output filename for the compile to default_target_compile"
173    }
174
175    set early_flags ""
176    set add_flags ""
177    set libs ""
178    set compiler_type "c"
179    set compiler ""
180    set linker ""
181    # linker_opts_order is one of "sources-then-flags", "flags-then-sources".
182    # The order matters for things like -Wl,--as-needed.  The default is to
183    # preserve existing behavior.
184    set linker_opts_order "sources-then-flags"
185    set ldflags ""
186    set dest [target_info name]
187
188    if {[info exists CFLAGS_FOR_TARGET]} {
189	append add_flags " $CFLAGS_FOR_TARGET"
190    }
191
192    if {[info exists target_info(host,name)]} {
193	set host [host_info name]
194    } else {
195	set host "unix"
196    }
197
198    foreach i $options {
199
200	if { $i == "ada" } {
201	    set compiler_type "ada"
202	    if {[board_info $dest exists adaflags]} {
203		append add_flags " [target_info adaflags]"
204	    }
205	    if {[board_info $dest exists gnatmake]} {
206		set compiler [target_info gnatmake]
207	    } else {
208		set compiler [find_gnatmake]
209	    }
210	}
211
212	if { $i == "c++" } {
213	    set compiler_type "c++"
214	    if {[board_info $dest exists cxxflags]} {
215		append add_flags " [target_info cxxflags]"
216	    }
217	    append add_flags " [g++_include_flags]"
218	    if {[board_info $dest exists c++compiler]} {
219		set compiler [target_info c++compiler]
220	    } else {
221		set compiler [find_g++]
222	    }
223	}
224
225	if { $i == "d" } {
226	    set compiler_type "d"
227	    if {[board_info $dest exists dflags]} {
228		append add_flags " [target_info dflags]"
229	    }
230	    if {[board_info $dest exists dcompiler]} {
231		set compiler [target_info dcompiler]
232	    } else {
233		set compiler [find_gdc]
234	    }
235	}
236
237	if { $i == "f77" } {
238	    set compiler_type "f77"
239	    if {[board_info $dest exists f77flags]} {
240		append add_flags " [target_info f77flags]"
241	    }
242	    if {[board_info $dest exists f77compiler]} {
243		set compiler [target_info f77compiler]
244	    } else {
245		set compiler [find_g77]
246	    }
247	}
248
249	if { $i == "f90" } {
250	    set compiler_type "f90"
251	    if {[board_info $dest exists f90flags]} {
252		append add_flags " [target_info f90flags]"
253	    }
254	    if {[board_info $dest exists f90compiler]} {
255		set compiler [target_info f90compiler]
256	    } else {
257		set compiler [find_gfortran]
258	    }
259	}
260
261	if { $i == "go" } {
262	    set compiler_type "go"
263	    if {[board_info $dest exists goflags]} {
264		append add_flags " [target_info goflags]"
265	    }
266	    if {[board_info $dest exists gocompiler]} {
267		set compiler [target_info gocompiler]
268	    } else {
269		set compiler [find_go]
270	    }
271	    if {[board_info $dest exists golinker]} {
272		set linker [target_info golinker]
273	    } else {
274		set linker [find_go_linker]
275	    }
276	    if {[board_info $dest exists golinker_opts_order]} {
277		set linker_opts_order [target_info golinker_opts_order]
278	    }
279	}
280
281	if { $i == "rust" } {
282	    set compiler_type "rust"
283	    if {[board_info $dest exists rustflags]} {
284		append add_flags " [target_info rustflags]"
285	    }
286	    if {[board_info $dest exists rustflags]} {
287		set compiler [target_info rustflags]
288	    } else {
289		set compiler [find_rustc]
290	    }
291	}
292
293	if {[regexp "^dest=" $i]} {
294	    regsub "^dest=" $i "" tmp
295	    if {[board_info $tmp exists name]} {
296		set dest [board_info $tmp name]
297	    } else {
298		set dest $tmp
299	    }
300	}
301	if {[regexp "^compiler=" $i]} {
302	    regsub "^compiler=" $i "" tmp
303	    set compiler $tmp
304	}
305	if {[regexp "^early_flags=" $i]} {
306	    regsub "^early_flags=" $i "" tmp
307	    append early_flags " $tmp"
308	}
309	if {[regexp "^additional_flags=" $i]} {
310	    regsub "^additional_flags=" $i "" tmp
311	    append add_flags " $tmp"
312	}
313	if {[regexp "^ldflags=" $i]} {
314	    regsub "^ldflags=" $i "" tmp
315	    append ldflags " $tmp"
316	}
317	if {[regexp "^libs=" $i]} {
318	    regsub "^libs=" $i "" tmp
319	    append libs " $tmp"
320	}
321	if {[regexp "^incdir=" $i]} {
322	    regsub "^incdir=" $i "-I" tmp
323	    append add_flags " $tmp"
324	}
325	if {[regexp "^libdir=" $i]} {
326	    regsub "^libdir=" $i "-L" tmp
327	    append add_flags " $tmp"
328	}
329	if {[regexp "^ldscript=" $i]} {
330	    regsub "^ldscript=" $i "" ldscript
331	}
332	if {[regexp "^redirect=" $i]} {
333	    regsub "^redirect=" $i "" redirect
334	}
335	if {[regexp "^optimize=" $i]} {
336	    regsub "^optimize=" $i "" optimize
337	}
338	if {[regexp "^timeout=" $i]} {
339	    regsub "^timeout=" $i "" timeout
340	}
341    }
342
343    if {[board_info $host exists cflags_for_target]} {
344	append add_flags " [board_info $host cflags_for_target]"
345    }
346
347    global CC_FOR_TARGET
348    global CXX_FOR_TARGET
349    global D_FOR_TARGET
350    global F77_FOR_TARGET
351    global F90_FOR_TARGET
352    global GNATMAKE_FOR_TARGET
353    global GO_FOR_TARGET
354    global GO_LD_FOR_TARGET
355    global RUSTC_FOR_TARGET
356
357    if {[info exists GNATMAKE_FOR_TARGET]} {
358	if { $compiler_type == "ada" } {
359	    set compiler $GNATMAKE_FOR_TARGET
360	}
361    }
362
363    if {[info exists CC_FOR_TARGET]} {
364	if { $compiler == "" } {
365	    set compiler $CC_FOR_TARGET
366	}
367    }
368
369    if {[info exists CXX_FOR_TARGET]} {
370	if { $compiler_type == "c++" } {
371	    set compiler $CXX_FOR_TARGET
372	}
373    }
374
375    if {[info exists D_FOR_TARGET]} {
376	if { $compiler_type == "d" } {
377	    set compiler $D_FOR_TARGET
378	}
379    }
380
381    if {[info exists F77_FOR_TARGET]} {
382	if { $compiler_type == "f77" } {
383	    set compiler $F77_FOR_TARGET
384	}
385    }
386
387    if {[info exists F90_FOR_TARGET]} {
388	if { $compiler_type == "f90" } {
389	    set compiler $F90_FOR_TARGET
390	}
391    }
392
393    if { $compiler_type == "go" } {
394	if {[info exists GO_FOR_TARGET]} {
395	    set compiler $GO_FOR_TARGET
396	}
397	if {[info exists GO_LD_FOR_TARGET]} {
398	    set linker $GO_LD_FOR_TARGET
399	}
400    }
401
402    if {[info exists RUSTC_FOR_TARGET]} {
403	if {$compiler_type == "rust"} {
404	    set compiler $RUSTC_FOR_TARGET
405	}
406    }
407
408    if { $type == "executable" && $linker != "" } {
409	set compiler $linker
410    }
411
412    if { $compiler == "" } {
413	set compiler [board_info $dest compiler]
414	if { $compiler == "" } {
415	    return "default_target_compile: No compiler to compile with"
416	}
417    }
418
419    if {![is_remote host]} {
420	if { [which $compiler] == 0 } {
421	    return "default_target_compile: Can't find $compiler."
422	}
423    }
424
425    if {$type == "object"} {
426	if {$compiler_type == "rust"} {
427	    append add_flags "--emit obj"
428	} else {
429	    append add_flags " -c"
430	}
431    }
432
433    if { $type == "preprocess" } {
434	append add_flags " -E"
435    }
436
437    if { $type == "assembly" } {
438	append add_flags " -S"
439    }
440
441    if {[board_info $dest exists cflags]} {
442	append add_flags " [board_info $dest cflags]"
443    }
444
445    if { $type == "executable" } {
446	if {[board_info $dest exists ldflags]} {
447	    append add_flags " [board_info $dest ldflags]"
448	}
449	if { $compiler_type == "c++" } {
450	    append add_flags " [g++_link_flags]"
451	}
452	if {[isnative]} {
453	    # This is a lose.
454	    catch "glob -nocomplain $tool_root_dir/libstdc++/libstdc++.so* $tool_root_dir/libstdc++/libstdc++.sl" tmp
455	    if { ${tmp} != "" } {
456		if {[regexp ".*solaris2.*" $target_triplet]} {
457		    # Solaris 2
458		    append add_flags " -R$tool_root_dir/libstdc++"
459		} elseif {[regexp ".*(osf|irix5|linux).*" $target_triplet]} {
460		    # OSF/1 or IRIX 5
461		    append add_flags " -Wl,-rpath,$tool_root_dir/libstdc++"
462		}
463	    }
464	}
465    }
466
467    if {![info exists ldscript]} {
468	set ldscript [board_info $dest ldscript]
469    }
470
471    foreach i $options {
472	if { $i == "debug" } {
473	    if {[board_info $dest exists debug_flags]} {
474		append add_flags " [board_info $dest debug_flags]"
475	    } else {
476		append add_flags " -g"
477	    }
478	}
479    }
480
481    if {[info exists optimize]} {
482	append add_flags " $optimize"
483    }
484
485    if { $type == "executable" } {
486	append add_flags " $ldflags"
487	foreach x $libs {
488	    if {[file exists $x]} {
489		append source " $x"
490	    } else {
491		append add_flags " $x"
492	    }
493	}
494
495	if {[board_info $dest exists libs]} {
496	    append add_flags " [board_info $dest libs]"
497	}
498
499	# This probably isn't such a good idea, but it avoids nasty
500	# hackiness in the testsuites.
501	# The math library must be linked in before the C library.  The C
502	# library is linked in by the linker script, so this must be before
503	# the linker script.
504	if {[board_info $dest exists mathlib]} {
505	    append add_flags " [board_info $dest mathlib]"
506	} else {
507	    append add_flags " -lm"
508	}
509
510	# This must be added here.
511	append add_flags " $ldscript"
512
513	if {[board_info $dest exists remote_link]} {
514	    # Relink option.
515	    append add_flags " -Wl,-r"
516	}
517	if {[board_info $dest exists output_format]} {
518	    append add_flags " -Wl,-oformat,[board_info $dest output_format]"
519	}
520    }
521
522    if {[board_info $dest exists multilib_flags]} {
523	append add_flags " [board_info $dest multilib_flags]"
524    }
525
526    verbose "doing compile"
527
528    set sources ""
529    if {[is_remote host]} {
530	foreach x $source {
531	    set file [remote_download host $x]
532	    if { $file == "" } {
533		warning "Unable to download $x to host."
534		return "Unable to download $x to host."
535	    } else {
536		append sources " $file"
537	    }
538	}
539    } else {
540	set sources $source
541    }
542
543    if {[is_remote host]} {
544	append add_flags " -o " [file tail $destfile]
545	remote_file host delete [file tail $destfile]
546    } else {
547	if { $destfile != "" } {
548	    append add_flags " -o $destfile"
549	}
550    }
551
552    # This is obscure: we put SOURCES at the end when building an
553    # object, because otherwise, in some situations, libtool will
554    # become confused about the name of the actual source file.
555    switch $type {
556	"object" {
557	    set opts "$early_flags $add_flags $sources"
558	}
559	"executable" {
560	    switch $linker_opts_order {
561		"flags-then-sources" {
562		    set opts "$early_flags $add_flags $sources"
563		}
564		"sources-then-flags" {
565		    set opts "$early_flags $sources $add_flags"
566		}
567		default {
568		    error "Invalid value for board_info linker_opts_order"
569		}
570	    }
571	}
572	default {
573	    set opts "$early_flags $sources $add_flags"
574	}
575    }
576
577    if {[is_remote host]} {
578	if {[host_info exists use_at]} {
579	    set fid [open "atfile" "w"]
580	    puts $fid "$opts"
581	    close $fid
582	    set opts "@[remote_download host atfile]"
583	    remote_file build delete atfile
584	}
585    }
586
587    verbose "Invoking the compiler as $compiler $opts" 2
588
589    if {[info exists redirect]} {
590	verbose "Redirecting output to $redirect" 2
591	set status [remote_exec host "$compiler $opts" "" "" $redirect]
592    } else {
593	if {[info exists timeout]} {
594	    verbose "Setting timeout to $timeout" 2
595	    set status [remote_exec host "$compiler $opts" "" "" "" $timeout]
596	} else {
597	    set status [remote_exec host "$compiler $opts"]
598	}
599    }
600
601    set compiler_flags $opts
602    if {[is_remote host]} {
603	remote_upload host [file tail $destfile] $destfile
604	remote_file host delete [file tail $destfile]
605    }
606    set comp_output [prune_warnings [lindex $status 1]]
607    regsub "^\[\r\n\]+" $comp_output "" comp_output
608    if { [lindex $status 0] != 0 } {
609	verbose -log "compiler exited with status [lindex $status 0]"
610    }
611    if { [lindex $status 1] != "" } {
612	verbose -log "output is:\n[lindex $status 1]" 2
613    }
614    if { [lindex $status 0] != 0 && "${comp_output}" == "" } {
615	set comp_output "exit status is [lindex $status 0]"
616    }
617    return ${comp_output}
618}
619
620# See if the version of dejaGNU being used to run the testsuite is
621# recent enough to contain support for building Ada programs or not.
622# If not, then use the functions above in place of the ones provided
623# by dejaGNU. This is only temporary (brobecker/2004-03-31).
624
625set use_gdb_compile 0
626if {[info procs find_gnatmake] == ""} {
627    rename gdb_find_gnatmake find_gnatmake
628    set use_gdb_compile 1
629}
630
631if {[info procs find_gfortran] == ""} {
632    rename gdb_find_gfortran find_gfortran
633    set use_gdb_compile 1
634}
635
636if {[info procs find_go_linker] == ""} {
637    rename gdb_find_go find_go
638    rename gdb_find_go_linker find_go_linker
639    set use_gdb_compile 1
640}
641
642if {[info procs find_gdc] == ""} {
643    rename gdb_find_gdc find_gdc
644    set use_gdb_compile 1
645}
646
647if {[info procs find_rustc] == ""} {
648    rename gdb_find_rustc find_rustc
649    set use_gdb_compile 1
650}
651
652if {$use_gdb_compile} {
653    catch {rename default_target_compile {}}
654    rename gdb_default_target_compile default_target_compile
655}
656
657
658# Provide 'lreverse' missing in Tcl before 7.5.
659
660if {[info procs lreverse] == ""} {
661    proc lreverse { arg } {
662	set retval {}
663	while { [llength $retval] < [llength $arg] } {
664	    lappend retval [lindex $arg end-[llength $retval]]
665	}
666	return $retval
667    }
668}
669
670# Various ccache versions provide incorrect debug info such as ignoring
671# different current directory, breaking GDB testsuite.
672set env(CCACHE_DISABLE) 1
673unset -nocomplain env(CCACHE_NODISABLE)
674