source: trunk/dports/_resources/port1.0/group/muniversal-1.0.tcl @ 103445

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

muniversal-1.0.tcl: don't add --host argument when configuring with cmake since it doesn't support or need that

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 34.3 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: muniversal-1.0.tcl 103445 2013-02-26 04:29:45Z ryandesign@macports.org $
3#
4# Copyright (c) 2009-2013 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 Apple Computer, Inc. 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# User variables:
34#         merger_configure_env: associative array of configure.env variables
35#             merger_build_env: associative array of build.env variables
36#                  merger_host: associative array of host values
37#        merger_configure_args: associative array of configure.args
38#            merger_build_args: associative array of build.args
39#    merger_configure_compiler: associative array of configure.compiler
40#    merger_configure_cppflags: associative array of configure.cppflags
41#      merger_configure_cflags: associative array of configure.cflags
42#    merger_configure_cxxflags: associative array of configure.cxxflags
43#   merger_configure_objcflags: associative array of configure.objcflags
44#     merger_configure_ldflags: associative array of configure.ldflags
45#             merger_arch_flag: if no, -arch xxx will not be appended configure.???flags
46#         merger_arch_compiler: if no, -arch xxx will not be appended to compilers
47#          merger_destroot_env: associative array of destroot.env variables
48#             merger_dont_diff: list of file names for which diff will not work
49#     merger_must_run_binaries: if yes, build platform must be able to run binaries for supported architectures
50#            merger_no_3_archs: if yes, merger will not work correctly if there are three supported architectures
51
52options universal_archs_supported merger_must_run_binaries merger_no_3_archs merger_arch_flag merger_arch_compiler
53default universal_archs_supported {${universal_archs}}
54default merger_must_run_binaries {no}
55default merger_no_3_archs {no}
56default merger_arch_flag {yes}
57default merger_arch_compiler {no}
58
59proc muniversal_arch_flag_supported {args} {
60    global configure.compiler
61    switch -exact ${configure.compiler} {
62        gcc-4.0 -
63        gcc-4.2 -
64        llvm-gcc-4.2 -
65        clang -
66        apple-gcc-4.0 -
67        apple-gcc-4.2 -
68        macports-clang-2.9 -
69        macports-clang-3.0 -
70        macports-clang-3.1 -
71        macports-clang {
72            return yes
73        }
74        default {
75            return no
76        }
77    }
78}
79
80proc muniversal_get_arch_flag {arch {fortran ""}} {
81    global os.arch
82    # Prefer -arch to -m
83    if {[muniversal_arch_flag_supported] && ${fortran}==""} {
84        set archf "-arch ${arch}"
85    } else {
86        if { ${os.arch}=="i386" && ${arch}=="i386" } {
87            set archf -m32
88        } elseif { ${os.arch}=="i386" && ${arch}=="x86_64" } {
89            set archf -m64
90        } elseif { ${os.arch}=="powerpc" && ${arch}=="ppc" } {
91            set archf -m32
92        } elseif { ${os.arch}=="powerpc" && ${arch}=="ppc64" } {
93            set archf -m64
94        } else {
95            if { ${fortran}=="" } {
96                return -code error "selected compiler can't build for ${arch}"
97            } else {
98                return ""
99            }
100        }
101    }
102    return ${archf}
103}
104
105variant universal {
106    global universal_archs_to_use
107
108    foreach arch ${universal_archs} {
109        configure.universal_cflags-delete    -arch ${arch}
110        configure.universal_cxxflags-delete  -arch ${arch}
111        configure.universal_ldflags-delete   -arch ${arch}
112    }
113
114    eval configure.args-append      ${configure.universal_args}
115    eval configure.cflags-append    ${configure.universal_cflags}
116    eval configure.cxxflags-append  ${configure.universal_cxxflags}
117    eval configure.objcflags-append ${configure.universal_cflags}
118    eval configure.ldflags-append   ${configure.universal_ldflags}
119    eval configure.cppflags-append  ${configure.universal_cppflags}
120
121    # user has specified that build platform must be able to run binaries for supported architectures
122    if { ${merger_must_run_binaries}=="yes" } {
123        if { ${os.arch}=="i386" } {
124            set universal_archs_supported [ldelete ${universal_archs_supported} "ppc64"]
125            if {${os.major} >= 9 && [sysctl hw.cpu64bit_capable] == 0} {
126                set universal_archs_supported [ldelete ${universal_archs_supported} "x86_64"]
127            }
128        } else {
129            set universal_archs_supported [ldelete ${universal_archs_supported} "i386"]
130            set universal_archs_supported [ldelete ${universal_archs_supported} "x86_64"]
131            if {${os.major} >= 9 && [sysctl hw.cpu64bit_capable] == 0} {
132                set universal_archs_supported [ldelete ${universal_archs_supported} "ppc64"]
133            }
134        }
135    }
136
137    # set universal_archs_to_use as the intersection of universal_archs and universal_archs_supported
138    set universal_archs_to_use {}
139    foreach arch ${universal_archs} {
140        set arch_ok no
141        foreach archt ${universal_archs_supported} {
142            if { ${arch}==${archt} } {
143                set arch_ok yes
144            }
145        }
146        if { ${arch_ok}=="yes" } {
147            lappend universal_archs_to_use ${arch}
148        }
149    }
150
151    # if merger_no_3_archs is yes, prune universal_archs_to_use until it only has two elements
152    if { ${merger_no_3_archs}=="yes" } {
153        if { [llength ${universal_archs_to_use}] == 3 } {
154            # first try to remove cross-compiled 64-bit arch
155            if { ${os.arch}=="i386" } {
156                set universal_archs_to_use [ldelete ${universal_archs_to_use} "ppc64"]
157            } else {
158                set universal_archs_to_use [ldelete ${universal_archs_to_use} "x86_64"]
159            }
160        }
161        if { [llength ${universal_archs_to_use}] == 3 } {
162            # next try to remove cross-compiled 32-bit arch
163            if { ${os.arch}=="i386" } {
164                set universal_archs_to_use [ldelete ${universal_archs_to_use} "ppc"]
165            } else {
166                set universal_archs_to_use [ldelete ${universal_archs_to_use} "i386"]
167            }
168        }
169        if { [llength ${universal_archs_to_use}] == 3 } {
170            # at least one arch should have been removed from universal_archs_to_use
171            error "Should Not Happen"
172        }
173    }
174
175    configure {
176        # Fix inability to find nm when cross-compiling (#22224, #23431, #23687, #24477, et al)
177        configure.env-append    NM=/usr/bin/nm
178
179        foreach arch ${universal_archs_to_use} {
180            ui_info "$UI_PREFIX [format [msgcat::mc "Configuring %1\$s for architecture %2\$s"] $name ${arch}]"
181
182            copy ${worksrcpath} ${worksrcpath}-${arch}
183
184            set archf [muniversal_get_arch_flag ${arch}]
185            set archff [muniversal_get_arch_flag ${arch} "fortran"]
186
187            if { ${merger_arch_flag} != "no" } {
188                configure.cflags-append    ${archf}
189                configure.cxxflags-append  ${archf}
190                configure.objcflags-append ${archf}
191                configure.fflags-append    ${archff}
192                configure.fcflags-append   ${archff}
193                configure.f90flags-append  ${archff}
194                configure.ldflags-append   ${archf}
195            }
196
197            if { [info exists merger_configure_env(${arch})] } {
198                configure.env-append  $merger_configure_env(${arch})
199            }
200            if { [info exists merger_configure_cppflags(${arch})] } {
201                configure.cppflags-append  $merger_configure_cppflags(${arch})
202            }
203            if { [info exists merger_configure_cflags(${arch})] } {
204                configure.cflags-append  $merger_configure_cflags(${arch})
205            }
206            if { [info exists merger_configure_cxxflags(${arch})] } {
207                configure.cxxflags-append  $merger_configure_cxxflags(${arch})
208            }
209            if { [info exists merger_configure_objcflags(${arch})] } {
210                configure.objcflags-append  $merger_configure_objcflags(${arch})
211            }
212            if { [info exists merger_configure_ldflags(${arch})] } {
213                configure.ldflags-append  $merger_configure_ldflags(${arch})
214            }
215
216            # Don't set the --host unless we have to.
217            set host ""
218            if { [info exists merger_host($arch)] } {
219                if { $merger_host($arch) != "" } {
220                    set host  --host=$merger_host($arch)
221                }
222            } elseif {[file tail ${configure.cmd}] != "cmake"} {
223                # check if building for a word length we can't run
224                set bits_differ 0
225                if {(${arch}=="x86_64" || ${arch}=="ppc64") &&
226                    (${os.major} < 9 || [sysctl hw.cpu64bit_capable] == 0)} {
227                    set bits_differ 1
228                }
229                # check if building for a completely different arch
230                if {$bits_differ || (${os.arch}=="i386" && (${arch}=="ppc" || ${arch}=="ppc64"))
231                        || (${os.arch}=="powerpc" && (${arch}=="i386" || ${arch}=="x86_64"))
232                        || $macosx_deployment_target != $macosx_version} {
233                    if {$macosx_deployment_target == $macosx_version} {
234                        set hostversion ${os.version}
235                    } else {
236                        set hostversion [expr [lindex [split $macosx_deployment_target .] 1] + 4]
237                    }
238                    switch -- ${arch} {
239                        x86_64  {set host "--host=x86_64-apple-${os.platform}${hostversion}"}
240                        i386    {set host "--host=i686-apple-${os.platform}${hostversion}"}
241                        ppc     {set host "--host=powerpc-apple-${os.platform}${hostversion}"}
242                        ppc64   {set host "--host=powerpc64-apple-${os.platform}${hostversion}"}
243                    }
244                }
245            }
246            if {$host != ""} {
247                configure.args-append  ${host}
248            }
249
250            if { [info exists merger_configure_args(${arch})] } {
251                configure.args-append  $merger_configure_args(${arch})
252            }
253
254            set configure_compiler_save ${configure.compiler}
255            set configure_cc_save       ${configure.cc}
256            set configure_cxx_save      ${configure.cxx}
257            set configure_objc_save     ${configure.objc}
258            set configure_fc_save       ${configure.fc}
259            set configure_f77_save      ${configure.f77}
260            set configure_f90_save      ${configure.f90}
261
262            if { [info exists merger_configure_compiler($arch)] } {
263                configure.compiler  $merger_configure_compiler($arch)
264                configure.cc        [portconfigure::configure_get_compiler cc]
265                configure.cxx       [portconfigure::configure_get_compiler cxx]
266                configure.objc      [portconfigure::configure_get_compiler objc]
267                configure.f77       [portconfigure::configure_get_compiler f77]
268                configure.f90       [portconfigure::configure_get_compiler f90]
269                configure.fc        [portconfigure::configure_get_compiler fc]
270            }
271
272            if { ${merger_arch_compiler} != "no" } {
273                configure.cc   ${configure.cc}   ${archf}
274                configure.cxx  ${configure.cxx}  ${archf}
275                configure.objc ${configure.objc} ${archf}
276                if { ${configure.fc}  != "" } { configure.fc   ${configure.fc}  ${archff} }
277                if { ${configure.f77} != "" } { configure.f77  ${configure.f77} ${archff} }
278                if { ${configure.f90} != "" } { configure.f90  ${configure.f90} ${archff} }
279            }
280
281            set configure_dir_save  ${configure.dir}
282            if { [string match "${worksrcpath}/*" ${configure.dir}] } {
283                # The configure directory is inside the source directory, so put in the new source directory name.
284                eval configure.dir  [string map "${worksrcpath} ${worksrcpath}-${arch}" ${configure.dir}]
285            } else {
286                # The configure directory is outside the source directory, so give it a new name by appending ${arch}.
287                configure.dir  ${configure.dir}-${arch}
288                if { ![file exists ${configure.dir}] } {
289                    file mkdir ${configure.dir}
290                }
291            }
292
293            set autoreconf_dir_save  ${autoreconf.dir}
294            if { [string match "${worksrcpath}/*" ${autoreconf.dir}] } {
295                # The autoreconf directory is inside the source directory, so put in the new source directory name.
296                eval autoreconf.dir  [string map "${worksrcpath} ${worksrcpath}-${arch}" ${autoreconf.dir}]
297            } else {
298                # The autoreconf directory is outside the source directory, so give it a new name by appending ${arch}.
299                autoreconf.dir  ${autoreconf.dir}-${arch}
300                if { ![file exists ${autoreconf.dir}] } {
301                    file mkdir ${autoreconf.dir}
302                }
303            }
304
305            portconfigure::configure_main
306
307            # Undo changes to the configure related variables
308            eval autoreconf.dir ${autoreconf_dir_save}
309            eval configure.dir  ${configure_dir_save}
310            eval configure.compiler ${configure_compiler_save}
311            eval configure.f90  ${configure_f90_save}
312            eval configure.f77  ${configure_f77_save}
313            eval configure.fc   ${configure_fc_save}
314            eval configure.cc   ${configure_cc_save}
315            eval configure.cxx  ${configure_cxx_save}
316            eval configure.objc ${configure_objc_save}
317            if { [info exists merger_configure_args(${arch})] } {
318                configure.args-delete  $merger_configure_args(${arch})
319            }
320            configure.args-delete  ${host}
321            if { [info exists merger_configure_ldflags(${arch})] } {
322                configure.ldflags-delete  $merger_configure_ldflags(${arch})
323            }
324            if { [info exists merger_configure_cxxflags(${arch})] } {
325                configure.cxxflags-delete  $merger_configure_cxxflags(${arch})
326            }
327            if { [info exists merger_configure_objcflags(${arch})] } {
328                configure.objcflags-delete  $merger_configure_objcflags(${arch})
329            }
330            if { [info exists merger_configure_cflags(${arch})] } {
331                configure.cflags-delete  $merger_configure_cflags(${arch})
332            }
333            if { [info exists merger_configure_cppflags(${arch})] } {
334                configure.cppflags-delete  $merger_configure_cppflags(${arch})
335            }
336            if { [info exists merger_configure_env(${arch})] } {
337                configure.env-delete  $merger_configure_env(${arch})
338            }
339            if { ${merger_arch_flag} != "no" } {
340                configure.ldflags-delete   ${archf}
341                configure.f90flags-delete  ${archff}
342                configure.fcflags-delete   ${archff}
343                configure.fflags-delete    ${archff}
344                configure.objcflags-delete ${archf}
345                configure.cxxflags-delete  ${archf}
346                configure.cflags-delete    ${archf}
347            }
348        }
349    }
350
351    build {
352        foreach arch ${universal_archs_to_use} {
353            ui_info "$UI_PREFIX [format [msgcat::mc "Building %1\$s for architecture %2\$s"] $name ${arch}]"
354
355            if { [info exists merger_build_env(${arch})] } {
356                build.env-append  $merger_build_env(${arch})
357            }
358            if { [info exists merger_build_args(${arch})] } {
359                build.args-append  $merger_build_args(${arch})
360            }
361            set build_dir_save  ${build.dir}
362            if { [string match "${worksrcpath}/*" ${build.dir}] } {
363                # The build directory is inside the source directory, so put in the new source directory name.
364                eval build.dir  [string map "${worksrcpath} ${worksrcpath}-${arch}" ${build.dir}]
365            } else {
366                # The build directory is outside the source directory, so give it a new name by appending ${arch}.
367                build.dir  ${build.dir}-${arch}
368                if { ![file exists ${build.dir}] } {
369                    file mkdir ${build.dir}
370                }
371            }
372
373            portbuild::build_main
374
375            eval build.dir  ${build_dir_save}
376            if { [info exists merger_build_args(${arch})] } {
377                build.args-delete $merger_build_args(${arch})
378            }
379            if { [info exists merger_build_env(${arch})] } {
380                build.env-delete  $merger_build_env(${arch})
381            }
382        }
383    }
384
385    destroot {
386        foreach arch ${universal_archs_to_use} {
387            ui_info "$UI_PREFIX [format [msgcat::mc "Staging %1\$s into destroot for architecture %2\$s"] $name ${arch}]"
388            copy ${destroot} ${workpath}/destroot-${arch}
389            set destdirSave ${destroot.destdir}
390            eval destroot.destdir  [string map "${destroot} ${workpath}/destroot-${arch}" ${destroot.destdir}]
391
392            if { [info exists merger_destroot_env(${arch})] } {
393                destroot.env-append  $merger_destroot_env(${arch})
394            }
395            set destroot_dir_save ${destroot.dir}
396            if { [string match "${worksrcpath}/*" ${destroot.dir}] } {
397                # The destroot directory is inside the source directory, so put in the new source directory name.
398                eval destroot.dir  [string map "${worksrcpath} ${worksrcpath}-${arch}" ${destroot.dir}]
399            } else {
400                # The destroot directory is outside the source directory, so give it a new name by appending ${arch}.
401                destroot.dir  ${destroot.dir}-${arch}
402                if { ![file exists ${destroot.dir}] } {
403                    file mkdir ${destroot.dir}
404                }
405            }
406
407            portdestroot::destroot_main
408
409            destroot.dir  ${destroot_dir_save}
410            if { [info exists merger_destroot_env(${arch})] } {
411                destroot.env-delete  $merger_destroot_env(${arch})
412            }
413            eval destroot.destdir ${destdirSave}
414        }
415        delete ${destroot}
416
417        # Merge ${base1}/${prefixDir} and ${base2}/${prefixDir} into dir ${base}/${prefixDir}
418        #        arch1, arch2: names to prepend to files if a diff merge of two files is forbidden by merger_dont_diff
419        #    merger_dont_diff: list of files for which /usr/bin/diff ${diffFormat} will not merge correctly
420        #          diffFormat: format used by diff to merge two text files
421        proc merge2Dir {base1 base2 base prefixDir arch1 arch2 merger_dont_diff diffFormat} {
422            set dir1  ${base1}/${prefixDir}
423            set dir2  ${base2}/${prefixDir}
424            set dir   ${base}/${prefixDir}
425
426            xinstall -d -m 0755 ${dir}
427
428            foreach fl [glob -directory ${dir2} -tails -nocomplain *] {
429                if { ![muniversal_file_or_symlink_exists ${dir1}/${fl}] } {
430                    # File only exists in ${dir1}
431                    ui_debug "universal: merge: ${prefixDir}/${fl} only exists in ${base2}"
432                    copy ${dir2}/${fl} ${dir}
433                }
434            }
435            foreach fl [glob -directory ${dir1} -tails -nocomplain *] {
436                if { ![muniversal_file_or_symlink_exists ${dir2}/${fl}] } {
437                    # File only exists in ${dir2}
438                    ui_debug "universal: merge: ${prefixDir}/${fl} only exists in ${base1}"
439                    copy ${dir1}/${fl} ${dir}
440                } else {
441                    # File exists in ${dir1} and ${dir2}
442                    ui_debug "universal: merge: merging ${prefixDir}/${fl} from ${base1} and ${base2}"
443
444                    # Ensure files are of same type
445                    if { [file type ${dir1}/${fl}]!=[file type ${dir2}/${fl}] } {
446                        error "${dir1}/${fl} and ${dir2}/${fl} are of different types"
447                    }
448
449                    if { [file type ${dir1}/${fl}]=="link" } {
450                        # Files are links
451                        ui_debug "universal: merge: ${prefixDir}/${fl} is a link"
452
453                        # Ensure links don't point to different things
454                        if { [file readlink ${dir1}/${fl}]==[file readlink ${dir2}/${fl}] } {
455                            copy ${dir1}/${fl} ${dir}
456                        } else {
457                            error "${dir1}/${fl} and ${dir2}/${fl} point to different targets (can't merge them)"
458                        }
459                    } elseif { [file isdirectory ${dir1}/${fl}] } {
460                        # Files are directories (but not links), so recursively call function
461                        merge2Dir ${base1} ${base2} ${base} ${prefixDir}/${fl} ${arch1} ${arch2} ${merger_dont_diff} ${diffFormat}
462                    } else {
463                        # Files are neither directories nor links
464                        if { ! [catch {system "/usr/bin/cmp \"${dir1}/${fl}\" \"${dir2}/${fl}\" && /bin/cp -v \"${dir1}/${fl}\" \"${dir}\""}] } {
465                            # Files are byte by byte the same
466                            ui_debug "universal: merge: ${prefixDir}/${fl} is identical in ${base1} and ${base2}"
467                        } else {
468                            # Actually try to merge the files
469                            # First try lipo, then libtool
470                            if { ! [catch {system "/usr/bin/lipo -create \"${dir1}/${fl}\" \"${dir2}/${fl}\" -output \"${dir}/${fl}\""}] } {
471                                # lipo worked
472                                ui_debug "universal: merge: lipo created ${prefixDir}/${fl}"
473                            } elseif { ! [catch {system "/usr/bin/libtool \"${dir1}/${fl}\" \"${dir2}/${fl}\" -o \"${dir}/${fl}\""}] } {
474                                # libtool worked
475                                ui_debug "universal: merge: libtool created ${prefixDir}/${fl}"
476                            } else {
477                                # lipo and libtool have failed, so assume they are text files to be merged
478                                set dontdiff no
479                                foreach dont ${merger_dont_diff} {
480                                    if { ${dont}=="${prefixDir}/${fl}" } {
481                                        set dontdiff yes
482                                    }
483                                }
484                                if { ${dontdiff}==yes } {
485                                    # user has specified that diff does not work
486                                    # attempt to give each file a unique name and create a new file which includes one of the original depending on the arch
487
488                                    set fh [open ${dir}/${arch1}-${fl} w 0644]
489                                    puts ${fh} "#include \"${arch1}-${fl}\""
490                                    close ${fh}
491
492                                    set fh [open ${dir}/${arch2}-${fl} w 0644]
493                                    puts ${fh} "#include \"${arch2}-${fl}\""
494                                    close ${fh}
495
496                                    ui_debug "universal: merge: created ${prefixDir}/${fl} to include ${prefixDir}/${arch1}-${fl} ${prefixDir}/${arch1}-${fl}"
497
498                                    system "/usr/bin/diff -d ${diffFormat} \"${dir}/${arch1}-${fl}\" \"${dir}/${arch2}-${fl}\" > \"${dir}/${fl}\"; test \$? -le 1"
499
500                                    copy -force ${dir1}/${fl} ${dir}/${arch1}-${fl}
501                                    copy -force ${dir2}/${fl} ${dir}/${arch2}-${fl}
502                                } else {
503                                    set known_file "no"
504
505                                    # Text file on which diff will not give correct results.
506                                    switch -glob ${fl} {
507                                        *.mod {
508                                            # .mod files from Fortran modules.
509                                            # Create a sepcial module directory for each architecture.
510                                            # To find these modules, GFortran might require -M or -J.
511                                            set known_file "yes"
512                                            file mkdir ${dir}/mods32
513                                            file mkdir ${dir}/mods64
514                                            if { ${arch1}=="i386" || ${arch1}=="ppc" } {
515                                                copy ${dir1}/${fl} ${dir}/mods32
516                                                copy ${dir2}/${fl} ${dir}/mods64
517                                            } else {
518                                                copy ${dir2}/${fl} ${dir}/mods32
519                                                copy ${dir1}/${fl} ${dir}/mods64
520                                            }
521                                        }
522                                        *.la -
523                                        *.pc -
524                                        *-config {
525                                            return -code error "${prefixDir}/${fl} differs in ${base1} and ${base2} and cannot be merged"
526                                        }
527                                    }
528
529                                    if { ${known_file}=="no" } {
530                                        if { ! [catch {system "/usr/bin/diff -dw ${diffFormat} \"${dir1}/${fl}\" \"${dir2}/${fl}\" > \"${dir}/${fl}\"; test \$? -le 1"} ] } {
531                                            # diff worked
532                                            ui_debug "universal: merge: used diff to create ${prefixDir}/${fl}"
533                                        } else {
534                                            # File created by diff is invalid
535                                            delete ${dir}/${fl}
536
537                                            # nothing has worked so far.
538                                            switch -glob ${fl} {
539                                                *.jar {
540                                                    # jar files can be different because of timestamp
541                                                    ui_debug "universal: merge: ${prefixDir}/${fl} differs in ${base1} and ${base2}; assume timestamp difference"
542                                                    copy ${dir1}/${fl} ${dir}
543                                                }
544                                                *.elc {
545                                                    # elc files can be different because they record when and where they were built.
546                                                    ui_debug "universal: merge: ${prefixDir}/${fl} differs in ${base1} and ${base2}; assume trivial difference"
547                                                    copy ${dir1}/${fl} ${dir}
548                                                }
549                                                *.gz -
550                                                *.bz2 {
551                                                    # compressed files can differ due to entropy
552                                                    switch -glob ${fl} {
553                                                        *.gz {
554                                                            set cat /usr/bin/gzcat
555                                                        }
556                                                        *.bz2 {
557                                                            set cat /usr/bin/bzcat
558                                                        }
559                                                    }
560                                                    set tempdir [mkdtemp "/tmp/muniversal.XXXXXXXX"]
561                                                    set tempfile1 "${tempdir}/${arch1}-[file rootname ${fl}]"
562                                                    set tempfile2 "${tempdir}/${arch2}-[file rootname ${fl}]"
563                                                    system "${cat} \"${dir1}/${fl}\" > \"${tempfile1}\""
564                                                    system "${cat} \"${dir2}/${fl}\" > \"${tempfile2}\""
565                                                    set identical "no"
566                                                    if { ! [catch {system "/usr/bin/cmp -s \"${tempfile1}\" \"${tempfile2}\""}] } {
567                                                        # files are identical
568                                                        ui_debug "universal: merge: ${prefixDir}/${fl} differs in ${base1} and ${base2} but the contents are the same"
569                                                        set identical "yes"
570                                                        copy ${dir1}/${fl} ${dir}
571                                                    }
572                                                    if { ${identical}=="no" } {
573                                                        switch -glob ${fl} {
574                                                            *.el.gz {
575                                                                # Emacs lisp files should be same across architectures
576                                                                # the emacs package (and perhaps others) records the date of automatically generated el files
577                                                                ui_debug "universal: merge: ${prefixDir}/${fl} differs in ${base1} and ${base2}; assume trivial difference"
578                                                                set identical "yes"
579                                                                copy ${dir1}/${fl} ${dir}
580                                                            }
581                                                        }
582                                                    }
583                                                    delete ${tempfile1} ${tempfile2} ${tempdir}
584                                                    if {${identical}=="no"} {
585                                                        return -code error "${prefixDir}/${fl} differs in ${base1} and ${base2} and cannot be merged"
586                                                    }
587                                                }
588                                                default {
589                                                    return -code error "${prefixDir}/${fl} differs in ${base1} and ${base2} and cannot be merged"
590                                                }
591                                            }
592                                        }
593                                    }
594                                }
595                            }
596                        }
597                    }
598                }
599            }
600        }
601
602        # /usr/bin/diff can merge two C/C++ files
603        # See http://www.gnu.org/software/diffutils/manual/html_mono/diff.html#If-then-else
604        # See http://www.gnu.org/software/diffutils/manual/html_mono/diff.html#Detailed%20If-then-else
605        set diffFormatProc {--old-group-format='#if (defined(__ppc__) || defined(__ppc64__))
606 %<#endif
607' \
608--new-group-format='#if defined (__i386__) || defined(__x86_64__)
609%>#endif
610' \
611--unchanged-group-format='%=' \
612--changed-group-format='#if (defined(__ppc__) || defined(__ppc64__))
613%<#else
614%>#endif
615'}
616
617        set diffFormatM "-D __LP64__"
618
619        if { ![info exists merger_dont_diff] } {
620            set merger_dont_diff {}
621        }
622
623        merge2Dir  ${workpath}/destroot-ppc      ${workpath}/destroot-ppc64 ${workpath}/destroot-powerpc  ""  ppc ppc64    ${merger_dont_diff}  ${diffFormatM}
624        merge2Dir  ${workpath}/destroot-i386     ${workpath}/destroot-x86_64 ${workpath}/destroot-intel   ""  i386 x86_64  ${merger_dont_diff}  ${diffFormatM}
625        merge2Dir  ${workpath}/destroot-powerpc  ${workpath}/destroot-intel ${workpath}/destroot          ""  powerpc x86  ${merger_dont_diff}  ${diffFormatProc}
626    }
627
628    test {
629        foreach arch ${universal_archs_to_use} {
630            # Rosetta does not translate G5 instructions
631            # PowerPC systems can't translate Intel instructions
632            if { (${os.arch}=="i386" && ${arch}!="ppc64") || (${os.arch}=="powerpc" && ${arch}!="i386" && ${arch}!="x86_64") } {
633                ui_info "$UI_PREFIX [format [msgcat::mc "Testing %1\$s for architecture %2\$s"] $name ${arch}]"
634                set test_dir_save ${test.dir}
635                if { [string match "${worksrcpath}/*" ${test.dir}] } {
636                    # The test directory is inside the source directory, so put in the new source directory name.
637                    eval test.dir  [string map "${worksrcpath} ${worksrcpath}-${arch}" ${test.dir}]
638                } else {
639                    # The test directory is outside the source directory, so give it a new name by appending ${arch}.
640                    test.dir  ${test.dir}-${arch}
641                    if { ![file exists ${test.dir}] } {
642                        file mkdir ${test.dir}
643                    }
644                }
645
646                porttest::test_main
647
648                test.dir ${test_dir_save}
649            }
650        }
651    }
652}
653
654# [muniversal_file_or_symlink_exists ${f}] tells you if ${f} exists. And unlike
655# [file exists ${f}], if used on a symlink, [muniversal_file_or_symlink_exists ${f}]
656# tells you about the symlink, not what it points to.
657proc muniversal_file_or_symlink_exists {f} {
658    # If [file type ${f}] throws an error, ${f} doesn't exist.
659    if {[catch {file type ${f}}]} {
660        return 0
661    }
662    # Otherwise, it does.
663    return 1
664}
Note: See TracBrowser for help on using the repository browser.