Ticket #55922: portconfigure.tcl

File portconfigure.tcl, 31.9 KB (added by ballapete (Peter "Pete" Dyballa), 7 years ago)

Local /opt/local/libexec/macports/lib/port1.0/portconfigure.tcl

Line 
1# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
2#
3# Copyright (c) 2007 - 2015 The MacPorts Project
4# Copyright (c) 2007 Markus W. Weissmann <mww@macports.org>
5# Copyright (c) 2002 - 2003 Apple Inc.
6# All rights reserved.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions
10# are met:
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 Apple Inc. nor the names of its contributors
17#    may be used to endorse or promote products derived from this software
18#    without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30# POSSIBILITY OF SUCH DAMAGE.
31#
32
33package provide portconfigure 1.0
34package require portutil 1.0
35
36set org.macports.configure [target_new org.macports.configure portconfigure::configure_main]
37target_provides ${org.macports.configure} configure
38target_requires ${org.macports.configure} main fetch checksum extract patch
39target_prerun ${org.macports.configure} portconfigure::configure_start
40
41namespace eval portconfigure {
42}
43
44
45# ********** BEGIN C++ / OBJECTIVE-C++ **********
46
47options configure.cxx \
48        configure.cxx_archflags \
49        configure.cxx_stdlib \
50        configure.cxxflags \
51        configure.objcxx \
52        configure.objcxx_archflags \
53        configure.objcxxflags \
54        configure.universal_cxxflags \
55        configure.universal_objcxxflags
56
57default configure.cxx                   {[portconfigure::configure_get_compiler cxx]}
58default configure.cxx_archflags         {[portconfigure::configure_get_archflags cxx]}
59default configure.cxx_stdlib            {$cxx_stdlib}
60default configure.cxxflags \
61        {[portconfigure::construct_cxxflags ${configure.optflags}]}
62default configure.objcxx                {[portconfigure::configure_get_compiler objcxx]}
63default configure.objcxx_archflags      {[portconfigure::configure_get_archflags objcxx]}
64# No current reason for OBJCXXFLAGS to differ from CXXFLAGS.
65default configure.objcxxflags           {${configure.cxxflags}}
66default configure.universal_cxxflags    {[portconfigure::configure_get_universal_cflags]}
67default configure.universal_objcxxflags {${configure.universal_cxxflags}}
68
69# Don't let Portfiles trash "-stdlib"; if they want to remove it, they
70# should clear configure.cxx_stdlib.
71option_proc configure.cxxflags portconfigure::stdlib_trace
72option_proc configure.objcxxflags portconfigure::stdlib_trace
73
74proc portconfigure::should_add_stdlib {} {
75    set has_stdlib [expr {[option configure.cxx_stdlib] ne ""}]
76    set is_clang [string match *clang* [option configure.cxx]]
77    return [expr {$has_stdlib && $is_clang}]
78}
79proc portconfigure::construct_cxxflags {flags} {
80    if {[portconfigure::should_add_stdlib]} {
81        lappend flags -stdlib=[option configure.cxx_stdlib]
82    }
83    return $flags
84}
85proc portconfigure::stdlib_trace {opt action args} {
86    foreach flag [lsearch -all -inline [option $opt] -stdlib=*] {
87        $opt-delete $flag
88    }
89    if {$action eq "read" && [portconfigure::should_add_stdlib]} {
90        $opt-append -stdlib=[option configure.cxx_stdlib]
91    }
92    return
93}
94
95# ********** END C++ / OBJECTIVE-C++ **********
96
97
98# define options
99commands configure autoreconf automake autoconf xmkmf
100# defaults
101default configure.env       ""
102default configure.pre_args  {--prefix=${prefix}}
103default configure.cmd       ./configure
104default configure.nice      {${buildnicevalue}}
105default configure.dir       {${worksrcpath}}
106default autoreconf.dir      {${worksrcpath}}
107default autoreconf.args     {{--install --verbose}}
108default autoconf.dir        {${worksrcpath}}
109default autoconf.args       {--verbose}
110default automake.dir        {${worksrcpath}}
111default automake.args       {--verbose}
112default xmkmf.cmd           xmkmf
113default xmkmf.dir           {${worksrcpath}}
114default use_configure       yes
115
116option_proc use_autoreconf  portconfigure::set_configure_type
117option_proc use_automake    portconfigure::set_configure_type
118option_proc use_autoconf    portconfigure::set_configure_type
119option_proc use_xmkmf       portconfigure::set_configure_type
120
121option_proc autoreconf.cmd  portconfigure::set_configure_type
122option_proc automake.cmd    portconfigure::set_configure_type
123option_proc autoconf.cmd    portconfigure::set_configure_type
124option_proc xmkmf.cmd       portconfigure::set_configure_type
125
126##
127# Local helper proc
128proc portconfigure::add_build_dep { type dep } {
129    global ${type}.cmd option_defaults
130
131    if {![info exists ${type}.cmd] || (
132        ([info exists option_defaults(${type}.cmd)] && [set ${type}.cmd] eq $option_defaults(${type}.cmd)) ||
133        (![info exists option_defaults(${type}.cmd)] && [set ${type}.cmd] eq ${type})
134        )} {
135            # Add dependencies if they are not already in the list
136            depends_build-delete {*}$dep
137            depends_build-append {*}$dep
138    }
139}
140
141##
142# Adds dependencies for the binaries which will be called, but only if it is
143# the default. If .cmd was overwritten the port has to care for deps itself.
144proc portconfigure::set_configure_type {option action args} {
145    global autoreconf.cmd automake.cmd autoconf.cmd xmkmf.cmd
146
147    array set configure_map {
148        autoconf    {port:autoconf port:automake port:libtool}
149        xmkmf       port:imake
150    }
151
152    if {$action eq "set"} {
153        switch $option {
154            autoreconf.cmd  -
155            automake.cmd    -
156            autoconf.cmd {
157                depends_build-delete {*}$configure_map(autoconf)
158            }
159            xmkmf.cmd {
160                depends_build-delete {*}$configure_map(xmkmf)
161            }
162            use_xmkmf {
163                if {[tbool args]} {
164                    depends_build-append {*}$configure_map(xmkmf)
165                }
166            }
167            default {
168                # strip "use_"
169                set type [string range $option 4 end]
170                if {[tbool args]} {
171                    add_build_dep $type $configure_map(autoconf)
172                }
173            }
174        }
175    }
176}
177
178options configure.asroot
179default configure.asroot no
180
181# Configure special environment variables.
182# We could have m32/m64/march/mtune be global configurable at some point.
183options configure.m32 configure.m64 configure.march configure.mtune
184default configure.march     {}
185default configure.mtune     {}
186# We could have debug/optimizations be global configurable at some point.
187options configure.optflags \
188        configure.cflags \
189        configure.objcflags \
190        configure.cppflags configure.ldflags configure.libs \
191        configure.fflags configure.f90flags configure.fcflags \
192        configure.classpath
193# compiler flags section
194default configure.optflags      {-Os}
195default configure.cflags        {${configure.optflags}}
196default configure.objcflags     {${configure.optflags}}
197default configure.cppflags      {-I${prefix}/include}
198default configure.ldflags       {"-L${prefix}/lib -Wl,-headerpad_max_install_names"}
199default configure.libs          {}
200default configure.fflags        {${configure.optflags}}
201default configure.f90flags      {${configure.optflags}}
202default configure.fcflags       {${configure.optflags}}
203default configure.classpath     {}
204
205# tools section
206options configure.perl configure.python configure.ruby \
207        configure.install configure.awk configure.bison \
208        configure.pkg_config configure.pkg_config_path
209default configure.perl              {}
210default configure.python            {}
211default configure.ruby              {}
212default configure.install           {${portutil::autoconf::install_command}}
213default configure.awk               {}
214default configure.bison             {}
215default configure.pkg_config        {}
216default configure.pkg_config_path   {}
217
218options configure.build_arch configure.ld_archflags \
219        configure.sdk_version configure.sdkroot
220default configure.build_arch    {[portconfigure::choose_supported_archs ${build_arch}]}
221default configure.ld_archflags  {[portconfigure::configure_get_ld_archflags]}
222default configure.sdk_version   {$macosx_sdk_version}
223default configure.sdkroot       {[portconfigure::configure_get_sdkroot ${configure.sdk_version}]}
224foreach tool {cc objc f77 f90 fc} {
225    options configure.${tool}_archflags
226    default configure.${tool}_archflags  "\[portconfigure::configure_get_archflags $tool\]"
227}
228
229options configure.universal_archs configure.universal_args \
230        configure.universal_cflags \
231        configure.universal_objcflags \
232        configure.universal_cppflags configure.universal_ldflags
233default configure.universal_archs       {[portconfigure::choose_supported_archs ${universal_archs}]}
234default configure.universal_args        {--disable-dependency-tracking}
235default configure.universal_cflags      {[portconfigure::configure_get_universal_cflags]}
236default configure.universal_objcflags   {${configure.universal_cflags}}
237default configure.universal_cppflags    {}
238default configure.universal_ldflags     {[portconfigure::configure_get_universal_ldflags]}
239
240# Select a distinct compiler (C, C preprocessor, C++)
241options configure.ccache configure.distcc configure.pipe configure.cc \
242        configure.cpp configure.objc configure.f77 \
243        configure.f90 configure.fc configure.javac configure.compiler \
244        compiler.blacklist compiler.whitelist compiler.fallback
245default configure.ccache        {${configureccache}}
246default configure.distcc        {${configuredistcc}}
247default configure.pipe          {${configurepipe}}
248foreach tool {cc objc cpp f77 f90 fc javac} {
249    default configure.$tool     "\[portconfigure::configure_get_compiler $tool\]"
250}
251default configure.compiler      {[portconfigure::configure_get_default_compiler]}
252default compiler.fallback       {[portconfigure::get_compiler_fallback]}
253default compiler.blacklist      {}
254default compiler.whitelist      {}
255
256set_ui_prefix
257
258proc portconfigure::configure_start {args} {
259    global UI_PREFIX
260
261    ui_notice "$UI_PREFIX [format [msgcat::mc "Configuring %s"] [option subport]]"
262
263    set compiler [option configure.compiler]
264    set valid_compilers {
265        {^apple-gcc-(4\.[02])$}             {MacPorts Apple GCC %s}
266        {^cc$}                              {System cc}
267        {^clang$}                           {Xcode Clang}
268        {^gcc$}                             {System GCC}
269        {^gcc-(3\.3|4\.[02])$}              {Xcode GCC %s}
270        {^llvm-gcc-4\.2$}                   {Xcode LLVM-GCC 4.2}
271        {^macports-clang$}                  {MacPorts Clang (port select)}
272        {^macports-clang-(\d+\.\d+)$}       {MacPorts Clang %s}
273        {^macports-dragonegg-(\d+\.\d+)$}   {MacPorts DragonEgg %s}
274        {^macports-dragonegg-(\d+\.\d+)-gcc-(\d+\.\d+)$}
275            {MacPorts DragonEgg %s with GCC %s}
276        {^macports-gcc$}                    {MacPorts GCC (port select)}
277        {^macports-gcc-(\d+(?:\.\d+)?)$}    {MacPorts GCC %s}
278        {^macports-llvm-gcc-4\.2$}          {MacPorts LLVM-GCC 4.2}
279    }
280    foreach {re fmt} $valid_compilers {
281        if {[set matches [regexp -inline $re $compiler]] ne ""} {
282            set compiler_name [format $fmt {*}[lrange $matches 1 end]]
283            break
284        }
285    }
286    if {![info exists compiler_name]} {
287        return -code error "Invalid value for configure.compiler: $compiler"
288    }
289    ui_debug "Preferred compilers: [option compiler.fallback]"
290    ui_debug "Using compiler '$compiler_name'"
291
292    # Additional ccache directory setup
293    global configure.ccache ccache_dir ccache_size macportsuser
294    if {${configure.ccache}} {
295        # Create ccache directory with correct permissions with root privileges
296        elevateToRoot "configure ccache"
297        if {[catch {
298                file mkdir ${ccache_dir}
299                file attributes ${ccache_dir} -owner ${macportsuser} -permissions 0755
300            } result]} {
301            ui_warn "ccache_dir ${ccache_dir} could not be created; disabling ccache: $result"
302            set configure.ccache no
303        }
304        dropPrivileges
305
306        # Initialize ccache directory with the given maximum size
307        if {${configure.ccache}} {
308            if {[catch {
309                exec ccache -M ${ccache_size} >/dev/null
310            } result]} {
311                ui_warn "ccache_dir ${ccache_dir} could not be initialized; disabling ccache: $result"
312                set configure.ccache no
313            }
314        }
315    }
316}
317
318# internal function to choose the default configure.build_arch and
319# configure.universal_archs based on supported_archs and build_arch or
320# universal_archs
321proc portconfigure::choose_supported_archs {archs} {
322    global supported_archs
323    if {$supported_archs eq ""} {
324        return $archs
325    }
326    set ret {}
327    foreach arch $archs {
328        if {$arch in $supported_archs} {
329            set add_arch $arch
330        } elseif {$arch eq "x86_64" && "i386" in $supported_archs} {
331            set add_arch "i386"
332        } elseif {$arch eq "ppc64" && "ppc" in $supported_archs} {
333            set add_arch "ppc"
334        } else {
335            continue
336        }
337        if {$add_arch ni $ret} {
338            lappend ret $add_arch
339        }
340    }
341    return $ret
342}
343
344# internal function to determine the compiler flags to select an arch
345proc portconfigure::configure_get_archflags {tool} {
346    global configure.build_arch configure.m32 configure.m64 configure.compiler
347    set flags ""
348    if {[tbool configure.m64]} {
349        set flags "-m64"
350    } elseif {[tbool configure.m32]} {
351        set flags "-m32"
352    } elseif {${configure.build_arch} ne ""} {
353        if {[arch_flag_supported ${configure.compiler}] &&
354            [regexp {^(?:cc|cxx|objc|objcxx)$} $tool]
355        } then {
356            set flags "-arch ${configure.build_arch}"
357        } elseif {${configure.build_arch} eq "x86_64" || ${configure.build_arch} eq "ppc64"} {
358            set flags "-m64"
359        } elseif {${configure.compiler} ne "gcc-3.3"} {
360            set flags "-m32"
361        }
362    }
363    return $flags
364}
365
366# internal function to determine the ld flags to select an arch
367# Unfortunately there's no consistent way to do this when the compiler
368# doesn't support -arch, because it could be used to link rather than using
369# ld directly. So we punt and let portfiles deal with that case.
370proc portconfigure::configure_get_ld_archflags {} {
371    global configure.build_arch configure.compiler
372    if {${configure.build_arch} ne "" && [arch_flag_supported ${configure.compiler}]} {
373        return "-arch ${configure.build_arch}"
374    } else {
375        return ""
376    }
377}
378
379proc portconfigure::configure_get_sdkroot {sdk_version} {
380    global developer_dir macosx_version xcodeversion os.arch os.platform
381    if {${os.platform} eq "darwin" && ($sdk_version ne $macosx_version
382        || (${os.arch} eq "powerpc" && $macosx_version eq "10.4" && [variant_exists universal] && [variant_isset universal]))} {
383        if {[vercmp $xcodeversion 4.3] < 0} {
384            set sdks_dir ${developer_dir}/SDKs
385        } else {
386            set sdks_dir ${developer_dir}/Platforms/MacOSX.platform/Developer/SDKs
387        }
388        if {$sdk_version eq "10.4"} {
389            set sdk ${sdks_dir}/MacOSX10.4u.sdk
390        } else {
391            set sdk ${sdks_dir}/MacOSX${sdk_version}.sdk
392        }
393        if {[file exists $sdk]} {
394            return $sdk
395        }
396    }
397    return {}
398}
399
400# internal function to determine the "-arch xy" flags for the compiler
401proc portconfigure::configure_get_universal_archflags {} {
402    global configure.universal_archs
403    set flags ""
404    foreach arch ${configure.universal_archs} {
405        if {$flags eq ""} {
406            set flags "-arch $arch"
407        } else {
408            append flags " -arch $arch"
409        }
410    }
411    return $flags
412}
413
414# internal function to determine the CFLAGS for the compiler
415proc portconfigure::configure_get_universal_cflags {} {
416    return [configure_get_universal_archflags]
417}
418
419# internal function to determine the LDFLAGS for the compiler
420proc portconfigure::configure_get_universal_ldflags {} {
421    return [configure_get_universal_archflags]
422}
423
424# internal proc to determine if the compiler supports -arch
425proc portconfigure::arch_flag_supported {compiler} {
426    return [regexp {^gcc-4|llvm|apple|clang} $compiler]
427}
428
429proc portconfigure::compiler_port_name {compiler} {
430    set valid_compiler_ports {
431        {^apple-gcc-(\d+)\.(\d+)$}                          {apple-gcc%s%s}
432        {^macports-clang-(\d+\.\d+)$}                       {clang-%s}
433        {^macports-dragonegg-(\d+\.\d+)(-gcc-\d+\.\d+)?$}   {dragonegg-%s%s}
434        {^macports-(llvm-)?gcc-(\d+)(?:\.(\d+))?$}          {%sgcc%s%s}
435    }
436    foreach {re fmt} $valid_compiler_ports {
437        if {[set matches [regexp -inline $re $compiler]] ne ""} {
438            return [format $fmt {*}[lrange $matches 1 end]]
439        }
440    }
441    return {}
442}
443
444proc portconfigure::compiler_is_port {compiler} {
445    return [expr {[portconfigure::compiler_port_name ${compiler}] ne ""}]
446}
447
448# internal function to determine the default compiler
449proc portconfigure::configure_get_default_compiler {} {
450    if {[option compiler.whitelist] ne ""} {
451        set search_list [option compiler.whitelist]
452    } else {
453        set search_list [option compiler.fallback]
454    }
455    foreach compiler $search_list {
456        set allowed yes
457        foreach pattern [option compiler.blacklist] {
458            if {[string match $pattern $compiler]} {
459                set allowed no
460                break
461            }
462        }
463        if {$allowed &&
464            ([file executable [configure_get_compiler cc $compiler]] ||
465             [compiler_is_port $compiler])
466        } then {
467            return $compiler
468        }
469    }
470    ui_warn "All compilers are either blacklisted or unavailable; defaulting to first fallback option"
471    return [lindex [option compiler.fallback] 0]
472}
473
474# internal function to choose compiler fallback list based on platform
475proc portconfigure::get_compiler_fallback {} {
476    global xcodeversion macosx_deployment_target default_compilers configure.sdkroot configure.cxx_stdlib os.major
477
478    # Check our override
479    if {[info exists default_compilers]} {
480        return $default_compilers
481    }
482
483    # Check for platforms without Xcode
484    if {$xcodeversion eq "none" || $xcodeversion eq ""} {
485        return {cc}
486    }
487
488    # Legacy cases
489    if {[vercmp $xcodeversion 4.0] < 0} {
490        if {[vercmp $xcodeversion 3.2] >= 0} {
491            if {[string match *10.4u* ${configure.sdkroot}]} {
492                return {gcc-4.0}
493            }
494        } elseif {[vercmp $xcodeversion 3.0] >= 0} {
495            return {gcc-4.2 apple-gcc-4.2 gcc-4.0 macports-clang-3.4 macports-clang-3.3}
496        } else {
497            return {apple-gcc-4.2 gcc-4.0 gcc-3.3 macports-clang-3.3}
498        }
499    }
500
501    set compilers {}
502
503    # Set our preferred Xcode-provided compilers
504    if {[vercmp $xcodeversion 5.0] >= 0} {
505        lappend compilers clang
506    } elseif {[vercmp $xcodeversion 4.3] >= 0} {
507        lappend compilers clang llvm-gcc-4.2
508    } elseif {[vercmp $xcodeversion 4.0] >= 0} {
509        lappend compilers llvm-gcc-4.2 clang
510    } else {
511        lappend compilers gcc-4.2 clang llvm-gcc-4.2
512    }
513
514    # Determine which versions of clang we prefer
515    if {${configure.cxx_stdlib} eq "libc++"} {
516        # clang-3.5+ require libc++
517        lappend compilers macports-clang-4.0
518
519        if {${os.major} < 17} {
520            # The High Sierra SDK requires a toolchain that can apply nullability to uuid_t
521            lappend compilers macports-clang-3.9
522        }
523
524        if {${os.major} < 16} {
525            # The Sierra SDK requires a toolchain that supports class properties
526            lappend compilers macports-clang-3.8 macports-clang-3.7
527        }
528    }
529
530    if {${os.major} < 16} {
531        # We dropped support for these compilers on Sierra
532        lappend compilers macports-clang-3.4 macports-llvm-gcc-4.2 apple-gcc-4.2
533    }
534
535    return $compilers
536}
537
538# Find a developer tool
539proc portconfigure::find_developer_tool {name} {
540        global developer_dir
541
542    # first try /usr/bin since this doesn't move around
543    set toolpath "/usr/bin/${name}"
544    if {[file executable $toolpath]} {
545        return $toolpath
546    }
547
548        # Use xcode's xcrun to find the named tool.
549        if {![catch {exec [findBinary xcrun $portutil::autoconf::xcrun_path] -find ${name}} toolpath]} {
550                return ${toolpath}
551        }
552
553        # If xcrun failed to find the tool, return a path from
554        # the developer_dir.
555        # The tool may not be there, but we'll leave it up to
556        # the invoking code to figure out that it doesn't have
557        # a valid compiler
558        return "${developer_dir}/usr/bin/${name}"
559}
560
561
562# internal function to find correct compilers
563proc portconfigure::configure_get_compiler {type {compiler {}}} {
564    global configure.compiler prefix
565    if {$compiler eq ""} {
566        set compiler ${configure.compiler}
567    }
568    # Tcl 8.4's switch doesn't support -matchvar.
569    if {[regexp {^apple-gcc(-4\.[02])$} $compiler -> suffix]} {
570        switch $type {
571            cc      -
572            objc    { return ${prefix}/bin/gcc-apple${suffix} }
573            cxx     -
574            objcxx  {
575                if {$suffix eq "-4.2"} {
576                    return ${prefix}/bin/g++-apple${suffix}
577                }
578            }
579            cpp     { return ${prefix}/bin/cpp-apple${suffix} }
580        }
581    } elseif {[regexp {^clang$} $compiler]} {
582        switch $type {
583            cc      -
584            objc    { return [find_developer_tool clang] }
585            cxx     -
586            objcxx  {
587                set clangpp [find_developer_tool clang++]
588                if {[file executable $clangpp]} {
589                    return $clangpp
590                }
591                return [find_developer_tool llvm-g++-4.2]
592            }
593        }
594    } elseif {[regexp {^gcc(-3\.3|-4\.[02])?$} $compiler -> suffix]} {
595        switch $type {
596            cc      -
597            objc    { return [find_developer_tool "gcc${suffix}"] }
598            cxx     -
599            objcxx  { return [find_developer_tool "g++${suffix}"] }
600            cpp     { return [find_developer_tool "cpp${suffix}"] }
601        }
602    } elseif {[regexp {^llvm-gcc-4\.2$} $compiler]} {
603        switch $type {
604            cc      -
605            objc    { return [find_developer_tool llvm-gcc-4.2] }
606            cxx     -
607            objcxx  { return [find_developer_tool llvm-g++-4.2] }
608            cpp     { return [find_developer_tool llvm-cpp-4.2] }
609        }
610    } elseif {[regexp {^macports-clang(-\d+\.\d+)?$} $compiler -> suffix]} {
611        if {$suffix ne ""} {
612            set suffix "-mp${suffix}"
613        }
614        switch $type {
615            cc      -
616            objc    { return ${prefix}/bin/clang${suffix} }
617            cxx     -
618            objcxx  { return ${prefix}/bin/clang++${suffix} }
619        }
620    } elseif {[regexp {^macports-dragonegg(-\d+\.\d+)(?:-gcc(-\d+\.\d+))?$} $compiler \
621                -> infix suffix]} {
622        if {$suffix ne ""} {
623            set suffix "-mp${suffix}"
624        }
625        switch $type {
626            cc      -
627            objc    { return ${prefix}/bin/dragonegg${infix}-gcc${suffix} }
628            cxx     -
629            objcxx  { return ${prefix}/bin/dragonegg${infix}-g++${suffix} }
630            cpp     { return ${prefix}/bin/dragonegg${infix}-cpp${suffix} }
631            fc      -
632            f77     -
633            f90     { return ${prefix}/bin/dragonegg${infix}-gfortran${suffix} }
634        }
635    } elseif {[regexp {^macports-gcc(-\d+(?:\.\d+)?)?$} $compiler -> suffix]} {
636        if {$suffix ne ""} {
637            set suffix "-mp${suffix}"
638        }
639        switch $type {
640            cc      -
641            objc    { return ${prefix}/bin/gcc${suffix} }
642            cxx     -
643            objcxx  { return ${prefix}/bin/g++${suffix} }
644            cpp     { return ${prefix}/bin/cpp${suffix} }
645            fc      -
646            f77     -
647            f90     { return ${prefix}/bin/gfortran${suffix} }
648        }
649    } elseif {[regexp {^macports-llvm-gcc-4\.2$} $compiler]} {
650        switch $type {
651            cc      -
652            objc    { return ${prefix}/bin/llvm-gcc-4.2 }
653            cxx     -
654            objcxx  { return ${prefix}/bin/llvm-g++-4.2 }
655            cpp     { return ${prefix}/bin/llvm-cpp-4.2 }
656        }
657    }
658    # Fallbacks
659    switch $type {
660        cc      -
661        objc    { return [find_developer_tool cc] }
662        cxx     -
663        objcxx  { return [find_developer_tool c++] }
664        cpp     { return [find_developer_tool cpp] }
665    }
666    return ""
667}
668
669# Automatically called from macports1.0 after evaluating the Portfile
670# Some of the compilers we use are provided by MacPorts itself; ensure we
671# automatically add a dependency when needed
672proc portconfigure::add_automatic_compiler_dependencies {} {
673    global configure.compiler configure.compiler.add_deps
674
675    if {!${configure.compiler.add_deps}} {
676        return
677    }
678
679    # The default value requires substitution before use.
680    set compiler [subst ${configure.compiler}]
681    if {![compiler_is_port $compiler]} {
682        return
683    }
684
685    ui_debug "Chosen compiler ${compiler} is provided by a port, adding dependency"
686
687    set compiler_port [portconfigure::compiler_port_name ${compiler}]
688    set deptype "build"
689    if {[string first "macports-gcc-" $compiler] == 0} {
690        set deptype "lib"
691    }
692    ui_debug "Adding depends_${deptype} port:$compiler_port"
693    depends_${deptype}-delete port:$compiler_port
694    depends_${deptype}-append port:$compiler_port
695
696    if {[arch_flag_supported $compiler]} {
697        ui_debug "Adding depends_skip_archcheck $compiler_port"
698        depends_skip_archcheck-delete $compiler_port
699        depends_skip_archcheck-append $compiler_port
700    }
701}
702# Register the above procedure as a callback after Portfile evaluation
703port::register_callback portconfigure::add_automatic_compiler_dependencies
704# and an option to turn it off if required
705options configure.compiler.add_deps
706default configure.compiler.add_deps yes
707
708proc portconfigure::configure_main {args} {
709    global [info globals]
710    global worksrcpath use_configure use_autoreconf use_autoconf use_automake use_xmkmf \
711           configure.env configure.pipe configure.libs configure.classpath configure.universal_args \
712           configure.perl configure.python configure.ruby configure.install configure.awk configure.bison \
713           configure.pkg_config configure.pkg_config_path \
714           configure.ccache configure.distcc configure.cpp configure.javac configure.sdkroot \
715           configure.march configure.mtune configure.cxx_stdlib \
716           os.platform os.major
717    foreach tool {cc cxx objc objcxx f77 f90 fc ld} {
718        global configure.${tool} configure.${tool}_archflags
719    }
720    foreach flags {cflags cppflags cxxflags objcflags objcxxflags ldflags fflags f90flags fcflags} {
721        global configure.${flags} configure.universal_${flags}
722    }
723   
724    if {[tbool use_autoreconf]} {
725        if {[catch {command_exec autoreconf} result]} {
726            return -code error "[format [msgcat::mc "%s failure: %s"] autoreconf $result]"
727        }
728    }
729   
730    if {[tbool use_automake]} {
731        if {[catch {command_exec automake} result]} {
732            return -code error "[format [msgcat::mc "%s failure: %s"] automake $result]"
733        }
734    }
735   
736    if {[tbool use_autoconf]} {
737        if {[catch {command_exec autoconf} result]} {
738            return -code error "[format [msgcat::mc "%s failure: %s"] autoconf $result]"
739        }
740    }
741
742    if {[tbool use_xmkmf]} {
743        parse_environment xmkmf
744        if {[catch {command_exec xmkmf} result]} {
745            return -code error "[format [msgcat::mc "%s failure: %s"] xmkmf $result]"
746        }
747
748        parse_environment xmkmf
749        if {[catch {command_exec "cd ${worksrcpath} && make Makefiles" -varprefix xmkmf} result]} {
750            return -code error "[format [msgcat::mc "%s failure: %s"] "make Makefiles" $result]"
751        }
752    } elseif {[tbool use_configure]} {
753        # Merge (ld|c|cpp|cxx)flags into the environment variable.
754        parse_environment configure
755
756        # Set pre-compiler filter to use (ccache/distcc), if any.
757        if {[tbool configure.ccache] && [tbool configure.distcc]} {
758            set filter ccache
759            append_to_environment_value configure "CCACHE_PREFIX" "distcc"
760        } elseif {[tbool configure.ccache]} {
761            set filter ccache
762        } elseif {[tbool configure.distcc]} {
763            set filter distcc
764        } else {
765            set filter ""
766        }
767        foreach env_var {CC CXX OBJC OBJCXX} {
768            append_to_environment_value configure $env_var $filter
769        }
770
771        # Set flags controlling the kind of compiler output.
772        if {[tbool configure.pipe]} {
773            set output -pipe
774        } else {
775            set output ""
776        }
777        foreach env_var {CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FFLAGS F90FLAGS FCFLAGS} {
778            append_to_environment_value configure $env_var $output
779        }
780
781        # Append configure flags.
782        foreach env_var { \
783            CC CXX OBJC OBJCXX FC F77 F90 JAVAC \
784            CFLAGS CPPFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS \
785            FFLAGS F90FLAGS FCFLAGS LDFLAGS LIBS CLASSPATH \
786            PERL PYTHON RUBY INSTALL AWK BISON PKG_CONFIG PKG_CONFIG_PATH \
787        } {
788            set value [option configure.[string tolower $env_var]]
789            append_to_environment_value configure $env_var {*}$value
790        }
791
792        # https://trac.macports.org/ticket/34221
793        if {${os.platform} eq "darwin" && ${os.major} == 12} {
794            append_to_environment_value configure "__CFPREFERENCES_AVOID_DAEMON" 1
795        }
796
797        # add SDK flags if cross-compiling (or universal on ppc tiger)
798        if {${configure.sdkroot} ne ""} {
799            foreach env_var {CPPFLAGS CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS} {
800                append_to_environment_value configure $env_var -isysroot${configure.sdkroot}
801            }
802            append_to_environment_value configure "LDFLAGS" -Wl,-syslibroot,${configure.sdkroot}
803        }
804
805        # add extra flags that are conditional on whether we're building universal
806        append_to_environment_value configure CFLAGS {*}[get_canonical_archflags cc]
807        foreach tool {cxx objc objcxx cpp f77 f90 fc ld} {
808            if {[catch {get_canonical_archflags $tool} flags]} {
809                continue
810            }
811            set env_var [string toupper $tool]FLAGS
812            append_to_environment_value configure $env_var {*}$flags
813        }
814        if {[variant_exists universal] && [variant_isset universal]} {
815            configure.pre_args-append {*}${configure.universal_args}
816        } else {
817            foreach env_var {CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FFLAGS F90FLAGS FCFLAGS LDFLAGS} {
818                if {${configure.march} ne ""} {
819                    append_to_environment_value configure $env_var -march=${configure.march}
820                }
821                if {${configure.mtune} ne ""} {
822                    append_to_environment_value configure $env_var -mtune=${configure.mtune}
823                }
824            }
825        }
826
827        # Execute the command (with the new environment).
828        if {[catch {command_exec configure} result]} {
829            global configure.dir
830            if {[file exists ${configure.dir}/config.log]} {
831                ui_error "[format [msgcat::mc "Failed to configure %s, consult %s/config.log"] [option subport] ${configure.dir}]"
832            }
833            return -code error "[format [msgcat::mc "%s failure: %s"] configure $result]"
834        }
835    }
836    return 0
837}