[45597] trunk/dports/_resources/port1.0/group/merge_universal-1.0.tcl

mcalhoun at macports.org mcalhoun at macports.org
Sun Jan 18 06:26:43 PST 2009


Revision: 45597
          http://trac.macports.org/changeset/45597
Author:   mcalhoun at macports.org
Date:     2009-01-18 06:26:41 -0800 (Sun, 18 Jan 2009)
Log Message:
-----------
New PortGroup: merge_universal-1.0.tcl
Intended to facilitate the building of more universal (especially 32/64-bit) binaries.
This PortGroup may disappear if the ideas prove general enough to replace the merge function.
Fixes #17972.

Added Paths:
-----------
    trunk/dports/_resources/port1.0/group/merge_universal-1.0.tcl

Added: trunk/dports/_resources/port1.0/group/merge_universal-1.0.tcl
===================================================================
--- trunk/dports/_resources/port1.0/group/merge_universal-1.0.tcl	                        (rev 0)
+++ trunk/dports/_resources/port1.0/group/merge_universal-1.0.tcl	2009-01-18 14:26:41 UTC (rev 45597)
@@ -0,0 +1,290 @@
+# -*- 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
+# merge_universal-1.0.tcl
+#
+# $Id$
+#
+# Copyright (c) 2009 The MacPorts Project,
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Apple Computer, Inc. nor the names of its
+#    contributors may be used to endorse or promote products derived from
+#    this software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+# User variables:
+#     merger_configure_env: associative array of configure.env variables
+#              merger_host: associative array of host values
+#    merger_configure_args: associative array of configure.args
+#         merger_dont_diff: list of file names for which diff will not work
+
+set universal_archs_supported  ${universal_archs}
+
+variant universal {
+    eval configure.args-append      ${configure.universal_args}
+    eval configure.cflags-append    ${configure.universal_cflags}
+    eval configure.cxxflags-append  ${configure.universal_cxxflags}
+    eval configure.ldflags-append   ${configure.universal_ldflags}
+    eval configure.cppflags-append  ${configure.universal_cppflags}
+
+    foreach arch ${universal_archs} {
+        configure.cflags-delete    -arch ${arch}
+        configure.cxxflags-delete  -arch ${arch}
+        configure.ldflags-delete   -arch ${arch}
+    }
+
+    configure {
+        foreach arch ${universal_archs_supported} {
+            ui_msg "universal: Running configure for architecture ${arch}"
+
+            copy ${worksrcpath} ${workpath}/${arch}
+
+            # Prefer -m to -arch
+            set archf "-arch ${arch}"
+            if { ${os.arch}=="i386" && ${arch}=="i386" } {
+                set archf -m32
+            } elseif { ${os.arch}=="i386" && ${arch}=="x86_64" } {
+                set archf -m64
+            } elseif { ${os.arch}=="powerpc" && ${arch}=="ppc" } {
+                set archf -m32
+            } elseif { ${os.arch}=="powerpc" && ${arch}=="ppc64" } {
+                set archf -m64
+            }
+            configure.cflags-append    ${archf}
+            configure.cxxflags-append  ${archf}
+
+            if { [info exists merger_configure_env(${arch})] } {
+                configure.env-append  $merger_configure_env(${arch})
+            }
+
+            # Don't set the --host unless we have to.
+            set host ""
+            if { ${os.arch}=="i386" && (${arch}=="ppc" || ${arch}=="ppc64") } {
+                if { [info exists merger_host(${arch})] } {
+                    if { $merger_host(${arch}) != "" } {
+                        set host  --host=$merger_host(${arch})
+                    }
+                } else {
+                    set host --host=powerpc64-apple-darwin
+                }
+            } elseif { ${os.arch}=="powerpc" && (${arch}=="i386" || ${arch}=="x86_64") } {
+                if { [info exists merger_host(${arch})] } {
+                    if { $merger_host(${arch}) != "" } {
+                        set host  --host=$merger_host(${arch})
+                    }
+                } else {
+                    set host --host=core2-apple-darwin
+                }
+            }
+            configure.args-append  ${host}
+
+            if { [info exists merger_configure_args(${arch})] } {
+                configure.args-append  $merger_configure_args(${arch})
+            }
+
+            set worksrcpathSave  ${worksrcpath}
+            set worksrcpath  ${workpath}/${arch}
+
+            configure_main
+
+            # Undo changes to the configure related variables
+            set worksrcpath  ${worksrcpathSave}
+            if { [info exists merger_configure_args(${arch})] } {
+                configure.args-delete  $merger_configure_args(${arch})
+            }
+            configure.args-delete  ${host}
+            if { [info exists merger_configure_env(${arch})] } {
+                configure.env-delete  $merger_configure_env(${arch})
+            }
+            configure.cxxflags-delete ${archf}
+            configure.cflags-delete ${archf}
+        }
+    }
+
+    build {
+        foreach arch ${universal_archs_supported} {
+            ui_msg "universal: Running build for architecture ${arch}"
+            build.dir  ${workpath}/${arch}
+			build_main
+		}
+    }
+
+	destroot {
+        foreach arch ${universal_archs_supported} {
+            ui_msg "universal: Running destroot for architecture ${arch}"
+            copy ${destroot} ${workpath}/destroot-${arch}
+            destroot.dir  ${workpath}/${arch}
+            set destdirSave ${destroot.destdir}
+            destroot.destdir  [string map "${destroot} ${workpath}/destroot-${arch}" ${destroot.destdir}]
+            destroot_main
+            destroot.destdir ${destdirSave} 
+        }
+        delete ${destroot}
+
+        # Merge ${base1}/${prefixDir} and ${base2}/${prefixDir} into dir ${base}/${prefixDir}
+        #        arch1, arch2: names to prepend to files if a diff merge of two files is forbiddend by merger_dont_diff
+        #    merger_dont_diff: list of files for which /usr/bin/diff ${diffFormat} will not merge correctly
+        #          diffFormat: format used by diff to merge two text files
+        proc merge2Dir {base1 base2 base prefixDir arch1 arch2 merger_dont_diff diffFormat} {
+            set dir1  ${base1}/${prefixDir}
+            set dir2  ${base2}/${prefixDir}
+            set dir   ${base}/${prefixDir}
+
+            xinstall -d -m 0755 ${dir}
+
+            foreach fl [glob -directory ${dir2} -tails -nocomplain *] {
+                if { ![file exists ${dir1}/${fl}] } {
+                    # File only exists in ${dir1}
+                    ui_debug "universal: merge: ${prefixDir}/${fl} only exists in ${base2}"
+                    copy ${dir2}/${fl} ${dir}
+                }
+            }
+            foreach fl [glob -directory ${dir1} -tails -nocomplain *] {
+                if { ![file exists ${dir2}/${fl}] } {
+                    # File only exists in ${dir2}
+                    ui_debug "universal: merge: ${prefixDir}/${fl} only exists in ${base1}"
+                    copy ${dir1}/${fl} ${dir}
+                } else {
+                    # File exists in ${dir1} and ${dir2}
+                    ui_debug "universal: merge: merging ${prefixDir}/${fl} from ${base1} and ${base2}"
+
+                    # Ensure files are of same type
+                    if { [file type ${dir1}/${fl}]!=[file type ${dir2}/${fl}] } {
+                        error "${dir1}/${fl} and ${dir2}/${fl} are of different types"
+                    }
+
+                    if { [file isdirectory ${dir1}/${fl}] } {
+                        # Files are directories, so recursively call function
+                        merge2Dir ${base1} ${base2} ${base} ${prefixDir}/${fl} ${arch1} ${arch2} ${merger_dont_diff} ${diffFormat}
+                    } elseif { [file type ${dir1}/${fl}]=="link" } {
+                        # Files are links
+                        ui_debug "universal: merge: ${prefixDir}/${fl} is a link"
+
+                        # Ensure links don't point to different things
+                        if { [file readlink ${dir1}/${fl}]==[file readlink ${dir2}/${fl}] } {
+                            copy ${dir1}/${fl} ${dir}
+                        } else {
+                            error "${dir1}/${fl} and ${dir2}/${fl} point to different targets (can't merge them)"
+                        }
+                    } else {
+                        # Files are neither directories nor links
+
+                        if { ! [catch {system "/usr/bin/cmp ${dir1}/${fl} ${dir2}/${fl} && /bin/cp -v ${dir1}/${fl} ${dir}"}] } {
+                            # Files are byte by byte the same
+                            ui_debug "universal: merge: ${prefixDir}${fl} is identical in ${base1} and ${base2}"
+                        } else {
+                            # Actually try to merge the files
+                            # First try lipo
+                            if { ! [catch {system "/usr/bin/lipo -create ${dir1}/${fl} ${dir2}/${fl} -output ${dir}/${fl}"}] } {
+                                # lipo worked
+                                ui_debug "universal: merge: lipo created ${prefixDir}/${fl}"
+                            } else {
+                                # lipo has failed, so assume they are text files to be merged
+                                set dontdiff no
+                                foreach dont ${merger_dont_diff} {
+                                    if { ${dont}=="${prefixDir}/${fl}" } {
+                                        set dontdiff yes
+                                    }
+                                }
+                                if { ${dontdiff}==yes } {
+                                    # user has specified that diff does not work
+                                    # attempt to give each file a unique name and create a new file which includes one of the origional depending on the arch
+
+                                    set fh [open ${dir}/${arch1}-${fl} w 0644]
+                                    puts ${fh} "#include \"${arch1}-${fl}\""
+                                    close ${fh}
+
+                                    set fh [open ${dir}/${arch2}-${fl} w 0644]
+                                    puts ${fh} "#include \"${arch2}-${fl}\""
+                                    close ${fh}
+
+                                    ui_debug "universal: merge: created ${prefixDir}/${fl} to include ${prefixDir}/${arch1}-${fl} ${prefixDir}/${arch1}-${fl}"
+
+                                    system "/usr/bin/diff -d ${diffFormat} ${dir}/${arch1}-${fl} ${dir}/${arch2}-${fl} > ${dir}/${fl}; test \$? -le 1"
+
+                                    copy -force ${dir1}/${fl} ${dir}/${arch1}-${fl}
+                                    copy -force ${dir2}/${fl} ${dir}/${arch2}-${fl}
+                                } elseif { ! [catch {system "/usr/bin/diff -dw ${diffFormat} ${dir1}/${fl} ${dir2}/${fl} > ${dir}/${fl}; test \$? -le 1"} ] } {
+                                    # diff worked
+                                    ui_debug "universal: merge: used diff to create ${prefixDir}/${fl}"
+                                } else {
+                                    # File created by diff is invalid
+                                    delete ${dir}/${fl}
+
+                                    # nothing has worked so far.
+                                    switch -glob ${fl} {
+                                        *.jar {
+                                            # jar files can be different becasue of timestamp
+                                            ui_debug "universal: merge: ${prefixDir}/${fl} is different in ${base1} and ${base2}; assume timestamp difference"
+                                            copy ${dir1}/${fl} ${dir}
+                                        }
+                                        default {
+                                            error "Can not create ${prefixDir}/${fl} from ${base1} and ${base2}"
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        # /usr/bin/diff can merge two C/C++ files
+        # See http://www.gnu.org/software/diffutils/manual/html_mono/diff.html#If-then-else
+        # See http://www.gnu.org/software/diffutils/manual/html_mono/diff.html#Detailed%20If-then-else
+        set diffFormatProc {--old-group-format='#if (defined(__ppc__) || defined(__ppc64__))
+ %<#endif /* __ppc__ || __ppc64__ */
+' \
+--new-group-format='#if defined (__i386__) || defined(__x86_64__)
+%>#endif /* __i386__ || __x86_64__ */
+' \
+--unchanged-group-format='%=' \
+--changed-group-format='#if (defined(__ppc__) || defined(__ppc64__))
+%<#else /* ! __ppc__ && ! __ppc64__ */
+%>#endif /* __ppc__ || __ppc64__ */
+'}
+
+        set diffFormatM "-D __LP64__"
+
+        if { ![info exists merger_dont_diff] } {
+            set merger_dont_diff {}
+        }
+
+        merge2Dir  ${workpath}/destroot-ppc      ${workpath}/destroot-ppc64 ${workpath}/destroot-powerpc  ""  ppc ppc64    ${merger_dont_diff}  ${diffFormatM}
+        merge2Dir  ${workpath}/destroot-i386     ${workpath}/destroot-x86_64 ${workpath}/destroot-intel   ""  i386 x86_64  ${merger_dont_diff}  ${diffFormatM}
+        merge2Dir  ${workpath}/destroot-powerpc  ${workpath}/destroot-intel ${workpath}/destroot          ""  powerpc x86  ${merger_dont_diff}  ${diffFormatProc}
+    }
+
+    test {
+        foreach arch ${universal_archs_supported} {
+            # Rosetta does not translate G5 instructions
+            # PowerPC systems can't translate Intel instructions
+            if { (${os.arch}=="i386" && ${arch}!="ppc64") || (${os.arch}=="powerpc" && ${arch}!="i386" && ${arch}!="x86_64") } {
+                ui_msg "universal: Running test for architecture ${arch}"
+                test.dir  ${workpath}/${arch}
+                test_main
+            }
+        }
+    }
+}


Property changes on: trunk/dports/_resources/port1.0/group/merge_universal-1.0.tcl
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20090118/fde69052/attachment.html>


More information about the macports-changes mailing list