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