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

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

compilers-1.0: add enforce_fortran proc

File size: 17.8 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) 2012 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
49
50set compilers.list {cc cxx cpp objc fc f77 f90}
51
52# build database of gcc 4{4..9} compiler attributes
53set gcc_versions {4 5 6 7 8 9}
54foreach v ${gcc_versions} {
55    lappend compilers.gcc_variants gcc4$v
56    set cdb(gcc4$v,variant)  gcc4$v
57    set cdb(gcc4$v,compiler) macports-gcc-4.$v
58    set cdb(gcc4$v,descrip)  "MacPorts gcc 4.$v"
59    set cdb(gcc4$v,depends)  port:gcc4$v
60    set cdb(gcc4$v,dependsl) path:lib/libgcc/libgcc_s.1.dylib:libgcc
61    set cdb(gcc4$v,dependsd) port:g95
62    set cdb(gcc4$v,dependsa) gcc4$v
63    set cdb(gcc4$v,conflict) "gfortran g95"
64    set cdb(gcc4$v,flags)    {
65        {{"-PIC"} {"-fPIC"}}
66    }
67    set cdb(gcc4$v,cc)       ${prefix}/bin/gcc-mp-4.$v
68    set cdb(gcc4$v,cxx)      ${prefix}/bin/g++-mp-4.$v
69    set cdb(gcc4$v,cpp)      ${prefix}/bin/cpp-mp-4.$v
70    set cdb(gcc4$v,objc)     ${prefix}/bin/gcc-mp-4.$v
71    set cdb(gcc4$v,fc)       ${prefix}/bin/gfortran-mp-4.$v
72    set cdb(gcc4$v,f77)      ${prefix}/bin/gfortran-mp-4.$v
73    set cdb(gcc4$v,f90)      ${prefix}/bin/gfortran-mp-4.$v
74}
75
76set clang_versions {0 1 2 3 4 5}
77foreach v ${clang_versions} {
78    lappend compilers.clang_variants clang3$v
79    set cdb(clang3$v,variant)  clang3$v
80    set cdb(clang3$v,compiler) macports-clang-3.$v
81    set cdb(clang3$v,descrip)  "MacPorts clang 3.$v"
82    set cdb(clang3$v,depends)  port:clang-3.$v
83    set cdb(clang3$v,dependsl) ""
84    set cdb(clang3$v,dependsd) ""
85    set cdb(clang3$v,dependsa) clang-3.$v
86    set cdb(clang3$v,conflict) ""
87    set cdb(clang3$v,flags)    {
88        {{"-PIC"} {"-fPIC"}}
89    }
90    set cdb(clang3$v,cc)       ${prefix}/bin/clang-mp-3.$v
91    set cdb(clang3$v,cxx)      ${prefix}/bin/clang++-mp-3.$v
92    set cdb(clang3$v,cpp)      "${prefix}/bin/clang-mp-3.$v -E"
93    set cdb(clang3$v,objc)     ""
94    set cdb(clang3$v,fc)       ""
95    set cdb(clang3$v,f77)      ""
96    set cdb(clang3$v,f90)      ""
97}
98
99# dragonegg versions will always match the corresponding clang version
100foreach v ${clang_versions} {
101    lappend compilers.dragonegg_variants dragonegg3$v
102    set cdb(dragonegg3$v,variant)  dragonegg3$v
103    set cdb(dragonegg3$v,compiler) macports-dragonegg-3.$v
104    set cdb(dragonegg3$v,descrip)  "MacPorts dragonegg 3.$v"
105    set cdb(dragonegg3$v,depends)  path:bin/dragonegg-3.$v-gcc:dragonegg-3.$v
106    set cdb(dragonegg3$v,dependsl) path:lib/libgcc/libgcc_s.1.dylib:libgcc
107    set cdb(dragonegg3$v,dependsd) port:g95
108    set cdb(dragonegg3$v,dependsa) dragonegg-3.$v
109    set cdb(dragonegg3$v,conflict) "gfortran g95"
110    set cdb(dragonegg3$v,flags)    {
111        {{"-PIC"} {"-fPIC"}}
112    }
113    set cdb(dragonegg3$v,cc)       ${prefix}/bin/dragonegg-3.$v-gcc
114    set cdb(dragonegg3$v,cxx)      ${prefix}/bin/dragonegg-3.$v-g++
115    set cdb(dragonegg3$v,cpp)      ${prefix}/bin/dragonegg-3.$v-cpp
116    set cdb(dragonegg3$v,objc)     ""
117    set cdb(dragonegg3$v,fc)       ${prefix}/bin/dragonegg-3.$v-gfortran
118    set cdb(dragonegg3$v,f77)      ${prefix}/bin/dragonegg-3.$v-gfortran
119    set cdb(dragonegg3$v,f90)      ${prefix}/bin/dragonegg-3.$v-gfortran
120}
121
122set cdb(llvm,variant)  llvm
123set cdb(llvm,compiler) llvm-gcc-4.2
124set cdb(llvm,descrip)  "Apple native llvm-gcc 4.2"
125set cdb(llvm,depends)  bin:llvm-gcc-4.2:llvm-gcc42
126set cdb(llvm,dependsl) ""
127set cdb(llvm,dependsd) ""
128set cdb(llvm,dependsa) ""
129set cdb(llvm,conflict) ""
130set cdb(llvm,flags)    {
131    {{"-fPIC"} {"-PIC"}}
132}
133set cdb(llvm,cc)       llvm-gcc-4.2
134set cdb(llvm,cxx)      llvm-g++-4.2
135set cdb(llvm,cpp)      llvm-cpp-4.2
136set cdb(llvm,objc)     llvm-gcc-4.2
137set cdb(llvm,fc)       ""
138set cdb(llvm,f77)      ""
139set cdb(llvm,f90)      ""
140
141# and lastly we add a gfortran and g95 variant for use with clang*; note that
142# we don't need gfortran when we are in an "only-fortran" mode
143set cdb(gfortran,variant)  gfortran
144set cdb(gfortran,compiler) gfortran
145set cdb(gfortran,descrip)  "Fortran compiler from gcc48"
146set cdb(gfortran,depends)  port:gcc48
147set cdb(gfortran,dependsl) path:lib/libgcc/libgcc_s.1.dylib:libgcc
148set cdb(gfortran,dependsd) ""
149set cdb(gfortran,dependsa) ""
150set cdb(gfortran,conflict) ""
151set cdb(gfortran,flags)    {
152    {{"-fPIC"} {"-PIC"}}
153}
154set cdb(gfortran,cc)       ""
155set cdb(gfortran,cxx)      ""
156set cdb(gfortran,cpp)      ""
157set cdb(gfortran,objc)     ""
158set cdb(gfortran,fc)       ${prefix}/bin/gfortran-mp-4.8
159set cdb(gfortran,f77)      ${prefix}/bin/gfortran-mp-4.8
160set cdb(gfortran,f90)      ${prefix}/bin/gfortran-mp-4.8
161
162set cdb(g95,variant)  g95
163set cdb(g95,compiler) g95
164set cdb(g95,descrip)  "Fortran compiler from g95"
165set cdb(g95,depends)  port:g95
166set cdb(g95,dependsl) ""
167set cdb(g95,dependsd) ""
168set cdb(g95,dependsa) g95
169set cdb(g95,conflict) ""
170set cdb(g95,flags)    {
171    {{"-fPIC"} {"-PIC"}}
172}
173set cdb(g95,cc)       ""
174set cdb(g95,cxx)      ""
175set cdb(g95,cpp)      ""
176set cdb(g95,objc)     ""
177set cdb(g95,fc)       ${prefix}/bin/g95
178set cdb(g95,f77)      ${prefix}/bin/g95
179set cdb(g95,f90)      ${prefix}/bin/g95
180
181foreach name [array names cdb *,variant] {
182    lappend compilers.variants $cdb($name)
183}
184
185foreach variant ${compilers.variants} {
186    if {$cdb($variant,f77) ne ""} {
187        lappend compilers.fortran_variants $variant
188    }
189}
190
191proc compilers.setup_variants {args} {
192    global cdb compilers.variants compilers.clang_variants compilers.gcc_variants
193    global compilers.dragonegg_variants compilers.fortran_variants compilers.list
194
195    foreach variant [split $args] {
196        if {$cdb($variant,f77) ne ""} {
197            lappend compilers.fortran_variants $variant
198        }
199
200        if {[variant_exists $variant]} {
201            ui_debug "$variant variant already exists, so not adding the default one"
202        } else {
203            set i [lsearch -exact ${compilers.variants} $variant]
204            set c [lreplace ${compilers.variants} $i $i]
205
206            # fortran doesn't conflict with clang
207            if {$variant eq "gfortran" || $variant eq "g95"} {
208                foreach clangcomp ${compilers.clang_variants} {
209                    set i [lsearch -exact $c $clangcomp]
210                    set c [lreplace $c $i $i]
211                }
212            } elseif {[string match clang* $variant]} {
213                set i [lsearch -exact $c gfortran]
214                set c [lreplace $c $i $i]
215                set i [lsearch -exact $c g95]
216                set c [lreplace $c $i $i]
217            }
218
219            # for each pair of flags (old,new), build a string of if statements to
220            # replace old with new
221            set f ""
222            foreach flag $cdb($variant,flags) {
223                foreach {old new} $flag {
224                    append f [subst {
225                        if {\[string first $old \${configure.cflags}\] > -1} {
226                            configure.cflags-delete $old
227                            configure.cflags-append $new
228                        }
229                    }]
230                }
231            }
232
233            foreach flag $cdb($variant,flags) {
234                foreach {old new} $flag {
235                    append f [subst {
236                        if {\[string first $old \${configure.cxxflags}\] > -1} {
237                            configure.cxxflags-delete $old
238                            configure.cxxflags-append $new
239                        }
240                    }]
241                }
242            }
243
244            # for each compiler, set the value if not empty; we can't use
245            # configure.compiler because of dragonegg and possibly other new
246            # compilers that aren't in macports portconfigure.tcl
247            set comp ""
248            foreach compiler ${compilers.list} {
249                if {$cdb($variant,$compiler) ne ""} {
250                    append comp [subst {
251                        configure.$compiler $cdb($variant,$compiler)
252
253                        # disable archflags
254                        if {"[info command configure.${compiler}_archflags]" ne ""} {
255                            configure.${compiler}_archflags
256                            configure.ld_archflags
257                        }
258                    }]
259                }
260            }
261
262            eval [subst {
263                variant ${variant} description \
264                    {Build using the $cdb($variant,descrip) compiler} \
265                    conflicts $c $cdb($variant,conflict) {
266
267                    depends_build-append   $cdb($variant,depends)
268                    depends_lib-append     $cdb($variant,dependsl)
269                    depends_lib-delete     $cdb($variant,dependsd)
270                    depends_skip_archcheck $cdb($variant,dependsa)
271
272                    $comp
273
274                    $f
275                }
276            }]
277        }
278    }
279}
280
281foreach variant ${compilers.gcc_variants} {
282    if {[variant_isset $variant]} {
283        depends_lib-delete      port:g95
284        break
285    }
286}
287
288proc c_active_variant_name {depspec} {
289    global compilers.variants compilers.fortran_variants
290    set c_list [remove_from_list ${compilers.variants} {gfortran g95}]
291
292    foreach c $c_list {
293        if {![catch {set result [active_variants $depspec $c ""]}]} {
294            if {$result} {
295                return $c
296            }
297        }
298    }
299
300    return ""
301}
302
303proc c_variant_name {} {
304    global compilers.variants compilers.fortran_variants
305    set c_list [remove_from_list ${compilers.variants} {gfortran g95}]
306
307    foreach cc $c_list {
308        if {[variant_isset $cc]} {
309            return $cc
310        }
311    }
312
313    return ""
314}
315
316proc fortran_active_variant_name {depspec} {
317    global compilers.fortran_variants
318
319    foreach fc ${compilers.fortran_variants} {
320        if {![catch {set result [active_variants $depspec $fc ""]}]} {
321            if {$result} {
322                return $fc
323            }
324        }
325    }
326
327    return ""
328}
329
330proc fortran_variant_name {} {
331    global compilers.fortran_variants
332
333    foreach fc ${compilers.fortran_variants} {
334        if {[variant_isset $fc]} {
335            return $fc
336        }
337    }
338
339    return ""
340}
341
342proc clang_variant_name {} {
343    global compilers.clang_variants compilers.dragonegg_variants
344
345    foreach c ${compilers.clang_variants} {
346        if {[variant_isset $c]} {
347            return $c
348        }
349    }
350
351    foreach c ${compilers.dragonegg_variants} {
352        if {[variant_isset $c]} {
353            return $c
354        }
355    }
356
357    return ""
358}
359
360proc clang_variant_isset {} {
361    return [expr {[clang_variant_name] ne ""}]
362}
363
364proc avx_compiler_isset {} {
365    global configure.cc
366
367    if {[string match *clang* ${configure.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    foreach portname $args {
429        if {![catch {set result [active_variants $portname "" ""]}]} {
430            set otcomp  [c_active_variant_name $portname]
431            set mycomp  [c_variant_name]
432
433            if {$otcomp ne "" && $mycomp eq ""} {
434                default_variants +$otcomp
435            } elseif {$otcomp ne $mycomp} {
436                ui_error "Install $portname +$mycomp"
437                return -code error "$portname +$mycomp not installed"
438            }
439        }
440    }
441}
442
443proc compilers.enforce_fortran {args} {
444    foreach portname $args {
445        if {![catch {set result [active_variants $portname "" ""]}]} {
446            set otf  [fortran_active_variant_name $portname]
447            set myf  [fortran_variant_name]
448
449            # gfortran is nothing more than the fortran compiler from gcc48
450            set equiv 0
451            if {($otf eq "gcc48" || $otf eq "gfortran") && ($myf eq "gcc48" || $myf eq "gfortran")} {
452                set equiv 1
453            }
454
455            if {$otf ne "" && $myf eq ""} {
456                default_variants +$otf
457            } elseif {$otf ne $myf && !$equiv} {
458                ui_error "Install $portname +$myf"
459                return -code error "$portname +$myf not installed"
460            }
461        }
462    }
463}
464
465proc compilers.setup {args} {
466    global cdb compilers.variants compilers.clang_variants compilers.gcc_variants
467    global compilers.dragonegg_variants compilers.fortran_variants
468    global compilers.require_fortran compilers.setup_done compilers.list
469
470    if {!${compilers.setup_done}} {
471        set add_list {}
472        set remove_list ${compilers.variants}
473
474        # if we are only setting fortran compilers, then we are in "only fortran
475        # mode", i.e. we just need +gccXY and +dragoneggXY for the fortran
476        # compilers so we remove +clangXY and +llvm
477        if {[compilers.is_fortran_only]} {
478            # remove gfortran since that only exists to "complete" clang/llvm
479            set remove_list [remove_from_list ${compilers.fortran_variants} gfortran]
480        } elseif {[compilers.is_c_only]} {
481            # remove gfortran and g95 since those are purely for fortran
482            set remove_list [remove_from_list ${compilers.variants} {gfortran g95}]
483        }
484
485        foreach v $args {
486            # if any negated compiler (e.g. -gcc47) is specified then we are
487            # removing from the default, complete list
488            set mode add
489            if {[string first - $v] == 0} {
490                set mode remove
491
492                #strip the beginning '-' character
493                set v [string range $v 1 end]
494            }
495
496            # handle special cases, such as 'gcc' -> all gcc variants
497            switch -exact $v {
498                gcc {
499                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] ${compilers.gcc_variants}]
500                }
501                dragonegg {
502                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] ${compilers.dragonegg_variants}]
503                }
504                fortran {
505                    # here we just check gfortran and g95, not every fortran
506                    # compatible variant since it makes more sense to specify
507                    # 'fortran' to mean add just the +gfortran and +g95 variants
508                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] {gfortran g95}]
509
510                }
511                clang {
512                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] ${compilers.clang_variants}]
513                }
514                require_fortran {
515                    # this signals that fortran is required and not optional
516                    set compilers.require_fortran 1
517                }
518                default {
519                    if {[info exists cdb($v,variant)] == 0} {
520                        return -code error "no such compiler: $v"
521                    }
522                    set ${mode}_list [${mode}_from_list [expr $${mode}_list] $cdb($v,variant)]
523                }
524            }
525        }
526
527        # remove duplicates
528        set duplicates {}
529        foreach foo $remove_list {
530            if {[lsearch $add_list $foo] != -1} {
531                lappend duplicates $foo
532            }
533        }
534
535        set compilers.variants [lsort [concat [remove_from_list $remove_list $duplicates] $add_list]]
536        eval compilers.setup_variants ${compilers.variants}
537
538        set compilers.setup_done 1
539    }
540}
541
542pre-fetch {
543    if {${compilers.require_fortran} && [fortran_variant_name] eq ""} {
544        return -code error "must set at least one fortran variant"
545    }
546}
Note: See TracBrowser for help on using the repository browser.