source: trunk/dports/_resources/port1.0/group/compilers-1.0.tcl @ 136116

Last change on this file since 136116 was 136116, checked in by sean@…, 4 years ago

compilers-1.0: remove assumption about gcc 4.x version; no behavioral change

File size: 20.5 KB
Line 
1# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
2# $Id$
3#
4# Copyright (c) 2014 The MacPorts Project
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are
9# met:
10#
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in the
15#    documentation and/or other materials provided with the distribution.
16# 3. Neither the name of The MacPorts Project nor the names of its
17#    contributors may be used to endorse or promote products derived from
18#    this software without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31#
32#
33# This PortGroup sets up default variants for projects that want m
34#
35# Usage:
36#
37#   PortGroup               compilers 1.0
38
39PortGroup active_variants 1.1
40
41options compilers.variants compilers.gcc_variants
42default compilers.variants {}
43default compilers.fortran_variants {}
44default compilers.gcc_variants {}
45default compilers.clang_variants {}
46default compilers.dragonegg_variants {}
47default compilers.require_fortran 0
48default compilers.setup_done 0
49default compilers.required_c {}
50default compilers.required_f {}
51
52set compilers.list {cc cxx cpp objc fc f77 f90}
53
54# build database of gcc 4{4..9} compiler attributes
55set gcc_versions {44 45 46 47 48 49}
56foreach v ${gcc_versions} {
57    # if the string is more than one character insert a '.' into it: e.g 49 -> 4.9
58    set version $v
59    if {[string length $v] > 1} {
60        set version [string index $v 0].[string index $v 1]
61    }
62    lappend compilers.gcc_variants gcc$v
63    set cdb(gcc$v,variant)  gcc$v
64    set cdb(gcc$v,compiler) macports-gcc-$version
65    set cdb(gcc$v,descrip)  "MacPorts gcc $version"
66    set cdb(gcc$v,depends)  port:gcc$v
67    set cdb(gcc$v,dependsl) path:lib/libgcc/libgcc_s.1.dylib:libgcc
68    set cdb(gcc$v,dependsd) port:g95
69    set cdb(gcc$v,dependsa) gcc$v
70    set cdb(gcc$v,conflict) "gfortran g95"
71    set cdb(gcc$v,cc)       ${prefix}/bin/gcc-mp-$version
72    set cdb(gcc$v,cxx)      ${prefix}/bin/g++-mp-$version
73    set cdb(gcc$v,cpp)      ${prefix}/bin/cpp-mp-$version
74    set cdb(gcc$v,objc)     ${prefix}/bin/gcc-mp-$version
75    set cdb(gcc$v,fc)       ${prefix}/bin/gfortran-mp-$version
76    set cdb(gcc$v,f77)      ${prefix}/bin/gfortran-mp-$version
77    set cdb(gcc$v,f90)      ${prefix}/bin/gfortran-mp-$version
78}
79
80set clang_versions {0 1 2 3 4 5}
81foreach v ${clang_versions} {
82    lappend compilers.clang_variants clang3$v
83    set cdb(clang3$v,variant)  clang3$v
84    set cdb(clang3$v,compiler) macports-clang-3.$v
85    set cdb(clang3$v,descrip)  "MacPorts clang 3.$v"
86    set cdb(clang3$v,depends)  port:clang-3.$v
87    set cdb(clang3$v,dependsl) ""
88    set cdb(clang3$v,dependsd) ""
89    set cdb(clang3$v,dependsa) clang-3.$v
90    set cdb(clang3$v,conflict) ""
91    set cdb(clang3$v,cc)       ${prefix}/bin/clang-mp-3.$v
92    set cdb(clang3$v,cxx)      ${prefix}/bin/clang++-mp-3.$v
93    set cdb(clang3$v,cpp)      "${prefix}/bin/clang-mp-3.$v -E"
94    set cdb(clang3$v,objc)     ""
95    set cdb(clang3$v,fc)       ""
96    set cdb(clang3$v,f77)      ""
97    set cdb(clang3$v,f90)      ""
98}
99
100# dragonegg versions match the corresponding clang version until 3.5
101set dragonegg_versions {3 4}
102foreach v ${dragonegg_versions} {
103    lappend compilers.dragonegg_variants dragonegg3$v
104    set cdb(dragonegg3$v,variant)  dragonegg3$v
105    set cdb(dragonegg3$v,compiler) macports-dragonegg-3.$v
106    set cdb(dragonegg3$v,descrip)  "MacPorts dragonegg 3.$v"
107    set cdb(dragonegg3$v,depends)  path:bin/dragonegg-3.$v-gcc:dragonegg-3.$v
108    set cdb(dragonegg3$v,dependsl) path:lib/libgcc/libgcc_s.1.dylib:libgcc
109    set cdb(dragonegg3$v,dependsd) port:g95
110    set cdb(dragonegg3$v,dependsa) dragonegg-3.$v
111    set cdb(dragonegg3$v,conflict) "gfortran g95"
112    set cdb(dragonegg3$v,cc)       ${prefix}/bin/dragonegg-3.$v-gcc
113    set cdb(dragonegg3$v,cxx)      ${prefix}/bin/dragonegg-3.$v-g++
114    set cdb(dragonegg3$v,cpp)      ${prefix}/bin/dragonegg-3.$v-cpp
115    set cdb(dragonegg3$v,objc)     ""
116    set cdb(dragonegg3$v,fc)       ${prefix}/bin/dragonegg-3.$v-gfortran
117    set cdb(dragonegg3$v,f77)      ${prefix}/bin/dragonegg-3.$v-gfortran
118    set cdb(dragonegg3$v,f90)      ${prefix}/bin/dragonegg-3.$v-gfortran
119}
120
121set cdb(llvm,variant)  llvm
122set cdb(llvm,compiler) llvm-gcc-4.2
123set cdb(llvm,descrip)  "Apple native llvm-gcc 4.2"
124set cdb(llvm,depends)  bin:llvm-gcc-4.2:llvm-gcc42
125set cdb(llvm,dependsl) ""
126set cdb(llvm,dependsd) ""
127set cdb(llvm,dependsa) ""
128set cdb(llvm,conflict) ""
129set cdb(llvm,cc)       llvm-gcc-4.2
130set cdb(llvm,cxx)      llvm-g++-4.2
131set cdb(llvm,cpp)      llvm-cpp-4.2
132set cdb(llvm,objc)     llvm-gcc-4.2
133set cdb(llvm,fc)       ""
134set cdb(llvm,f77)      ""
135set cdb(llvm,f90)      ""
136
137# and lastly we add a gfortran and g95 variant for use with clang*; note that
138# we don't need gfortran when we are in an "only-fortran" mode
139set compilers.gfortran_equiv    gcc49
140set cdb(gfortran,variant)  gfortran
141set cdb(gfortran,compiler) $cdb(${compilers.gfortran_equiv},compiler)
142set cdb(gfortran,descrip)  $cdb(${compilers.gfortran_equiv},descrip)
143set cdb(gfortran,depends)  $cdb(${compilers.gfortran_equiv},depends)
144set cdb(gfortran,dependsl) $cdb(${compilers.gfortran_equiv},dependsl)
145set cdb(gfortran,dependsd) $cdb(${compilers.gfortran_equiv},dependsd)
146set cdb(gfortran,dependsa) $cdb(${compilers.gfortran_equiv},dependsa)
147set cdb(gfortran,conflict) $cdb(${compilers.gfortran_equiv},conflict)
148set cdb(gfortran,cc)       $cdb(${compilers.gfortran_equiv},cc)
149set cdb(gfortran,cxx)      $cdb(${compilers.gfortran_equiv},cxx)
150set cdb(gfortran,cpp)      $cdb(${compilers.gfortran_equiv},cpp)
151set cdb(gfortran,objc)     $cdb(${compilers.gfortran_equiv},objc)
152set cdb(gfortran,fc)       $cdb(${compilers.gfortran_equiv},fc)
153set cdb(gfortran,f77)      $cdb(${compilers.gfortran_equiv},f77)
154set cdb(gfortran,f90)      $cdb(${compilers.gfortran_equiv},f90)
155
156set cdb(g95,variant)  g95
157set cdb(g95,compiler) g95
158set cdb(g95,descrip)  "Fortran compiler from g95"
159set cdb(g95,depends)  port:g95
160set cdb(g95,dependsl) ""
161set cdb(g95,dependsd) ""
162set cdb(g95,dependsa) g95
163set cdb(g95,conflict) ""
164set cdb(g95,cc)       ""
165set cdb(g95,cxx)      ""
166set cdb(g95,cpp)      ""
167set cdb(g95,objc)     ""
168set cdb(g95,fc)       ${prefix}/bin/g95
169set cdb(g95,f77)      ${prefix}/bin/g95
170set cdb(g95,f90)      ${prefix}/bin/g95
171
172foreach cname [array names cdb *,variant] {
173    lappend compilers.variants $cdb($cname)
174}
175
176foreach variant ${compilers.variants} {
177    if {$cdb($variant,f77) ne ""} {
178        lappend compilers.fortran_variants $variant
179    }
180}
181
182proc compilers.setup_variants {args} {
183    global cdb compilers.variants compilers.clang_variants compilers.gcc_variants
184    global compilers.dragonegg_variants compilers.fortran_variants compilers.list
185
186    foreach variant [split $args] {
187        if {$cdb($variant,f77) ne ""} {
188            lappend compilers.fortran_variants $variant
189        }
190
191        if {[variant_exists $variant]} {
192            ui_debug "$variant variant already exists, so not adding the default one"
193        } else {
194            set i [lsearch -exact ${compilers.variants} $variant]
195            set c [lreplace ${compilers.variants} $i $i]
196
197            # fortran doesn't conflict with clang
198            if {$variant eq "gfortran" || $variant eq "g95"} {
199                foreach clangcomp ${compilers.clang_variants} {
200                    set i [lsearch -exact $c $clangcomp]
201                    set c [lreplace $c $i $i]
202                }
203            } elseif {[string match clang* $variant]} {
204                set i [lsearch -exact $c gfortran]
205                set c [lreplace $c $i $i]
206                set i [lsearch -exact $c g95]
207                set c [lreplace $c $i $i]
208            }
209
210            # only add conflicts from the compiler database (set above) if we
211            # actually have the compiler in the list of allowed variants
212            foreach j $cdb($variant,conflict) {
213                if {[lsearch -exact $j ${compilers.variants}] > -1} {
214                    lappend c $j
215                }
216            }
217
218            # for each compiler, set the value if not empty; we can't use
219            # configure.compiler because of dragonegg and possibly other new
220            # compilers that aren't in macports portconfigure.tcl
221            set comp ""
222            foreach compiler ${compilers.list} {
223                if {$cdb($variant,$compiler) ne ""} {
224                    append comp [subst {
225                        configure.$compiler $cdb($variant,$compiler)
226
227                        # disable archflags
228                        if {"[info command configure.${compiler}_archflags]" ne ""} {
229                            configure.${compiler}_archflags
230                            configure.ld_archflags
231                        }
232                    }]
233                }
234            }
235
236            eval [subst {
237                variant ${variant} description \
238                    {Build using the $cdb($variant,descrip) compiler} \
239                    conflicts $c {
240
241                    depends_build-append   $cdb($variant,depends)
242                    depends_lib-append     $cdb($variant,dependsl)
243                    depends_lib-delete     $cdb($variant,dependsd)
244                    depends_skip_archcheck $cdb($variant,dependsa)
245
246                    $comp
247                }
248            }]
249        }
250    }
251}
252
253foreach variant ${compilers.gcc_variants} {
254    # we need to check the default_variants so we can't use variant_isset
255    if {[info exists variations($variant)] && $variations($variant) eq "+"} {
256        depends_lib-delete      port:g95
257        break
258    }
259}
260
261proc c_active_variant_name {depspec} {
262    global compilers.variants compilers.fortran_variants
263    set c_list [remove_from_list ${compilers.variants} {gfortran g95}]
264
265    foreach c $c_list {
266        if {![catch {set result [active_variants $depspec $c ""]}]} {
267            if {$result} {
268                return $c
269            }
270        }
271    }
272
273    return ""
274}
275
276proc c_variant_name {} {
277    global compilers.variants compilers.fortran_variants
278    set c_list [remove_from_list ${compilers.variants} {gfortran g95}]
279
280    foreach cc $c_list {
281        if {[variant_isset $cc]} {
282            return $cc
283        }
284    }
285
286    return ""
287}
288
289proc fortran_active_variant_name {depspec} {
290    global compilers.fortran_variants
291
292    foreach fc ${compilers.fortran_variants} {
293        if {![catch {set result [active_variants $depspec $fc ""]}]} {
294            if {$result} {
295                return $fc
296            }
297        }
298    }
299
300    return ""
301}
302
303proc fortran_variant_name {} {
304    global compilers.fortran_variants variations
305
306    foreach fc ${compilers.fortran_variants} {
307        # we need to check the default_variants so we can't use variant_isset
308        if {[info exists variations($fc)] && $variations($fc) eq "+"} {
309            return $fc
310        }
311    }
312
313    return ""
314}
315
316proc clang_variant_name {} {
317    global compilers.clang_variants compilers.dragonegg_variants variations
318
319    foreach c ${compilers.clang_variants} {
320        # we need to check the default_variants so we can't use variant_isset
321        if {[info exists variations($c)] && $variations($c) eq "+"} {
322            return $c
323        }
324    }
325
326    foreach c ${compilers.dragonegg_variants} {
327        # we need to check the default_variants so we can't use variant_isset
328        if {[info exists variations($c)] && $variations($c) eq "+"} {
329            return $c
330        }
331    }
332
333    return ""
334}
335
336proc clang_variant_isset {} {
337    return [expr {[clang_variant_name] ne ""}]
338}
339
340proc gcc_variant_name {} {
341    global compilers.gcc_variants variations
342
343    foreach c ${compilers.gcc_variants} {
344        # we need to check the default_variants so we can't use variant_isset
345        if {[info exists variations($c)] && $variations($c) eq "+"} {
346            return $c
347        }
348    }
349
350    return ""
351}
352
353proc gcc_variant_isset {} {
354    return [expr {[gcc_variant_name] ne ""}]
355}
356
357proc avx_compiler_isset {} {
358    global configure.cc
359
360    set cc ${configure.cc}
361
362    # check for mpi
363    if {[string match *mpi* $cc]} {
364        set cc [exec ${configure.cc} -show]
365    }
366
367    if {[string match *clang* $cc]} {
368        return 1
369    }
370
371    return 0
372}
373
374proc fortran_variant_isset {} {
375    return [expr {[fortran_variant_name] ne ""}]
376}
377
378# remove all elements in R from L
379proc remove_from_list {L R} {
380    foreach e $R {
381        set idx [lsearch $L $e]
382        set L [lreplace $L $idx $idx]
383    }
384    return $L
385}
386
387# add all elements in R from L
388proc add_from_list {L A} {
389    return [concat $L $A]
390}
391
392proc compilers.choose {args} {
393    global compilers.list
394
395    # zero out the variable before and append args
396    set compilers.list {}
397    foreach v $args {
398        lappend compilers.list $v
399    }
400}
401
402proc compilers.is_fortran_only {} {
403    global compilers.list
404
405    foreach c {cc cxx cpp objc} {
406        if {[lsearch -exact ${compilers.list} $c] >= 0} {
407            return 0
408        }
409    }
410
411    return 1
412}
413
414proc compilers.is_c_only {} {
415    global compilers.list
416
417    foreach c {f77 f90 fc} {
418        if {[lsearch -exact ${compilers.list} $c] >= 0} {
419            return 0
420        }
421    }
422
423    return 1
424}
425
426# for the c compiler
427proc compilers.enforce_c {args} {
428    global compilers.required_c
429    set compilers.required_c $args
430}
431
432proc compilers.action_enforce_c {args} {
433    foreach portname $args {
434        if {![catch {set result [active_variants $portname "" ""]}]} {
435            set otcomp  [c_active_variant_name $portname]
436            set mycomp  [c_variant_name]
437
438            if {$otcomp ne "" && $mycomp eq ""} {
439                default_variants +$otcomp
440            } elseif {$otcomp ne $mycomp} {
441                ui_error "Install $portname +$mycomp"
442                return -code error "$portname +$mycomp not installed"
443            }
444        }
445    }
446}
447
448proc compilers.enforce_fortran {args} {
449    global compilers.required_f
450    set compilers.required_f $args
451}
452
453proc compilers.action_enforce_f {args} {
454    global compilers.gfortran_equiv
455    foreach portname $args {
456        if {![catch {set result [active_variants $portname "" ""]}]} {
457            set otf  [fortran_active_variant_name $portname]
458            set myf  [fortran_variant_name]
459
460            # gfortran is nothing more than the fortran compiler from a default version of gcc
461            set equiv 0
462            if {($otf eq ${compilers.gfortran_equiv} || $otf eq "gfortran") &&
463                ($myf eq ${compilers.gfortran_equiv} || $myf eq "gfortran")} {
464                set equiv 1
465            }
466
467            if {$otf ne "" && $myf eq ""} {
468                default_variants +$otf
469            } elseif {$otf ne $myf && !$equiv} {
470                ui_error "Install $portname +$myf"
471                return -code error "$portname +$myf not installed"
472            }
473        }
474    }
475}
476
477proc compilers.setup {args} {
478    global cdb compilers.variants compilers.clang_variants compilers.gcc_variants
479    global compilers.dragonegg_variants compilers.fortran_variants
480    global compilers.require_fortran compilers.setup_done compilers.list
481    global compiler.blacklist
482
483    if {!${compilers.setup_done}} {
484        set add_list {}
485        set remove_list ${compilers.variants}
486
487        # if we are only setting fortran compilers, then we are in "only fortran
488        # mode", i.e. we just need +gccXY and +dragoneggXY for the fortran
489        # compilers so we remove +clangXY and +llvm
490        if {[compilers.is_fortran_only]} {
491            # remove gfortran since that only exists to "complete" clang/llvm
492            set remove_list [remove_from_list ${compilers.fortran_variants} gfortran]
493        } elseif {[compilers.is_c_only]} {
494            # remove gfortran and g95 since those are purely for fortran
495            set remove_list [remove_from_list ${compilers.variants} {gfortran g95}]
496        }
497
498        foreach v $args {
499            # if any negated compiler (e.g. -gcc47) is specified then we are
500            # removing from the default, complete list
501            set mode add
502            if {[string first - $v] == 0} {
503                set mode remove
504
505                #strip the beginning '-' character
506                set v [string range $v 1 end]
507            }
508
509            # handle special cases, such as 'gcc' -> all gcc variants
510            switch -exact $v {
511                gcc {
512                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] ${compilers.gcc_variants}]
513                }
514                dragonegg {
515                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] ${compilers.dragonegg_variants}]
516                }
517                fortran {
518                    # here we just check gfortran and g95, not every fortran
519                    # compatible variant since it makes more sense to specify
520                    # 'fortran' to mean add just the +gfortran and +g95 variants
521                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] {gfortran g95}]
522
523                }
524                clang {
525                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] ${compilers.clang_variants}]
526                }
527                require_fortran {
528                    # this signals that fortran is required and not optional
529                    set compilers.require_fortran 1
530                }
531                default {
532                    if {[info exists cdb($v,variant)] == 0} {
533                        return -code error "no such compiler: $v"
534                    }
535                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] $cdb($v,variant)]
536                }
537            }
538        }
539
540        # also remove compilers blacklisted
541        foreach compiler ${compiler.blacklist} {
542            set matched no
543            foreach variant ${compilers.variants} {
544                if {[string match $compiler $cdb($variant,compiler)]} {
545                    set matched yes
546                    set remove_list [remove_from_list $remove_list $cdb($variant,variant)]
547                }
548            }
549
550            if {!$matched} {
551                ui_debug "Unmatched blacklisted compiler: $compiler"
552            }
553        }
554
555        # remove duplicates
556        set duplicates {}
557        foreach foo $remove_list {
558            if {[lsearch $add_list $foo] != -1} {
559                lappend duplicates $foo
560            }
561        }
562
563        set compilers.variants [lsort [concat [remove_from_list $remove_list $duplicates] $add_list]]
564        eval compilers.setup_variants ${compilers.variants}
565
566        if {${compilers.require_fortran} && ![fortran_variant_isset]} {
567            if {[lsearch -exact ${compilers.variants} gfortran] > -1} {
568                default_variants-append +gfortran
569            } elseif {[lsearch -exact ${compilers.variants} gcc49] > -1} {
570                default_variants-append +gcc49
571            } elseif {[lsearch -exact ${compilers.variants} gcc48] > -1} {
572                default_variants-append +gcc48
573            } elseif {[lsearch -exact ${compilers.variants} gcc47] > -1} {
574                default_variants-append +gcc47
575            } elseif {[lsearch -exact ${compilers.variants} gcc46] > -1} {
576                default_variants-append +gcc46
577            } elseif {[lsearch -exact ${compilers.variants} gcc45] > -1} {
578                default_variants-append +gcc45
579            } elseif {[lsearch -exact ${compilers.variants} gcc44] > -1} {
580                default_variants-append +gcc44
581            } elseif {[lsearch -exact ${compilers.variants} g95] > -1} {
582                default_variants-append +g95
583            }
584        }
585
586        set compilers.setup_done 1
587    }
588}
589
590# this might also need to be in pre-archivefetch
591pre-fetch {
592    if {${compilers.require_fortran} && [fortran_variant_name] eq ""} {
593        return -code error "must set at least one fortran variant"
594    }
595    eval compilers.action_enforce_c ${compilers.required_c}
596    eval compilers.action_enforce_f ${compilers.required_f}
597}
Note: See TracBrowser for help on using the repository browser.