install

installer
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/install

commit 02acbf7030ae13bfb064eff6fa33f92caba86636
parent fa3d2e1744cedac60a04d0ec0e8fb25689d9e819
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Thu,  1 Dec 2016 18:20:01 +0100

Add(Time estimation, better progress bar, gcc package)

Diffstat:
Mpkgs/binutils_p1/binutils_p1.py | 6+++---
Apkgs/gcc_p1/__init__.py | 0
Apkgs/gcc_p1/gcc_p1.py | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mscreens/install/install.py | 95++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
4 files changed, 162 insertions(+), 23 deletions(-)

diff --git a/pkgs/binutils_p1/binutils_p1.py b/pkgs/binutils_p1/binutils_p1.py @@ -39,7 +39,7 @@ class Binutils_P1: "archive": "binutils-2.27.tar.bz2", # Archive name "SBU": 1, # SBU (Compilation time) "tmp_install": True, # Is this package part of the temporary install - "next": False, # Next package to install + "next": "gcc", # Next package to install "after": False, "urls": [ # Url to download the package. The first one must be morphux servers "https://install.morphux.org/packages/binutils-2.27.tar.bz2", @@ -49,7 +49,7 @@ class Binutils_P1: return self.config def before(self): - res = self.e(["mkdir", "-v", "build"]) + res = self.e(["mkdir", "-vp", "build"]) os.chdir("build") return res @@ -64,7 +64,7 @@ class Binutils_P1: ]) def make(self): - return self.e(["make"]) + return self.e(["make", "-j", self.conf_lst["cpus"]]) def install(self): if self.conf_lst["arch"] == "x86_64": diff --git a/pkgs/gcc_p1/__init__.py b/pkgs/gcc_p1/__init__.py diff --git a/pkgs/gcc_p1/gcc_p1.py b/pkgs/gcc_p1/gcc_p1.py @@ -0,0 +1,84 @@ +################################### LICENSE #################################### +# Copyright 2016 Morphux # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +################################################################################ + +## +# gcc_p1.py +# Created: 01/12/2016 +# By: Louis Solofrizzo <louis@morphux.org> +## + +import os + +class Gcc_P1: + + conf_lst = {} + e = False + root_dir = "" + + def init(self, c_lst, ex, root_dir): + self.conf_lst = c_lst + self.e = ex + self.root_dir = root_dir + self.config = { + "name": "gcc", # Name of the package + "version": "6.2.0", # Version of the package + "size": 2500, # Size of the installed package (MB) + "archive": "gcc-6.2.0.tar.bz2", # Archive name + "SBU": 8.3, # SBU (Compilation time) + "tmp_install": True, # Is this package part of the temporary install + "next": False, # Next package to install + "after": False, + "urls": [ # Url to download the package. The first one must be morphux servers + "https://install.morphux.org/packages/gcc-6.2.0.tar.bz2" + ] + } + return self.config + + def before(self): + res = self.e(["./morphux_patch.sh"]) + self.e(["mkdir", "-pv", "build"]) + os.chdir("build") + return res + + def configure(self): + return self.e(["../configure", + "--target="+ self.conf_lst["target"], + "--prefix=/tools", + "--with-glibc-version=2.11", + "--with-sysroot="+ self.root_dir, + "--with-newlib", + "--without-headers", + "--with-local-prefix=/tools", + "--disable-nls", + "--disable-shared", + "--disable-multilib", + "--disable-decimal-float", + "--disable-threads", + "--disable-libatomic", + "--disable-libgomp", + "--disable-libmpx", + "--disable-libquadmath", + "--disable-libssp", + "--disable-libvtv", + "--disable-libstdcxx", + "--enable-languages=c,c++" + ]) + + def make(self): + return self.e(["make", "-j", self.conf_lst["cpus"]]) + + def install(self): + return self.e(["make", "install"]) diff --git a/screens/install/install.py b/screens/install/install.py @@ -22,9 +22,13 @@ import json import os +import sys import time +import datetime +import threading from urllib.request import urlretrieve from subprocess import Popen, PIPE, STDOUT, call +import multiprocessing class Install: @@ -42,6 +46,10 @@ class Install: sum_file = "CHECKSUMS" checksums = {} # Object of packages sums m_gauge = {} # Object used for easy progress install + sbu_time = 0 # Standard Build Unit time + total_sbus = 0 # Total SBU to install the system + current_time = 0 # Current install time + in_install = 0 ## # Functions @@ -72,12 +80,13 @@ class Install: self.conf_lst["arch"] = self.exec(["uname", "-m"])[0].decode().split("\n")[0] self.conf_lst["target"] = self.exec(["uname", "-m"])[0].decode().split("\n")[0] + "-morphux-linux-gnu" + # Get number of CPUs + self.conf_lst["cpus"] = str(multiprocessing.cpu_count()) + # Load packages files self.load_pkgs() - #self.phase_1_install() - #sys.exit(1) - # If a pre-existing install is present, format it + # If a pre-existing install is present, clean it if os.path.isdir(self.mnt_point): self.dlg.infobox("Cleaning "+ self.mnt_point +" repository...", width=50, height=3) @@ -102,6 +111,10 @@ class Install: self.exec(["ln", "-sv", self.mnt_point + "/tools", "/"]) self.phase_1_install() + self.dlg.msgbox("The installation is finished. Hit 'Enter' to close this dialog and reboot.", title="Success !") + # Need reboot here + sys.exit(1) + # Load all the packages configuration files # path: Default to ./pkgs def load_pkgs(self, path = "pkgs"): @@ -267,14 +280,18 @@ class Install: total_sbus = 0 # Total time of the install, in SBUs for name, pkg in self.pkgs.items(): - if pkg[1]["tmp_install"]: + if pkg[1]["tmp_install"] == True: total_size += pkg[1]["size"] total_sbus += pkg[1]["SBU"] pkg_phase_1[name] = pkg self.pkg_download(pkg_phase_1) - self.inst_title = "Phase 1: Temporary" + self.inst_title = "Phase 1: Temporary Install" + self.total_sbus = total_sbus + self.current_time = time.time() + self.in_install = 1 self.install(pkg_phase_1, "binutils") + self.in_install = 0 # This function take an object of packages, check if the sources are there. # If they aren't, the function download them. @@ -351,7 +368,7 @@ class Install: sys.exit(1) # All good, we update the gauge - self.dlg.gauge_update(int(to_check * 100 / checked)) + self.dlg.gauge_update(int(checked * 100 / to_check)) checked += 1 # Stop the gauge @@ -389,12 +406,18 @@ class Install: installed = 1 while pkg != False: - # Init the global progress bar - self.global_progress_bar(text="Installing "+ pkg[1]["name"] +"-"+ pkg[1]["version"], - percent=int((to_install * 100) / installed), + # Init the global progress bar + self.global_progress_bar(text="Installing "+ pkg[1]["name"] +"-"+ pkg[1]["version"]+ "...", + percent=int((installed * 100) / to_install), decomp="In Progress", conf="N/A", comp="N/A", inst="N/A", post_comp="N/A", pre_comp="N/A") + # If the package is the first, we measure the time + if self.sbu_time == 0 and first == pkg[1]["name"]: + start = time.time() + self.async_progress_bar() + + # Decompress the archive self.untar(pkg[1]) @@ -430,7 +453,7 @@ class Install: self.global_progress_bar(comp="Skipped") self.global_progress_bar(inst="In Progress") - # make install instructions + # make install instructions if "install" not in pkg[1]: res = pkg[0].install() if res[1] != 0: @@ -449,12 +472,18 @@ class Install: else: self.global_progress_bar(post_comp="Skipped") + # If the package is first, we stock the total build time + if self.sbu_time == 0 and first == pkg[1]["name"]: + self.sbu_time = (time.time() - start) + self.global_progress_bar(reset=True) if pkg[1]["next"] in lst: pkg = lst[pkg[1]["next"]] else: pkg = False installed += 1 + + self.install = 0 return 0 # This function take a package configuration, and untar an archive in @@ -509,20 +538,46 @@ class Install: self.m_gauge = {} return 0 - self.dlg.mixedgauge(self.m_gauge["text"], percent=self.m_gauge["percent"], - elements = [ - ("Decompressing", self.m_gauge["decomp"]), - ("Pre-Compilation", self.m_gauge["pre_comp"]), - ("Configuration", self.m_gauge["conf"]), - ("Compilation", self.m_gauge["comp"]), - ("Installation", self.m_gauge["inst"]), - ("Post-Compilation", self.m_gauge["post_comp"]), - ], title=self.inst_title) + # Asynchronous function, that display the bar + # Called every one second + def async_progress_bar(self): + if self.in_install == 1: + + # Add the estimated time + if self.sbu_time == 0: + s_time = "\nEstimated time of install: N/A\n" + else: + est_time = self.sbu_time * self.total_sbus + s_time = "\nEstimated time of install: " + time.strftime("%H:%M:%S", time.gmtime(est_time)) + "\n" + + s_time += "Current installation time: " + time.strftime("%H:%M:%S", time.gmtime(time.time() - self.current_time)) + + self.dlg.mixedgauge(self.m_gauge["text"] + s_time, percent=self.m_gauge["percent"], + elements = [ + ("Decompressing", self.m_gauge["decomp"]), + ("Pre-Compilation", self.m_gauge["pre_comp"]), + ("Configuration", self.m_gauge["conf"]), + ("Compilation", self.m_gauge["comp"]), + ("Installation", self.m_gauge["inst"]), + ("Post-Compilation", self.m_gauge["post_comp"]), + ], title=self.inst_title) + + threading.Timer(1, self.async_progress_bar).start() # Function that handle installation error # exec_return arg is a tuple of (string_out, return_code) def inst_error(self, exec_return): - code = self.dlg.yesno("An error happened during the installation :(\nDo you want to see the log file ?") + # Stop the progress bar thread + self.in_install = 0 + + # Print a dialog to ask the user if we want to see the log + code = self.dlg.yesno("An error happened during the installation :(\nReturn code: "+ + str(exec_return[1])+"\nDo you want to see the log file ?") + + # If user press 'Yes' if code == "ok": + # Show the output of the command self.dlg.scrollbox(exec_return[0].decode()) + + # Abort the installation sys.exit(1)