2010-04-11 02:22:15 +00:00
|
|
|
# TODO: split this file up, it's too long!
|
|
|
|
|
2010-06-18 22:50:15 +00:00
|
|
|
import sys, os, ConfigParser, subprocess, shutil, re
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
class InternalCommands:
|
|
|
|
|
|
|
|
project = 'synergy-plus'
|
|
|
|
setup_version = 3
|
|
|
|
website_url = 'http://code.google.com/p/synergy-plus'
|
|
|
|
|
|
|
|
this_cmd = 'hm'
|
|
|
|
cmake_cmd = 'cmake'
|
|
|
|
|
|
|
|
make_cmd = 'make'
|
|
|
|
xcodebuild_cmd = 'xcodebuild'
|
|
|
|
|
|
|
|
source_dir = '..' # Source, relative to build.
|
|
|
|
cmake_dir = 'cmake'
|
|
|
|
bin_dir = 'bin'
|
|
|
|
|
|
|
|
sln_filename = '%s.sln' % project
|
|
|
|
xcodeproj_filename = '%s.xcodeproj' % project
|
|
|
|
config_filename = '%s.cfg' % this_cmd
|
|
|
|
|
|
|
|
# try_chdir(...) and restore_chdir() will use this
|
|
|
|
prevdir = ''
|
2010-06-15 22:29:32 +00:00
|
|
|
|
|
|
|
# by default, no index specified as arg
|
2010-06-15 22:41:47 +00:00
|
|
|
generator_id = None
|
2010-06-15 22:29:32 +00:00
|
|
|
|
|
|
|
# by default, prompt user for input
|
|
|
|
no_prompts = False
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
win32_generators = {
|
|
|
|
'1' : 'Visual Studio 10',
|
|
|
|
'2' : 'Visual Studio 10 Win64',
|
|
|
|
'3' : 'Visual Studio 9 2008',
|
|
|
|
'4' : 'Visual Studio 9 2008 Win64',
|
|
|
|
'5' : 'Visual Studio 8 2005',
|
|
|
|
'6' : 'Visual Studio 8 2005 Win64',
|
|
|
|
'10' : 'CodeBlocks - MinGW Makefiles',
|
|
|
|
'11' : 'CodeBlocks - Unix Makefiles',
|
|
|
|
'12': 'Eclipse CDT4 - MinGW Makefiles',
|
|
|
|
'13': 'Eclipse CDT4 - NMake Makefiles',
|
|
|
|
'14': 'Eclipse CDT4 - Unix Makefiles',
|
|
|
|
'15': 'MinGW Makefiles',
|
|
|
|
'16': 'NMake Makefiles',
|
|
|
|
'17': 'Unix Makefiles',
|
|
|
|
'18': 'Borland Makefiles',
|
|
|
|
'19': 'MSYS Makefiles',
|
|
|
|
'20': 'Watcom WMake',
|
|
|
|
}
|
|
|
|
|
|
|
|
unix_generators = {
|
|
|
|
'1' : 'Unix Makefiles',
|
|
|
|
'2' : 'CodeBlocks - Unix Makefiles',
|
|
|
|
'3' : 'Eclipse CDT4 - Unix Makefiles',
|
|
|
|
'4' : 'KDevelop3',
|
|
|
|
'5' : 'KDevelop3 - Unix Makefiles',
|
|
|
|
}
|
|
|
|
|
|
|
|
darwin_generators = {
|
|
|
|
'1' : 'Xcode',
|
|
|
|
'2' : 'Unix Makefiles',
|
|
|
|
'3' : 'CodeBlocks - Unix Makefiles',
|
|
|
|
'4' : 'Eclipse CDT4 - Unix Makefiles',
|
|
|
|
'5' : 'KDevelop3',
|
|
|
|
'6' : 'KDevelop3 - Unix Makefiles',
|
|
|
|
}
|
|
|
|
|
|
|
|
def config_filepath(self):
|
|
|
|
return '%s/%s' % (self.bin_dir, self.config_filename)
|
|
|
|
|
|
|
|
def sln_filepath(self):
|
|
|
|
return '%s\%s' % (self.bin_dir, self.sln_filename)
|
|
|
|
|
|
|
|
def xcodeproj_filepath(self):
|
|
|
|
return '%s/%s' % (self.bin_dir, self.xcodeproj_filename)
|
|
|
|
|
|
|
|
def usage(self):
|
|
|
|
app = sys.argv[0]
|
2010-06-15 22:29:32 +00:00
|
|
|
print ('Usage: %s <command> [-g <index>|-v|--no-prompts|<command-options>]\n'
|
2010-04-11 02:22:15 +00:00
|
|
|
'\n'
|
|
|
|
'Replace [command] with one of:\n'
|
|
|
|
' about Show information about this script\n'
|
|
|
|
' setup Runs the initial setup for this script\n'
|
|
|
|
' conf Runs cmake (generates project files)\n'
|
|
|
|
' open Attempts to open the generated project file\n'
|
|
|
|
' build Builds using the platform build chain\n'
|
|
|
|
' clean Cleans using the platform build chain\n'
|
|
|
|
' kill Kills all synergy processes (run as admin)\n'
|
|
|
|
' update Updates the source code from repository\n'
|
|
|
|
' revision Display the current source code revision\n'
|
|
|
|
' package Create a distribution package (e.g. tar.gz)\n'
|
|
|
|
' install Installs the program\n'
|
|
|
|
' reformat Reformat .cpp and .h files using AStyle\n'
|
|
|
|
' usage Shows the help screen\n'
|
|
|
|
'\n'
|
2010-06-15 22:29:32 +00:00
|
|
|
'Example: %s build -g 3'
|
2010-04-11 02:22:15 +00:00
|
|
|
) % (app, app)
|
2010-06-15 22:29:32 +00:00
|
|
|
|
|
|
|
def configure(self):
|
2010-06-16 18:55:06 +00:00
|
|
|
self.configure_internal()
|
|
|
|
|
|
|
|
print ('Configure complete!\n\n'
|
|
|
|
'Open project now: %s open\n'
|
|
|
|
'Command line build: %s build'
|
|
|
|
) % (self.this_cmd, self.this_cmd)
|
|
|
|
|
|
|
|
def configure_internal(self):
|
|
|
|
|
|
|
|
# ensure latest setup and do not ask config for generator (only fall
|
|
|
|
# back to prompt if not specified as arg)
|
|
|
|
self.ensure_setup_latest()
|
|
|
|
|
|
|
|
# ensure that we have access to cmake
|
|
|
|
_cmake_cmd = self.persist_cmake()
|
|
|
|
|
|
|
|
# now that we know we've got the latest setup, we can ask the config
|
|
|
|
# file for the generator (but again, we only fall back to this if not
|
|
|
|
# specified as arg).
|
|
|
|
generator = self.get_generator_from_config()
|
|
|
|
|
|
|
|
if generator != '':
|
|
|
|
cmake_args = '%s -G "%s"' % (self.source_dir, generator)
|
2010-04-11 02:22:15 +00:00
|
|
|
else:
|
2010-06-16 18:55:06 +00:00
|
|
|
cmake_args = self.source_dir
|
|
|
|
|
|
|
|
cmake_cmd_string = '%s %s' % (_cmake_cmd, cmake_args)
|
|
|
|
|
|
|
|
print "Configuring with CMake (%s)..." % cmake_cmd_string
|
|
|
|
|
|
|
|
# Run from build dir so we have an out-of-source build.
|
|
|
|
self.try_chdir(self.bin_dir)
|
|
|
|
err = os.system(cmake_cmd_string)
|
|
|
|
self.restore_chdir()
|
|
|
|
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('CMake encountered error: ' + str(err))
|
|
|
|
|
|
|
|
self.set_conf_run()
|
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def persist_cmake(self):
|
|
|
|
if sys.platform == 'win32':
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-18 22:50:15 +00:00
|
|
|
version = '>= 2.8.0'
|
2010-04-11 02:22:15 +00:00
|
|
|
found_cmd = ''
|
|
|
|
for test_cmd in (self.cmake_cmd, r'tool\cmake\bin\%s' % self.cmake_cmd):
|
2010-04-22 22:16:23 +00:00
|
|
|
print 'Testing for CMake version %s by running `%s`...' % (version, test_cmd)
|
2010-04-11 02:22:15 +00:00
|
|
|
p = subprocess.Popen([test_cmd, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
|
|
stdout, stderr = p.communicate()
|
2010-06-18 22:50:15 +00:00
|
|
|
m = re.search('cmake version (2\.8\.\d+)', stdout)
|
|
|
|
if p.returncode == 0 and m:
|
2010-04-11 02:22:15 +00:00
|
|
|
# found one that works, hurrah!
|
2010-06-18 22:50:15 +00:00
|
|
|
print 'Found valid CMake version %s' % m.group(1)
|
2010-04-11 02:22:15 +00:00
|
|
|
found_cmd = test_cmd
|
|
|
|
# HACK: gotta go out so just hacking this for now
|
|
|
|
if found_cmd == r'tool\cmake\bin\%s' % self.cmake_cmd:
|
|
|
|
found_cmd = r'..\tool\cmake\bin\%s' % self.cmake_cmd
|
|
|
|
break
|
|
|
|
|
|
|
|
if not found_cmd:
|
2010-06-15 22:29:32 +00:00
|
|
|
|
|
|
|
found_cmake = False
|
|
|
|
|
|
|
|
# if prompting allowed
|
|
|
|
if not self.no_prompts:
|
|
|
|
msg = 'CMake 2.8.0 not installed. Auto download now? [Y/n]'
|
|
|
|
print msg,
|
|
|
|
yn = raw_input()
|
|
|
|
|
|
|
|
# if response was anyting but no
|
|
|
|
if yn not in ['n', 'N']:
|
|
|
|
if not os.path.exists('tool'):
|
|
|
|
os.mkdir('tool')
|
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
err = os.system(r'svn checkout https://synergy-plus.googlecode.com/svn/tools/win/cmake tool\cmake')
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('Unable to get cmake from repository with error code code: ' + str(err))
|
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
found_cmd = r'..\tool\cmake\bin\%s' % self.cmake_cmd
|
|
|
|
found_cmake = True
|
|
|
|
|
|
|
|
# if cmake was not found
|
|
|
|
if not found_cmake:
|
2010-06-16 18:55:06 +00:00
|
|
|
raise Exception('Cannot continue without CMake, exiting.')
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
return found_cmd
|
|
|
|
else:
|
|
|
|
return self.cmake_cmd
|
|
|
|
|
|
|
|
def build(self, mode = None):
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
self.ensure_setup_latest()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if not self.has_conf_run():
|
2010-06-16 18:55:06 +00:00
|
|
|
self.configure_internal()
|
2010-04-11 02:22:15 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
generator = self.get_generator_from_config()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if generator == "Unix Makefiles":
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
print 'Building with GNU Make...'
|
|
|
|
self.try_chdir(self.bin_dir)
|
2010-06-02 07:36:47 +00:00
|
|
|
err = os.system(self.make_cmd)
|
2010-04-11 02:22:15 +00:00
|
|
|
self.restore_chdir()
|
2010-06-16 18:55:06 +00:00
|
|
|
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('GNU Make failed: ' + str(err))
|
2010-04-11 02:22:15 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
elif generator.startswith('Visual Studio'):
|
2010-04-11 02:22:15 +00:00
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
self.run_vcbuild(generator, mode)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
elif generator == 'Xcode':
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
print 'Building with Xcode...'
|
|
|
|
self.try_chdir(self.bin_dir)
|
2010-06-05 10:28:41 +00:00
|
|
|
err = os.system(self.xcodebuild_cmd)
|
2010-04-11 02:22:15 +00:00
|
|
|
self.restore_chdir()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
if err != 0:
|
|
|
|
raise Exception('Xcode failed:', err)
|
2010-04-11 02:22:15 +00:00
|
|
|
|
2010-04-10 21:16:10 +00:00
|
|
|
else:
|
2010-06-16 18:55:06 +00:00
|
|
|
raise Exception('Not supported with generator: ' + generator)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def clean(self, mode = None):
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
generator = self.get_generator_from_config()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if generator == "Unix Makefiles":
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
print 'Cleaning with GNU Make...'
|
|
|
|
self.try_chdir(self.bin_dir)
|
2010-06-02 07:36:47 +00:00
|
|
|
err = os.system(self.make_cmd + ' clean')
|
2010-04-11 02:22:15 +00:00
|
|
|
self.restore_chdir()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
if err != 0:
|
|
|
|
raise Exception('GNU Make failed: ' + str(err))
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
# special case for version 10, use new /target:clean
|
2010-04-11 02:22:15 +00:00
|
|
|
elif generator.startswith('Visual Studio 10'):
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
self.run_vcbuild(generator, mode, '/target:clean')
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
# any other version of visual studio, use /clean
|
|
|
|
elif generator.startswith('Visual Studio'):
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
self.run_vcbuild(generator, mode, '/clean')
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
elif generator == 'Xcode':
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
print 'Cleaning with Xcode...'
|
|
|
|
self.try_chdir(self.bin_dir)
|
|
|
|
err = os.system(xcodebuild_cmd + ' clean')
|
|
|
|
self.restore_chdir()
|
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
if err != 0:
|
|
|
|
raise Exception('Xcode failed:', err)
|
2010-04-11 02:22:15 +00:00
|
|
|
|
2010-04-10 21:16:10 +00:00
|
|
|
else:
|
2010-06-16 18:55:06 +00:00
|
|
|
raise Exception('Not supported with generator: ' + generator)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def open(self):
|
2010-06-15 22:29:32 +00:00
|
|
|
generator = self.get_generator_from_config()
|
2010-04-11 02:22:15 +00:00
|
|
|
if generator.startswith('Visual Studio'):
|
|
|
|
print 'Opening with %s...' % generator
|
|
|
|
self.open_internal(self.sln_filepath())
|
2010-06-16 18:55:06 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
elif generator.startswith('Xcode'):
|
|
|
|
print 'Opening with %s...' % generator
|
|
|
|
self.open_internal(xcodeproj_filepath(), 'open')
|
2010-06-16 18:55:06 +00:00
|
|
|
|
2010-04-10 21:16:10 +00:00
|
|
|
else:
|
2010-06-16 18:55:06 +00:00
|
|
|
raise Exception('Not supported with generator: ' + generator)
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def update(self):
|
|
|
|
print "Running Subversion update..."
|
2010-06-16 18:55:06 +00:00
|
|
|
err = os.system('svn update')
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('Could not update from repository with error code code: ' + str(err))
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def revision(self):
|
|
|
|
# While this doesn't print out the revision specifically, it will do.
|
2010-06-16 18:55:06 +00:00
|
|
|
err = os.system('svn info')
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('Could not get revision info with error code code: ' + str(err))
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def kill(self):
|
|
|
|
if sys.platform == 'win32':
|
2010-06-16 18:55:06 +00:00
|
|
|
return os.system('taskkill /F /FI "IMAGENAME eq synergy*"')
|
2010-04-10 21:16:10 +00:00
|
|
|
else:
|
2010-06-16 18:55:06 +00:00
|
|
|
raise Exception('Not implemented for platform: ' + sys.platform)
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def package(self, type):
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
# Package is supported by default.
|
|
|
|
package_unsupported = False
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if type == None:
|
|
|
|
self.package_usage()
|
|
|
|
elif type == 'src':
|
|
|
|
if sys.platform in ['linux2', 'darwin']:
|
2010-06-16 18:55:06 +00:00
|
|
|
self.package_run('make package_source')
|
2010-04-11 02:22:15 +00:00
|
|
|
else:
|
|
|
|
package_unsupported = True
|
|
|
|
elif type == 'rpm':
|
|
|
|
if sys.platform == 'linux2':
|
2010-06-16 18:55:06 +00:00
|
|
|
self.package_run('cpack -G RPM')
|
2010-04-11 02:22:15 +00:00
|
|
|
else:
|
|
|
|
package_unsupported = True
|
|
|
|
elif type == 'deb':
|
|
|
|
if sys.platform == 'linux2':
|
2010-06-16 18:55:06 +00:00
|
|
|
self.package_run('cpack -G DEB')
|
2010-04-11 02:22:15 +00:00
|
|
|
else:
|
|
|
|
package_unsupported = True
|
|
|
|
elif type == 'win':
|
|
|
|
if sys.platform == 'win32':
|
2010-06-16 18:55:06 +00:00
|
|
|
self.package_run('cpack -G NSIS')
|
2010-04-11 02:22:15 +00:00
|
|
|
else:
|
|
|
|
package_unsupported = True
|
|
|
|
elif type == 'mac':
|
|
|
|
if sys.platform == 'darwin':
|
2010-06-16 18:55:06 +00:00
|
|
|
self.package_run('cpack -G PackageMaker')
|
2010-04-11 02:22:15 +00:00
|
|
|
else:
|
|
|
|
package_unsupported = True
|
2010-04-10 21:16:10 +00:00
|
|
|
else:
|
2010-04-11 02:22:15 +00:00
|
|
|
print 'Not yet implemented: package %s' % type
|
|
|
|
|
|
|
|
if package_unsupported:
|
2010-06-16 18:55:06 +00:00
|
|
|
raise Exception(
|
|
|
|
("Package type, '%s' is not supported for platform, '%s'")
|
|
|
|
% (type, sys.platform))
|
|
|
|
|
|
|
|
def package_run(self, command):
|
2010-04-11 02:22:15 +00:00
|
|
|
self.try_chdir(self.bin_dir)
|
2010-06-16 18:55:06 +00:00
|
|
|
err = os.system(command)
|
2010-04-11 02:22:15 +00:00
|
|
|
self.restore_chdir()
|
2010-06-16 18:55:06 +00:00
|
|
|
if err != 0:
|
|
|
|
raise Exception('Package failed: ' + str(err))
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def package_usage(self):
|
|
|
|
print ('Usage: %s package [package-type]\n'
|
|
|
|
'\n'
|
|
|
|
'Replace [package-type] with one of:\n'
|
|
|
|
' src .tar.gz source (Posix only)\n'
|
|
|
|
' rpm .rpm package (Red Hat)\n'
|
|
|
|
' deb .deb paclage (Debian)\n'
|
|
|
|
' win .exe installer (Windows)\n'
|
|
|
|
' mac .dmg package (Mac OS X)\n'
|
|
|
|
'\n'
|
|
|
|
'Example: %s package src-tgz') % (self.this_cmd, self.this_cmd)
|
|
|
|
|
|
|
|
def about(self):
|
|
|
|
print ('Help Me script, from the Synergy+ project.\n'
|
|
|
|
'%s\n'
|
|
|
|
'\n'
|
|
|
|
'For help, run: %s help') % (self.website_url, self.this_cmd)
|
|
|
|
|
|
|
|
def try_chdir(self, dir):
|
|
|
|
|
|
|
|
# Ensure temp build dir exists.
|
|
|
|
if not os.path.exists(dir):
|
|
|
|
os.mkdir(dir)
|
|
|
|
|
|
|
|
global prevdir
|
|
|
|
prevdir = os.path.abspath(os.curdir)
|
|
|
|
|
|
|
|
# It will exist by this point, so it's safe to chdir.
|
|
|
|
os.chdir(dir)
|
|
|
|
|
|
|
|
def restore_chdir(self):
|
|
|
|
global prevdir
|
|
|
|
os.chdir(prevdir)
|
|
|
|
|
|
|
|
def open_internal(self, project_filename, application = ''):
|
|
|
|
|
|
|
|
if not os.path.exists(project_filename):
|
2010-06-16 18:55:06 +00:00
|
|
|
raise Exception('Project file (%s) not found, run hm conf first.' % project_filename)
|
2010-04-10 21:16:10 +00:00
|
|
|
else:
|
2010-04-11 02:22:15 +00:00
|
|
|
path = project_filename
|
2010-06-16 18:55:06 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if application != '':
|
|
|
|
path = application + ' ' + path
|
2010-06-16 18:55:06 +00:00
|
|
|
|
|
|
|
err = os.system(path)
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('Could not open project with error code code: ' + str(err))
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
def setup(self):
|
2010-04-11 02:22:15 +00:00
|
|
|
print "Running setup..."
|
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
# always either get generator from args, or prompt user when
|
|
|
|
# running setup
|
|
|
|
generator = self.get_generator_from_prompt()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
# Create build dir, since config file resides there.
|
|
|
|
if not os.path.exists(self.bin_dir):
|
|
|
|
os.mkdir(self.bin_dir)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if os.path.exists(self.config_filepath()):
|
|
|
|
config = ConfigParser.ConfigParser()
|
|
|
|
config.read(self.config_filepath())
|
|
|
|
else:
|
|
|
|
config = ConfigParser.ConfigParser()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if not config.has_section('hm'):
|
|
|
|
config.add_section('hm')
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if not config.has_section('cmake'):
|
|
|
|
config.add_section('cmake')
|
|
|
|
|
|
|
|
config.set('hm', 'setup_version', self.setup_version)
|
2010-06-15 22:29:32 +00:00
|
|
|
|
|
|
|
# store the generator so we don't need to ask again
|
2010-04-11 02:22:15 +00:00
|
|
|
config.set('cmake', 'generator', generator)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
self.write_config(config)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
cmakecache_filename = '%s/CMakeCache.txt' % self.bin_dir
|
|
|
|
if os.path.exists(cmakecache_filename):
|
|
|
|
print "Removing %s, since generator changed." % cmakecache_filename
|
|
|
|
os.remove(cmakecache_filename)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
print "\nSetup complete."
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def write_config(self, config):
|
|
|
|
configfile = open(self.config_filepath(), 'wb')
|
|
|
|
config.write(configfile)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
def get_generator_from_config(self):
|
2010-06-15 22:41:47 +00:00
|
|
|
if self.generator_id:
|
2010-06-15 22:29:32 +00:00
|
|
|
generators = self.get_generators()
|
2010-06-15 22:41:47 +00:00
|
|
|
return generators[self.generator_id]
|
2010-06-15 22:29:32 +00:00
|
|
|
else:
|
|
|
|
config = ConfigParser.RawConfigParser()
|
|
|
|
config.read(self.config_filepath())
|
|
|
|
return config.get('cmake', 'generator')
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def min_setup_version(self, version):
|
|
|
|
if os.path.exists(self.config_filepath()):
|
|
|
|
config = ConfigParser.RawConfigParser()
|
|
|
|
config.read(self.config_filepath())
|
|
|
|
|
|
|
|
try:
|
|
|
|
return config.getint('hm', 'setup_version') >= version
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
else:
|
2010-04-10 21:16:10 +00:00
|
|
|
return False
|
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def has_conf_run(self):
|
|
|
|
if self.min_setup_version(2):
|
|
|
|
config = ConfigParser.RawConfigParser()
|
|
|
|
config.read(self.config_filepath())
|
|
|
|
try:
|
|
|
|
return config.getboolean('hm', 'has_conf_run')
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
else:
|
2010-04-10 21:16:10 +00:00
|
|
|
return False
|
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def set_conf_run(self):
|
|
|
|
if self.min_setup_version(3):
|
|
|
|
config = ConfigParser.RawConfigParser()
|
|
|
|
config.read(self.config_filepath())
|
|
|
|
config.set('hm', 'has_conf_run', True)
|
|
|
|
self.write_config(config)
|
|
|
|
else:
|
|
|
|
raise Exception("User does not have correct setup version.")
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
def get_generators(self):
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
return self.win32_generators
|
|
|
|
elif sys.platform in ['linux2', 'sunos5', 'freebsd7']:
|
|
|
|
return self.unix_generators
|
|
|
|
elif sys.platform == 'darwin':
|
|
|
|
return self.darwin_generators
|
|
|
|
else:
|
|
|
|
raise Exception('Unsupported platform: ' + sys.platform)
|
|
|
|
|
|
|
|
def get_generator_from_prompt(self):
|
|
|
|
|
|
|
|
generators = self.get_generators()
|
|
|
|
|
|
|
|
# if user has specified a generator as an argument
|
2010-06-15 22:41:47 +00:00
|
|
|
if self.generator_id:
|
|
|
|
return generators[self.generator_id]
|
2010-04-11 02:22:15 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
# if we can accept user input
|
|
|
|
elif not self.no_prompts:
|
|
|
|
generator_options = ''
|
|
|
|
generators_sorted = sorted(generators.iteritems(), key=lambda t: int(t[0]))
|
|
|
|
|
|
|
|
for id, generator in generators_sorted:
|
|
|
|
generator_options += '\n ' + id + ': ' + generator
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
print ('\nChoose a CMake generator:%s'
|
|
|
|
) % generator_options
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
return self.setup_generator_prompt(generators)
|
|
|
|
|
|
|
|
else:
|
|
|
|
raise Exception('No generator specified, and cannot prompt user.')
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def setup_generator_prompt(self, generators):
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
if self.no_prompts:
|
|
|
|
raise Exception('User prompting is disabled.')
|
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
prompt = 'Enter a number:'
|
|
|
|
print prompt,
|
2010-06-15 22:29:32 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
generator_id = raw_input()
|
|
|
|
|
|
|
|
if generator_id in generators:
|
|
|
|
print 'Selected generator:', generators[generator_id]
|
|
|
|
else:
|
|
|
|
print 'Invalid number, try again.'
|
|
|
|
self.setup_generator_prompt(generators)
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
return generators[generator_id]
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def get_vcvarsall(self, generator):
|
|
|
|
import platform, _winreg
|
|
|
|
|
|
|
|
# os_bits should be loaded with '32bit' or '64bit'
|
|
|
|
(os_bits, other) = platform.architecture()
|
|
|
|
|
|
|
|
# visual studio is a 32-bit app, so when we're on 64-bit, we need to check the WoW dungeon
|
|
|
|
if os_bits == '64bit':
|
|
|
|
key_name = r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7'
|
|
|
|
else:
|
|
|
|
key_name = r'SOFTWARE\Microsoft\VisualStudio\SxS\VC7'
|
|
|
|
|
2010-06-16 19:36:17 +00:00
|
|
|
try:
|
|
|
|
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key_name)
|
|
|
|
except:
|
|
|
|
raise Exception('Unable to open Visual Studio registry key. Application may not be installed.')
|
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
if generator.startswith('Visual Studio 8'):
|
|
|
|
value,type = _winreg.QueryValueEx(key, '8.0')
|
|
|
|
elif generator.startswith('Visual Studio 9'):
|
|
|
|
value,type = _winreg.QueryValueEx(key, '9.0')
|
|
|
|
elif generator.startswith('Visual Studio 10'):
|
|
|
|
value,type = _winreg.QueryValueEx(key, '10.0')
|
|
|
|
else:
|
|
|
|
raise Exception('Cannot determin vcvarsall.bat location for: ' + generator)
|
|
|
|
|
|
|
|
# not sure why, but the value on 64-bit differs slightly to the original
|
|
|
|
if os_bits == '64bit':
|
|
|
|
path = value + r'vc\vcvarsall.bat'
|
|
|
|
else:
|
|
|
|
path = value + r'vcvarsall.bat'
|
|
|
|
|
|
|
|
if not os.path.exists(path):
|
|
|
|
raise Exception("'%s' not found." % path)
|
2010-06-16 18:55:06 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
return path
|
|
|
|
|
|
|
|
def run_vcbuild(self, generator, mode, args=''):
|
|
|
|
import platform
|
|
|
|
|
|
|
|
# os_bits should be loaded with '32bit' or '64bit'
|
|
|
|
(os_bits, other) = platform.architecture()
|
|
|
|
# Now we choose the parameters bases on OS 32/64 and our target 32/64
|
|
|
|
# http://msdn.microsoft.com/en-us/library/x4d2c09s%28VS.80%29.aspx
|
|
|
|
|
|
|
|
# valid options are only: ia64 amd64 x86_amd64 x86_ia64
|
|
|
|
# but calling vcvarsall.bat does not garantee that it will work
|
|
|
|
# ret code from vcvarsall.bat is always 0 so the only way of knowing that I worked is by analysing the text output
|
|
|
|
# ms bugg: install VS9, FeaturePack, VS9SP1 and you'll obtain a vcvarsall.bat that fails.
|
|
|
|
if generator.find('Win64') != -1:
|
|
|
|
# target = 64bit
|
|
|
|
if os_bits == '32bit':
|
|
|
|
vcvars_platform = 'x86_amd64' # 32bit OS building 64bit app
|
|
|
|
else:
|
|
|
|
vcvars_platform = 'amd64' # 64bit OS building 64bit app
|
|
|
|
config_platform = 'x64'
|
|
|
|
else: # target = 32bit
|
|
|
|
vcvars_platform = 'x86' # 32/64bit OS building 32bit app
|
|
|
|
config_platform = 'Win32'
|
|
|
|
if mode == 'release':
|
|
|
|
config = 'Release'
|
|
|
|
else:
|
|
|
|
config = 'Debug'
|
|
|
|
|
|
|
|
if generator.startswith('Visual Studio 10'):
|
|
|
|
cmd = ('@echo off\n'
|
|
|
|
'call "%s" %s \n'
|
|
|
|
'msbuild /nologo %s /p:Configuration="%s" /p:Platform="%s" "%s"'
|
|
|
|
) % (self.get_vcvarsall(generator), vcvars_platform, args, config, config_platform, self.sln_filepath())
|
|
|
|
else:
|
|
|
|
config = config + '|' + config_platform
|
|
|
|
cmd = ('@echo off\n'
|
|
|
|
'call "%s" %s \n'
|
|
|
|
'vcbuild /nologo %s "%s" "%s"'
|
|
|
|
) % (self.get_vcvarsall(generator), vcvars_platform, args, self.sln_filepath(), config)
|
2010-06-15 22:29:32 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
# Generate a batch file, since we can't use environment variables directly.
|
|
|
|
temp_bat = self.bin_dir + r'\vcbuild.bat'
|
|
|
|
file = open(temp_bat, 'w')
|
|
|
|
file.write(cmd)
|
|
|
|
file.close()
|
|
|
|
|
2010-06-16 18:55:06 +00:00
|
|
|
err = os.system(temp_bat)
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('Microsoft compiler failed with error code: ' + str(err))
|
2010-04-11 02:22:15 +00:00
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
def ensure_setup_latest(self):
|
2010-04-11 02:22:15 +00:00
|
|
|
if not self.min_setup_version(self.setup_version):
|
2010-06-15 22:29:32 +00:00
|
|
|
self.setup()
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def reformat(self):
|
2010-06-16 18:55:06 +00:00
|
|
|
err = os.system(
|
2010-04-11 02:22:15 +00:00
|
|
|
r'tool\astyle\AStyle.exe '
|
|
|
|
'--quiet --suffix=none --style=java --indent=force-tab=4 --recursive '
|
|
|
|
'lib/*.cpp lib/*.h cmd/*.cpp cmd/*.h')
|
2010-06-16 18:55:06 +00:00
|
|
|
|
|
|
|
if err != 0:
|
|
|
|
raise Exception('Reformat failed with error code: ' + str(err))
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
# the command handler should be called only from hm.py (i.e. directly
|
|
|
|
# from the command prompt). the purpose of this class is so that we
|
|
|
|
# don't need to do argument handling all over the place in the internal
|
|
|
|
# commands class.
|
|
|
|
class CommandHandler:
|
|
|
|
ic = InternalCommands()
|
|
|
|
|
2010-06-15 22:29:32 +00:00
|
|
|
def __init__(self, argv, opts, args):
|
|
|
|
|
|
|
|
self.opts = opts
|
|
|
|
self.args = args
|
|
|
|
|
|
|
|
for o, a in self.opts:
|
|
|
|
if o == '--no-prompts':
|
|
|
|
self.ic.no_prompts = True
|
|
|
|
elif o in ('-g', '--generator'):
|
2010-06-15 22:41:47 +00:00
|
|
|
self.ic.generator_id = a
|
2010-04-11 02:22:15 +00:00
|
|
|
|
|
|
|
def get_build_mode(self):
|
|
|
|
mode = None
|
2010-06-15 22:29:32 +00:00
|
|
|
for o, a in self.opts:
|
|
|
|
if o == ('-d', '--debug'):
|
|
|
|
mode = 'debug'
|
|
|
|
elif o == ('-r', '--release'):
|
|
|
|
mode = 'release'
|
2010-04-11 02:22:15 +00:00
|
|
|
return mode
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def about(self):
|
|
|
|
self.ic.about()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def setup(self):
|
|
|
|
self.ic.setup()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def configure(self):
|
2010-06-15 22:29:32 +00:00
|
|
|
self.ic.configure()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def build(self):
|
|
|
|
self.ic.build(self.get_build_mode())
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def clean(self):
|
|
|
|
self.ic.clean(self.get_build_mode())
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def update(self):
|
|
|
|
self.ic.update()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def install(self):
|
|
|
|
print 'Not yet implemented: install'
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def package(self):
|
|
|
|
self.ic.package()
|
2010-04-10 21:16:10 +00:00
|
|
|
|
2010-04-11 02:22:15 +00:00
|
|
|
def destroy(self):
|
|
|
|
self.ic.destroy()
|
|
|
|
|
|
|
|
def package(self):
|
|
|
|
type = None
|
|
|
|
if len(self.args) > 0:
|
|
|
|
type = self.args[0]
|
|
|
|
self.ic.package(type)
|
|
|
|
|
|
|
|
def kill(self):
|
|
|
|
self.ic.kill()
|
|
|
|
|
|
|
|
def usage(self):
|
|
|
|
self.ic.usage()
|
|
|
|
|
|
|
|
def revision(self):
|
|
|
|
self.ic.revision()
|
|
|
|
|
|
|
|
def hammer(self):
|
|
|
|
self.ic.hammer()
|
|
|
|
|
|
|
|
def reformat(self):
|
|
|
|
self.ic.reformat()
|
|
|
|
|
|
|
|
def open(self):
|
|
|
|
self.ic.open()
|