""" Install solc """ import functools import os import stat import subprocess import sys import contextlib import zipfile V0_4_1 = 'v0.4.1' V0_4_2 = 'v0.4.2' V0_4_6 = 'v0.4.6' V0_4_7 = 'v0.4.7' V0_4_8 = 'v0.4.8' V0_4_9 = 'v0.4.9' V0_4_11 = 'v0.4.11' V0_4_12 = 'v0.4.12' V0_4_13 = 'v0.4.13' V0_4_14 = 'v0.4.14' V0_4_15 = 'v0.4.15' V0_4_16 = 'v0.4.16' V0_4_17 = 'v0.4.17' V0_4_18 = 'v0.4.18' V0_4_19 = 'v0.4.19' V0_4_20 = 'v0.4.20' V0_4_21 = 'v0.4.21' V0_4_22 = 'v0.4.22' V0_4_23 = 'v0.4.23' V0_4_24 = 'v0.4.24' V0_4_25 = 'v0.4.25' LINUX = 'linux' OSX = 'darwin' WINDOWS = 'win32' # # System utilities. # @contextlib.contextmanager def chdir(path): original_path = os.getcwd() try: os.chdir(path) yield finally: os.chdir(original_path) def get_platform(): if sys.platform.startswith('linux'): return LINUX elif sys.platform == OSX: return OSX elif sys.platform == WINDOWS: return WINDOWS else: raise KeyError("Unknown platform: {0}".format(sys.platform)) def is_executable_available(program): def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) fpath = os.path.dirname(program) if fpath: if is_exe(program): return True else: for path in os.environ["PATH"].split(os.pathsep): path = path.strip('"') exe_file = os.path.join(path, program) if is_exe(exe_file): return True return False def ensure_path_exists(dir_path): """ Make sure that a path exists """ if not os.path.exists(dir_path): os.makedirs(dir_path) return True return False def ensure_parent_dir_exists(path): ensure_path_exists(os.path.dirname(path)) def check_subprocess_call(command, message=None, stderr=subprocess.STDOUT, **proc_kwargs): if message: print(message) print("Executing: {0}".format(" ".join(command))) return subprocess.check_call( command, stderr=subprocess.STDOUT, **proc_kwargs ) def check_subprocess_output(command, message=None, stderr=subprocess.STDOUT, **proc_kwargs): if message: print(message) print("Executing: {0}".format(" ".join(command))) return subprocess.check_output( command, stderr=subprocess.STDOUT, **proc_kwargs ) def chmod_plus_x(executable_path): current_st = os.stat(executable_path) os.chmod(executable_path, current_st.st_mode | stat.S_IEXEC) SOLIDITY_GIT_URI = "https://github.com/ethereum/solidity.git" def is_git_repository(path): git_dir = os.path.join( path, '.git', ) return os.path.exists(git_dir) # # Installation filesystem path utilities # def get_base_install_path(identifier): if 'SOLC_BASE_INSTALL_PATH' in os.environ: return os.path.join( os.environ['SOLC_BASE_INSTALL_PATH'], 'solc-{0}'.format(identifier), ) else: return os.path.expanduser(os.path.join( '~', '.py-solc', 'solc-{0}'.format(identifier), )) def get_repository_path(identifier): return os.path.join( get_base_install_path(identifier), 'source', ) def get_release_zipfile_path(identifier): return os.path.join( get_base_install_path(identifier), 'release.zip', ) def get_extract_path(identifier): return os.path.join( get_base_install_path(identifier), 'bin', ) def get_executable_path(identifier): extract_path = get_extract_path(identifier) return os.path.join( extract_path, 'solc', ) def get_build_dir(identifier): repository_path = get_repository_path(identifier) return os.path.join( repository_path, 'build', ) def get_built_executable_path(identifier): build_dir = get_build_dir(identifier) return os.path.join( build_dir, 'solc', 'solc', ) # # Installation primitives. # def clone_solidity_repository(identifier): if not is_executable_available('git'): raise OSError("The `git` is required but was not found") repository_path = get_repository_path(identifier) ensure_parent_dir_exists(repository_path) command = [ "git", "clone", "--recurse-submodules", "--branch", identifier, "--depth", "10", SOLIDITY_GIT_URI, repository_path, ] return check_subprocess_call( command, message="Checking out solidity repository @ {0}".format(identifier), ) def initialize_repository_submodules(identifier): if not is_executable_available('git'): raise OSError("The `git` is required but was not found") repository_path = get_repository_path(identifier) command = [ "git", "submodule", "update", "--init", "--recursive", ] check_subprocess_call( command, "Initializing repository submodules @ {0}".format(repository_path), ) DOWNLOAD_UBUNTU_RELEASE_URI_TEMPLATE = "https://github.com/ethereum/solidity/releases/download/{0}/solidity-ubuntu-trusty.zip" # noqa: E501 def download_ubuntu_release(identifier): download_uri = DOWNLOAD_UBUNTU_RELEASE_URI_TEMPLATE.format(identifier) release_zipfile_path = get_release_zipfile_path(identifier) ensure_parent_dir_exists(release_zipfile_path) command = [ "wget", download_uri, '-c', # resume previously incomplete download. '-O', release_zipfile_path, ] return check_subprocess_call( command, message="Downloading ubuntu release from {0}".format(download_uri), ) DOWNLOAD_STATIC_RELEASE_URI_TEMPLATE = "https://github.com/ethereum/solidity/releases/download/{0}/solc-static-linux" # noqa: E501 def download_static_release(identifier): download_uri = DOWNLOAD_STATIC_RELEASE_URI_TEMPLATE.format(identifier) static_binary_path = get_executable_path(identifier) ensure_parent_dir_exists(static_binary_path) command = [ "wget", download_uri, '-c', # resume previously incomplete download. '-O', static_binary_path, ] return check_subprocess_call( command, message="Downloading static linux binary from {0}".format(download_uri), ) def extract_release(identifier): release_zipfile_path = get_release_zipfile_path(identifier) extract_path = get_extract_path(identifier) ensure_path_exists(extract_path) print("Extracting zipfile: {0} -> {1}".format(release_zipfile_path, extract_path)) with zipfile.ZipFile(release_zipfile_path) as zipfile_file: zipfile_file.extractall(extract_path) executable_path = get_executable_path(identifier) print("Making `solc` binary executable: `chmod +x {0}`".format(executable_path)) chmod_plus_x(executable_path) def install_solc_dependencies(identifier): repository_path = get_repository_path(identifier) if not is_git_repository(repository_path): raise OSError("Git repository not found @ {0}".format(repository_path)) with chdir(repository_path): install_deps_script_path = os.path.join(repository_path, 'scripts', 'install_deps.sh') return check_subprocess_call( command=["sh", install_deps_script_path], message="Running dependency installation script `install_deps.sh` @ {0}".format( install_deps_script_path, ), ) def install_solc_from_ubuntu_release_zip(identifier): download_ubuntu_release(identifier) extract_release(identifier) extract_path = get_extract_path(identifier) executable_path = get_executable_path(identifier) assert os.path.exists(executable_path), "Executable not found @".format(executable_path) check_version_command = [executable_path, '--version'] check_subprocess_output( check_version_command, message="Checking installed executable version @ {0}".format(executable_path), env={'LD_LIBRARY_PATH': extract_path}, ) print("solc successfully installed at: {0}".format(executable_path)) def install_solc_from_static_linux(identifier): download_static_release(identifier) executable_path = get_executable_path(identifier) chmod_plus_x(executable_path) check_version_command = [executable_path, '--version'] check_subprocess_output( check_version_command, message="Checking installed executable version @ {0}".format(executable_path), ) print("solc successfully installed at: {0}".format(executable_path)) def build_solc_from_source(identifier): if not is_git_repository(get_repository_path(identifier)): clone_solidity_repository(identifier) build_dir = get_build_dir(identifier) ensure_path_exists(build_dir) with chdir(build_dir): cmake_command = ["cmake", ".."] check_subprocess_call( cmake_command, message="Running cmake build command", ) make_command = ["make"] check_subprocess_call( make_command, message="Running make command", ) built_executable_path = get_built_executable_path(identifier) chmod_plus_x(built_executable_path) executable_path = get_executable_path(identifier) ensure_parent_dir_exists(executable_path) os.symlink(built_executable_path, executable_path) chmod_plus_x(executable_path) def install_from_ubuntu_release(identifier): if not is_git_repository(get_repository_path(identifier)): clone_solidity_repository(identifier) install_solc_dependencies(identifier) install_solc_from_ubuntu_release_zip(identifier) executable_path = get_executable_path(identifier) print("Succesfully installed solc @ `{0}`".format(executable_path)) install_v0_4_1_linux = functools.partial(install_from_ubuntu_release, V0_4_1) install_v0_4_2_linux = functools.partial(install_from_ubuntu_release, V0_4_2) install_v0_4_6_linux = functools.partial(install_from_ubuntu_release, V0_4_6) install_v0_4_7_linux = functools.partial(install_from_ubuntu_release, V0_4_7) install_v0_4_8_linux = functools.partial(install_from_ubuntu_release, V0_4_8) install_v0_4_9_linux = functools.partial(install_from_ubuntu_release, V0_4_9) def install_from_static_linux(identifier): install_solc_from_static_linux(identifier) executable_path = get_executable_path(identifier) print("Succesfully installed solc @ `{0}`".format(executable_path)) install_v0_4_11_linux = functools.partial(install_solc_from_static_linux, V0_4_11) install_v0_4_12_linux = functools.partial(install_solc_from_static_linux, V0_4_12) install_v0_4_13_linux = functools.partial(install_solc_from_static_linux, V0_4_13) install_v0_4_14_linux = functools.partial(install_solc_from_static_linux, V0_4_14) install_v0_4_15_linux = functools.partial(install_solc_from_static_linux, V0_4_15) install_v0_4_16_linux = functools.partial(install_solc_from_static_linux, V0_4_16) install_v0_4_17_linux = functools.partial(install_solc_from_static_linux, V0_4_17) install_v0_4_18_linux = functools.partial(install_solc_from_static_linux, V0_4_18) install_v0_4_19_linux = functools.partial(install_solc_from_static_linux, V0_4_19) install_v0_4_20_linux = functools.partial(install_solc_from_static_linux, V0_4_20) install_v0_4_21_linux = functools.partial(install_solc_from_static_linux, V0_4_21) install_v0_4_22_linux = functools.partial(install_solc_from_static_linux, V0_4_22) install_v0_4_23_linux = functools.partial(install_solc_from_static_linux, V0_4_23) install_v0_4_24_linux = functools.partial(install_solc_from_static_linux, V0_4_24) install_v0_4_25_linux = functools.partial(install_solc_from_static_linux, V0_4_25) def install_from_source(identifier): if not is_git_repository(get_repository_path(identifier)): clone_solidity_repository(identifier) install_solc_dependencies(identifier) build_solc_from_source(identifier) executable_path = get_executable_path(identifier) print("Succesfully installed solc @ `{0}`".format(executable_path)) install_v0_4_8_osx = functools.partial(install_from_source, V0_4_8) install_v0_4_11_osx = functools.partial(install_from_source, V0_4_11) install_v0_4_12_osx = functools.partial(install_from_source, V0_4_12) install_v0_4_13_osx = functools.partial(install_from_source, V0_4_13) install_v0_4_14_osx = functools.partial(install_from_source, V0_4_14) install_v0_4_15_osx = functools.partial(install_from_source, V0_4_15) install_v0_4_16_osx = functools.partial(install_from_source, V0_4_16) install_v0_4_17_osx = functools.partial(install_from_source, V0_4_17) install_v0_4_18_osx = functools.partial(install_from_source, V0_4_18) install_v0_4_19_osx = functools.partial(install_from_source, V0_4_19) install_v0_4_20_osx = functools.partial(install_from_source, V0_4_20) install_v0_4_21_osx = functools.partial(install_from_source, V0_4_21) install_v0_4_22_osx = functools.partial(install_from_source, V0_4_22) install_v0_4_23_osx = functools.partial(install_from_source, V0_4_23) install_v0_4_24_osx = functools.partial(install_from_source, V0_4_24) install_v0_4_25_osx = functools.partial(install_from_source, V0_4_25) INSTALL_FUNCTIONS = { LINUX: { V0_4_1: install_v0_4_1_linux, V0_4_2: install_v0_4_2_linux, V0_4_6: install_v0_4_6_linux, V0_4_7: install_v0_4_7_linux, V0_4_8: install_v0_4_8_linux, V0_4_9: install_v0_4_9_linux, V0_4_11: install_v0_4_11_linux, V0_4_12: install_v0_4_12_linux, V0_4_13: install_v0_4_13_linux, V0_4_14: install_v0_4_14_linux, V0_4_15: install_v0_4_15_linux, V0_4_16: install_v0_4_16_linux, V0_4_17: install_v0_4_17_linux, V0_4_18: install_v0_4_18_linux, V0_4_19: install_v0_4_19_linux, V0_4_20: install_v0_4_20_linux, V0_4_21: install_v0_4_21_linux, V0_4_22: install_v0_4_22_linux, V0_4_23: install_v0_4_23_linux, V0_4_24: install_v0_4_24_linux, V0_4_25: install_v0_4_25_linux, }, OSX: { V0_4_8: install_v0_4_8_osx, V0_4_11: install_v0_4_11_osx, V0_4_12: install_v0_4_12_osx, V0_4_13: install_v0_4_13_osx, V0_4_14: install_v0_4_14_osx, V0_4_15: install_v0_4_15_osx, V0_4_16: install_v0_4_16_osx, V0_4_17: install_v0_4_17_osx, V0_4_18: install_v0_4_18_osx, V0_4_19: install_v0_4_19_osx, V0_4_20: install_v0_4_20_osx, V0_4_21: install_v0_4_21_osx, V0_4_22: install_v0_4_22_osx, V0_4_23: install_v0_4_23_osx, V0_4_24: install_v0_4_24_osx, V0_4_25: install_v0_4_25_osx, } } def install_solc(identifier, platform=None): if platform is None: platform = get_platform() if platform not in INSTALL_FUNCTIONS: raise ValueError( "Installation of solidity is not supported on your platform ({0}). " "Supported platforms are: {1}".format( platform, ', '.join(sorted(INSTALL_FUNCTIONS.keys())), ) ) elif identifier not in INSTALL_FUNCTIONS[platform]: raise ValueError( "Installation of solidity=={0} is not supported. Must be one of {1}".format( identifier, ', '.join(sorted(INSTALL_FUNCTIONS[platform].keys())), ) ) install_fn = INSTALL_FUNCTIONS[platform][identifier] install_fn() if __name__ == "__main__": try: identifier = sys.argv[1] except IndexError: print("Invocation error. Should be invoked as `./install_solc.py <release-tag>`") sys.exit(1) install_solc(identifier)