def get_eosio_cpp_version(): """Get the version code of *eosio-cpp*. """ return utils.process( [config.eosio_cpp(), "-version"], "Cannot determine the version of 'eosio-cpp'." ).replace("eosio-cpp version ", "")
def wasm(src_file, wasm_file, options=[]): '''Given a source file and an output file path, make a corresponding wasm file. ''' cl = [config.eosio_cpp()] cl.extend(options) cl.extend(["-o", wasm_file, src_file]) import eosfactory.core.teos as teos teos.process(cl)
def build( contract_dir_hint, c_cpp_properties_path=None, compile_only=False, is_test_mode=False, is_execute=False, verbosity=None): '''Produce ABI and WASM files. Compiler options come with the argument 'c_cpp_properties_path', as components of 'compilerOptions' list. Option can be any of the 'eosio-cpp' options, plus the following ones: * --src - list of the source files, absolute or relative to 'src' or project directories, for example: --src hello.cpp tests/hello_test.cpp * -o - the same as the corresponding eosio-cpp option, but may be relative to 'build' directory Without any option set, the only source file is determined as a result of the function :func:`.core.config.contract_source_files`, if the result is a single file. If it is not, an error is thrown, stating that the source file has to be specified with the '--src' option. The ABI and WASM targets are named after the contract source file. Args: contract_dir_hint (str): Path, may be partial, to the project directory. c_cpp_properties_path (str): If set, the path to a c_cpp_properties json file in '.vscode' folder in the project directory. compile_only (bool): If set, do not link. verbosity (([.core.logger.Verbosity])): Verbosity parameter, used in loggers. ''' contract_dir = config.contract_dir(contract_dir_hint) # contract_source_files[0] is directory, contract_source_files[1] is contents: contract_source_files = config.contract_source_files(contract_dir) c_cpp_properties = get_c_cpp_properties( contract_dir, c_cpp_properties_path) build_dir = get_target_dir(contract_dir) target_path = None compile_options = [] source_files = [] ############################################################################ # begin compiler option logics ############################################################################ recardian_dir = "-R=" + get_recardian_dir(contract_source_files[0]) if is_test_mode \ and vscode.TEST_OPTIONS in c_cpp_properties[CONFIGURATIONS][0]: compile_options_ = c_cpp_properties[CONFIGURATIONS][0]\ [vscode.TEST_OPTIONS] elif not is_test_mode \ and vscode.CODE_OPTIONS in c_cpp_properties[CONFIGURATIONS][0]: compile_options_ = c_cpp_properties[CONFIGURATIONS][0]\ [vscode.CODE_OPTIONS] else: compile_options_ = [] contract_src_name = None is_verbose = False if not "-abigen" in compile_options_: compile_options.append("-abigen") if is_test_mode and not "-fnative" in compile_options_: compile_options.append("-fnative") for i in range(0, len(compile_options_)): entry = compile_options_[i] if "-R=" in entry: recardian_dir = entry elif "-contract=" in entry: contract_src_name = entry.replace("-contract=", "").strip() compile_options.append(entry) elif "--verbose" in entry: is_verbose = True elif "-o" in entry: target_path = utils.wslMapWindowsLinux( entry.replace("-o", "").strip()) if not target_path: if i + 1 < len(compile_options_): target_path = compile_options_[i + 1] else: raise errors.Error(''' The option '-o' does not has its value set: {} '''.format(compile_options_)) if not os.path.isabs(target_path): target_path = os.path.join(build_dir, target_path) target_dir = os.path.dirname(target_path) if not os.path.exists(target_dir): try: os.makedirs(target_dir) except Exception as e: raise errors.Error(''' Cannot make directory set with the option '-o'. {} '''.format(str(e))) elif "-abigen_output" in entry: abigen_path = utils.wslMapWindowsLinux( entry.replace("-abigen_output=", "").strip()) if not os.path.isabs(abigen_path): abigen_path = os.path.join(build_dir, abigen_path) abigen_dir = os.path.dirname(abigen_path) if not os.path.exists(abigen_dir): try: os.makedirs(abigen_dir) except Exception as e: raise errors.Error(''' Cannot make directory set with the option '-abigen_output'. {} '''.format(str(e))) compile_options.append("-abigen_output={}".format(abigen_path)) elif "--src" in entry: input_files_ = utils.wslMapWindowsLinux( entry.replace("--src", "").strip()) if not input_files_: next_index = i + 1 while True: if next_index >= len(compile_options_): break next_item = compile_options_[next_index] if "-" in next_item: break input_files_ = input_files_ + " " + next_item if not input_files_: raise errors.Error(''' The option '--src' does not has its value set: {} '''.format(compile_options_)) for input_file in input_files_.split(" "): temp = input_file if not os.path.isabs(temp): temp = os.path.join(contract_source_files[0], input_file) if not contract_src_name: contract_src_name = os.path.splitext( os.path.basename(temp))[0] if not os.path.exists(temp): temp = os.path.join(contract_dir, input_file) if not os.path.exists(temp): raise errors.Error(''' The source file {} cannot be found. It is neither absolute nor relative to the contract directory or relative to the 'src' directory. '''.format(input_file)) temp = os.path.normpath(temp) if not temp in source_files: source_files.append(temp) else: compile_options.append(entry) compile_options.append(recardian_dir) if not source_files: source_files = contract_source_files[1] if not source_files: raise errors.Error(''' Cannot find any source file (".c", ".cpp",".cxx", ".c++") in the contract folder. ''') if not is_test_mode and len(source_files) > 1: raise errors.Error(''' Cannot determine the source file of the contract. There is many files in the 'src' directory, namely: {} Specify the file with the compiler option '--src', for example: --src src_dir/hello.cpp The file path is to be absolute or relative to the project directory. '''.format("\n".join(source_files))) if not contract_src_name: contract_src_name = os.path.splitext( os.path.basename(source_files[0]))[0] if not contract_src_name and len(source_files) == 1: contract_src_name = os.path.splitext( os.path.basename(source_files[0]))[0] ############################################################################ # end compiler option logics ############################################################################ if not target_path: target_path = os.path.normpath( os.path.join(build_dir, contract_src_name + ".wasm")) abigen_path = os.path.normpath( os.path.join(build_dir, contract_src_name + ".abi")) if is_execute: logger.TRACE(''' Executing target {} '''.format(target_path)) command_line = [target_path] if setup.is_print_command_lines and setup.is_save_command_lines: setup.add_to__command_line_file(" ".join(command_line)) if setup.is_print_command_lines or is_verbose: logger.DEBUG(''' ######## command line: {} '''.format(" ".join(command_line)), [logger.Verbosity.DEBUG]) utils.long_process(command_line, build_dir, is_verbose=True, prompt=target_path) return command_line = [config.eosio_cpp()] if compile_only: command_line.append("-c") else: command_line.extend(["-o", target_path]) for entry in c_cpp_properties[CONFIGURATIONS][0][vscode.INCLUDE_PATH]: if WORKSPACE_FOLDER in entry: entry = entry.replace(WORKSPACE_FOLDER, contract_dir) command_line.append("-I=" + linuxize_path(entry)) else: path = linuxize_path(entry) if not path in config.eosio_cpp_includes(): command_line.append( "-I=" + path) for entry in c_cpp_properties[CONFIGURATIONS][0][vscode.LIBS]: command_line.append( "-l=" + linuxize_path(entry)) for entry in compile_options: command_line.append(entry) for input_file in source_files: command_line.append(input_file) if setup.is_print_command_lines and setup.is_save_command_lines: setup.add_to__command_line_file(" ".join(command_line)) if setup.is_print_command_lines or is_verbose: logger.DEBUG(''' ######## command line: {} '''.format(" ".join(command_line)), [logger.Verbosity.DEBUG]) utils.long_process(command_line, build_dir, is_verbose=True, prompt="eosio-cpp") if not compile_only: if "wasm" in target_path: logger.TRACE(''' ABI file writen to file: {} '''.format(os.path.normpath(abigen_path)), verbosity) logger.TRACE(''' WASM file writen to file: {} '''.format(os.path.normpath(target_path)), verbosity) else: logger.TRACE(''' terget writen to file: {} '''.format(os.path.normpath(target_path)), verbosity) print("eosio-cpp: OK")
def ABI( contract_dir_hint=None, c_cpp_properties_path=None, verbosity=None): '''Given a hint to a contract directory, produce ABI file. ''' contract_dir = config.contract_dir(contract_dir_hint) # source_files[0] is directory, source_files[1] is contents: contract_source_files = config.contract_source_files(contract_dir) source_files = [] source_ext = [".c", ".cpp",".cxx", ".c++"] for file in contract_source_files[1]: if os.path.splitext(file)[1].lower() in source_ext: source_files.append(file) if not source_files: raise errors.Error(''' "The source is empty. The assumed contract dir is {} '''.format(contract_dir)) return code_name = os.path.splitext(os.path.basename(source_files[0]))[0] target_dir = get_target_dir(contract_source_files[0]) target_path = os.path.normpath( os.path.join(target_dir, code_name + ".abi")) for file in contract_source_files[1]: if os.path.splitext(file)[1].lower() == ".abi": logger.INFO(''' NOTE: An ABI exists in the source directory. Cannot overwrite it: {} Just copying it to the target directory. '''.format(file), verbosity) shutil.move(file, target_path) return command_line = [ config.eosio_cpp(), "-contract=" + code_name, "-R=" + get_resources_dir(contract_source_files[0]), "-abigen", "-abigen_output=" + target_path] c_cpp_properties = get_c_cpp_properties( contract_dir, c_cpp_properties_path) for entry in c_cpp_properties[CONFIGURATIONS][0][INCLUDE_PATH]: if WORKSPACE_FOLDER in entry: entry = entry.replace(WORKSPACE_FOLDER, contract_dir) command_line.append( "-I" + utils.wslMapWindowsLinux(entry)) else: if not EOSIO_CPP_INCLUDE in entry: command_line.append( "-I" + utils.wslMapWindowsLinux( strip_wsl_root(entry))) for file in source_files: command_line.append(file) try: eosio_cpp(command_line, target_dir) except Exception as e: raise errors.Error(str(e)) logger.TRACE(''' ABI file writen to file: {} '''.format(target_path), verbosity)
def WASM( contract_dir_hint, c_cpp_properties_path=None, compile_only=False, verbosity=None): '''Produce WASM code. ''' contract_dir = config.contract_dir(contract_dir_hint) # source_files[0] is directory, source_files[1] is contents: contract_source_files = config.contract_source_files(contract_dir) source_files = [] source_ext = [".c", ".cpp",".cxx", ".c++"] for file in contract_source_files[1]: if os.path.splitext(file)[1].lower() in source_ext: source_files.append(file) if not source_files: raise errors.Error(''' "The source is empty. The assumed contract dir is {} '''.format(contract_dir)) return code_name = os.path.splitext(os.path.basename(source_files[0]))[0] target_dir = get_target_dir(contract_source_files[0]) target_path = os.path.normpath( os.path.join(target_dir, code_name + ".wasm")) c_cpp_properties = get_c_cpp_properties( contract_dir, c_cpp_properties_path) command_line = [config.eosio_cpp()] for entry in c_cpp_properties[CONFIGURATIONS][0][INCLUDE_PATH]: if WORKSPACE_FOLDER in entry: entry = entry.replace(WORKSPACE_FOLDER, contract_dir) command_line.append("-I=" + utils.wslMapWindowsLinux(entry)) else: if not EOSIO_CPP_INCLUDE in entry: command_line.append( "-I=" + utils.wslMapWindowsLinux(strip_wsl_root(entry))) for entry in c_cpp_properties[CONFIGURATIONS][0]["libs"]: command_line.append( "-l=" + utils.wslMapWindowsLinux(strip_wsl_root(entry))) for entry in c_cpp_properties[CONFIGURATIONS][0]["compilerOptions"]: command_line.append(entry) for file in source_files: command_line.append(file) if setup.is_print_command_line: print("######## \n{}:".format(" ".join(command_line))) if compile_only: command_line.append("-c=") command_line.append("-o=" + target_path) try: eosio_cpp(command_line, target_dir) except Exception as e: raise errors.Error(str(e)) if not compile_only: logger.TRACE(''' WASM file writen to file: {} '''.format(os.path.normpath(target_path)), verbosity)
def ABI(contract_dir_hint=None, c_cpp_properties_path=None, verbosity=None): '''Given a hint to a contract directory, produce ABI file. ''' contract_dir = config.contract_dir(contract_dir_hint) # source_files[0] is directory, source_files[1] is contents: contract_source_files = config.contract_source_files(contract_dir) source_files = [] source_ext = [".c", ".cpp", ".cxx", ".c++"] for file in contract_source_files[1]: if os.path.splitext(file)[1].lower() in source_ext: source_files.append(file) if not source_files: raise errors.Error(''' "The source is empty. The assumed contract dir is {} '''.format(contract_dir)) return code_name = os.path.splitext(os.path.basename(source_files[0]))[0] target_path = os.path.normpath( os.path.join(get_target_dir(contract_source_files[0]), code_name + ".abi")) for file in contract_source_files[1]: if os.path.splitext(file)[1].lower() == ".abi": logger.INFO( ''' NOTE: An ABI exists in the source directory. Cannot overwrite it: {} Just copying it to the target directory. '''.format(file), verbosity) shutil.move(file, target_path) return command_line = [ config.eosio_cpp(), "-contract=" + code_name, "-R=" + get_resources_dir(contract_source_files[0]), "-abigen", "-abigen_output=" + target_path ] c_cpp_properties = get_c_cpp_properties(contract_dir, c_cpp_properties_path) for entry in c_cpp_properties["configurations"][0]["includePath"]: if entry == "${workspaceFolder}": command_line.append("-I=" + contract_dir) else: command_line.append("-I=" + strip_wsl_root(entry)) for file in source_files: command_line.append(file) try: process(command_line) except Exception as e: raise errors.Error(str(e)) logger.TRACE( ''' ABI file writen to file: {} '''.format(target_path), verbosity)
def WAST(contract_dir_hint, c_cpp_properties_path=None, compile_only=False, verbosity=None): '''Produce WASM code. ''' contract_dir = config.contract_dir(contract_dir_hint) # source_files[0] is directory, source_files[1] is contents: contract_source_files = config.contract_source_files(contract_dir) source_files = [] source_ext = [".c", ".cpp", ".cxx", ".c++"] for file in contract_source_files[1]: if os.path.splitext(file)[1].lower() in source_ext: source_files.append(file) if not source_files: raise errors.Error(''' "The source is empty. The assumed contract dir is {} '''.format(contract_dir)) return code_name = os.path.splitext(os.path.basename(source_files[0]))[0] target_path = os.path.normpath( os.path.join(get_target_dir(contract_source_files[0]), code_name + ".wasm")) c_cpp_properties = get_c_cpp_properties(contract_dir, c_cpp_properties_path) command_line = [config.eosio_cpp()] for entry in c_cpp_properties["configurations"][0]["includePath"]: if entry == "${workspaceFolder}": command_line.append("-I=" + contract_dir) else: command_line.append("-I=" + strip_wsl_root(entry)) for entry in c_cpp_properties["configurations"][0]["libs"]: command_line.append("-l=" + strip_wsl_root(entry)) for entry in c_cpp_properties["configurations"][0]["compilerOptions"]: command_line.append(entry) for file in source_files: command_line.append(file) if setup.is_print_command_line: print("######## \n{}:".format(" ".join(command_line))) if not compile_only: command_line.append("-o=" + target_path) try: process(command_line) except Exception as e: raise errors.Error(str(e)) if not compile_only: logger.TRACE( ''' WASM file writen to file: {} '''.format(os.path.normpath(target_path)), verbosity)
def WAST(contract_dir_hint, code_name=None, include_dir=None, compile_only=False): '''Given a hint to a contract directory, produce WAST and WASM code. ''' contract_dir = config.contract_dir(contract_dir_hint) source = config.contract_source_files(contract_dir) srcs = source[1] if not srcs: raise errors.Error(''' "The source is empty. The assumed contract dir is {} '''.format(contract_dir)) return targetPathWast = None target_dir_path = get_target_dir(source[0]) workdir = os.path.join(target_dir_path, "working_dir") if not os.path.exists(workdir): os.makedirs(workdir) workdir_build = os.path.join(workdir, "build") if not os.path.exists(workdir_build): os.mkdir(workdir_build) objectFileList = [] extensions = [".h", ".hpp", ".hxx", ".c", ".cpp", ".cxx", ".c++"] if not code_name: code_name = os.path.splitext(os.path.basename(srcs[0]))[0] targetPathWast = os.path.join(target_dir_path, code_name + ".wast") target_path_wasm = os.path.join(target_dir_path, code_name + ".wasm") eosio_cpp = None try: eosio_cpp = config.eosio_cpp() except: pass if eosio_cpp: command_line = [config.eosio_cpp(), "-o", target_path_wasm] for file in srcs: if not os.path.splitext(file)[1].lower() in extensions: continue command_line.append(file) try: process(command_line) except Exception as e: raise errors.Error(str(e)) else: ########################################################################### # eosio.cdt is not available. for file in srcs: if not os.path.splitext(file)[1].lower() in extensions: continue command_line = [ config.wasm_clang_exe(), "-emit-llvm", "-O3", "--std=c++14", "--target=wasm32", "-nostdinc", #"-DBOOST_DISABLE_ASSERTS -DBOOST_EXCEPTION_DISABLE", "-nostdlib", "-nostdlibinc", "-ffreestanding", "-nostdlib", "-fno-threadsafe-statics", "-fno-rtti", "-fno-exceptions", "-I", config.eosio_repository_dir() + "/contracts/libc++/upstream/include", "-I", config.eosio_repository_dir() + "/contracts/musl/upstream/include", "-I", config.eosio_repository_dir() + "/externals/magic_get/include", "-I", config.boost_include_dir(), "-I", config.eosio_repository_dir() + "/contracts", "-I", config.eosio_repository_dir() + "/build/contracts", "-I", contract_dir ] if include_dir: include_dirs = include_dir.split(",") for dir in include_dirs: command_line.extend(["-I", dir]) output = os.path.join(workdir_build, code_name + ".o") objectFileList.append(output) command_line.extend(["-c", file, "-o", output]) if setup.is_print_command_line: print("######## {}:".format(config.wasm_clang_exe())) print(" ".join(command_line)) try: process(command_line) except Exception as e: try: shutil.rmtree(workdir) except: pass raise errors.Error(str(e)) if not compile_only: command_line = [ config.wasm_llvm_link_exe(), "-only-needed", "-o", workdir + "/linked.bc", " ".join(objectFileList), config.eosio_repository_dir() + "/build/contracts/musl/libc.bc", config.eosio_repository_dir() + "/build/contracts/libc++/libc++.bc", config.eosio_repository_dir() + "/build/contracts/eosiolib/eosiolib.bc" ] if setup.is_print_command_line: print("######## {}:".format(config.wasm_llvm_link_exe())) print(" ".join(command_line)) try: process(command_line) except Exception as e: raise errors.Error(str(e)) command_line = [ config.wasm_llc_exe(), "-thread-model=single", "--asm-verbose=false", "-o", workdir + "/assembly.s", workdir + "/linked.bc" ] if setup.is_print_command_line: print("######## {}:".format(config.wasm_llc_exe())) print(" ".join(command_line)) try: process(command_line) except Exception as e: raise errors.Error(str(e)) try: shutil.rmtree(workdir) except: pass raise errors.Error(str(e)) command_line = [ config.s2wasm_exe(), "-o", targetPathWast, "-s", "16384", workdir + "/assembly.s" ] if setup.is_print_command_line: print("######## {}:".format(config.s2wasm_exe())) print(" ".join(command_line)) try: process(command_line) except Exception as e: try: shutil.rmtree(workdir) except: pass raise errors.Error(str(e)) logger.TRACE(''' WAST file writen to file: {} '''.format(os.path.normpath(targetPathWast))) command_line = [ config.wast2wasm_exe(), targetPathWast, target_path_wasm, "-n" ] if setup.is_print_command_line: print("######## {}:".format(config.wast2wasm_exe())) print(" ".join(command_line)) try: process(command_line) except Exception as e: try: shutil.rmtree(workdir) except: pass raise errors.Error(str(e)) try: shutil.rmtree(workdir) except: pass logger.TRACE(''' WASM file writen to file: {} '''.format(os.path.normpath(target_path_wasm)))