def setUp(self): config.PATH_SANDBOX = "unit_tests/test_sandbox/" config.PATH_DATA = "unit_tests/test_data/" config.PATH_TESTS = "unit_tests/test_data/tests/" if not path.exists(config.PATH_SANDBOX): makedirs(config.PATH_SANDBOX) if not path.exists(config.PATH_DATA): makedirs(config.PATH_DATA) if not path.exists(config.PATH_TESTS): makedirs(config.PATH_TESTS) # First, we need to create an Evaluator object self.evaluator = self.get_evaluator( "unit_tests/fixtures/tests_runner.json") # Then create the sandbox dir self.evaluator.create_sandbox_dir() # Then we need to compile the source Compiler.compile("C++", "unit_tests/fixtures/ThreeSum/ThreeSum.cpp", self.evaluator.path_executable) # Then we need to copy the tests to the test_data folder for test in self.evaluator.tests: shutil.copy("unit_tests/fixtures/ThreeSum/" + test["inpFile"], config.PATH_TESTS + test["inpHash"]) shutil.copy("unit_tests/fixtures/ThreeSum/" + test["solFile"], config.PATH_TESTS + test["solHash"])
def test_compiler(self): for i, file in enumerate(os.listdir("tests_bad")): with self.subTest(i=i): compiler = Compiler("tests_bad/{}".format(file), "out.mr") compiler.read_from_file() compiler.compile() self.assertFalse(compiler.write_to_file())
def main(): compiler = Compiler() try: opts, args = getopt.getopt(sys.argv[1:], "d:i:o:h", ["debug=", "inputfile=", "outputfile=", "help"]) except getopt.GetoptError as error: print(error) exit() #Go through the options, initializing and configuring the compiler. for opt, arg in opts: if opt in ("-h", "--help"): exit() elif opt in ('-d', '--debug'): compiler.setDebug(arg) elif opt in ("-i", "--inputfile"): try: compiler.input = open(arg, mode='rt', encoding='utf-8') except IOError as ioe: print(ioe) sys.exit(2) elif opt in ("-o", "--outputfile"): try: compiler.output = open(arg, mode='wb') except IOError as ioe: print(ioe) sys.exit(2) compiler.compile() sys.exit(0)
def build_modules_info(self, resources_dir, app_bin_dir): self.app_modules = [] (modules, external_child_modules) = bindings.get_all_module_bindings() compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, os.path.dirname(app_bin_dir)) compiler.compile(compile_bytecode=False, info_message=None) for module in compiler.modules: module_bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module + ".") and "." not in method: module_bindings.append(method[len(module) + 1 :]) module_class = None module_apiName = None for m in modules.keys(): if modules[m]["fullAPIName"].lower() == module: module_class = m module_apiName = modules[m]["fullAPIName"] break if module_apiName == None: continue # module wasn't found if "." not in module: ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[module_class]: if child_module["fullAPIName"].lower() in compiler.modules: ext_modules.append(child_module) self.app_modules.append( { "api_name": module_apiName, "class_name": module_class, "bindings": module_bindings, "external_child_modules": ext_modules, } ) # discover app modules detector = ModuleDetector(self.project_dir) missing, detected_modules = detector.find_app_modules(self.tiapp, "android") for missing_module in missing: print "[WARN] Couldn't find app module: %s" % missing_module["id"] self.custom_modules = [] for module in detected_modules: if module.jar == None: continue module_jar = zipfile.ZipFile(module.jar) module_bindings = bindings.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings["modules"].keys(): module_id = module_bindings["proxies"][module_class]["proxyAttrs"]["id"] print "[DEBUG] module_id = %s" % module_id if module_id == module.manifest.moduleid: print "[DEBUG] appending module: %s" % module_class self.custom_modules.append({"class_name": module_class, "manifest": module.manifest})
def build_modules_info(self, resources_dir, app_bin_dir, include_all_ti_modules=False): self.app_modules = [] (modules, external_child_modules) = bindings.get_all_module_bindings() compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, os.path.dirname(app_bin_dir), include_all_modules=include_all_ti_modules) compiler.compile(compile_bytecode=False, info_message=None) for module in compiler.modules: module_bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module+'.') and '.' not in method: module_bindings.append(method[len(module)+1:]) module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == module: module_class = m module_apiName = modules[m]['fullAPIName'] break if module_apiName == None: continue # module wasn't found if '.' not in module: ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[module_class]: if child_module['fullAPIName'].lower() in compiler.modules: ext_modules.append(child_module) self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': module_bindings, 'external_child_modules': ext_modules }) # discover app modules detector = ModuleDetector(self.project_dir) missing, detected_modules = detector.find_app_modules(self.tiapp, 'android') for missing_module in missing: print '[WARN] Couldn\'t find app module: %s' % missing_module['id'] self.custom_modules = [] for module in detected_modules: if module.jar == None: continue module_jar = zipfile.ZipFile(module.jar) module_bindings = bindings.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings['modules'].keys(): module_id = module_bindings['proxies'][module_class]['proxyAttrs']['id'] print '[DEBUG] module_id = %s' % module_id if module_id == module.manifest.moduleid: print '[DEBUG] appending module: %s' % module_class self.custom_modules.append({ 'class_name': module_class, 'manifest': module.manifest })
def build_modules_info(self, resources_dir, app_bin_dir): self.app_modules = [] (modules, external_child_modules) = bindings.get_all_module_bindings() compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, os.path.dirname(app_bin_dir)) compiler.compile(compile_bytecode=False, info_message=None) for module in compiler.modules: module_bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module+'.') and '.' not in method: module_bindings.append(method[len(module)+1:]) module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == module: module_class = m module_apiName = modules[m]['fullAPIName'] break if module_apiName == None: continue # module wasn't found if '.' not in module: ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[module_class]: if child_module['fullAPIName'].lower() in compiler.modules: ext_modules.append(child_module) self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': module_bindings, 'external_child_modules': ext_modules }) # discover app modules detector = ModuleDetector(self.project_dir) missing, detected_modules = detector.find_app_modules(self.tiapp, 'android') for missing_module in missing: print '[WARN] Couldn\'t find app module: %s' % missing_module['id'] self.custom_modules = [] for module in detected_modules: if module.jar == None: continue module_jar = zipfile.ZipFile(module.jar) module_bindings = bindings.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings['modules'].keys(): module_id = module_bindings['proxies'][module_class]['proxyAttrs']['id'] print '[DEBUG] module_id = %s' % module_id if module_id == module.manifest.moduleid: print '[DEBUG] appending module: %s' % module_class self.custom_modules.append({ 'class_name': module_class, 'manifest': module.manifest })
def run_godel(compile_only, filename, input_list, verbose): g = Godel(verbose) g.open(filename) interpreter = Compiler(verbosity=verbose) interpreter.code = g.code interpreter.compile() interpreter.save('%s.s' % filename[:-6]) interpreter.save('%s.express.s' % filename[:-6], True) if not compile_only: interpreter.run(input_list) return interpreter
def release(input_file, output_dir): "Compile a cablelang script in release mode" try: mkdir(output_dir) except: pass copy_std_to_dir(output_dir) c = Compiler(input_file, output_dir + '/main.cpp') c.compile() c.write() build_release(output_dir)
class Workspace: def __init__(self, user_root_uri, compiler_path, compiler_args): self.user_root = parse_uri(user_root_uri) + '/' self.compiler = Compiler(self.user_root, compiler_path, compiler_args) self.files = {} compilation_order = [] if os.path.exists(self.user_root + '/compilation_order.txt'): with open(self.user_root + '/compilation_order.txt', 'r') as f: line = f.readline().rstrip() compilation_order = line.split(' ') if compilation_order: eprint("Compilation order: " + str(compilation_order)) for f in compilation_order: self.compiler.compile(f) def save_file(self, path, content, new=False): if new: self.files[path] = File(path, content, self.compiler) else: if path not in self.files: return None self.files[path].update_content(content) if self.files[path].has_diagnostics(): return self.files[path].diagnostics else: return None def close_file(self, path): if path in self.files: del self.files[path] def get_symbols(self, path): if path in self.files: return self.files[path].get_symbols() else: return None def get_definition(self, path, line, column): if path in self.files: return self.files[path].get_definition(line, column) else: return None def rel_path(self, path): # Normalize absolute path to be relative to user's root dir. path = path.replace(self.user_root, '', 1) path.lstrip('/') return path
def deploy(slug, testing_url, production_url, theme_url, production_server, production_dir): build_dir = os.path.join(SETTINGS.BUILD_DIR, slug) archive_dir = os.path.join(SETTINGS.ARCHIVE_DIR, slug) compiler = Compiler(build_dir, testing_url, production_url, theme_url) compiler.compile() archiver = Archiver(slug, build_dir, archive_dir) archive = archiver.archive() deployer = Deployer(production_server, SETTINGS.SSH_KEY, archive_dir, production_dir) deployer.deploy(archive) return True
def build_modules_info(self, resources_dir, app_bin_dir): compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, os.path.dirname(app_bin_dir)) compiler.compile(compile_bytecode=False) self.app_modules = [] template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename) android_modules_dir = os.path.abspath(os.path.join(template_dir, 'modules')) modules = {} for jar in os.listdir(android_modules_dir): if not jar.endswith('.jar'): continue module_path = os.path.join(android_modules_dir, jar) module_jar = zipfile.ZipFile(module_path) bindings_path = None for name in module_jar.namelist(): if name.endswith('.json') and name.startswith('org/appcelerator/titanium/bindings/'): bindings_path = name break if bindings_path is None: continue bindings_json = module_jar.read(bindings_path) module_bindings = simplejson.loads(bindings_json) for module_class in module_bindings['modules'].keys(): full_api_name = module_bindings['proxies'][module_class]['proxyAttrs']['fullAPIName'] print '[INFO] module_class = ' + module_class + ', api_name=' + module_bindings['modules'][module_class]['apiName'] + ', full_api_name='+full_api_name modules[module_class] = module_bindings['modules'][module_class] modules[module_class]['fullAPIName'] = full_api_name for module in compiler.modules: bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module+'.') and '.' not in method: bindings.append(method[len(module)+1:]) module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == module: module_class = m module_apiName = modules[m]['fullAPIName'] break if module_apiName == None: continue # module wasn't found self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': bindings })
def test_run_program_concurrent_cpu_access_large_tl(self): path_source = os.path.join(self.PATH_FIXTURES, "summer_cpu.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "summer_cpu.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") num_runs = self.get_num_runs(20) input_file = NamedTemporaryFile(mode="w+b", delete=False) input_file.write(b"500000000") input_file.flush() # Run the same thing over and over again as quickly as possible to see if there is any inconsistency times = [1e100] * num_runs pool = ThreadPoolExecutor(max_workers=config.MAX_PARALLEL_WORKERS) futures = [ pool.submit(self.concurrent_helper, input_file.name, path_executable) for _ in range(num_runs) ] for i in range(len(futures)): run_result = futures[i].result() self.assertEqual(run_result.exit_code, 0) self.assertEqual(int(run_result.output.decode().strip()), 250010718184821892) times[i] = round(run_result.exec_time, 2) input_file.close() print(times) print("TIME: {:.3f}s vs {:.3f}s".format(min(times), max(times))) # Best time should be almost identical to the worst time in order to consider the results consistent # (at most 10% difference or 0.05s, whichever larger) self.assertLessEqual(max(times), max(min(times) + 0.05, min(times) * 1.1))
class Game(): def __init__(self, gru_file=None): self.compiler = Compiler() if gru_file: self.stream = self.compiler.decompile(gru_file) else: self.stream = self.compiler.compile(None) self.metadata = self.stream.metadata self.flags = Flags(self.stream) self.wheel = Wheel(config) self.title = Title(config) self.inventory = Inventory(self.stream, self.flags, config) self.combiner = Combiner(self.stream, self.flags, self.inventory) self.page = Page(config, self.flags, self.combiner, self.inventory) self.state = State(self.stream, self.flags, self.inventory, self.wheel, self.combiner, self.title, self.page) if self.metadata.has_key("start"): start = self.metadata["start"] self.state.update(start) else: self.state.update("start") def draw(self, tick): self.inventory.draw() self.wheel.draw() self.title.draw() self.page.draw(tick)
def main(): if len(sys.argv) != 2: print "Usage:" print " main.py input output" print "input is the file to be compiled" print "output is the file where the generated code will be stored" sys.exit(1) try: fp = open(sys.argv[1], "r") except IOError: print "Either the file", sys.argv[1], "does not exist or it cannot be read" sys.exit(1) inp = fp.read() + '\0' fp.close() comp = Compiler() try: output = open(sys.argv[2], "w") except IOError: print "File", sys.args[2], "could not be opened" sys.exit(1) printWriter = PrintWriter(output) try: program = comp.compile(inp, printWriter) except Exception, e: print e
def load_scripts(self): log("Reading scripts...") for script in ['wm0.ev', 'wm2.ev', 'wm3.ev']: directory = self.directory + '/' + script functions = [] if not isdir(directory): error("Script directory not found: " + directory) exit(1) files = [] for prefix in ['system', 'model', 'mesh']: for r, d, f in walk(directory): for file in f: if prefix not in file: continue files.append(file) files.sort() offset = 1 for filename in files: with open(directory + '/' + filename) as file: compiler = Compiler(file, offset) code = compiler.compile() offset += int(len(code) / 2) functions.append((filename, code)) self.scripts.append((script, functions))
def process(src,filename=None): from parser import Parser from compiler import Compiler parser = Parser(src,filename=filename) block = parser.parse() compiler = Compiler(block) return compiler.compile()
def test_interactive_game_is(self): # The only difference with the previous is that this problem has much larger input and output # and the tester has to print lots of information in the end (thus, may take its time to finish) evaluator = self.get_evaluator("games_interactive_is.json", config.LANGUAGE_CPP) # Configure fake paths to the tester and its executable and compile it evaluator.path_tester_source = os.path.join( self.PATH_FIXTURES, "ImageScanner/Tester/ImageScannerTester.cpp") evaluator.path_tester_executable = os.path.join( config.PATH_TESTERS, "ImageScannerTester.o") # Compile the tester compilation_status = Compiler.compile( language=config.LANGUAGE_CPP, path_source=evaluator.path_tester_source, path_executable=evaluator.path_tester_executable) self.assertEqual(compilation_status, "") # OK self.standard_problem_helper( evaluator=evaluator, language=config.LANGUAGE_CPP, source=os.path.join(self.PATH_FIXTURES, "ImageScanner/Solutions/ImageScanner.cpp"), time_lb=0.0, memory_lb=0.0, expected_errors={})
def exec_helper(self, add_info, path_source, tests, run_config, expected_results): updater = Updater("fake/endpoint", 42, []) updater_results = [] add_info.side_effect = lambda result: updater_results.append(result) # Configure fake paths to the solution and its executable and compile it language = common.get_language_by_source_name(path_source) path_executable = os.path.join(config.PATH_SANDBOX, "solution.{}".format(common.get_executable_extension(language))) compilation_status = Compiler.compile( language=language, path_source=path_source, path_executable=path_executable ) self.assertEqual(compilation_status, "") run_config.executable_path = path_executable try: for test in tests: execute_problem(updater=updater, submit_id=42, result_id=0, test=test, run_config=run_config) except: self.fail("Failed during execution of tests.") self.assertEqual(add_info.call_count, len(tests) * 2) for result in updater_results: if result["status"] != TestStatus.TESTING.name: # print(result) found = False for i in range(len(expected_results)): if result["status"] == expected_results[i].name: found = True del expected_results[i] break self.assertTrue(found, msg="Status '{}' not among expected results.".format(result["status"]))
def test_cpp_successful_compilation(self): # Successful, returns an empty string as an error message path_source = "unit_tests/fixtures/HelloWorldCppOK.cpp" path_executable = "unit_tests/test_sandbox/HelloWorldCppOK.o" message = Compiler.compile("C++", path_source, path_executable) self.assertEqual("", message, "The C++ compilation expected to pass, but failed.")
def test_run_program_exec_time_sleeping(self): path_source = os.path.join(self.PATH_FIXTURES, "sleeper.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "sleeper.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") # Sleeping programs don't waste CPU, thus have negligible exec_time (although high clock-time) start_time = perf_counter() run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=32000000, timeout=0.5, input_bytes=None) self.assertEqual(run_result.exit_code, 0) self.assertLess(run_result.exec_time, 0.1) self.assertGreaterEqual(perf_counter() - start_time, 0.4) self.assertLess(perf_counter() - start_time, 0.6) self.assertEqual(run_result.output.decode().strip(), "2075") # ... except if they don't exceed the time limit, in which case their clock time is recorded start_time = perf_counter() run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=32000000, timeout=0.3, input_bytes=None) self.assertEqual(run_result.exit_code, 9) self.assertGreaterEqual(run_result.exec_time, 0.29) self.assertLess(run_result.exec_time, 0.4) self.assertGreaterEqual(perf_counter() - start_time, 0.3) self.assertLess(perf_counter() - start_time, 0.5) self.assertEqual(run_result.output.decode().strip(), "")
def main(): inp = "(- (+ 5 4) 1)" comp = Compiler() expr = comp.compile(inp) expr.genC() print
def test_python_unsuccessful_compilation(self): # Unsuccessful, returns the compilation message as an error string path_source = "unit_tests/fixtures/HelloWorldPythonCE.py" path_executable = "unit_tests/test_sandbox/HelloWorldPythonCE.py" message = Compiler.compile("Python", path_source, path_executable) self.assertNotEqual("", message, "The Python compilation expected error message, but passed successfully.")
def test_compilation_timeout_okay(self): # Slow compilation, but within the 10 second limit path_source = "unit_tests/fixtures/LongCompilation.cpp" path_executable = "unit_tests/test_sandbox/LongCompilation.o" message = Compiler.compile("C++", path_source, path_executable) self.assertEqual("", message, "The C++ compilation failed, but expected to pass.")
def test_compilation_timeout_fail(self): # Too slow compilation: over the 10 second limit (>20s on the grader machine) path_source = "unit_tests/fixtures/TemplateFibo.cpp" path_executable = "unit_tests/test_sandbox/TemplateFibo.o" message = Compiler.compile("C++", path_source, path_executable) self.assertNotEqual("", message, "The C++ compilation expected to fail, but passed.")
def main(): import sys filename = sys.argv[1] f = open(filename) comp = Compiler() program = comp.compile(f.read()) program.genC()
def test_java_successful_compilation(self): # Successful, returns an empty string as an error message path_source = "unit_tests/fixtures/HelloWorldJavaOK.java" path_executable = "unit_tests/test_sandbox/HelloWorldJavaOK.jar" message = Compiler.compile("Java", path_source, path_executable) self.assertEqual("", message, "The Java compilation expected to pass, but failed.") self.assertTrue(path.exists(path_executable))
def test_compilation_timeout_fail(self): # Too slow compilation: over the 3 second limit (5.84s on the machine I'm currently writing this) language = "C++" path_source = "unit_tests/fixtures/TemplateFibo.cpp" path_executable = "unit_tests/test_sandbox/TemplateFibo.o" message = Compiler.compile(language, path_source, path_executable) self.assertNotEqual( "", message, "The C++ compilation expected to fail, but passed.")
def test_java_different_class_name(self): # Unsuccessful, returns the compilation message as an error string path_source = "unit_tests/fixtures/HelloWorldJavaDifferentClassName.java" path_executable = "unit_tests/test_sandbox/HelloWorldJavaDifferentClassName.jar" message = Compiler.compile("Java", path_source, path_executable) self.assertNotIn("error", message) self.assertEqual("", message, "The Java compilation expected to pass, but failed.") self.assertTrue(path.exists(path_executable))
def test_cpp_successful_compilation(self): # Successful, returns an empty string as an error message language = "C++" path_source = "unit_tests/fixtures/HelloWorldOK.cpp" path_executable = "unit_tests/test_sandbox/HelloWorldOK.o" message = Compiler.compile(language, path_source, path_executable) self.assertEqual("", message, "The C++ compilation expected to pass, but failed.")
def main(): inp = "a = 1 b = 3 : (- (+ a 4) b)" comp = Compiler() program = comp.compile(inp) program.genC() print print "Value = ", program.eval()
def test_java_unsuccessful_compilation(self): # Unsuccessful, returns the compilation message as an error string path_source = "unit_tests/fixtures/HelloWorldJavaCE.java" path_executable = "unit_tests/test_sandbox/HelloWorldJavaCE.jar" message = Compiler.compile("Java", path_source, path_executable) self.assertIn("error", message) self.assertNotEqual("", message, "The Java compilation expected error message, but passed successfully.") self.assertFalse(path.exists(path_executable))
def test_compiler(self): costs = [] files = [ f for f in os.listdir("tests_schmidt") if os.path.isfile(os.path.join("tests_schmidt", f)) ] for i, file in enumerate(files): with self.subTest(i=i): compiler = Compiler("tests_schmidt/{}".format(file), "out.mr") compiler.read_from_file() compiler.compile() self.assertTrue(compiler.write_to_file()) inputs_file = open("tests_schmidt/in/{}".format(file), "r") inputs = inputs_file.read().split("X") inputs_file.close() inputs = [x.strip().split() for x in inputs] corrects_file = open("tests_schmidt/correct/{}".format(file), "r") corrects = corrects_file.read().split("X") corrects_file.close() corrects = [x.strip().split() for x in corrects] for i, data_set in enumerate(inputs): correct = corrects[i] os.system( "echo \"{}\" | ./maszyna-wirtualna-cln-test out.mr > out.txt" .format(" ".join(data_set))) result_file = open("out.txt", "r") result = result_file.read().split() result_file.close() cost = int(result[-1]) costs.append({"name": file, "cost": cost}) result.pop() self.assertEqual(result, correct) sum_of_costs = 0 for cost in costs: sum_of_costs += cost["cost"] csv_columns = ['name', 'cost'] costs_file1 = open("costs/schmidt.csv", "w") writer = csv.DictWriter(costs_file1, csv_columns) writer.writeheader() for data in costs: writer.writerow(data) costs_file1.close() cost_full.append({"name": "schmidt", "cost": sum_of_costs})
def test_python_successful_compilation(self): # Successful, returns an empty string as an error message path_source = "unit_tests/fixtures/HelloWorldPythonOK.py" path_executable = "unit_tests/test_sandbox/HelloWorldPythonOK.py" message = Compiler.compile("Python", path_source, path_executable) self.assertEqual("", message, "The Python compilation expected to pass, but failed.") self.assertTrue(path.exists(path_executable)) # The "compiled" file should be the same as the source self.assertTrue(filecmp.cmp(path_source, path_executable, shallow=False))
def test_run_program_io(self): path_source = os.path.join(self.PATH_FIXTURES, "reverser.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "reverser.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=32000000, timeout=1.0, input_bytes=b"espr1t") self.assertEqual(run_result.exit_code, 0) self.assertEqual(run_result.output.decode().strip(), "t1rpse")
def test_run_program_output_limit(self): path_source = os.path.join(self.PATH_FIXTURES, "outputlimit.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "outputlimit.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=64000000, timeout=1.0, input_bytes=None) self.assertEqual(run_result.exit_code, 0) self.assertEqual(len(run_result.output.decode()), config.MAX_EXECUTION_OUTPUT)
def test_cpp_unsuccessful_compilation(self): # Unsuccessful, returns the compilation message as an error string language = "C++" path_source = "unit_tests/fixtures/HelloWorldCE.cpp" path_executable = "unit_tests/test_sandbox/HelloWorldCE.o" message = Compiler.compile(language, path_source, path_executable) self.assertNotEqual( "", message, "The C++ compilation expected error message, but passed successfully." )
def standard_problem_helper(self, add_info, evaluator, language, source, time_lb, memory_lb, expected_errors): evaluator.create_sandbox_dir() compilation_status = Compiler.compile( language=language, path_source=source, path_executable=evaluator.path_executable) self.assertEqual(compilation_status, "") updater_results = [] add_info.side_effect = lambda result: updater_results.append(result) self.assertTrue(evaluator.run_solution()) self.assertEqual(add_info.call_count, len(evaluator.tests) * 2) actual_non_ok = {} max_time, max_memory = -1e100, -1e100 for res in updater_results: if res["status"] != TestStatus.TESTING.name: # print(res) if res["status"] != TestStatus.ACCEPTED.name: # This is only because we only test wrong answers from the task with checkers # In real tasks this is usually empty if res["status"] == TestStatus.WRONG_ANSWER.name: self.assertNotEqual(res["info"], "") if res["status"] not in actual_non_ok: actual_non_ok[res["status"]] = 1 else: actual_non_ok[res["status"]] += 1 max_time = max(max_time, res["exec_time"]) max_memory = max(max_memory, res["exec_memory"]) time_upper_bound = evaluator.time_limit * 3 + max( 0.2, evaluator.time_limit * 0.2) self.assertGreaterEqual(max_time, time_lb) self.assertLessEqual(max_time, time_upper_bound) self.assertGreaterEqual(max_memory, memory_lb) self.assertLessEqual(max_memory, evaluator.memory_limit) for key in actual_non_ok.keys(): if key not in expected_errors: self.fail("Got status {} which was not expected.".format(key)) if actual_non_ok[key] != expected_errors[key]: self.fail( "Expected {} results with status {} but got {}.".format( expected_errors[key], key, actual_non_ok[key])) for key in expected_errors.keys(): if key not in actual_non_ok: self.fail( "Expected status {} but didn't receive it.".format(key))
def test_run_program_memory_py(self): path_source = os.path.join(self.PATH_FIXTURES, "hello.py") path_executable = os.path.join(config.PATH_SANDBOX, "hello.py") status = Compiler.compile(config.LANGUAGE_PYTHON, path_source, path_executable) self.assertEqual(status, "") run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=64000000, timeout=1.0) self.assertEqual(run_result.exit_code, 0) self.assertEqual(run_result.output.decode().strip(), "Hello, World!") self.assertGreater(run_result.exec_memory, 0) self.assertLess(run_result.exec_memory, 2000000) # Max 2MB overhead using this function
def test_run_program_memory_python_fifty(self): path_source = os.path.join(self.PATH_FIXTURES, "fifty.py") path_executable = os.path.join(config.PATH_SANDBOX, "fifty.py") status = Compiler.compile(config.LANGUAGE_PYTHON, path_source, path_executable) self.assertEqual(status, "") memory_target, memory_limit = 50000000, 64000000 run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=memory_limit, timeout=1.0, input_bytes=str(memory_target).encode()) self.assertEqual(run_result.exit_code, 0) self.assertEqual(run_result.output.decode().strip(), "57864746") self.assertGreater(run_result.exec_memory, memory_target) self.assertLess(run_result.exec_memory, memory_limit)
def compile(filename, options): f = open(filename, 'rt') data = f.read() f.close() filename = filename.replace('\\', '/') comp = Compiler(filename, options) output = comp.compile(data) if options.output: with open(options.output, "wt") as f: f.write('\n'.join(output)) else: print '\n'.join(output)
def run_compiler(file_name, output_file=None): print(f"Compiling '{file_name}'") compiler = Compiler(file_name) code = compiler.compile() print("\n# COMPILED CODE #") print(code) if output_file is not None: with open(output_file, 'w') as f: f.write(code) print() print(f"Saved to: '{output_file}'")
def test_run_program_memory_java_with_imports(self): path_source = os.path.join(self.PATH_FIXTURES, "hello_imports.java") path_executable = os.path.join(config.PATH_SANDBOX, "hello_imports.jar") status = Compiler.compile(config.LANGUAGE_JAVA, path_source, path_executable) self.assertEqual(status, "") run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=64000000, timeout=1.0) self.assertEqual(run_result.exit_code, 0) self.assertEqual(run_result.output.decode().strip(), "Hello, World!") # Note that Java's Garbage Collector makes the process quite volatile (and unpredictable) # in terms of memory usage. Set more relaxed limitations for Java self.assertGreaterEqual(run_result.exec_memory, 0) self.assertLess(run_result.exec_memory, 4000000) # Max 4MB overhead using this function
def test_run_program_concurrent_hdd_access(self): # Cannot test concurrency if there is none if config.MAX_PARALLEL_WORKERS <= 1: return path_source = os.path.join(self.PATH_FIXTURES, "summer_hdd.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "summer_hdd.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") # Write many integers into a (big) file input_file = NamedTemporaryFile(mode="w+b", delete=False) num_runs = self.get_num_runs(20) target_size = 100000000 # 100MB number_list = [999999999 - i for i in range(target_size // 10)] expected_output = sum(number_list) input_file.write( str(number_list).replace('[', '').replace(']', '').replace( ',', '').encode("ascii")) input_file.flush() # Actual file size should be +/- 1% of the target self.assertAlmostEqual( os.path.getsize(input_file.name) / target_size, 1.0, 2) times = [1e100] * num_runs # Run the same thing several times as quickly as possible to see if there is any significant increase pool = ThreadPoolExecutor(max_workers=config.MAX_PARALLEL_WORKERS) futures = [ pool.submit(self.concurrent_helper, input_file.name, path_executable) for _ in range(num_runs) ] for i in range(len(futures)): run_result = futures[i].result() self.assertEqual(run_result.exit_code, 0) self.assertEqual(int(run_result.output.decode().strip()), expected_output) times[i] = round(run_result.exec_time, 2) input_file.close() print(times) print("TIME: {:.3f}s vs {:.3f}s".format(min(times), max(times))) # Best time should be almost identical to the worst time in order to consider the results consistent # (at most 10% difference or 0.05s, whichever larger) self.assertLessEqual(max(times), max(min(times) + 0.05, min(times) * 1.1))
def test_run_program_exec_time_cpu_intensive(self): path_source = os.path.join(self.PATH_FIXTURES, "cpuintensive.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "cpuintensive.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") # CPU intensive programs have their execution time recorded properly start_time = perf_counter() run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=32000000, timeout=0.5, input_bytes=None) self.assertEqual(run_result.exit_code, 0) self.assertGreaterEqual(run_result.exec_time, 0.29) self.assertGreaterEqual(perf_counter() - start_time, 0.3) self.assertLess(run_result.exec_time, 0.4) self.assertLess(perf_counter() - start_time, 0.5) self.assertNotEqual(run_result.output.decode().strip(), "")
def test_run_program_args_are_appended(self): path_source = os.path.join(self.PATH_FIXTURES, "printargs.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "printargs.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") # Empty string when no arguments are passed run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=32000000, timeout=0.5) self.assertEqual(run_result.exit_code, 0) self.assertEqual(run_result.output.decode().strip(), "") # If there are arguments, prints their concatenation run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=32000000, timeout=0.5, args=["foo", "bar", "baz"]) self.assertEqual(run_result.exit_code, 0) self.assertEqual(run_result.output.decode().strip(), "foobarbaz")
def test_run_program_privileged(self): path_source = os.path.join(self.PATH_FIXTURES, "tryingtowrite.cpp") path_executable = os.path.join(config.PATH_SANDBOX, "tryingtowrite.o") status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") # Writing without privileges leads to an error sandbox = Sandbox() run_result = Runner.run_program(sandbox=sandbox, executable_path=path_executable, memory_limit=32000000, timeout=0.5, input_bytes=None) self.assertNotEqual(run_result.exit_code, 0) self.assertFalse(sandbox.has_file("foo.txt")) # But we can give privileges run_result = Runner.run_program(sandbox=sandbox, executable_path=path_executable, memory_limit=32000000, timeout=0.5, input_bytes=None, privileged=True) self.assertEqual(run_result.exit_code, 0) self.assertTrue(sandbox.has_file("foo.txt"))
def test_task_with_checker(self): evaluator = self.get_evaluator("problems_checker_ruler.json", config.LANGUAGE_CPP) # Configure fake paths to the checker and its executable and compile it evaluator.path_checker_source = os.path.join( self.PATH_FIXTURES, "Ruler/Checker/RulerChecker.cpp") evaluator.path_checker_executable = os.path.join( config.PATH_CHECKERS, "RulerChecker.o") compilation_status = Compiler.compile( language=config.LANGUAGE_CPP, path_source=evaluator.path_checker_source, path_executable=evaluator.path_checker_executable) self.assertEqual(compilation_status, "") # AC self.standard_problem_helper(evaluator=evaluator, language=config.LANGUAGE_CPP, source=os.path.join( self.PATH_FIXTURES, "Ruler/Solutions/Ruler.cpp"), time_lb=0.0, memory_lb=0.0, expected_errors={}) # TL self.standard_problem_helper(evaluator=evaluator, language=config.LANGUAGE_CPP, source=os.path.join( self.PATH_FIXTURES, "Ruler/Solutions/RulerTL.cpp"), time_lb=0.2, memory_lb=1.0, expected_errors={"TIME_LIMIT": 7}) # WA self.standard_problem_helper(evaluator=evaluator, language=config.LANGUAGE_CPP, source=os.path.join( self.PATH_FIXTURES, "Ruler/Solutions/RulerWA.cpp"), time_lb=0.0, memory_lb=0.0, expected_errors={"WRONG_ANSWER": 4})
def test_run_program_exit_code(self): programs = [ ("hello", 0), # Exiting without errors ("exit42", 42), # Exiting with custom error code ("divbyzero", 4), # Exiting after division by zero ("outofbounds", 6), # Exiting after accessing invalid memory ("toomuchmemory", 6), # Exiting after trying to allocate too much memory ("timelimit", 9), # Being killed after exceeding the time limit ("tryingtowrite", 11), # Being killed after trying to write ] for program_name, expected_code in programs: path_source = os.path.join(self.PATH_FIXTURES, program_name + config.SOURCE_EXTENSION_CPP) path_executable = os.path.join(config.PATH_SANDBOX, program_name + config.EXECUTABLE_EXTENSION_CPP) status = Compiler.compile(config.LANGUAGE_CPP, path_source, path_executable) self.assertEqual(status, "") run_result = Runner.run_program(sandbox=Sandbox(), executable_path=path_executable, memory_limit=32000000, timeout=0.5, input_bytes=None) self.assertEqual(run_result.exit_code, expected_code)
def build_and_run(self, install, avd_id, keystore=None, keystore_pass='******', keystore_alias='tidev', dist_dir=None): deploy_type = 'development' if install: if keystore == None: deploy_type = 'test' else: deploy_type = 'production' aapt = os.path.join(self.tools_dir,'aapt') jar = os.path.join(self.platform_dir,'android.jar') dx = os.path.join(self.tools_dir,'dx') apkbuilder = os.path.join(self.sdk,'tools','apkbuilder') if platform.system() == "Windows": aapt += ".exe" dx += ".bat" apkbuilder += ".bat" if keystore==None: keystore = os.path.join(self.support_dir,'dev_keystore') curdir = os.getcwd() tijar = os.path.join(self.support_dir,'titanium.jar') timapjar = os.path.join(self.support_dir,'titanium-map.jar') try: os.chdir(self.project_dir) if os.path.exists('bin'): shutil.rmtree('bin') os.makedirs('bin') if os.path.exists('lib'): shutil.copy(tijar,'lib') resources_dir = os.path.join(self.top_dir,'Resources') assets_dir = os.path.join('bin','assets') asset_resource_dir = os.path.join(assets_dir,'Resources') # we re-run the create each time through in case any of our key files # have changed android = Android(self.name,self.app_id,self.sdk) android.create(os.path.abspath(os.path.join(self.top_dir,'..')),True) # transform resources def strip_slash(s): if s[0:1]=='/' or s[0:1]=='\\': return s[1:] return s def recursive_cp(dir,dest): for root, dirs, files in os.walk(dir): # Remove file from the list of files copied # that shouldn't appear in the binaries for name in ignoreFiles: if name in files: files.remove(name); for name in ignoreDirs: if name in dirs: dirs.remove(name) # Copy remaining files relative = strip_slash(root.replace(dir,'')) relative_dest = os.path.join(dest,relative) if not os.path.exists(relative_dest): os.makedirs(relative_dest) for f in files: fullpath = os.path.join(root,f) relativedest = os.path.join(dest,relative,f) print "[TRACE] COPYING: %s => %s" %(fullpath,relativedest) shutil.copy(fullpath,relativedest) if os.path.exists(asset_resource_dir): shutil.rmtree(asset_resource_dir) os.makedirs(asset_resource_dir) recursive_cp(resources_dir,asset_resource_dir) if os.path.exists(os.path.join(asset_resource_dir,'iphone')): shutil.rmtree(os.path.join(asset_resource_dir,'iphone')) if os.path.exists(os.path.join(resources_dir,'android')): recursive_cp(os.path.join(resources_dir,'android'),asset_resource_dir) shutil.rmtree(os.path.join(asset_resource_dir,'android')) sys.stdout.flush() if not os.path.exists(assets_dir): os.makedirs(assets_dir) my_avd = None google_apis_supported = False # find the AVD we've selected and determine if we support Google APIs for avd_props in avd.get_avds(self.sdk): if avd_props['id'] == avd_id: my_avd = avd_props google_apis_supported = (my_avd['name'].find('Google')!=-1) break # compile resources full_resource_dir = os.path.join(self.project_dir,asset_resource_dir) compiler = Compiler(self.app_id,full_resource_dir,False) compiler.compile() # Android SDK version --- FIXME: this is hardcoded until i hook in Nolan's code from Developer android_sdk_version = '3' # NOTE: these are built-in permissions we need -- we probably need to refine when these are needed too permissions_required = ['INTERNET','ACCESS_WIFI_STATE','ACCESS_NETWORK_STATE'] GEO_PERMISSION = [ 'ACCESS_COARSE_LOCATION', 'ACCESS_FINE_LOCATION', 'ACCESS_MOCK_LOCATION'] CONTACTS_PERMISSION = ['READ_CONTACTS'] VIBRATE_PERMISSION = ['VIBRATE'] CAMERA_PERMISSION = ['CAMERA'] # this is our module method to permission(s) trigger - for each method on the left, require the permission(s) on the right permission_mapping = { # GEO 'Geolocation.watchPosition' : GEO_PERMISSION, 'Geolocation.getCurrentPosition' : GEO_PERMISSION, 'Geolocation.watchHeading' : GEO_PERMISSION, 'Geolocation.getCurrentHeading' : GEO_PERMISSION, # MEDIA 'Media.vibrate' : VIBRATE_PERMISSION, 'Media.createVideoPlayer' : CAMERA_PERMISSION, 'Media.showCamera' : CAMERA_PERMISSION, # CONTACTS 'Contacts.createContact' : CONTACTS_PERMISSION, 'Contacts.saveContact' : CONTACTS_PERMISSION, 'Contacts.removeContact' : CONTACTS_PERMISSION, 'Contacts.addContact' : CONTACTS_PERMISSION, 'Contacts.getAllContacts' : CONTACTS_PERMISSION, 'Contacts.showContactPicker' : CONTACTS_PERMISSION, } VIDEO_ACTIVITY = """<activity android:name="org.appcelerator.titanium.TitaniumVideoActivity" android:configChanges="keyboardHidden|orientation" android:launchMode="singleTask" />""" MAP_ACTIVITY = """<activity android:name="org.appcelerator.titanium.module.map.TitaniumMapActivity" android:configChanges="keyboardHidden|orientation" android:launchMode="singleTask" /> <uses-library android:name="com.google.android.maps" />""" FACEBOOK_ACTIVITY = """<activity android:name="org.appcelerator.titanium.module.facebook.FBActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" />""" activity_mapping = { # MEDIA 'Media.createVideoPlayer' : VIDEO_ACTIVITY, # MAPS 'Map.createView' : MAP_ACTIVITY, # FACEBOOK 'Facebook.setup' : FACEBOOK_ACTIVITY, 'Facebook.login' : FACEBOOK_ACTIVITY, 'Facebook.createLoginButton' : FACEBOOK_ACTIVITY, } # this is a map of our APIs to ones that require Google APIs to be available on the device google_apis = { "Map.createView" : True } activities = [] # figure out which permissions we need based on the used module methods for mn in compiler.module_methods: try: perms = permission_mapping[mn] if perms: for perm in perms: try: permissions_required.index(perm) except: permissions_required.append(perm) except: pass try: mappings = activity_mapping[mn] try: if google_apis[mn] and not google_apis_supported: print "[WARN] Google APIs detected but a device has been selected that doesn't support them. The API call to Titanium.%s will fail using '%s'" % (mn,my_avd['name']) sys.stdout.flush() continue except: pass try: activities.index(mappings) except: activities.append(mappings) except: pass # build the permissions XML based on the permissions detected permissions_required_xml = "" for p in permissions_required: permissions_required_xml+="<uses-permission android:name=\"android.permission.%s\"/>\n\t" % p # copy any module image directories for module in compiler.modules: if module.lower() == 'map' and google_apis_supported: tijar = timapjar print "[INFO] Detected Google Maps dependency. Using Titanium + Maps" img_dir = os.path.abspath(os.path.join(template_dir,'modules',module.lower(),'images')) if os.path.exists(img_dir): dest_img_dir = os.path.join(full_resource_dir,'modules',module.lower(),'images') if os.path.exists(dest_img_dir): shutil.rmtree(dest_img_dir) os.makedirs(dest_img_dir) copy_resources(img_dir,dest_img_dir) shutil.copy(os.path.join(self.top_dir,'tiapp.xml'), assets_dir) tiapp = open(os.path.join(assets_dir, 'tiapp.xml')).read() finalxml = os.path.join(assets_dir,'tiapp.xml') tiapp = TiAppXML(finalxml) tiapp.setDeployType(deploy_type) iconname = tiapp.properties['icon'] iconpath = os.path.join(asset_resource_dir,iconname) iconext = os.path.splitext(iconpath)[1] if not os.path.exists(os.path.join('res','drawable')): os.makedirs(os.path.join('res','drawable')) existingicon = os.path.join('res','drawable','appicon%s' % iconext) if os.path.exists(existingicon): os.remove(existingicon) if os.path.exists(iconpath): shutil.copy(iconpath,existingicon) # make our Titanium theme for our icon resfiledir = os.path.join('res','values') if not os.path.exists(resfiledir): os.makedirs(resfiledir) resfilepath = os.path.join(resfiledir,'theme.xml') if not os.path.exists(resfilepath): resfile = open(resfilepath,'w') TITANIUM_THEME="""<?xml version="1.0" encoding="utf-8"?> <resources> <style name="Theme.Titanium" parent="android:Theme"> <item name="android:windowBackground">@drawable/background</item> </style> </resources> """ resfile.write(TITANIUM_THEME) resfile.close() # create our background image which acts as splash screen during load splashimage = os.path.join(asset_resource_dir,'default.png') if os.path.exists(splashimage): print "[DEBUG] found splash screen at %s" % os.path.abspath(splashimage) shutil.copy(splashimage,os.path.join('res','drawable','background.png')) src_dir = os.path.join(self.project_dir, 'src') android_manifest = os.path.join(self.project_dir, 'AndroidManifest.xml') android_manifest_to_read = android_manifest # NOTE: allow the user to use their own custom AndroidManifest if they put a file named # AndroidManifest.custom.xml in their android project directory in which case all bets are # off android_custom_manifest = os.path.join(self.project_dir, 'AndroidManifest.custom.xml') if os.path.exists(android_custom_manifest): android_manifest_to_read = android_custom_manifest print "[INFO] Detected custom ApplicationManifest.xml -- no Titanium version migration supported" # we need to write out the new manifest manifest_contents = open(android_manifest_to_read,'r').read() manifest_contents = manifest_contents.replace('<!-- TI_ACTIVITIES -->',"\n\n\t\t".join(activities)) manifest_contents = manifest_contents.replace('<!-- TI_PERMISSIONS -->',permissions_required_xml) manifest_contents = manifest_contents.replace('<uses-sdk android:minSdkVersion="3" />', '<uses-sdk android:minSdkVersion="%s" />' % android_sdk_version) # write out the new manifest amf = open(android_manifest,'w') amf.write(manifest_contents) amf.close() res_dir = os.path.join(self.project_dir, 'res') output = run.run([aapt, 'package', '-m', '-J', src_dir, '-M', android_manifest, '-S', res_dir, '-I', jar]) if output == None: sys.exit(1) success = re.findall(r'ERROR (.*)',output) if len(success) > 0: print "[ERROR] %s" % success[0] sys.exit(1) srclist = [] jarlist = [] for root, dirs, files in os.walk(os.path.join(self.project_dir,'src')): # Strip out directories we shouldn't traverse for name in ignoreDirs: if name in dirs: dirs.remove(name) if len(files) > 0: for f in files: if f in ignoreFiles : continue path = root + os.sep + f srclist.append(path) project_module_dir = os.path.join(self.top_dir,'modules','android') if os.path.exists(project_module_dir): for root, dirs, files in os.walk(project_module_dir): # Strip out directories we shouldn't traverse for name in ignoreDirs: if name in dirs: dirs.remove(name) if len(files) > 0: for f in files: path = root + os.sep + f ext = splitext(f)[-1] if ext in ('.java'): srclist.append(path) elif ext in ('.jar'): jarlist.append(path) classes_dir = os.path.join(self.project_dir, 'bin', 'classes') if not os.path.exists(classes_dir): os.makedirs(classes_dir) jarsigner = "jarsigner" javac = "javac" if platform.system() == "Windows": if os.environ.has_key("JAVA_HOME"): home_jarsigner = os.path.join(os.environ["JAVA_HOME"], "bin", "jarsigner.exe") home_javac = os.path.join(os.environ["JAVA_HOME"], "bin", "javac.exe") if os.path.exists(home_jarsigner): jarsigner = home_jarsigner if os.path.exists(home_javac): javac = home_javac else: found = False for path in os.environ['PATH'].split(os.pathsep): if os.path.exists(os.path.join(path, 'jarsigner.exe')) and os.path.exists(os.path.join(path, 'javac.exe')): jarsigner = os.path.join(path, 'jarsigner.exe') javac = os.path.join(path, 'javac.exe') found = True break if not found: print "[ERROR] Error locating JDK: set $JAVA_HOME or put javac and jarsigner on your $PATH" sys.exit(1) # see if the user has app data and if so, compile in the user data # such that it can be accessed automatically using Titanium.App.Properties.getString app_data_cfg = os.path.join(self.top_dir,"appdata.cfg") if os.path.exists(app_data_cfg): props = read_properties(open(app_data_cfg,"r")) module_data = '' for key in props.keys(): data = props[key] module_data+="properties.setString(\"%s\",\"%s\");\n " % (key,data) print("[DEBUG] detected user application data at = %s"% app_data_cfg) sys.stdout.flush() dtf = os.path.join(src_dir,"AppUserData.java") if os.path.exists(dtf): os.remove(dtf) ctf = open(dtf,"w") cf_template = open(os.path.join(template_dir,'templates','AppUserData.java'),'r').read() cf_template = cf_template.replace('__MODULE_BODY__',module_data) ctf.write(cf_template) ctf.close() srclist.append(dtf) classpath = jar + os.pathsep + tijar + os.pathsep.join(jarlist) javac_command = [javac, '-classpath', classpath, '-d', classes_dir, '-sourcepath', src_dir] javac_command += srclist print "[DEBUG] %s" % javac_command sys.stdout.flush() out = run.run(javac_command) classes_dex = os.path.join(self.project_dir, 'bin', 'classes.dex') if platform.system() == "Windows": run.run([dx, '--dex', '--output='+classes_dex, classes_dir, tijar]) else: run.run([dx, '-JXmx512M', '--dex', '--output='+classes_dex, classes_dir, tijar]) ap_ = os.path.join(self.project_dir, 'bin', 'app.ap_') run.run([aapt, 'package', '-f', '-M', 'AndroidManifest.xml', '-A', assets_dir, '-S', 'res', '-I', jar, '-I', tijar, '-F', ap_]) unsigned_apk = os.path.join(self.project_dir, 'bin', 'app-unsigned.apk') run.run([apkbuilder, unsigned_apk, '-u', '-z', ap_, '-f', classes_dex, '-rf', src_dir, '-rj', tijar]) if dist_dir: app_apk = os.path.join(dist_dir, project_name + '.apk') else: app_apk = os.path.join(self.project_dir, 'bin', 'app.apk') output = run.run([jarsigner, '-storepass', keystore_pass, '-keystore', keystore, '-signedjar', app_apk, unsigned_apk, keystore_alias]) success = re.findall(r'RuntimeException: (.*)',output) if len(success) > 0: print "[ERROR] %s " %success[0] sys.exit(1) # NOTE: we can't zipalign until we officially support 1.6+ # # attempt to zipalign -- this only exists in 1.6 and above so be nice # zipalign = os.path.join(self.tools_dir,'zipalign') # if platform.system() == "Windows": # zipalign+=".exe" # # if os.path.exists(zipalign): # #zipalign -v 4 source.apk destination.apk # run.run([zipalign, '-v', '4', app_apk, app_apk+'z']) # os.rename(app_apk+'z',app_apk) if dist_dir: sys.exit(0) out = subprocess.Popen([self.adb,'get-state'], stderr=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0] out = str(out).strip() # try a few times as sometimes it fails waiting on boot attempts = 0 launched = False launch_failed = False while attempts < 5: try: cmd = [self.adb] if install: self.wait_for_device('d') print "[INFO] Installing application on emulator" cmd += ['-d', 'install', '-r', app_apk] else: self.wait_for_device('e') print "[INFO] Installing application on device" cmd += ['-e', 'install', '-r', app_apk] if run.run(cmd)==None: launch_failed = True elif not install: launched = True break except: time.sleep(3) attempts+=1 if launched: print "[INFO] Launching application ... %s" % self.name sys.stdout.flush() run.run([self.adb, '-e' , 'shell', 'am', 'start', '-a', 'android.intent.action.MAIN', '-c','android.intent.category.LAUNCHER', '-n', '%s/.%sActivity' % (self.app_id , self.classname)]) print "[INFO] Deployed %s ... Application should be running." % self.name elif launch_failed==False: print "[INFO] Application installed. Launch from drawer on Home Screen" finally: os.chdir(curdir) sys.stdout.flush()
def main(args): argc = len(args) if argc < 5 or (argc > 1 and args[1] == 'distribute' and argc!=9): print "%s <command> <version> <project_dir> <appid> <name> [uuid] [dist_name] [output_dir]" % os.path.basename(args[0]) print print "available commands: " print print " install install the app to itunes for testing on iphone" print " simulator build and run on the iphone simulator" print " distribute build final distribution bundle" sys.exit(1) print "[INFO] One moment, building ..." sys.stdout.flush() start_time = time.time() iphone_version = dequote(args[2].decode("utf-8")) simulator = os.path.abspath(os.path.join(template_dir,'iphonesim')) command = args[1].decode("utf-8") project_dir = os.path.expanduser(dequote(args[3].decode("utf-8"))) appid = dequote(args[4].decode("utf-8")) name = dequote(args[5].decode("utf-8")) target = 'Debug' deploytype = 'development' devicefamily = 'iphone' debug = False if command == 'distribute': appuuid = dequote(args[6].decode("utf-8")) dist_name = dequote(args[7].decode("utf-8")) output_dir = os.path.expanduser(dequote(args[8].decode("utf-8"))) target = 'Release' deploytype = 'production' elif command == 'simulator': deploytype = 'development' debug = True devicefamily = dequote(args[6].decode("utf-8")) elif command == 'install': appuuid = dequote(args[6].decode("utf-8")) dist_name = dequote(args[7].decode("utf-8")) deploytype = 'test' iphone_dir = os.path.abspath(os.path.join(project_dir,'build','iphone')) project_resources = os.path.join(project_dir,'Resources') app_name = name+'.app' app_folder_name = '%s-iphoneos' % target app_dir = os.path.abspath(os.path.join(iphone_dir,'build','%s-iphonesimulator'%target,name+'.app')) app_bundle_folder = os.path.abspath(os.path.join(iphone_dir,'build',app_folder_name)) app_bundle = os.path.join(app_bundle_folder,app_name) iphone_resources_dir = os.path.join(iphone_dir,'Resources') iphone_tmp_dir = os.path.join(iphone_dir,'tmp') if not os.path.exists(iphone_dir): print "Could not find directory: %s" % iphone_dir sys.exit(1) cwd = os.getcwd() app_js = os.path.join(project_dir,'Resources','app.js') if not os.path.exists(app_js): print "[ERROR] This project looks to not be ported to 0.9+." print "[ERROR] Your project is missing app.js. Please make sure to port your application to 0.9+ API" print "[ERROR] before continuing or choose a previous version of the SDK." sys.exit(1) tiapp_xml = os.path.join(project_dir,'tiapp.xml') if not os.path.exists(tiapp_xml): print "Missing tiapp.xml at %s" % tiapp_xml sys.exit(3) ti = TiAppXML(tiapp_xml) encrypt = False if ti.properties.has_key('encrypt'): encrypt = (ti.properties['encrypt']=='true') # compile resources compiler = Compiler(appid,project_dir,encrypt,debug) compiler.compile() # find the module directory relative to the root of the SDK tp_module_dir = os.path.abspath(os.path.join(template_dir,'..','..','..','..','modules','iphone')) tp_modules = [] for module in ti.properties['modules']: tp_name = module['name'].lower() tp_version = module['version'] tp_dir = os.path.join(tp_module_dir,tp_name,tp_version) if not os.path.exists(tp_dir): print "[ERROR] Third-party module: %s/%s detected in tiapp.xml but not found at %s" % (tp_name,tp_version,tp_dir) #sys.exit(1) tp_module = os.path.join(tp_dir,'lib%s.a' % tp_name) if not os.path.exists(tp_module): print "[ERROR] Third-party module: %s/%s missing library at %s" % (tp_name,tp_version,tp_module) #sys.exit(1) tp_modules.append(tp_module) print "[INFO] Detected third-party module: %s/%s" % (tp_name,tp_version) # copy module resources img_dir = os.path.join(tp_dir,'assets','images') if os.path.exists(img_dir): dest_img_dir = os.path.join(iphone_tmp_dir,'modules',tp_name,'images') if os.path.exists(dest_img_dir): shutil.rmtree(dest_img_dir) os.makedirs(dest_img_dir) copy_module_resources(img_dir,dest_img_dir) # compiler dependencies dependscompiler = DependencyCompiler() dependscompiler.compile(template_dir,project_dir,tp_modules) # copy any module image directories for module in dependscompiler.modules: img_dir = os.path.abspath(os.path.join(template_dir,'modules',module.lower(),'images')) if os.path.exists(img_dir): dest_img_dir = os.path.join(iphone_tmp_dir,'modules',module.lower(),'images') if os.path.exists(dest_img_dir): shutil.rmtree(dest_img_dir) os.makedirs(dest_img_dir) copy_module_resources(img_dir,dest_img_dir) # copy over main since it can change with each release main_template = codecs.open(os.path.join(template_dir,'main.m'),'r','utf-8','replace').read() main_template = main_template.replace('__PROJECT_NAME__',name) main_template = main_template.replace('__PROJECT_ID__',appid) main_template = main_template.replace('__DEPLOYTYPE__',deploytype) main_template = main_template.replace('__APP_ID__',appid) main_template = main_template.replace('__APP_ANALYTICS__',ti.properties['analytics']) main_template = main_template.replace('__APP_PUBLISHER__',ti.properties['publisher']) main_template = main_template.replace('__APP_URL__',ti.properties['url']) main_template = main_template.replace('__APP_NAME__',ti.properties['name']) main_template = main_template.replace('__APP_VERSION__',ti.properties['version']) main_template = main_template.replace('__APP_DESCRIPTION__',ti.properties['description']) main_template = main_template.replace('__APP_COPYRIGHT__',ti.properties['copyright']) main_template = main_template.replace('__APP_GUID__',ti.properties['guid']) main_dest = codecs.open(os.path.join(iphone_dir,'main.m'),'w','utf-8','replace') main_dest.write(main_template.encode("utf-8")) main_dest.close() # attempt to use a slightly faster xcodeproject template when simulator which avoids # optimizing PNGs etc if deploytype == 'simulator': xcodeproj = codecs.open(os.path.join(template_dir,'project_simulator.pbxproj'),'r','utf-8','replace').read() else: xcodeproj = codecs.open(os.path.join(template_dir,'project.pbxproj'),'r','utf-8','replace').read() xcodeproj = xcodeproj.replace('__PROJECT_NAME__',name) xcodeproj = xcodeproj.replace('__PROJECT_ID__',appid) xcode_dir = os.path.join(iphone_dir,name+'.xcodeproj') xcode_pbx = codecs.open(os.path.join(xcode_dir,'project.pbxproj'),'w','utf-8','replace') xcode_pbx.write(xcodeproj.encode("utf-8")) xcode_pbx.close() # copy in the default PNG default_png = os.path.join(project_resources,'iphone','Default.png') if os.path.exists(default_png): target_png = os.path.join(iphone_resources_dir,'Default.png') if os.path.exists(target_png): os.remove(target_png) shutil.copy(default_png,target_png) # TODO: review this with new module SDK # in case the developer has their own modules we can pick them up project_module_dir = os.path.join(project_dir,"modules","iphone") # copy in any resources in our module like icons if os.path.exists(project_module_dir): copy_module_resources(project_module_dir,iphone_tmp_dir) sys.stdout.flush() source_lib=os.path.join(template_dir,'libTiCore.a') target_lib=os.path.join(iphone_resources_dir,'libTiCore.a') # attempt to only copy (this takes ~7sec) if its changed if not os.path.exists(target_lib) or os.path.getsize(source_lib)!=os.path.getsize(target_lib): shutil.copy(os.path.join(template_dir,'libTiCore.a'),os.path.join(iphone_resources_dir,'libTiCore.a')) # must copy the XIBs each time since they can change per SDK xib = 'MainWindow_%s.xib' % devicefamily s = os.path.join(template_dir,xib) t = os.path.join(iphone_resources_dir,'MainWindow.xib') if not os.path.exists(t) or os.path.getsize(s)!=os.path.getsize(t): shutil.copy(s,t) def is_adhoc(uuid): path = "~/Library/MobileDevice/Provisioning Profiles/%s.mobileprovision" % uuid f = os.path.expanduser(path) if os.path.exists(f): c = codecs.open(f,'r','utf-8','replace').read() return c.find("ProvisionedDevices")!=-1 return False def add_plist(dir): if not os.path.exists(dir): os.makedirs(dir) # write out the modules we're using in the APP for m in dependscompiler.required_modules: print "[INFO] Detected required module: Titanium.%s" % (m) if command == 'install': version = ti.properties['version'] # we want to make sure in debug mode the version always changes version = "%s.%d" % (version,time.time()) ti.properties['version']=version # write out the updated Info.plist infoplist_tmpl = os.path.join(iphone_dir,'Info.plist.template') infoplist = os.path.join(iphone_dir,'Info.plist') appicon = ti.generate_infoplist(infoplist,infoplist_tmpl,appid,devicefamily) # copy the app icon to the build resources iconf = os.path.join(iphone_tmp_dir,appicon) iconf_dest = os.path.join(dir,appicon) if os.path.exists(iconf): shutil.copy(iconf, iconf_dest) try: os.chdir(iphone_dir) # write out plist add_plist(os.path.join(iphone_dir,'Resources')) print "[DEBUG] compile checkpoint: %0.2f seconds" % (time.time()-start_time) print "[INFO] Executing XCode build..." print "[BEGIN_VERBOSE] Executing XCode Compiler <span>[toggle output]</span>" sys.stdout.flush() if command == 'simulator': # first build it log_id = uuid.uuid4() # make sure it's clean if os.path.exists(app_dir): shutil.rmtree(app_dir) deploy_target = "IPHONEOS_DEPLOYMENT_TARGET=3.1" device_target = "TARGETED_DEVICE_FAMILY=iPhone" if devicefamily == 'ipad': iphone_version='3.2' device_target=" TARGETED_DEVICE_FAMILY=iPad" output = run.run([ "xcodebuild", "-configuration", "Debug", "-sdk", "iphonesimulator%s" % iphone_version, "WEB_SRC_ROOT=%s" % iphone_tmp_dir, "GCC_PREPROCESSOR_DEFINITIONS=__LOG__ID__=%s DEPLOYTYPE=development DEBUG=1" % log_id, deploy_target, device_target ]) print output print "[END_VERBOSE]" sys.stdout.flush() shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1 or output.find("ld returned 1")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # first make sure it's not running kill_simulator() logger = os.path.realpath(os.path.join(template_dir,'logger.py')) # start the logger log = subprocess.Popen([ logger, str(log_id)+'.log', iphone_version ]) sim = None def handler(signum, frame): print "[INFO] Simulator is exiting" sys.stdout.flush() if not log == None: try: os.system("kill -2 %s" % str(log.pid)) except: pass if not sim == None and signum!=3: try: os.system("kill -3 %s" % str(sim.pid)) except: pass kill_simulator() sys.exit(0) signal.signal(signal.SIGHUP, handler) signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGABRT, handler) signal.signal(signal.SIGTERM, handler) print "[INFO] Launching application in Simulator" sys.stdout.flush() sys.stderr.flush() # launch the simulator sim = subprocess.Popen("\"%s\" launch \"%s\" %s %s" % (simulator,app_dir,iphone_version,devicefamily),shell=True) # activate the simulator window ass = os.path.join(template_dir,'iphone_sim_activate.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) end_time = time.time()-start_time print "[INFO] Launched application in Simulator (%0.2f seconds)" % end_time sys.stdout.flush() sys.stderr.flush() os.waitpid(sim.pid,0) print "[INFO] Application has exited from Simulator" # in this case, the user has exited the simulator itself # and not clicked Stop Emulator from within Developer so we kill # our tail log process but let simulator keep running if not log == None: try: os.system("kill -2 %s" % str(log.pid)) except: pass sys.exit(0) elif command == 'install': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) output = run.run(["xcodebuild", "-configuration", "Debug", "-sdk", "iphoneos%s" % iphone_version, "CODE_SIGN_ENTITLEMENTS=", "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=test'", "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Developer: %s" % dist_name ]) shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print "[ERROR] Code sign error: %s" % error[0].strip() sys.exit(1) print "[INFO] Installing application in iTunes ... one moment" sys.stdout.flush() # for install, launch itunes with the app cmd = "open -b com.apple.itunes \"%s\"" % app_bundle os.system(cmd) # now run our applescript to tell itunes to sync to get # the application on the phone ass = os.path.join(template_dir,'itunes_sync.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) print "[INFO] iTunes sync initiated" sys.stdout.flush() elif command == 'distribute': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) # in this case, we have to do different things based on if it's # an ad-hoc distribution cert or not - in the case of non-adhoc # we don't use the entitlements file but in ad hoc we need to adhoc_line = "CODE_SIGN_ENTITLEMENTS=" deploytype = "production_adhoc" if not is_adhoc(appuuid): adhoc_line="CODE_SIGN_ENTITLEMENTS = Resources/Entitlements.plist" deploytype = "production" # build the final release distribution output = run.run(["xcodebuild", "-configuration", "Release", "-sdk", "iphoneos%s" % iphone_version, "%s" % adhoc_line, "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=%s'" % deploytype, "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Distribution: %s" % dist_name ]) shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print "[ERROR] Code sign error: %s" % error[0].strip() sys.exit(1) # switch to app_bundle for zip os.chdir(app_bundle_folder) # you *must* use ditto here or it won't upload to appstore os.system('ditto -ck --keepParent --sequesterRsrc "%s" "%s/%s.zip"' % (app_name,output_dir,app_name)) sys.exit(0) else: print "Unknown command: %s" % command sys.exit(2) finally: os.chdir(cwd)
def main(args): argc = len(args) if argc < 5 or (argc > 1 and args[1] == 'distribute' and argc!=9): print "%s <command> <version> <project_dir> <appid> <name> [uuid] [dist_name] [output_dir]" % os.path.basename(args[0]) print print "available commands: " print print " install install the app to itunes for testing on iphone" print " simulator build and run on the iphone simulator" print " distribute build final distribution bundle" sys.exit(1) print "One moment, building ..." simulator = os.path.abspath(os.path.join(template_dir,'iphonesim')) command = args[1] iphone_version = dequote(args[2]) project_dir = os.path.expanduser(dequote(args[3])) appid = dequote(args[4]) name = dequote(args[5]) target = 'Debug' deploytype = 'development' if command == 'distribute': appuuid = dequote(args[6]) dist_name = dequote(args[7]) output_dir = os.path.expanduser(dequote(args[8])) target = 'Release' deploytype = 'production' elif command == 'simulator': deploytype = 'test' elif command == 'install': appuuid = dequote(args[6]) dist_name = dequote(args[7]) iphone_dir = os.path.abspath(os.path.join(project_dir,'build','iphone')) project_resources = os.path.join(project_dir,'Resources') app_name = name+'.app' app_folder_name = '%s-iphoneos' % target app_dir = os.path.abspath(os.path.join(iphone_dir,'build','%s-iphonesimulator'%target,name+'.app')) app_bundle_folder = os.path.abspath(os.path.join(iphone_dir,'build',app_folder_name)) app_bundle = os.path.join(app_bundle_folder,app_name) iphone_resources_dir = os.path.join(iphone_dir,'Resources') iphone_tmp_dir = os.path.join(iphone_dir,'tmp') if not os.path.exists(iphone_dir): print "Could not find directory: %s" % iphone_dir sys.exit(1) cwd = os.getcwd() # compile resources compiler = Compiler(appid,project_dir) compiler.compile() # copy in the default PNG default_png = os.path.join(project_resources,'iphone','Default.png') if os.path.exists(default_png): target_png = os.path.join(iphone_resources_dir,'Default.png') if os.path.exists(target_png): os.remove(target_png) shutil.copy(default_png,target_png) # copy in the write version of the titanium runtime based on which iphone # version the project is building for shutil.copy(os.path.join(template_dir,'libTitanium-%s.a'%iphone_version),os.path.join(iphone_resources_dir,'libTitanium.a')) # must copy the XIBs each time since they can change per SDK os.chdir(template_dir) for xib in glob.glob('*.xib'): shutil.copy(os.path.join(template_dir,xib),os.path.join(iphone_resources_dir,xib)) os.chdir(cwd) # cleanup compiled resources def cleanup_compiled_resources(dir): for root, dirs, files in os.walk(dir): if len(files) > 0: for f in files: fp = os.path.splitext(f) if len(fp)!=2: continue if not fp[1] in ['.html','.js','.css','.a']: continue basedir = root.replace(dir+'/','') os.remove(os.path.join(dir,basedir,f)) def add_plist(dir): tiapp_xml = os.path.join(project_dir,'tiapp.xml') if not os.path.exists(tiapp_xml): print "Missing tiapp.xml at %s" % tiapp_xml sys.exit(3) if not os.path.exists(dir): os.makedirs(dir) plist_f = os.path.join(dir,'tiapp.plist') plist = open(plist_f,'w+') module_str = '' # write out the modules we're using in the APP for m in compiler.modules: module_str += ' <key>%s</key>\n <real>0.0</real>\n' % (m.lower()) ti = TiAppXML(tiapp_xml) tip = TiPlist(ti) plist_template = tip.generate(module_str,appid,deploytype) # write out the generated tiapp.plist plist.write(plist_template) plist.close() # write out the updated Info.plist infoplist_tmpl = os.path.join(iphone_dir,'Info.plist.template') infoplist = os.path.join(iphone_dir,'Info.plist') appicon = tip.generate_infoplist(infoplist,infoplist_tmpl,appid) # copy the app icon to the build resources iconf = os.path.join(iphone_tmp_dir,appicon) iconf_dest = os.path.join(dir,appicon) if os.path.exists(iconf): shutil.copy(iconf, iconf_dest) # compile to binary plist os.system("/usr/bin/plutil -convert binary1 \"%s\"" % plist_f) try: os.chdir(iphone_dir) # write out plist add_plist(os.path.join(iphone_dir,'Resources')) if command == 'simulator': # first build it log_id = uuid.uuid4() # make sure it's clean if os.path.exists(app_dir): shutil.rmtree(app_dir) os.system("xcodebuild -configuration Debug -sdk iphonesimulator%s WEB_SRC_ROOT='%s' GCC_PREPROCESSOR_DEFINITIONS='__LOG__ID__=%s DEPLOYTYPE=development'" % (iphone_version,iphone_tmp_dir,log_id)) # clean since the xcodebuild copies cleanup_compiled_resources(app_dir) # first make sure it's not running kill_simulator() logger = os.path.realpath(os.path.join(template_dir,'logger.py')) # start the logger log = subprocess.Popen([ logger, str(log_id)+'.log' ]) sim = None def handler(signum, frame): print "signal caught: %d" % signum if not log == None: print "calling log kill on %d" % log.pid try: os.system("kill -3 %d" % log.pid) except: pass if not sim == None: print "calling sim kill on %d" % sim.pid try: os.system("kill -3 %d" % sim.pid) except: pass kill_simulator() sys.exit(0) signal.signal(signal.SIGHUP, handler) signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGABRT, handler) signal.signal(signal.SIGTERM, handler) # launch the simulator sim = subprocess.Popen("\"%s\" launch \"%s\" %s" % (simulator,app_dir,iphone_version),shell=True) # activate the simulator window ass = os.path.join(template_dir,'iphone_sim_activate.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) os.waitpid(sim.pid,0) sim = None handler(3,None) sys.exit(0) elif command == 'install': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) # clean since the xcodebuild copies cleanup_compiled_resources(app_bundle) output = run.run(["xcodebuild", "-configuration", "Debug", "-sdk", "iphoneos%s" % iphone_version, "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=test'", "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Developer: %s" % dist_name ]) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print error[0].strip() sys.exit(1) # for install, launch itunes with the app cmd = "open -b com.apple.itunes \"%s\"" % app_bundle os.system(cmd) # now run our applescript to tell itunes to sync to get # the application on the phone ass = os.path.join(template_dir,'itunes_sync.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) elif command == 'distribute': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) # build the final release distribution output = run.run(["xcodebuild", "-configuration", "Release", "-sdk", "iphoneos%s" % iphone_version, "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=production'", "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Distribution: %s" % dist_name ]) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print error[0].strip() sys.exit(1) # switch to app_bundle for zip os.chdir(app_bundle_folder) # you *must* use ditto here or it won't upload to appstore os.system('ditto -ck --keepParent --sequesterRsrc "%s" "%s/%s.zip"' % (app_name,output_dir,app_name)) sys.exit(0) else: print "Unknown command: %s" % command sys.exit(2) finally: os.chdir(cwd)
def main(args): argc = len(args) if argc == 2 and (args[1]=='--help' or args[1]=='-h'): print "%s <command> <version> <project_dir> <appid> <name> [options]" % os.path.basename(args[0]) print print "available commands: " print print " install install the app to itunes for testing on iphone" print " simulator build and run on the iphone simulator" print " distribute build final distribution bundle" sys.exit(1) print "[INFO] One moment, building ..." sys.stdout.flush() start_time = time.time() iphone_version = dequote(args[2].decode("utf-8")) iphonesim = os.path.abspath(os.path.join(template_dir,'iphonesim')) command = args[1].decode("utf-8") project_dir = os.path.expanduser(dequote(args[3].decode("utf-8"))) appid = dequote(args[4].decode("utf-8")) name = dequote(args[5].decode("utf-8")) target = 'Debug' deploytype = 'development' devicefamily = None debug = False simulator = False if command == 'distribute': appuuid = dequote(args[6].decode("utf-8")) dist_name = dequote(args[7].decode("utf-8")) output_dir = os.path.expanduser(dequote(args[8].decode("utf-8"))) if argc > 9: devicefamily = dequote(args[9].decode("utf-8")) target = 'Release' deploytype = 'production' elif command == 'simulator': deploytype = 'development' debug = True simulator = True if argc > 6: devicefamily = dequote(args[6].decode("utf-8")) elif command == 'install': appuuid = dequote(args[6].decode("utf-8")) dist_name = dequote(args[7].decode("utf-8")) if argc > 8: devicefamily = dequote(args[8].decode("utf-8")) deploytype = 'test' iphone_dir = os.path.abspath(os.path.join(project_dir,'build','iphone')) project_resources = os.path.join(project_dir,'Resources') app_name = name+'.app' app_folder_name = '%s-iphoneos' % target app_dir = os.path.abspath(os.path.join(iphone_dir,'build','%s-iphonesimulator'%target,name+'.app')) app_bundle_folder = os.path.abspath(os.path.join(iphone_dir,'build',app_folder_name)) app_bundle = os.path.join(app_bundle_folder,app_name) iphone_resources_dir = os.path.join(iphone_dir,'Resources') iphone_tmp_dir = os.path.join(iphone_dir,'tmp') # TODO: review this with new module SDK # in case the developer has their own modules we can pick them up project_module_dir = os.path.join(project_dir,"modules","iphone") if not os.path.exists(iphone_dir): print "Could not find directory: %s" % iphone_dir sys.exit(1) cwd = os.getcwd() app_js = os.path.join(project_dir,'Resources','app.js') if not os.path.exists(app_js): print "[ERROR] This project looks to not be ported to 0.9+." print "[ERROR] Your project is missing app.js. Please make sure to port your application to 0.9+ API" print "[ERROR] before continuing or choose a previous version of the SDK." sys.exit(1) tiapp_xml = os.path.join(project_dir,'tiapp.xml') if not os.path.exists(tiapp_xml): print "Missing tiapp.xml at %s" % tiapp_xml sys.exit(3) ti = TiAppXML(tiapp_xml) encrypt = False if ti.properties.has_key('encrypt'): encrypt = (ti.properties['encrypt']=='true') force_rebuild = True force_compile = False version_file = None log_id = None source_lib=os.path.join(template_dir,'libTiCore.a') target_lib=os.path.join(iphone_resources_dir,'libTiCore.a') lib_hash = None # for simulator, we only need to compile once so we check to # see if we've already compiled for the simulator for the # same version of titanium and if so, we don't need to rebuild if simulator: version_file = os.path.join(iphone_resources_dir,'.simulator') if os.path.exists(app_dir): if os.path.exists(version_file): line = open(version_file).read().strip() lines = line.split(",") v = lines[0] log_id = lines[1] if len(lines) > 2: lib_hash = lines[2] if iphone_version!=lines[3]: force_rebuild=True if lib_hash==None: force_rebuild = True else: if template_dir==v and force_rebuild==False: force_rebuild = False else: log_id = None if force_rebuild==False: if not os.path.exists(os.path.join(iphone_dir,'Classes','ApplicationRouting.h')): force_rebuild = True force_compile = True if force_rebuild==False and not os.path.exists(os.path.join(iphone_dir,'Classes','ApplicationRouting.m')): force_rebuild = True force_compile = True # if using custom modules, we have to force rebuild each time for now if force_rebuild==False and ti.properties.has_key('modules') and len(ti.properties['modules']) > 0: force_rebuild = True fd = open(source_lib,'rb') m = hashlib.md5() m.update(fd.read(1024)) # just read 1K, it's binary new_lib_hash = m.hexdigest() fd.close() if new_lib_hash!=lib_hash: force_rebuild=True lib_hash=new_lib_hash # only do this stuff when we're in a force rebuild which is either # non-simulator build or when we're simulator and it's the first time # or different version of titanium # if force_rebuild: print "[INFO] Performing full rebuild. This will take a little bit. Hold tight..." if os.path.exists(app_dir): shutil.rmtree(app_dir) # compile resources only if non-simulator (for speedups) compiler = Compiler(appid,project_dir,encrypt,debug) compiler.compile() # find the module directory relative to the root of the SDK tp_module_dir = os.path.abspath(os.path.join(template_dir,'..','..','..','..','modules','iphone')) tp_modules = [] tp_depends = [] def find_depends(config,depends): for line in open(config).readlines(): if line.find(':')!=-1: (token,value)=line.split(':') for entry in value.join(','): entry = entry.strip() try: depends.index(entry) except: depends.append(entry) for module in ti.properties['modules']: tp_name = module['name'].lower() tp_version = module['version'] tp_dir = os.path.join(tp_module_dir,tp_name,tp_version) if not os.path.exists(tp_dir): print "[ERROR] Third-party module: %s/%s detected in tiapp.xml but not found at %s" % (tp_name,tp_version,tp_dir) #sys.exit(1) tp_module = os.path.join(tp_dir,'lib%s.a' % tp_name) if not os.path.exists(tp_module): print "[ERROR] Third-party module: %s/%s missing library at %s" % (tp_name,tp_version,tp_module) #sys.exit(1) tp_config = os.path.join(tp_dir,'manifest') if not os.path.exists(tp_config): print "[ERROR] Third-party module: %s/%s missing manifest at %s" % (tp_name,tp_version,tp_config) find_depends(tp_config,tp_depends) tp_modules.append(tp_module) print "[INFO] Detected third-party module: %s/%s" % (tp_name,tp_version) # copy module resources img_dir = os.path.join(tp_dir,'assets','images') if os.path.exists(img_dir): dest_img_dir = os.path.join(iphone_tmp_dir,'modules',tp_name,'images') if os.path.exists(dest_img_dir): shutil.rmtree(dest_img_dir) os.makedirs(dest_img_dir) copy_module_resources(img_dir,dest_img_dir) # compiler dependencies dependscompiler = DependencyCompiler() dependscompiler.compile(template_dir,project_dir,tp_modules,tp_depends,simulator,iphone_version) # copy over main since it can change with each release main_template = codecs.open(os.path.join(template_dir,'main.m'),'r','utf-8','replace').read() main_template = main_template.replace('__PROJECT_NAME__',name) main_template = main_template.replace('__PROJECT_ID__',appid) main_template = main_template.replace('__DEPLOYTYPE__',deploytype) main_template = main_template.replace('__APP_ID__',appid) main_template = main_template.replace('__APP_ANALYTICS__',ti.properties['analytics']) main_template = main_template.replace('__APP_PUBLISHER__',ti.properties['publisher']) main_template = main_template.replace('__APP_URL__',ti.properties['url']) main_template = main_template.replace('__APP_NAME__',ti.properties['name']) main_template = main_template.replace('__APP_VERSION__',ti.properties['version']) main_template = main_template.replace('__APP_DESCRIPTION__',ti.properties['description']) main_template = main_template.replace('__APP_COPYRIGHT__',ti.properties['copyright']) main_template = main_template.replace('__APP_GUID__',ti.properties['guid']) if simulator: main_template = main_template.replace('__APP_RESOURCE_DIR__',os.path.abspath(app_dir)) else: main_template = main_template.replace('__APP_RESOURCE_DIR__','') # copy any module image directories for module in dependscompiler.modules: img_dir = os.path.abspath(os.path.join(template_dir,'modules',module.lower(),'images')) if os.path.exists(img_dir): dest_img_dir = os.path.join(iphone_tmp_dir,'modules',module.lower(),'images') if os.path.exists(dest_img_dir): shutil.rmtree(dest_img_dir) os.makedirs(dest_img_dir) copy_module_resources(img_dir,dest_img_dir) main_dest = codecs.open(os.path.join(iphone_dir,'main.m'),'w','utf-8','replace') main_dest.write(main_template.encode("utf-8")) main_dest.close() # attempt to use a slightly faster xcodeproject template when simulator which avoids # optimizing PNGs etc if simulator: xcodeproj = codecs.open(os.path.join(template_dir,'project_simulator.pbxproj'),'r','utf-8','replace').read() else: xcodeproj = codecs.open(os.path.join(template_dir,'project.pbxproj'),'r','utf-8','replace').read() xcodeproj = xcodeproj.replace('__PROJECT_NAME__',name) xcodeproj = xcodeproj.replace('__PROJECT_ID__',appid) xcode_dir = os.path.join(iphone_dir,name+'.xcodeproj') xcode_pbx = codecs.open(os.path.join(xcode_dir,'project.pbxproj'),'w','utf-8','replace') xcode_pbx.write(xcodeproj.encode("utf-8")) xcode_pbx.close() # attempt to only copy (this takes ~7sec) if its changed if not os.path.exists(target_lib) or os.path.getsize(source_lib)!=os.path.getsize(target_lib): shutil.copy(os.path.join(template_dir,'libTiCore.a'),os.path.join(iphone_resources_dir,'libTiCore.a')) # must copy the XIBs each time since they can change per SDK if devicefamily!=None: xib = 'MainWindow_%s.xib' % devicefamily else: xib = 'MainWindow_iphone.xib' s = os.path.join(template_dir,xib) t = os.path.join(iphone_resources_dir,'MainWindow.xib') shutil.copy(s,t) def is_adhoc(uuid): path = "~/Library/MobileDevice/Provisioning Profiles/%s.mobileprovision" % uuid f = os.path.expanduser(path) if os.path.exists(f): c = codecs.open(f,'r','utf-8','replace').read() return c.find("ProvisionedDevices")!=-1 return False def add_plist(dir): if not os.path.exists(dir): os.makedirs(dir) # write out the modules we're using in the APP for m in dependscompiler.required_modules: print "[INFO] Detected required module: Titanium.%s" % (m) if command == 'install': version = ti.properties['version'] # we want to make sure in debug mode the version always changes version = "%s.%d" % (version,time.time()) ti.properties['version']=version # write out the updated Info.plist infoplist_tmpl = os.path.join(iphone_dir,'Info.plist.template') infoplist = os.path.join(iphone_dir,'Info.plist') if devicefamily!=None: appicon = ti.generate_infoplist(infoplist,infoplist_tmpl,appid,devicefamily) else: appicon = ti.generate_infoplist(infoplist,infoplist_tmpl,appid,'iphone') # copy the app icon to the build resources iconf = os.path.join(iphone_tmp_dir,appicon) iconf_dest = os.path.join(dir,appicon) if os.path.exists(iconf): shutil.copy(iconf, iconf_dest) # update our simulator file with the current version if simulator: f = open(version_file,'w+') log_id = ti.properties['guid'] f.write("%s,%s,%s,%s" % (template_dir,log_id,lib_hash,iphone_version)) f.close() # copy in the default PNG default_png = os.path.join(project_resources,'iphone','Default.png') if os.path.exists(default_png): target_png = os.path.join(iphone_resources_dir,'Default.png') if os.path.exists(target_png): os.remove(target_png) shutil.copy(default_png,target_png) # copy in any resources in our module like icons if os.path.exists(project_module_dir): copy_module_resources(project_module_dir,iphone_tmp_dir) if force_rebuild: copy_module_resources(project_resources,iphone_tmp_dir) copy_module_resources(os.path.join(project_resources,'iphone'),iphone_tmp_dir) if os.path.exists(os.path.join(iphone_tmp_dir,'iphone')): shutil.rmtree(os.path.join(iphone_tmp_dir,'iphone')) try: os.chdir(iphone_dir) if force_rebuild: # write out plist add_plist(os.path.join(iphone_dir,'Resources')) print "[DEBUG] compile checkpoint: %0.2f seconds" % (time.time()-start_time) print "[INFO] Executing XCode build..." print "[BEGIN_VERBOSE] Executing XCode Compiler <span>[toggle output]</span>" elif simulator: print "[INFO] Detected pre-compiled app, will run in interpreted mode to speed launch" sys.stdout.flush() deploy_target = "IPHONEOS_DEPLOYMENT_TARGET=3.1" device_target = 'TARGETED_DEVICE_FAMILY=iPhone' # this is non-sensical, but you can't pass empty string if devicefamily!=None: if devicefamily == 'ipad': device_target=" TARGETED_DEVICE_FAMILY=iPad" deploy_target = "IPHONEOS_DEPLOYMENT_TARGET=3.2" if command == 'simulator': if force_rebuild: output = run.run([ "xcodebuild", "-configuration", "Debug", "-sdk", "iphonesimulator%s" % iphone_version, "WEB_SRC_ROOT=%s" % iphone_tmp_dir, "GCC_PREPROCESSOR_DEFINITIONS=__LOG__ID__=%s DEPLOYTYPE=development DEBUG=1" % log_id, deploy_target, device_target ]) print output print "[END_VERBOSE]" sys.stdout.flush() if os.path.exists(iphone_tmp_dir): shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1 or output.find("ld returned 1")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # first make sure it's not running kill_simulator() # sometimes the simulator doesn't remove old log files # in which case we get our logging jacked - we need to remove # them before running the simulator def cleanup_app_logfiles(): def find_all_log_files(folder, fname): results = [] for root, dirs, files in os.walk(os.path.expanduser(folder)): for file in files: if fname==file: fullpath = os.path.join(root, file) results.append(fullpath) return results for f in find_all_log_files("~/Library/Application Support/iPhone Simulator",'%s.log' % log_id): print "[DEBUG] removing old log file: %s" % f sys.stdout.flush() os.remove(f) cleanup_app_logfiles() sim = None def handler(signum, frame): print "[INFO] Simulator is exiting" sys.stdout.flush() if not log == None: try: os.system("kill -2 %s" % str(log.pid)) except: pass if not sim == None and signum!=3: try: os.system("kill -3 %s" % str(sim.pid)) except: pass kill_simulator() sys.exit(0) signal.signal(signal.SIGHUP, handler) signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGABRT, handler) signal.signal(signal.SIGTERM, handler) print "[INFO] Launching application in Simulator" sys.stdout.flush() sys.stderr.flush() # we have to do this in simulator *after* the potential compile since his screen # removes html, etc for module in os.listdir(os.path.join(template_dir,'modules')): img_dir = os.path.abspath(os.path.join(template_dir,'modules',module.lower(),'images')) if os.path.exists(img_dir): dest_img_dir = os.path.join(app_dir,'modules',module.lower(),'images') if os.path.exists(dest_img_dir): shutil.rmtree(dest_img_dir) os.makedirs(dest_img_dir) copy_module_resources(img_dir,dest_img_dir) copy_module_resources(project_resources,app_dir,True,True) copy_module_resources(os.path.join(project_resources,'iphone'),app_dir,True,True) if os.path.exists(os.path.join(app_dir,'iphone')): shutil.rmtree(os.path.join(app_dir,'iphone')) if os.path.exists(os.path.join(app_dir,'android')): shutil.rmtree(os.path.join(app_dir,'android')) # launch the simulator if devicefamily==None: sim = subprocess.Popen("\"%s\" launch \"%s\" %s iphone" % (iphonesim,app_dir,iphone_version),shell=True) else: sim = subprocess.Popen("\"%s\" launch \"%s\" %s %s" % (iphonesim,app_dir,iphone_version,devicefamily),shell=True) # activate the simulator window ass = os.path.join(template_dir,'iphone_sim_activate.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) end_time = time.time()-start_time print "[INFO] Launched application in Simulator (%0.2f seconds)" % end_time sys.stdout.flush() sys.stderr.flush() # give the simulator a bit to get started and up and running before # starting the logger time.sleep(2) logger = os.path.realpath(os.path.join(template_dir,'logger.py')) # start the logger log = subprocess.Popen([ logger, str(log_id)+'.log', iphone_version ]) os.waitpid(sim.pid,0) print "[INFO] Application has exited from Simulator" # in this case, the user has exited the simulator itself # and not clicked Stop Emulator from within Developer so we kill # our tail log process but let simulator keep running if not log == None: try: os.system("kill -2 %s" % str(log.pid)) except: pass sys.exit(0) elif command == 'install': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) output = run.run(["xcodebuild", "-configuration", "Debug", "-sdk", "iphoneos%s" % iphone_version, "CODE_SIGN_ENTITLEMENTS=", "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=test'", "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Developer: %s" % dist_name, deploy_target, device_target ]) shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print "[ERROR] Code sign error: %s" % error[0].strip() sys.exit(1) print "[INFO] Installing application in iTunes ... one moment" sys.stdout.flush() # for install, launch itunes with the app cmd = "open -b com.apple.itunes \"%s\"" % app_bundle os.system(cmd) # now run our applescript to tell itunes to sync to get # the application on the phone ass = os.path.join(template_dir,'itunes_sync.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) print "[INFO] iTunes sync initiated" sys.stdout.flush() elif command == 'distribute': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) # in this case, we have to do different things based on if it's # an ad-hoc distribution cert or not - in the case of non-adhoc # we don't use the entitlements file but in ad hoc we need to adhoc_line = "CODE_SIGN_ENTITLEMENTS=" deploytype = "production_adhoc" if not is_adhoc(appuuid): adhoc_line="CODE_SIGN_ENTITLEMENTS = Resources/Entitlements.plist" deploytype = "production" # build the final release distribution output = run.run(["xcodebuild", "-configuration", "Release", "-sdk", "iphoneos%s" % iphone_version, "%s" % adhoc_line, "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=%s'" % deploytype, "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Distribution: %s" % dist_name, deploy_target, device_target ]) shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print "[ERROR] Code sign error: %s" % error[0].strip() sys.exit(1) # switch to app_bundle for zip os.chdir(app_bundle_folder) # you *must* use ditto here or it won't upload to appstore os.system('ditto -ck --keepParent --sequesterRsrc "%s" "%s/%s.zip"' % (app_name,output_dir,app_name)) sys.exit(0) else: print "Unknown command: %s" % command sys.exit(2) finally: os.chdir(cwd)
def build_modules_info(self, resources_dir, app_bin_dir, include_all_ti_modules=False): self.app_modules = [] (modules, external_child_modules) = bindings.get_all_module_bindings() compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, None, os.path.dirname(app_bin_dir), include_all_modules=include_all_ti_modules) compiler.compile(compile_bytecode=False, info_message=None) for module in compiler.modules: module_bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module+'.') and '.' not in method: module_bindings.append(method[len(module)+1:]) module_onAppCreate = None module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == module: module_class = m module_apiName = modules[m]['fullAPIName'] if 'onAppCreate' in modules[m]: module_onAppCreate = modules[m]['onAppCreate'] break if module_apiName == None: continue # module wasn't found ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[module_class]: if child_module['fullAPIName'].lower() in compiler.modules: ext_modules.append(child_module) self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': module_bindings, 'external_child_modules': ext_modules, 'on_app_create': module_onAppCreate }) # discover app modules detector = ModuleDetector(self.project_dir) missing, detected_modules = detector.find_app_modules(self.tiapp, 'android', self.deploy_type) for missing_module in missing: print '[WARN] Couldn\'t find app module: %s' % missing_module['id'] self.custom_modules = [] for module in detected_modules: if module.jar == None: continue module_jar = zipfile.ZipFile(module.jar) module_bindings = bindings.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings['modules'].keys(): module_apiName = module_bindings['modules'][module_class]['apiName'] module_proxy = module_bindings['proxies'][module_class] module_id = module_proxy['proxyAttrs']['id'] module_proxy_class_name = module_proxy['proxyClassName'] module_onAppCreate = None if 'onAppCreate' in module_proxy: module_onAppCreate = module_proxy['onAppCreate'] print '[DEBUG] module_id = %s' % module_id if module_id == module.manifest.moduleid: # make sure that the module was not built before 1.8.0.1 try: module_api_version = int(module.manifest.apiversion) if module_api_version < 2: print "[ERROR] The 'apiversion' for '%s' in the module manifest is less than version 2. The module was likely built against a Titanium SDK pre 1.8.0.1. Please use a version of the module that has 'apiversion' 2 or greater" % module_id touch_tiapp_xml(os.path.join(self.project_dir, 'tiapp.xml')) sys.exit(1) except(TypeError, ValueError): print "[ERROR] The 'apiversion' for '%s' in the module manifest is not a valid value. Please use a version of the module that has an 'apiversion' value of 2 or greater set in it's manifest file" % module_id touch_tiapp_xml(os.path.join(self.project_dir, 'tiapp.xml')) sys.exit(1) is_native_js_module = (hasattr(module.manifest, 'commonjs') and module.manifest.commonjs) print '[DEBUG] appending module: %s' % module_class self.custom_modules.append({ 'module_id': module_id, 'module_apiName': module_apiName, 'proxy_name': module_proxy_class_name, 'class_name': module_class, 'manifest': module.manifest, 'on_app_create': module_onAppCreate, 'is_native_js_module': is_native_js_module }) if is_native_js_module: # Need to look at the app modules used in this external js module metadata_file = os.path.join(module.path, "metadata.json") metadata = None try: f = open(metadata_file, "r") metadata = f.read() finally: f.close() if metadata: metadata = simplejson.loads(metadata) if metadata.has_key("exports"): exported_module_ids = metadata["exports"] already_included_module_ids = [m["api_name"].lower() for m in self.app_modules] need_to_add = [m for m in exported_module_ids if m not in already_included_module_ids] if need_to_add: for to_add in need_to_add: module_onAppCreate = None module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == to_add: module_class = m module_apiName = modules[m]['fullAPIName'] if 'onAppCreate' in modules[m]: module_onAppCreate = modules[m]['onAppCreate'] break if module_apiName == None: continue # module wasn't found ext_modules = [] if module_class in external_child_modules: for child_module in external_child_modules[module_class]: if child_module['fullAPIName'].lower() in compiler.modules: ext_modules.append(child_module) self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': [], 'external_child_modules': ext_modules, 'on_app_create': module_onAppCreate })
def main(): inp = "(- (+ 5 4) 1)" comp = Compiler() comp.compile(inp)
def main(args): argc = len(args) if argc < 5 or (argc > 1 and args[1] == 'distribute' and argc!=9): print "%s <command> <version> <project_dir> <appid> <name> [uuid] [dist_name] [output_dir]" % os.path.basename(args[0]) print print "available commands: " print print " install install the app to itunes for testing on iphone" print " simulator build and run on the iphone simulator" print " distribute build final distribution bundle" sys.exit(1) print "[INFO] One moment, building ..." sys.stdout.flush() simulator = os.path.abspath(os.path.join(template_dir,'iphonesim')) command = args[1].decode("utf-8") iphone_version = dequote(args[2].decode("utf-8")) project_dir = os.path.expanduser(dequote(args[3].decode("utf-8"))) appid = dequote(args[4].decode("utf-8")) name = dequote(args[5].decode("utf-8")) target = 'Debug' deploytype = 'development' debug = False if command == 'distribute': appuuid = dequote(args[6].decode("utf-8")) dist_name = dequote(args[7].decode("utf-8")) output_dir = os.path.expanduser(dequote(args[8].decode("utf-8"))) target = 'Release' deploytype = 'production' elif command == 'simulator': deploytype = 'test' debug = True elif command == 'install': appuuid = dequote(args[6].decode("utf-8")) dist_name = dequote(args[7].decode("utf-8")) iphone_dir = os.path.abspath(os.path.join(project_dir,'build','iphone')) project_resources = os.path.join(project_dir,'Resources') app_name = name+'.app' app_folder_name = '%s-iphoneos' % target app_dir = os.path.abspath(os.path.join(iphone_dir,'build','%s-iphonesimulator'%target,name+'.app')) app_bundle_folder = os.path.abspath(os.path.join(iphone_dir,'build',app_folder_name)) app_bundle = os.path.join(app_bundle_folder,app_name) iphone_resources_dir = os.path.join(iphone_dir,'Resources') iphone_tmp_dir = os.path.join(iphone_dir,'tmp') if not os.path.exists(iphone_dir): print "Could not find directory: %s" % iphone_dir sys.exit(1) cwd = os.getcwd() tiapp_xml = os.path.join(project_dir,'tiapp.xml') if not os.path.exists(tiapp_xml): print "Missing tiapp.xml at %s" % tiapp_xml sys.exit(3) ti = TiAppXML(tiapp_xml) encrypt = False if ti.properties.has_key('encrypt'): encrypt = (ti.properties['encrypt']=='true') # compile resources compiler = Compiler(appid,project_dir,encrypt,debug) compiler.compile() # copy over main since it can change with each release main_template = codecs.open(os.path.join(template_dir,'main.m'),'r','utf-8','replace').read() main_template = main_template.replace('__PROJECT_NAME__',name) main_template = main_template.replace('__PROJECT_ID__',appid) main_dest = codecs.open(os.path.join(iphone_dir,'main.m'),'w','utf-8','replace') main_dest.write(main_template.encode("utf-8")) main_dest.close() # migrate the xcode project given that it can change per release of sdk if iphone_version == '2.2.1': xcodeproj = codecs.open(os.path.join(template_dir,'project_221.pbxproj'),'r','utf-8','replace').read() else: xcodeproj = codecs.open(os.path.join(template_dir,'project.pbxproj'),'r','utf-8','replace').read() xcodeproj = xcodeproj.replace('__PROJECT_NAME__',name) xcodeproj = xcodeproj.replace('__PROJECT_ID__',appid) xcode_dir = os.path.join(iphone_dir,name+'.xcodeproj') xcode_pbx = codecs.open(os.path.join(xcode_dir,'project.pbxproj'),'w','utf-8','replace') xcode_pbx.write(xcodeproj.encode("utf-8")) xcode_pbx.close() # copy in the default PNG default_png = os.path.join(project_resources,'iphone','Default.png') if os.path.exists(default_png): target_png = os.path.join(iphone_resources_dir,'Default.png') if os.path.exists(target_png): os.remove(target_png) shutil.copy(default_png,target_png) iphone_tmp_module_dir = os.path.join(iphone_dir,"_modules") if os.path.exists(iphone_tmp_module_dir): shutil.rmtree(iphone_tmp_module_dir) os.mkdir(iphone_tmp_module_dir) # in case the developer has their own modules we can pick them up project_module_dir = os.path.join(project_dir,"modules","iphone") # copy in any resources in our module like icons if os.path.exists(project_module_dir): copy_module_resources(project_module_dir,iphone_tmp_dir) # see if the user has app data and if so, compile in the user data # such that it can be accessed automatically using Titanium.App.Properties.getString app_data_cfg = os.path.join(project_dir,"appdata.cfg") if os.path.exists(app_data_cfg): props = read_properties(open(app_data_cfg,"r")) module_data = '' for key in props.keys(): value = props[key] data = str(value).encode("hex") module_data+="[[NSUserDefaults standardUserDefaults] setObject:[[[NSString alloc] initWithData:dataWithHexString(@\"%s\") encoding:NSUTF8StringEncoding] autorelease] forKey:@\"%s\"];\n" % (data,key) print("[DEBUG] detected user application data at = %s"% app_data_cfg) sys.stdout.flush() dtf = os.path.join(iphone_tmp_module_dir,"UserDataModule.m") if os.path.exists(dtf): os.remove(dtf) ctf = codecs.open(dtf,'w','utf-8','replace') cf_template = codecs.open(os.path.join(template_dir,'UserDataModule.m'),'r','utf-8','replace').read() cf_template = cf_template.replace('__MODULE_BODY__',module_data) ctf.write(cf_template.encode("utf-8")) ctf.close() compiler.modules.append('Userdata') # we build a new libTitanium that is basically only the modules used by the application all injected into the # final libTitanium that is used by xcode os.chdir(iphone_tmp_module_dir) modules_detected=['Userdata'] for arch in ['i386','armv6']: os.mkdir(os.path.join(iphone_tmp_module_dir,arch)) os.chdir(os.path.join(iphone_tmp_module_dir,arch)) for module_name in compiler.modules: module_normalized_name = module_name[0:1].capitalize() + module_name[1:] if len(module_normalized_name) == 2: module_normalized_name = module_normalized_name.upper() libname = "lib%s-%s.a" % (module_normalized_name,iphone_version) libpath = os.path.join(template_dir,libname) if not os.path.exists(libpath): # check to see if its in the user's project module dir libpath = os.path.join(project_module_dir,libname) if os.path.exists(libpath): if not module_normalized_name in modules_detected: modules_detected.append(module_normalized_name) print "[DEBUG] module library dependency detected Titanium.%s" % (module_normalized_name) os.system("/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/lipo \"%s\" -thin %s -o tmp.a" % (libpath,arch)) os.system("ar -x tmp.a") os.remove("tmp.a") else: if not os.path.exists(os.path.join(project_module_dir,"%sModule.m"%module_normalized_name)) and module_normalized_name!='Userdata': print "[WARN] couldn't find module library for Titanium.%s" % module_normalized_name elif not module_normalized_name in modules_detected: print "[DEBUG] module library dependency detected Titanium.%s" % (module_normalized_name) modules_detected.append(module_normalized_name) os.chdir(iphone_tmp_module_dir) # copy any module image directories for module in modules_detected: img_dir = os.path.abspath(os.path.join(template_dir,'modules',module.lower(),'images')) if os.path.exists(img_dir): dest_img_dir = os.path.join(iphone_tmp_dir,'modules',module.lower(),'images') if os.path.exists(dest_img_dir): shutil.rmtree(dest_img_dir) os.makedirs(dest_img_dir) copy_module_resources(img_dir,dest_img_dir) for arch in ['i386','armv6']: arch_dir = os.path.join(iphone_tmp_module_dir,arch) if not os.path.exists(arch_dir): os.mkdir(arch_dir) # extract our main libTitanium by architecture and then rebuild the final static library which includes # libTitanium as well as our dependent modules only os.system("/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/lipo \"%s\" -thin i386 -output \"%s\"" % (os.path.join(template_dir,'libTitanium-%s.a'%iphone_version),os.path.join(iphone_tmp_module_dir,'i386','libTitanium-i386.a'))) os.system("/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/lipo \"%s\" -thin armv6 -output \"%s\"" % (os.path.join(template_dir,'libTitanium-%s.a'%iphone_version),os.path.join(iphone_tmp_module_dir,'armv6','libTitanium-armv6.a'))) for arch in ['i386','armv6']: os.chdir(os.path.join(iphone_tmp_module_dir,arch)) os.system("ar -x \"%s\"" % os.path.join(iphone_tmp_module_dir,arch,"libTitanium-%s.a"%arch)) #compile in any user source import inliner include_dir = os.path.join(template_dir,"include") if os.path.exists(include_dir) and os.path.exists(project_module_dir): inliner.inliner(include_dir,iphone_version,arch,project_module_dir,os.path.join(iphone_tmp_module_dir,arch)) if os.path.exists(include_dir) and os.path.exists(iphone_tmp_module_dir): inliner.inliner(include_dir,iphone_version,arch,iphone_tmp_module_dir,os.path.join(iphone_tmp_module_dir,arch)) os.system("/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/libtool -static -o \"%s\" *.o" % os.path.join(iphone_tmp_module_dir,"libTitanium-%s.a"%arch)) os.chdir(iphone_tmp_module_dir) sys.stdout.flush() # remake the combined architecture lib os.system("/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/lipo libTitanium-i386.a libTitanium-armv6.a -create -output \"%s\"" % os.path.join(iphone_resources_dir,'libTitanium.a')) shutil.rmtree(iphone_tmp_module_dir) # must copy the XIBs each time since they can change per SDK os.chdir(template_dir) for xib in glob.glob('*.xib'): shutil.copy(os.path.join(template_dir,xib),os.path.join(iphone_resources_dir,xib)) os.chdir(cwd) def is_adhoc(uuid): path = "~/Library/MobileDevice/Provisioning Profiles/%s.mobileprovision" % uuid f = os.path.expanduser(path) if os.path.exists(f): c = codecs.open(f,'r','utf-8','replace').read() return c.find("ProvisionedDevices")!=-1 return False def add_plist(dir): if not os.path.exists(dir): os.makedirs(dir) plist_f = os.path.join(dir,'tiapp.plist') plist = open(plist_f,'w+') module_str = '' # write out the modules we're using in the APP for m in compiler.modules: module_str += ' <key>%s</key>\n <real>0.0</real>\n' % (m.lower()) tip = TiPlist(ti) if command == 'install': version = tip.tiapp.properties['version'] # we want to make sure in debug mode the version always changes version = "%s.%d" % (version,time.time()) tip.tiapp.properties['version']=version plist_template = tip.generate(module_str,appid,deploytype) # write out the generated tiapp.plist plist.write(plist_template) plist.close() # write out the updated Info.plist infoplist_tmpl = os.path.join(iphone_dir,'Info.plist.template') infoplist = os.path.join(iphone_dir,'Info.plist') appicon = tip.generate_infoplist(infoplist,infoplist_tmpl,appid) # copy the app icon to the build resources iconf = os.path.join(iphone_tmp_dir,appicon) iconf_dest = os.path.join(dir,appicon) if os.path.exists(iconf): shutil.copy(iconf, iconf_dest) # compile to binary plist os.system("/usr/bin/plutil -convert binary1 \"%s\"" % plist_f) try: os.chdir(iphone_dir) # write out plist add_plist(os.path.join(iphone_dir,'Resources')) print "[INFO] Executing XCode build..." print "[BEGIN_VERBOSE] Executing XCode Compiler <span>[toggle output]</span>" sys.stdout.flush() if command == 'simulator': # first build it log_id = uuid.uuid4() # make sure it's clean if os.path.exists(app_dir): shutil.rmtree(app_dir) output = run.run([ "xcodebuild", "-configuration", "Debug", "-sdk", "iphonesimulator%s" % iphone_version, "WEB_SRC_ROOT=%s" % iphone_tmp_dir, "GCC_PREPROCESSOR_DEFINITIONS=__LOG__ID__=%s DEPLOYTYPE=development DEBUG=1" % log_id ]) print output print "[END_VERBOSE]" sys.stdout.flush() shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1 or output.find("ld returned 1")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # first make sure it's not running kill_simulator() logger = os.path.realpath(os.path.join(template_dir,'logger.py')) # start the logger log = subprocess.Popen([ logger, str(log_id)+'.log' ]) sim = None def handler(signum, frame): print "[INFO] Simulator is exiting" sys.stdout.flush() if not log == None: try: os.system("kill -2 %s" % str(log.pid)) except: pass if not sim == None and signum!=3: try: os.system("kill -3 %s" % str(sim.pid)) except: pass kill_simulator() sys.exit(0) signal.signal(signal.SIGHUP, handler) signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGABRT, handler) signal.signal(signal.SIGTERM, handler) print "[INFO] Launching application in Simulator" sys.stdout.flush() sys.stderr.flush() #launch the simulator sim = subprocess.Popen("\"%s\" launch \"%s\" %s" % (simulator,app_dir,iphone_version),shell=True) # activate the simulator window ass = os.path.join(template_dir,'iphone_sim_activate.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) print "[INFO] Launched application in Simulator" sys.stdout.flush() sys.stderr.flush() os.waitpid(sim.pid,0) print "[INFO] Application has exited from Simulator" # in this case, the user has exited the simulator itself # and not clicked Stop Emulator from within Developer so we kill # our tail log process but let simulator keep running if not log == None: try: os.system("kill -2 %s" % str(log.pid)) except: pass sys.exit(0) elif command == 'install': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) output = run.run(["xcodebuild", "-configuration", "Debug", "-sdk", "iphoneos%s" % iphone_version, "CODE_SIGN_ENTITLEMENTS=", "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=test'", "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Developer: %s" % dist_name ]) shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print "[ERROR] Code sign error: %s" % error[0].strip() sys.exit(1) print "[INFO] Installing application in iTunes ... one moment" sys.stdout.flush() # for install, launch itunes with the app cmd = "open -b com.apple.itunes \"%s\"" % app_bundle os.system(cmd) # now run our applescript to tell itunes to sync to get # the application on the phone ass = os.path.join(template_dir,'itunes_sync.scpt') cmd = "osascript \"%s\"" % ass os.system(cmd) print "[INFO] iTunes sync initiated" sys.stdout.flush() elif command == 'distribute': # make sure it's clean if os.path.exists(app_bundle): shutil.rmtree(app_bundle) # in this case, we have to do different things based on if it's # an ad-hoc distribution cert or not - in the case of non-adhoc # we don't use the entitlements file but in ad hoc we need to adhoc_line = "CODE_SIGN_ENTITLEMENTS=" deploytype = "production_adhoc" if not is_adhoc(appuuid): adhoc_line="CODE_SIGN_ENTITLEMENTS = Resources/Entitlements.plist" deploytype = "production" # build the final release distribution output = run.run(["xcodebuild", "-configuration", "Release", "-sdk", "iphoneos%s" % iphone_version, "%s" % adhoc_line, "GCC_PREPROCESSOR_DEFINITIONS='DEPLOYTYPE=%s'" % deploytype, "PROVISIONING_PROFILE[sdk=iphoneos*]=%s" % appuuid, "CODE_SIGN_IDENTITY[sdk=iphoneos*]=iPhone Distribution: %s" % dist_name ]) shutil.rmtree(iphone_tmp_dir) if output.find("** BUILD FAILED **")!=-1: print "[ERROR] Build Failed. Please see output for more details" sys.exit(1) # look for a code signing error error = re.findall(r'Code Sign error:(.*)',output) if len(error) > 0: print "[ERROR] Code sign error: %s" % error[0].strip() sys.exit(1) # switch to app_bundle for zip os.chdir(app_bundle_folder) # you *must* use ditto here or it won't upload to appstore os.system('ditto -ck --keepParent --sequesterRsrc "%s" "%s/%s.zip"' % (app_name,output_dir,app_name)) sys.exit(0) else: print "Unknown command: %s" % command sys.exit(2) finally: os.chdir(cwd)
from compilerexception import CompilerException from compiler import Compiler if __name__ == '__main__': #inputfile = 'input-compiler/set1.t1x' #inputfile = 'apertium-en-ca.en-ca.t1x' inputfile = 'apertium-en-ca.ca-en.t1x' #inputfile = 'input-compiler/macro_conj_verb1.t1x' try: compiler = Compiler(inputfile) compiler.compile() compiler.optimize() #print compiler.def_cats #print compiler.variables #print compiler.def_attrs #print compiler.def_lists compiler.printCode() #compiler.printLabels() #print compiler.symbolTable.symbolList #pprint(compiler.symbolTable.childList) except CompilerException, ex: print ex
def build_modules_info(self, resources_dir, app_bin_dir): compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, os.path.dirname(app_bin_dir)) compiler.compile(compile_bytecode=False) self.app_modules = [] template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename) android_modules_dir = os.path.abspath(os.path.join(template_dir, 'modules')) modules = {} for jar in os.listdir(android_modules_dir): if not jar.endswith('.jar'): continue module_path = os.path.join(android_modules_dir, jar) module_jar = zipfile.ZipFile(module_path) module_bindings = self.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings['modules'].keys(): full_api_name = module_bindings['proxies'][module_class]['proxyAttrs']['fullAPIName'] modules[module_class] = module_bindings['modules'][module_class] modules[module_class]['fullAPIName'] = full_api_name for module in compiler.modules: bindings = [] # TODO: we should also detect module properties for method in compiler.module_methods: if method.lower().startswith(module+'.') and '.' not in method: bindings.append(method[len(module)+1:]) module_class = None module_apiName = None for m in modules.keys(): if modules[m]['fullAPIName'].lower() == module: module_class = m module_apiName = modules[m]['fullAPIName'] break if module_apiName == None: continue # module wasn't found self.app_modules.append({ 'api_name': module_apiName, 'class_name': module_class, 'bindings': bindings }) # discover app modules detector = ModuleDetector(self.project_dir) missing, detected_modules = detector.find_app_modules(self.tiapp) for missing_module in missing: print '[WARN] Couldn\'t find app module: %s' % missing_module['name'] self.custom_modules = [] for module in detected_modules: module_jar = zipfile.ZipFile(module.path) module_bindings = self.get_module_bindings(module_jar) if module_bindings is None: continue for module_class in module_bindings['modules'].keys(): module_id = module_bindings['proxies'][module_class]['proxyAttrs']['id'] print '[DEBUG] module_id = %s' % module_id if module_id == module.manifest.moduleid: print '[DEBUG] appending module: %s' % module_class self.custom_modules.append({ 'class_name': module_class, 'manifest': module.manifest })
class CpuTests(unittest.TestCase): def __init__(self, parameters): unittest.TestCase.__init__(self, parameters) self.compiler = Compiler() # (RAM, TERMINAL NotYetImpl def test_IfCanCompileEmptySourceCode(self): sourceCode = "" binary = self.compiler.compile(sourceCode) self.assertEquals(binary, []) def test_IfCouldDecodeRegisters(self): sourceCode = "MOV R0, R1" binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x00, 0x00, 0x01]) def test_IfItHandleLabels(self): sourceCode = ("start:\n" "MOV R0, R1\n") binary = self.compiler.compile(sourceCode) self.assertIn('start', self.compiler.labels) def test_IfItHandleLabelsDeclaredAfterUse(self): sourceCode = ("start:\n" "JMP end\n" "end:\n") binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x40, 0x00]) def test_IfItThrowExceptionOnError(self): sourceCode = "some error in source\n" self.assertRaises(Exception, self.compiler.compile, sourceCode) def test_IfItCalculateJumpsProperly(self): sourceCode = ("start:\n" "MOV R1, R2\n" "JZ start\n") binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x00, 0x01, 0x02, 0x21, 0xFB]) def test_IfItCompilerImmValuesProperly(self): sourceCode = ("SET R1, 0x12\n") binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x01, 0x01, 0x12]) sourceCode = ("SET R1, 12\n") binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x01, 0x01, 0xC]) def test_IfItThrowExceptionOnUnknownRegister(self): sourceCode = "MOV RnotExisting\n" self.assertRaises(Exception, self.compiler.compile, sourceCode) def test_IfItThrowExceptionOnUnknownLabel(self): sourceCode = "JMP notExistingLabel\n" self.assertRaises(Exception, self.compiler.compile, sourceCode) def test_IfDecodesOffsetsinINTformat(self): sourceCode = ("JZ 0\n") binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x21, 0xFF]) def test_IfDecodesOffsetsinHEXformat(self): sourceCode = ("JZ 0x00\n") binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x21, 0xFF]) def test_IfItThrowExceptionWhenNotSufficientCountOfArgumentsForMnemonic(self): sourceCode = "MOV R0\n" self.assertRaises(Exception, self.compiler.compile, sourceCode) def test_IfCouldSkipTheComments(self): sourceCode = "MOV R0, R1 ; this moves something somewhere" binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x00, 0x00, 0x01]) def test_IfCouldSkipTheCommentsOnBeginingOfLine(self): sourceCode = ";this moves something somewhere\n MOV R0, R1" binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x00, 0x00, 0x01]) def test_IfCouldHandleNoArgumentOpcodes(self): sourceCode = "RET" binary = self.compiler.compile(sourceCode) self.assertEquals(binary, [0x44]) def test_IfItThrowsExceptionWhenImmValueCantBeDecoded(self): sourceCode = ("SET R1, trolololo\n") self.assertRaises(Exception, self.compiler.compile, sourceCode)