def _search_girfiles(self): ''' Search for typelibs in lib/girepository-1.0/ ''' if not self.config.variants.gi: return [] girs = [] if hasattr(self, 'files_' + self.TYPELIB_CAT): girs += getattr(self, 'files_' + self.TYPELIB_CAT) if hasattr(self, 'platform_files_' + self.TYPELIB_CAT): d = getattr(self, 'platform_files_' + self.TYPELIB_CAT) girs += d.get(self.config.target_platform, []) # Use a * for the arch in universal builds pattern = 'share/gir-1.0/%s.gir' files = shell.ls_files([pattern % x for x in girs], self.config.prefix) if not girs: # Add the architecture for universal builds pattern = 'share/gir-1.0/%s/%%s.gir' % \ self.config.target_arch files = shell.ls_files([pattern % x for x in girs], self.config.prefix) return files
def _search_typelibfiles(self, files): """ Search for typelibs in lib/girepository-1.0/ """ if not self.config.variants.gi: return [] pattern = "lib/girepository-1.0/%s.typelib" typelibs = shell.ls_files([pattern % x for x in files], self.config.prefix) if not typelibs: # Add the architecture for universal builds pattern = "lib/%s/girepository-1.0/%%s.typelib" % self.config.target_arch typelibs = shell.ls_files([pattern % x for x in files], self.config.prefix) return typelibs
async def split_library_worker(): while True: lib, thin_arch = await split_queue.get() tmpdir_thinarch = os.path.join(tmpdir, thin_arch) libprefix = os.path.split(lib)[-1].replace('.', '_') if len(archs) > 1: #should be a fat file, split only to the arch we want libprefix += '_%s_' % thin_arch lib_tmpdir = await self._split_static_lib(lib, thin_arch) else: lib_tmpdir = await self._split_static_lib(lib) if lib_tmpdir is None: # arch is not supported in the static lib, skip it status.inc_arch (thin_arch) split_queue.task_done() continue obj_files = shell.ls_files(['*.o'], lib_tmpdir) obj_dict = {} for obj_f in obj_files: obj_path = os.path.join(lib_tmpdir, obj_f) md5 = (await shell.async_call_output(['md5', '-q', obj_path], env=self.env)).split('\n')[0] md5 = '%s-%s' % (md5, os.path.getsize(obj_path)) obj_dict[obj_f] = md5 join_queues[thin_arch].put_nowait((lib, lib_tmpdir, obj_dict)) split_queue.task_done()
def _search_devel_libraries(self): devel_libs = [] for category in self.categories: if category != self.LIBS_CAT and \ not category.startswith(self.LIBS_CAT + '_'): continue pattern = 'lib/%(f)s.a lib/%(f)s.la ' if self.platform == Platform.LINUX: pattern += 'lib/%(f)s.so ' elif self.platform == Platform.WINDOWS: pattern += 'lib/%(f)s.dll.a ' pattern += 'lib/%(f)s.def ' pattern += 'lib/%(fnolib)s.lib ' elif self.platform in [Platform.DARWIN, Platform.IOS]: pattern += 'lib/%(f)s.dylib ' libsmatch = [ pattern % { 'f': x, 'fnolib': x[3:] } for x in self._get_category_files_list(category) ] devel_libs.extend(shell.ls_files(libsmatch, self.config.prefix)) return devel_libs
def _search_devel_libraries(self): devel_libs = [] for category in self.categories: if category != self.LIBS_CAT and \ not category.startswith(self.LIBS_CAT + '_'): continue pattern = 'lib/%(f)s.a lib/%(f)s.la ' if self.platform == Platform.LINUX: pattern += 'lib/%(f)s.so ' elif self.platform == Platform.WINDOWS: pattern += 'lib/%(f)s.dll.a ' pattern += 'lib/%(f)s.def ' pattern += 'lib/%(fnolib)s.lib ' elif self.platform in [Platform.DARWIN, Platform.IOS]: pattern += 'lib/%(f)s.dylib ' libsmatch = [] for x in self._get_category_files_list(category): libsmatch.append(pattern % {'f': x, 'fnolib': x[3:]}) # PDB names are derived from DLL library names (which are # arbitrary), so we must use the same search function for them. if self.platform == Platform.WINDOWS and self.can_msvc: devel_libs += find_pdb_implib(x[3:], self.config.prefix) devel_libs.extend(shell.ls_files(libsmatch, self.config.prefix)) return devel_libs
def _search_libraries(self, files): ''' Search libraries in the prefix. Unfortunately the filename might vary depending on the platform and we need to match the library name and it's extension. There is a corner case on windows where a libray might be named libfoo.dll or libfoo-1.dll ''' if len(files) == 0: return [] dlls = [] # on windows check libfoo.dll too instead of only libfoo-x.dll if self.config.target_platform == Platform.WINDOWS: pattern = '%(sdir)s/%%s.dll' % self.extensions for f in files: path = os.path.join(self.config.prefix, pattern % f) if os.path.exists(path): dlls.append(pattern % f) files = list(set(files) - set(dlls)) pattern = '%(sdir)s/%(file)s%(sext)s' libsmatch = [] for f in files: self.extensions['file'] = f libsmatch.append(pattern % self.extensions) return shell.ls_files(libsmatch, self.config.prefix) + dlls
def _search_langfiles(self, files): ''' Search for translations in share/locale/*/LC_MESSAGES/ ' ''' pattern = 'share/locale/*/LC_MESSAGES/%s.mo' return shell.ls_files([pattern % x for x in files], self.config.prefix)
def _search_files(self, files): ''' Search plugin files and arbitrary files in the prefix, doing the extension replacements, globbing, and listing directories ''' # replace extensions files_expanded = [f % self.extensions for f in files] fs = [] for f in files_expanded: if not f.endswith('.dll'): fs.append(f) continue fs += self._find_plugin_dll_files(f) # fill directories dirs = [ x for x in fs if os.path.isdir(os.path.join(self.config.prefix, x)) ] for directory in dirs: fs.remove(directory) fs.extend(self._ls_dir(os.path.join(self.config.prefix, directory))) # fill paths with pattern expansion * paths = [x for x in fs if '*' in x] if len(paths) != 0: for path in paths: fs.remove(path) fs.extend(shell.ls_files(paths, self.config.prefix)) return fs
def _search_typelibfiles(self, files): ''' Search for typelibs in lib/girepository-1.0/ ''' if not self.config.variants.gi: return [] pattern = 'lib/girepository-1.0/%s.typelib' typelibs = shell.ls_files([pattern % x for x in files], self.config.prefix) if not typelibs: # Add the architecture for universal builds pattern = 'lib/%s/girepository-1.0/%%s.typelib' % \ self.config.target_arch typelibs = shell.ls_files([pattern % x for x in files], self.config.prefix) return typelibs
def _create_framework_library(self, libraries): tmpdir = tempfile.mkdtemp() libname = os.path.basename(self.libname) # just to make sure if self.arch == Architecture.UNIVERSAL: archs = self.universal_archs else: archs = [self.arch] archs = [a if a != Architecture.X86 else 'i386' for a in archs] for thin_arch in archs: object_files_md5 = [] shell.call('mkdir -p %s' % thin_arch, tmpdir) tmpdir_thinarch = os.path.join(tmpdir, thin_arch) for lib in libraries: libprefix = os.path.split(lib)[-1].replace('.', '_') if len( archs ) > 1: #should be a fat file, split only to the arch we want libprefix += '_%s_' % thin_arch lib_tmpdir = self._split_static_lib(lib, thin_arch) else: lib_tmpdir = self._split_static_lib(lib) obj_files = shell.ls_files(['*.o'], lib_tmpdir) for obj_f in obj_files: obj_path = os.path.join(lib_tmpdir, obj_f) md5 = shell.check_call('md5 -q %s' % obj_path).split('\n')[0] md5 = '%s-%s' % (md5, os.path.getsize(obj_path)) if md5 not in object_files_md5: shell.call( 'cp %s %s' % (obj_path, '%s-%s' % (libprefix, obj_f)), tmpdir_thinarch) shell.call( 'ar -cqS %s %s-%s' % (libname, libprefix, obj_f), tmpdir_thinarch) object_files_md5.append(md5) shutil.rmtree(lib_tmpdir) shell.call('ar -s %s' % (libname), tmpdir_thinarch) files = [os.path.join(tmpdir, arch, libname) for arch in archs] self._check_duplicated_symbols(files, tmpdir) if len(archs) > 1: #merge the final libs into a fat file again shell.call( 'lipo %s -create -output %s' % (' '.join(files), self.install_name), tmpdir) else: shell.call( 'cp %s %s' % (os.path.join(tmpdir, self.arch, libname), self.install_name), tmpdir) shutil.rmtree(tmpdir)
def _search_gtkdocfiles(self): ''' Search for the gtk-doc files ''' files = [] rel_path = os.path.join('share', 'gtk-doc', 'html') abs_path = os.path.join(self.config.prefix, rel_path) doc_dirs = [s for s in os.listdir(abs_path) if self.name in s] abs_doc_dirs = [os.path.join(abs_path, d) for d in doc_dirs] for d in abs_doc_dirs: files.extend([os.path.join(rel_path, os.path.basename(d), f) for f in shell.ls_files("*", d)]) return files
def install_bin_deps(self): # FIXME: build intltool as part of the build tools bootstrap for url in WINDOWS_BIN_DEPS: temp = fix_winpath(tempfile.mkdtemp()) path = os.path.join(temp, 'download.zip') shell.download(GNOME_FTP + url, path) shell.unpack(path, self.config.toolchain_prefix) # replace /opt/perl/bin/perl in intltool files = shell.ls_files(['bin/intltool*'], self.config.toolchain_prefix) for f in files: shell.replace(os.path.join(self.config.toolchain_prefix, f), {'/opt/perl/bin/perl': '/bin/perl'}) return
def install_bin_deps(self): # On windows, we need to install first wget and pkg-config. # pkg-config can't be installed otherwise because it depends # on glib and glib depends on pkg-config for url in WINDOWS_BIN_DEPS: temp = fix_winpath(tempfile.mkdtemp()) path = os.path.join(temp, 'download.zip') shell.download(GNOME_FTP + url, path) shell.unpack(path, self.config.toolchain_prefix) # replace /opt/perl/bin/perl in intltool files = shell.ls_files(['bin/intltool*'], self.config.toolchain_prefix) for f in files: shell.replace(os.path.join(self.config.toolchain_prefix, f), {'/opt/perl/bin/perl': '/bin/perl'}) return
def _search_gtkdocfiles(self): ''' Search for the gtk-doc files ''' files = [] rel_path = os.path.join('share', 'gtk-doc', 'html') abs_path = os.path.join(self.config.prefix, rel_path) doc_dirs = [s for s in os.listdir(abs_path) if self.name in s] abs_doc_dirs = [os.path.join(abs_path, d) for d in doc_dirs] for d in abs_doc_dirs: files.extend([ os.path.join(rel_path, os.path.basename(d), f) for f in shell.ls_files("*", d) ]) return files
def _create_framework_library(self, libraries): tmpdir = tempfile.mkdtemp() libname = os.path.basename (self.libname) # just to make sure if self.arch == Architecture.UNIVERSAL: archs = self.universal_archs else: archs = [self.arch] archs = [a if a != Architecture.X86 else 'i386' for a in archs] for thin_arch in archs: object_files_md5 = [] shell.call ('mkdir -p %s' % thin_arch, tmpdir) tmpdir_thinarch = os.path.join(tmpdir, thin_arch) for lib in libraries: libprefix = os.path.split(lib)[-1].replace('.', '_') if len(archs) > 1: #should be a fat file, split only to the arch we want libprefix += '_%s_' % thin_arch lib_tmpdir = self._split_static_lib(lib, thin_arch) else: lib_tmpdir = self._split_static_lib(lib) obj_files = shell.ls_files(['*.o'], lib_tmpdir) for obj_f in obj_files: obj_path = os.path.join(lib_tmpdir, obj_f) md5 = shell.check_call('md5 -q %s' % obj_path).split('\n')[0] md5 = '%s-%s' % (md5, os.path.getsize(obj_path)) if md5 not in object_files_md5: shell.call('cp %s %s' % (obj_path, '%s-%s' % (libprefix, obj_f)), tmpdir_thinarch) shell.call('ar -cqS %s %s-%s' % (libname, libprefix, obj_f), tmpdir_thinarch) object_files_md5.append(md5) shutil.rmtree(lib_tmpdir) shell.call('ar -s %s' % (libname), tmpdir_thinarch) files = [os.path.join(tmpdir, arch, libname) for arch in archs] self._check_duplicated_symbols(files, tmpdir) if len(archs) > 1: #merge the final libs into a fat file again shell.call('lipo %s -create -output %s' % (' '.join(files), self.install_name), tmpdir) else: shell.call('cp %s %s' % (os.path.join(tmpdir, self.arch, libname), self.install_name), tmpdir) shutil.rmtree(tmpdir)
def _search_files(self, files): ''' Search plugin files and arbitrary files in the prefix, doing the extension replacements, globbing, and listing directories FIXME: Curently plugins are also searched using this, but there should be a separate system for those. ''' # replace extensions files_expanded = [f % self.extensions for f in files] fs = [] for f in files_expanded: if f.endswith('.dll') and self.using_msvc(): fs.append(self._get_msvc_dll(f)) else: fs.append(f) # Look for a PDB file and add it if self.using_msvc() and self.config.variants.debug: # We try to find a pdb file corresponding to the plugin's .a # file instead of the .dll because we want it to go into the # devel package, not the runtime package. m = self._FILES_STATIC_PLUGIN_REGEX.match(f) if m: fs += self._search_pdb_files(f, ''.join(m.groups())) # For plugins, the .la file is generated using the .pc file, but we # don't add the .pc to files_devel. It has the same name, so we can # add it using the .la entry. if f.startswith('lib/gstreamer-1.0/') and f.endswith('.la'): fs.append(self._get_plugin_pc(f)) # fill directories dirs = [ x for x in fs if os.path.isdir(os.path.join(self.config.prefix, x)) ] for directory in dirs: fs.remove(directory) fs.extend(self._ls_dir(os.path.join(self.config.prefix, directory))) # fill paths with pattern expansion * paths = [x for x in fs if '*' in x] if len(paths) != 0: for path in paths: fs.remove(path) fs.extend(shell.ls_files(paths, self.config.prefix)) return fs
def _search_files(self, files): ''' Search files in the prefix, doing the extension replacements and listing directories ''' # replace extensions fs = [f % self.extensions for f in files] # fill directories dirs = [x for x in fs if os.path.isdir(os.path.join(self.config.prefix, x))] for directory in dirs: fs.remove(directory) fs.extend(self._ls_dir(os.path.join(self.config.prefix, directory))) # fill paths with pattern expansion * paths = [x for x in fs if '*' in x] if len(paths) != 0: for path in paths: fs.remove(path) fs.extend(shell.ls_files(paths, self.config.prefix)) return fs
def _search_devel_libraries(self): devel_libs = [] for category in self.categories: if category != self.LIBS_CAT and not category.startswith(self.LIBS_CAT + "_"): continue pattern = "lib/%(f)s.a lib/%(f)s.la " if self.platform == Platform.LINUX: pattern += "lib/%(f)s.so " elif self.platform == Platform.WINDOWS: pattern += "lib/%(f)s.dll.a " pattern += "lib/%(f)s.def " pattern += "lib/%(fnolib)s.lib " elif self.platform in [Platform.DARWIN, Platform.IOS]: pattern += "lib/%(f)s.dylib " libsmatch = [pattern % {"f": x, "fnolib": x[3:]} for x in self._get_category_files_list(category)] devel_libs.extend(shell.ls_files(libsmatch, self.config.prefix)) return devel_libs
def _search_devel_libraries(self): if self.runtime_dep: return [] devel_libs = [] for category in self.categories: if category != self.LIBS_CAT and \ not category.startswith(self.LIBS_CAT + '_'): continue pattern = '' if self.library_type != LibraryType.NONE: pattern += 'lib/%(f)s.la ' if self.library_type in (LibraryType.BOTH, LibraryType.STATIC): pattern += 'lib/%(f)s.a ' if self.library_type in (LibraryType.BOTH, LibraryType.SHARED): if self.platform == Platform.LINUX: pattern += 'lib/%(f)s.so ' elif self.platform == Platform.WINDOWS: pattern += 'lib/%(f)s.dll.a ' pattern += 'lib/%(f)s.def ' pattern += 'lib/%(fnolib)s.lib ' elif self.platform in [Platform.DARWIN, Platform.IOS]: pattern += 'lib/%(f)s.dylib ' libsmatch = [] for x in self._get_category_files_list(category): libsmatch.append(pattern % {'f': x, 'fnolib': x[3:]}) # PDB names are derived from DLL library names (which are # arbitrary), so we must use the same search function for them. if self.platform != Platform.WINDOWS: continue if not self.using_msvc() or self.config.variants.nodebug: continue if self.library_type in (LibraryType.STATIC, LibraryType.NONE): continue devel_libs += find_pdb_implib(self.config, x[3:], self.config.prefix) devel_libs.extend(shell.ls_files(libsmatch, self.config.prefix)) return devel_libs
def _search_devel_libraries(self): devel_libs = [] for category in self.categories: if category != self.LIBS_CAT and \ not category.startswith(self.LIBS_CAT + '_'): continue; pattern = 'lib/%(f)s.a lib/%(f)s.la ' if self.platform == Platform.LINUX: pattern += 'lib/%(f)s.so ' elif self.platform == Platform.WINDOWS: pattern += 'lib/%(f)s.dll.a ' pattern += 'lib/%(f)s.def ' pattern += 'lib/%(fnolib)s.lib ' elif self.platform == Platform.DARWIN: pattern += 'lib/%(f)s.dylib ' libsmatch = [pattern % {'f':x, 'fnolib': x[3:]} for x in \ self._get_category_files_list(category)] devel_libs.extend(shell.ls_files(libsmatch, self.config.prefix)) return devel_libs
def _search_files(self, files): ''' Search plugin files and arbitrary files in the prefix, doing the extension replacements, globbing, and listing directories ''' # replace extensions files_expanded = [f % self.extensions for f in files] fs = [] for f in files_expanded: if not f.endswith('.dll'): fs.append(f) continue # Plugins DLLs are required to be simple: libfoo.dll or foo.dll if not f.startswith('lib'): raise AssertionError( 'Plugin files must start with "lib": {!r}'.format(f)) if (Path(self.config.prefix) / f).is_file(): # libfoo.dll, built with MinGW fs.append(f) elif (Path(self.config.prefix) / f[3:]).is_file(): # foo.dll, built with MSVC fs.append(f[3:]) # foo.pdb fs.append(f[3:-3] + 'pdb') # fill directories dirs = [ x for x in fs if os.path.isdir(os.path.join(self.config.prefix, x)) ] for directory in dirs: fs.remove(directory) fs.extend(self._ls_dir(os.path.join(self.config.prefix, directory))) # fill paths with pattern expansion * paths = [x for x in fs if '*' in x] if len(paths) != 0: for path in paths: fs.remove(path) fs.extend(shell.ls_files(paths, self.config.prefix)) return fs
def _search_files(self, files): ''' Search plugin files and arbitrary files in the prefix, doing the extension replacements, globbing, and listing directories ''' # replace extensions files_expanded = [f % self.extensions for f in files] fs = [] for f in files_expanded: if not f.endswith('.dll'): fs.append(f) continue # Plugins DLLs are required to be simple: libfoo.dll or foo.dll if not f.startswith('lib'): raise AssertionError('Plugin files must start with "lib": {!r}'.format(f)) if (Path(self.config.prefix) / f).is_file(): # libfoo.dll, built with MinGW fs.append(f) elif (Path(self.config.prefix) / f[3:]).is_file(): # foo.dll, built with MSVC fs.append(f[3:]) # foo.pdb fs.append(f[3:-3] + 'pdb') # fill directories dirs = [x for x in fs if os.path.isdir(os.path.join(self.config.prefix, x))] for directory in dirs: fs.remove(directory) fs.extend(self._ls_dir(os.path.join(self.config.prefix, directory))) # fill paths with pattern expansion * paths = [x for x in fs if '*' in x] if len(paths) != 0: for path in paths: fs.remove(path) fs.extend(shell.ls_files(paths, self.config.prefix)) return fs
def _create_framework_library(self, libraries): tmpdir = tempfile.mkdtemp() libname = os.path.basename (self.libname) # just to make sure if self.arch == Architecture.UNIVERSAL: archs = self.universal_archs else: archs = [self.arch] archs = [a if a != Architecture.X86 else 'i386' for a in archs] for thin_arch in archs: shell.call ('mkdir -p %s' % thin_arch, tmpdir) tmpdir_thinarch = os.path.join(tmpdir, thin_arch) for lib in libraries: libprefix = os.path.split(lib)[-1].replace('.', '_') if len(archs) > 1: #should be a fat file, split only to the arch we want libprefix += '_%s_' % thin_arch lib_tmpdir = self._split_static_lib(lib, thin_arch) else: lib_tmpdir = self._split_static_lib(lib) obj_files = shell.ls_files(['*.o'], lib_tmpdir) for obj_f in obj_files: shell.call('cp %s %s' % (os.path.join(lib_tmpdir, obj_f), '%s-%s' % (libprefix, obj_f)), tmpdir_thinarch) shell.call('ar -cqS %s %s-%s' % (libname, libprefix, obj_f), tmpdir_thinarch) shell.call('ar -s %s' % (libname), tmpdir_thinarch) if len(archs) > 1: #merge the final libs into a fat file again shell.call('lipo %s -create -output %s' % (' '.join([os.path.join(tmpdir, arch, libname) for arch in archs]), self.install_name), tmpdir) else: shell.call('cp %s %s' % (os.path.join(tmpdir, self.arch, libname), self.install_name), tmpdir)
def fix_bin_deps(self): # replace /opt/perl/bin/perl in intltool files = shell.ls_files(['bin/intltool*'], self.prefix) for f in files: shell.replace(os.path.join(self.prefix, f), {'/opt/perl/bin/perl': '/bin/perl'})
def _create_framework_library(self, libraries): tmpdir = tempfile.mkdtemp() libname = os.path.basename(self.libname) # just to make sure if self.arch == Architecture.UNIVERSAL: archs = self.universal_archs else: archs = [self.arch] archs = [a if a != Architecture.X86 else 'i386' for a in archs] for thin_arch in archs: object_files_md5 = [] shell.call('mkdir -p %s' % thin_arch, tmpdir) tmpdir_thinarch = os.path.join(tmpdir, thin_arch) for lib in libraries: libprefix = os.path.split(lib)[-1].replace('.', '_') if len( archs ) > 1: #should be a fat file, split only to the arch we want libprefix += '_%s_' % thin_arch lib_tmpdir = self._split_static_lib(lib, thin_arch) else: lib_tmpdir = self._split_static_lib(lib) obj_files = shell.ls_files(['*.o'], lib_tmpdir) target_objs = [] for obj_f in obj_files: obj_path = os.path.join(lib_tmpdir, obj_f) md5 = shell.check_call('md5 -q %s' % obj_path).split('\n')[0] md5 = '%s-%s' % (md5, os.path.getsize(obj_path)) if md5 not in object_files_md5: target_name = '%s-%s' % (libprefix, obj_f) try: # Hard link source file to the target name os.link(obj_path, tmpdir_thinarch + '/' + target_name) except: # Fall back to cp if hard link doesn't work for any reason shell.call('cp %s %s' % (obj_path, target_name), tmpdir_thinarch) # If we have a duplicate object, commit any collected ones if target_name in target_objs: m.warning("Committing %d objects due to dup %s" % (len(target_objs), target_name)) shell.call( 'ar -cqS %s %s' % (libname, " ".join(target_objs)), tmpdir_thinarch) target_objs = [] target_objs.append(target_name) object_files_md5.append(md5) # Put all the collected target_objs in the archive. cmdline limit is 262k args on OSX. if len(target_objs): shell.call( 'ar -cqS %s %s' % (libname, " ".join(target_objs)), tmpdir_thinarch) shutil.rmtree(lib_tmpdir) shell.call('ar -s %s' % (libname), tmpdir_thinarch) files = [os.path.join(tmpdir, arch, libname) for arch in archs] self._check_duplicated_symbols(files, tmpdir) if len(archs) > 1: #merge the final libs into a fat file again shell.call( 'lipo %s -create -output %s' % (' '.join(files), self.install_name), tmpdir) else: shell.call( 'cp %s %s' % (os.path.join(tmpdir, self.arch, libname), self.install_name), tmpdir) shutil.rmtree(tmpdir)
def _create_framework_library(self, libraries): tmpdir = tempfile.mkdtemp() libname = os.path.basename (self.libname) # just to make sure if self.arch == Architecture.UNIVERSAL: archs = self.universal_archs else: archs = [self.arch] archs = [a if a != Architecture.X86 else 'i386' for a in archs] for thin_arch in archs: object_files_md5 = [] shell.call ('mkdir -p %s' % thin_arch, tmpdir) tmpdir_thinarch = os.path.join(tmpdir, thin_arch) for lib in libraries: libprefix = os.path.split(lib)[-1].replace('.', '_') if len(archs) > 1: #should be a fat file, split only to the arch we want libprefix += '_%s_' % thin_arch lib_tmpdir = self._split_static_lib(lib, thin_arch) else: lib_tmpdir = self._split_static_lib(lib) obj_files = shell.ls_files(['*.o'], lib_tmpdir) target_objs = [] for obj_f in obj_files: obj_path = os.path.join(lib_tmpdir, obj_f) md5 = shell.check_call('md5 -q %s' % obj_path).split('\n')[0] md5 = '%s-%s' % (md5, os.path.getsize(obj_path)) if md5 not in object_files_md5: target_name = '%s-%s' % (libprefix, obj_f) try: # Hard link source file to the target name os.link(obj_path, tmpdir_thinarch + '/' + target_name) except: # Fall back to cp if hard link doesn't work for any reason shell.call('cp %s %s' % (obj_path, target_name), tmpdir_thinarch) # If we have a duplicate object, commit any collected ones if target_name in target_objs: m.warning ("Committing %d objects due to dup %s" % (len (target_objs), target_name)) shell.call('ar -cqS %s %s' % (libname, " ".join (target_objs)), tmpdir_thinarch) target_objs = [] target_objs.append (target_name) object_files_md5.append(md5) # Put all the collected target_objs in the archive. cmdline limit is 262k args on OSX. if len(target_objs): shell.call('ar -cqS %s %s' % (libname, " ".join (target_objs)), tmpdir_thinarch) shutil.rmtree(lib_tmpdir) shell.call('ar -s %s' % (libname), tmpdir_thinarch) files = [os.path.join(tmpdir, arch, libname) for arch in archs] self._check_duplicated_symbols(files, tmpdir) if len(archs) > 1: #merge the final libs into a fat file again shell.call('lipo %s -create -output %s' % (' '.join(files), self.install_name), tmpdir) else: shell.call('cp %s %s' % (os.path.join(tmpdir, self.arch, libname), self.install_name), tmpdir) shutil.rmtree(tmpdir)