This big hammer makes Samba4 binaries usable (again).

Tested successfully on i386. Unless someone objects, or come with
better solution, I'll commit this at the next evening.

--
WBR,
  Vadim Zhukov


Index: patches/patch-buildtools_wafadmin_Tools_cc_py
===================================================================
RCS file: patches/patch-buildtools_wafadmin_Tools_cc_py
diff -N patches/patch-buildtools_wafadmin_Tools_cc_py
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-buildtools_wafadmin_Tools_cc_py       22 May 2014 18:39:34 
-0000
@@ -0,0 +1,16 @@
+$OpenBSD$
+Reorder object files to minimize library interrefs count.
+Speeds up loading of library files.
+--- buildtools/wafadmin/Tools/cc.py.orig       Mon May 19 17:29:02 2014
++++ buildtools/wafadmin/Tools/cc.py    Mon May 19 18:05:26 2014
+@@ -93,8 +93,8 @@ cls = Task.simple_task_type('cc', cc_str, 'GREEN', ext
+ cls.scan = ccroot.scan
+ cls.vars.append('CCDEPS')
+ 
+-link_str = '${LINK_CC} ${CCLNK_SRC_F}${SRC} 
${CCLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}'
+-cls = Task.simple_task_type('cc_link', link_str, color='YELLOW', ext_in='.o', 
ext_out='.bin', shell=False)
++link_str = '${LINK_CC} ${CCLNK_SRC_F} `set -- ${SRC}; test $# -gt 0 && lorder 
"$@" | tsort -q` ${CCLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}'
++cls = Task.simple_task_type('cc_link', link_str, color='YELLOW', ext_in='.o', 
ext_out='.bin', shell=True)
+ cls.maxjobs = 1
+ cls.install = Utils.nada
+ 
Index: patches/patch-buildtools_wafadmin_Tools_ccroot_py
===================================================================
RCS file: 
/cvs/ports/net/samba4/patches/patch-buildtools_wafadmin_Tools_ccroot_py,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 patch-buildtools_wafadmin_Tools_ccroot_py
--- patches/patch-buildtools_wafadmin_Tools_ccroot_py   4 May 2014 16:08:29 
-0000       1.1.1.1
+++ patches/patch-buildtools_wafadmin_Tools_ccroot_py   22 May 2014 18:39:34 
-0000
@@ -1,9 +1,171 @@
 $OpenBSD: patch-buildtools_wafadmin_Tools_ccroot_py,v 1.1.1.1 2014/05/04 
16:08:29 zhuk Exp $
-Make Samba4 WAF respect OpenBSD shared libraries versioning conventions.
-BUG: https://bugzilla.samba.org/show_bug.cgi?id=9774
---- buildtools/wafadmin/Tools/ccroot.py.orig   Mon May 27 17:48:53 2013
-+++ buildtools/wafadmin/Tools/ccroot.py        Mon May 27 18:06:35 2013
-@@ -568,7 +568,7 @@ def apply_implib(self):
+1. Make Samba4 WAF respect OpenBSD shared libraries versioning conventions.
+   BUG: https://bugzilla.samba.org/show_bug.cgi?id=9774
+
+2. Speed up starting Samba binaries by a factor of 10 by reordering.
+   This adds debug printing "SCANNING" to give a clue that build is
+   still going.
+libraries during linking.
+--- buildtools/wafadmin/Tools/ccroot.py.orig   Mon May 19 19:54:23 2014
++++ buildtools/wafadmin/Tools/ccroot.py        Thu May 22 22:28:51 2014
+@@ -4,7 +4,7 @@
+ 
+ "base for all c/c++ programs and libraries"
+ 
+-import os, sys, re
++import os, sys, re, stat, subprocess
+ import TaskGen, Task, Utils, preproc, Logs, Build, Options
+ from Logs import error, debug, warn
+ from Utils import md5
+@@ -19,6 +19,9 @@ except ImportError:
+ import config_c # <- necessary for the configuration, do not touch
+ 
+ USE_TOP_LEVEL = False
++LIBFILES_CACHE = {}
++DIR_CACHE = {}
++NM_CACHE = {}
+ 
+ def get_cc_version(conf, cc, gcc=False, icc=False):
+ 
+@@ -450,6 +453,15 @@ def apply_objdeps(self):
+               for t in y.compiled_tasks:
+                       self.link_task.inputs.extend(t.outputs)
+ 
++def libver_key(file):
++      """generate sort key for library file path"""
++      v = re.search('\.so((\.[0-9]+)*)$', file).group(1).lstrip('.')
++      s = ''
++      for i in v.split('.'):
++              if len(i) > 0:
++                      s = "%s.%04d" % (s, int(i))
++      return s
++
+ @feature('cprogram', 'cshlib', 'cstaticlib')
+ @after('apply_lib_vars')
+ def apply_obj_vars(self):
+@@ -484,8 +496,120 @@ def apply_obj_vars(self):
+               if v['STATICLIB'] or v['LIB']:
+                       v.append_value('LINKFLAGS', v['SHLIB_MARKER'])
+ 
+-      app('LINKFLAGS', [lib_st % i for i in v['LIB']])
++      libsleft = v['LIB'][:]
++      if sys.platform.startswith("openbsd"):
++              bldpath = self.bld.bldnode.abspath()
++              libdirs = []
++              for i in v['LIBPATH']:
++                      if i.startswith(bldpath) and not i in libdirs:
++                              libdirs.append(i) 
++              for i in v['LIBPATH']:
++                      if not i.startswith(bldpath) and not i in libdirs:
++                              libdirs.append(i)
+ 
++              # Search for libraries and sort them using lorder(1),
++              # lowering number ld.so needs to load libraries in final
++              # binaries, and thus binaries start much faster.
++              libfiles = []
++              for dir in libdirs:
++                      if not os.path.isabs(dir):
++                              dir = os.path.join(bldpath, dir)
++
++                      if dir in LIBFILES_CACHE:
++                              dircache = LIBFILES_CACHE[dir]
++                              newleft = libsleft
++                              for lib in libsleft:
++                                      if lib in dircache:
++                                              libfiles.append(dircache[lib])
++                                              newleft = [i for i in newleft 
if i != lib]
++                              libsleft = newleft
++                      if len(libsleft) == 0:
++                              break
++
++                      if dir not in DIR_CACHE:
++                              dirlibs = []
++                              for file in os.listdir(dir):
++                                      path = os.path.join(dir, file)
++                                      if not 
stat.S_ISREG(os.stat(path).st_mode): continue
++                                      if not 
re.match('(lib)?.*\.so(\.[0-9]+)*', file): continue
++                                      dirlibs.append(path)
++                              DIR_CACHE[dir] = dirlibs
++                                      
++
++                      candidates = {}
++                      newleft = libsleft
++                      for path in DIR_CACHE[dir]:
++                              for lib in libsleft:
++                                      if 
re.match('.*%s(lib)?%s\.so(\.[0-9]+)*' % (os.sep, lib), path):
++                                              if lib not in candidates:
++                                                      candidates[lib] = []
++                                              candidates[lib].append(path)
++
++                                              #
++                                              # Avoid searching for libraries 
in future dirs.
++                                              #
++                                              # XXX Incorrect if called 
second time with
++                                              # additional directory 
containing given library
++                                              # and placed in list before 
other one, where
++                                              # the library given was found 
already.
++                                              #
++                                              newleft = [i for i in newleft 
if i != lib]
++
++                      libsleft = newleft
++                      for lib in candidates.keys():
++                              bestpath = sorted(candidates[lib], 
key=libver_key).pop()
++                              if not dir in LIBFILES_CACHE:
++                                      LIBFILES_CACHE[dir] = {}
++                              LIBFILES_CACHE[dir][lib] = bestpath
++                              libfiles.append(bestpath)
++
++              if len(libfiles) > 0:
++                      for f in libfiles:
++                              if not f in NM_CACHE:
++                                      print "SCANNING %s" % f
++                                      exports = set()
++                                      refs = set()
++                                      out = subprocess.check_output(['nm', 
'-gop', '--', f])
++                                      for l in out.splitlines():
++                                              path, info = l.split(':', 2)
++                                              parts = info.split(None, 3)    
# addr, type, sym
++                                              if parts[0] == 'U':
++                                                      refs.add(parts[1])
++                                              elif 'TDGR'.find(parts[1]) != 
-1:
++                                                      exports.add(parts[2])
++                                      NM_CACHE[f] = (refs, exports)
++
++                      sortedfiles = [ libfiles.pop() ]
++                      # print "BEGINNING WITH %s" % sortedfiles[0]
++                      while len(libfiles) > 0:
++                              f = libfiles.pop()
++                              if f in sortedfiles:
++                                      # print "\tSKIPPING %s AS IT IS ALREADY 
THERE" % f
++                                      continue
++                              # print "SEARCHING WHERE TO PLACE %s" % f
++                              refs2, exports2 = NM_CACHE[f]
++                              inspos = None
++                              for i in range(len(sortedfiles)):
++                                      # print "\t\tCOMPARING WITH %s" % 
sortedfiles[i]
++                                      refs1, exports1 = 
NM_CACHE[sortedfiles[i]]
++                                      for r in refs2:
++                                              if r in exports1:
++                                                      # print "%s DEPENDS ON 
%s" % (f, sortedfiles[i])
++                                                      inspos = i
++                                                      break
++                                      if inspos is not None:
++                                              break
++                              if inspos is None:
++                                      # print "%s WILL BE ADDED TO THE END" % 
f
++                                      inspos = len(sortedfiles)
++                              sortedfiles.insert(inspos, f)
++
++                      app('LINKFLAGS', sortedfiles)
++
++      if len(libsleft) > 0:
++              print "APPENDING LIBS: %s" % libsleft
++              app('LINKFLAGS', [lib_st % i for i in libsleft])
++
+ @after('apply_link')
+ def process_obj_files(self):
+       if not hasattr(self, 'obj_files'): return
+@@ -568,7 +692,7 @@ def apply_implib(self):
  @before('apply_lib_vars', 'default_link_install')
  def apply_vnum(self):
        """
@@ -12,7 +174,7 @@ BUG: https://bugzilla.samba.org/show_bug
        """
        if not getattr(self, 'vnum', '') or not 'cshlib' in self.features or 
os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'):
                return
-@@ -576,19 +576,33 @@ def apply_vnum(self):
+@@ -576,19 +700,33 @@ def apply_vnum(self):
        self.meths.remove('default_link_install')
  
        link = self.link_task
@@ -51,7 +213,7 @@ BUG: https://bugzilla.samba.org/show_bug
                self.env.append_value('LINKFLAGS', v.split())
  
        bld = self.bld
-@@ -598,11 +612,11 @@ def apply_vnum(self):
+@@ -598,11 +736,11 @@ def apply_vnum(self):
        if not path: return
  
        bld.install_as(path + os.sep + name3, node, env=self.env)
Index: patches/patch-buildtools_wafadmin_Tools_cxx_py
===================================================================
RCS file: patches/patch-buildtools_wafadmin_Tools_cxx_py
diff -N patches/patch-buildtools_wafadmin_Tools_cxx_py
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-buildtools_wafadmin_Tools_cxx_py      22 May 2014 18:39:34 
-0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+Reorder object files to minimize library interrefs count.
+Speeds up loading of library files.
+--- buildtools/wafadmin/Tools/cxx.py.orig      Mon May 19 18:30:35 2014
++++ buildtools/wafadmin/Tools/cxx.py   Mon May 19 18:31:28 2014
+@@ -97,7 +97,7 @@ cls = Task.simple_task_type('cxx', cxx_str, color='GRE
+ cls.scan = ccroot.scan
+ cls.vars.append('CXXDEPS')
+ 
+-link_str = '${LINK_CXX} ${CXXLNK_SRC_F}${SRC} 
${CXXLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}'
++link_str = '${LINK_CXX} ${CXXLNK_SRC_F} `set -- ${SRC}; test $# -gt 0 && 
lorder "$@" | tsort -q` ${CXXLNK_TGT_F}${TGT[0].abspath(env)} ${LINKFLAGS}'
+ cls = Task.simple_task_type('cxx_link', link_str, color='YELLOW', 
ext_in='.o', ext_out='.bin', shell=False)
+ cls.maxjobs = 1
+ cls.install = Utils.nada

Reply via email to