import msys
from distutils.extension import read_setup_file
import os
import re
import sys
prebuilt_dir = 'prebuilt'
lib_subdir = 'lib'
class MakePrebuiltError(Exception):
pass
def file_copy(src, dest):
if os.path.isdir(dest):
dest = os.path.join(dest, os.path.split(src)[1])
s = open(src, 'rb')
try:
d = open(dest, 'wb')
try:
d.write(s.read())
print "%s => %s" % (src, dest)
finally:
d.close()
finally:
s.close()
def find_import_libraries(path, roots):
match = re.compile(r'lib(%s)\.dll\.a$' % '|'.join(roots)).match
return [name for name in os.listdir(path) if match(name) is not None]
def copy_dir(src, dest):
if dest == '.':
ignore, dest = os.path.split(src)
if src == dest:
raise IOError("%s: Source and destination are identical" % src)
mkdir(dest)
for name in os.listdir(src):
src_path = os.path.join(src, name)
if os.path.isfile(src_path):
file_copy(src_path, os.path.join(dest, name))
def confirm(message):
"ask a yes/no question, return result"
reply = msys.msys_raw_input("\n%s [Y/n]:" % message)
if reply and reply[0].lower() == 'n':
return 0
return 1
created_dirs = set()
def mkdir(path):
path = os.path.abspath(path)
if path in created_dirs:
pass
elif not os.path.exists(path):
os.mkdir(path)
created_dirs.add(path)
elif not os.path.isdir(path):
raise MakePrebuiltError("%s is not a directory" % path)
def main(dest_dir=None):
# Top level directories.
if dest_dir is None:
dest_dir = prebuilt_dir
if re.match(r'([A-Za-z]:){0,1}[^"<>:|?*]+$', dest_dir) is None:
print "Invalid directory path name %s" % dest_dir
return 1
dest_dir = os.path.abspath(dest_dir)
if os.path.isdir(dest_dir):
if not confirm("Directory %s already exists;\ncontinue" % dest_dir):
return 1
mkdir(dest_dir)
m = msys.Msys()
src_dir = os.path.join(m.msys_root, 'local')
prebuilt_template = os.path.abspath('prebuilt-template')
dest_lib_dir = os.path.join(dest_dir, lib_subdir)
# Read setup file.
src_file = os.path.join(prebuilt_template, 'Setup_Win.in')
file_copy(src_file, dest_dir)
deps = read_setup_file(src_file)
setup_in = open(src_file)
match = re.compile('[A-Z_][A-Z0-9_]* *=(.*)').match
header_dir_pat = re.compile(' -I([^ ]+)')
lib_pat = re.compile(' -l([^ ]+)')
macros = []
for line in setup_in:
matches = match(line)
if matches is not None:
flags = matches.group(1)
header_dirs = header_dir_pat.findall(flags)
libs = lib_pat.findall(flags)
macros.append((header_dirs, libs))
# Copy DLLs.
src_bin_dir = os.path.join(src_dir, 'bin')
have_dlls = set()
for dep in deps:
path_elements = dep.library_dirs[0].split('/') # / required by setup.
dll_name = path_elements[-1]
src_dll_path = os.path.join(src_bin_dir, dll_name)
if os.path.exists(src_dll_path):
if path_elements[0] == '.':
path_elements = path_elements[2:]
else:
path_elements = path_elements[1:]
dest_dll_dir = dest_dir
for dir_name in path_elements[:-1]:
dest_dll_dir = os.path.join(dest_dll_dir, dir_name)
mkdir(dest_dll_dir)
file_copy(os.path.join(src_bin_dir, dll_name),
os.path.join(dest_dll_dir, dll_name))
have_dlls.add(dep.name[8:])
# Copy required import libraries only.
copied_files = set()
src_lib_dir = os.path.join(src_dir, 'lib')
mkdir(dest_lib_dir)
for ignore, libs in macros:
use = False
for lib in libs:
if lib in have_dlls:
use = True
break
if use and lib not in copied_files:
copied_files.add(lib)
lib_name = 'lib%s.dll.a' % lib
src_lib_path = os.path.join(src_lib_dir, lib_name)
if not os.path.exists(src_lib_path):
print "Missing import library %s" % lib_name
return 1
file_copy(src_lib_path, os.path.join(dest_lib_dir, lib_name))
# Copy required header directories only.
copied_dirs = set()
for header_dirs, libs in macros:
use = False
for lib in libs:
if lib in have_dlls:
use = True
break
if use:
for header_dir in header_dirs:
path_elements = header_dir.split('/')
if path_elements[0] == '.':
path_elements = path_elements[2:]
else:
path_elements = path_elements[1:]
src_header_dir = os.path.join(src_dir, *path_elements)
if not os.path.exists(src_header_dir):
print "Missing include directory %s" % src_header_dir
return 1
dest_header_dir = dest_dir
for dir_name in path_elements:
dest_header_dir = os.path.join(dest_header_dir, dir_name)
mkdir(dest_header_dir)
if not src_header_dir in copied_dirs:
copy_dir(src_header_dir, dest_header_dir)
copied_dirs.add(src_header_dir)
if 'SDL' in have_dlls:
# For MSVC use SDL_config_win32.h in place of configure
# generated SDL_config.h.
file_copy(
os.path.join(src_dir, 'include', 'SDL', 'SDL_config_win32.h'),
os.path.join(dest_dir, 'include', 'SDL', 'SDL_config.h'))
# msvcr71.dll linking support.
src_msvcr71_dir = os.path.join(src_dir, 'lib', 'msvcr71')
dest_msvcr71_dir = os.path.join(dest_dir, 'lib', 'msvcr71')
copy_dir(src_msvcr71_dir, dest_msvcr71_dir)
# Def file bat.
make_defs = open(os.path.join(dest_lib_dir, 'MakeDefs.bat'), 'w')
try:
make_defs.write('@echo off\n'
'rem Make .def files needed for .lib file creation.\n'
'rem Requires pexports.exe on the search path\n'
'rem (found in altbinutils-pe as SourceForge,\n'
'rem http://sourceforge.net/projects/mingwrep/).\n\n')
for dep in deps:
dll_name = os.path.split(dep.library_dirs[0])[1]
lib = dep.name[8:]
lib_name = 'lib%s.dll.a' % lib
if os.path.exists(os.path.join(dest_lib_dir, lib_name)):
start = ''
else:
start = 'rem '
make_defs.write('%spexports %s >%s.def\n' %
(start, dll_name, lib))
finally:
make_defs.close()
# Lib import files bat.
make_libs = open(os.path.join(dest_lib_dir, 'MakeLibs.bat'), 'w')
try:
make_libs.write('@echo off\n'
'rem Make .lib import libraries.\n'
'rem Requires Visual C++ Studio or Toolkit.\n'
'rem VCVARS32.BAT (VCVARS64.BAT (?) for 64 bit build)\n'
'rem must be run first to use LIB.EXE.\n\n')
for dep in deps:
dll_name = os.path.split(dep.library_dirs[0])[1]
lib = dep.name[8:]
lib_name = 'lib%s.dll.a' % lib
if os.path.exists(os.path.join(dest_lib_dir, lib_name)):
start = ''
else:
start = 'rem '
make_libs.write('%sLIB.EXE /NOLOGO /DEF:%s.def /MACHINE:IX86 /OUT:%s.lib\n' %
(start, lib, lib))
finally:
make_libs.close()
# Top level make batch file for 32 bit build.
file_copy(os.path.join(prebuilt_template, 'Make32.bat'), dest_lib_dir)
return 0
if __name__ =='__main__':
dest_dir = None
if len(sys.argv) > 1:
dest_dir = sys.argv[1]
try:
sys.exit(main(dest_dir))
except MakePrebuiltError, e:
print "*** %s; execution halted" % e
sys.exit(1)
|