Ejemplo n.º 1
0
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 ", "")
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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")            
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
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)))