Beispiel #1
0
    def gdb(self, command, src_dir=True):
        """
        Run a command with gdb in the build folder.
        ```
            self.gdb('bin/NanoMeshTests')
        ```
        """
        if self.android or self.ios or self.raspi:
            console('Cannot run tests for Android, iOS, Raspi builds.')
            return  # nothing to run

        split = command.split(' ', 1)
        cmd = split[0].lstrip('.')
        args = split[1] if len(split) >= 2 else ''
        path = self.dep.src_dir if src_dir else self.dep.build_dir
        path = f"{path}/{os.path.dirname(cmd).lstrip('/')}"
        exe = os.path.basename(cmd)

        if self.windows:
            if not src_dir: path = f'{path}/{self.cmake_build_type}'
            gdb = f'{exe} {args}'
        elif self.macos:
            # b: batch, q: quiet, -o r: run
            # -k bt: on crash, backtrace
            # -k q: on crash, quit
            gdb = f'lldb -b -o r -k bt -k q  -- ./{exe} {args}'
        else:  # linux
            # r: run;  bt: give backtrace;  q: quit when done;
            gdb = f'gdb -batch -return-child-result -ex=r -ex=bt -ex=q --args ./{exe} {args}'

        if not (os.path.exists(f'{path}/{exe}')
                or os.path.exists(f'{path}/{exe}.exe')):
            raise IOError(f'Could not find {path}/{exe}')
        execute_echo(path, gdb)
Beispiel #2
0
 def current_commit(self):
     result = execute_piped(['git', 'show', '--oneline', '-s'],
                            cwd=self.dep.src_dir)
     if self.dep.config.verbose:
         console(
             f'  {self.dep.name: <16} git show --oneline -s:   {result}')
     return result
Beispiel #3
0
 def cmake_install(self):
     if self.config.print:
         console(
             '\n\n#############################################################'
         )
         console(f"CMake install {self.name} ...")
     cmake.run_build(self, install=True)
Beispiel #4
0
def export_lib(target, relative_path, src_dir):
    path = target_root_path(target, relative_path, src_dir)
    if os.path.exists(path):
        target.exported_libs.append(path)
        target.exported_libs = _get_unique_basenames(target.exported_libs)
    else:
        console(f'export_lib failed to find: {path}')
Beispiel #5
0
    def _should_build(self, conf, target, is_target, git_changed):
        def build(r):
            if conf.print:
                args = f'{target.args}' if target.args else ''
                console(f'  - Target {target.name: <16}   BUILD [{r}]  {args}')
            return True

        if conf.target and not is_target:  # if we called: "target=SpecificProject"
            return False  # skip build if target doesn't match

        ## build also entails packaging
        if conf.clean and is_target: return build('cleaned target')
        if self.is_root: return build('root target')
        if conf.target and is_target: return build('target=' + conf.target)
        if self.always_build: return build('always build')
        if update_mamafile_tag(self.mamafile_path(), self.build_dir):
            return build(target.name + '/mamafile.py modified')
        if update_cmakelists_tag(self.cmakelists_path(), self.build_dir):
            return build(target.name + '/CMakeLists.txt modified')
        if git_changed: return build('git commit changed')

        if not self.nothing_to_build:
            if not self.has_build_files(): return build('not built yet')
            if not target.build_dependencies:
                return build('no build dependencies')

        missing_product = self.find_first_missing_build_product()
        if missing_product: return build(f'{missing_product} does not exist')

        missing_dep = self.find_missing_dependency()
        if missing_dep: return build(f'{missing_dep} was removed')

        if conf.print:
            console(f'  - Target {target.name: <16}   OK')
        return False  # do not build, all is ok
Beispiel #6
0
def export_asset(target, asset, category, src_dir):
    full_asset = target_root_path(target, asset, src_dir)
    if os.path.exists(full_asset):
        target.exported_assets.append(Asset(asset, full_asset, category))
        return True
    else:
        console(f'export_asset failed to find: {full_asset}')
        return False
Beispiel #7
0
def has_tag_changed(old_tag_file, new_tag):
    if not os.path.exists(old_tag_file):
        return True
    old_tag = pathlib.Path(old_tag_file).read_text()
    if old_tag != new_tag:
        console(f" tagchange '{old_tag.strip()}'\n"+
                f"      ---> '{new_tag.strip()}'")
        return True
    return False
Beispiel #8
0
 def find_default_fortran_compiler(self):
     paths = []
     if System.linux:
         paths += [find_executable_from_system('gfortran')]
     
     for fortran_path in paths:
         if fortran_path and os.path.exists(fortran_path):
             if self.verbose: console(f'Found Fortran: {fortran_path}')
             return fortran_path
     return None
Beispiel #9
0
 def get_visualstudio_cmake_id(self):
     if self._visualstudio_cmake_id:
         return self._visualstudio_cmake_id
     
     path = self.get_visualstudio_path()
     if '\\2019\\' in path: self._visualstudio_cmake_id = 'Visual Studio 16 2019'
     else:                  self._visualstudio_cmake_id = 'Visual Studio 15 2017'
     
     if self.verbose: console(f'Detected CMake Generator: -G"{self._visualstudio_cmake_id}" -A {self.get_visualstudio_cmake_arch()}')
     return self._visualstudio_cmake_id
Beispiel #10
0
 def cmake_build(self):
     if self.config.print:
         console(
             '\n\n#############################################################'
         )
         console(f"CMakeBuild {self.name}  ({self.cmake_build_type})")
     self.dep.ensure_cmakelists_exists()
     cmake.inject_env(self)
     cmake.run_config(self)  # THROWS on CMAKE failure
     cmake.run_build(self, install=True)  # THROWS on CMAKE failure
Beispiel #11
0
 def prefer_gcc(self, target_name):
     if not self.linux or self.raspi or self.gcc: return
     if not self.compiler_cmd:
         self.clang = False
         self.gcc   = True
         self.compiler_cmd = True
         if self.print:
             console(f'Target {target_name} requests GCC. Using GCC since no explicit compiler set.')
     else:
         if self.print:
             console(f'Target {target_name} requested GCC but compiler already set to Clang.')
Beispiel #12
0
 def copy(self, src, dst):
     """
     Utility for copying files and folders
     ```
         # copies built .so into an android archive
         self.copy(self.build_dir('libAwesome.so'), 
                   self.source_dir('deploy/Awesome.aar/jni/armeabi-v7a'))
     ```
     """
     console(f'copy {src} --> {dst}')
     copy_if_needed(src, dst)
Beispiel #13
0
def deploy_framework(framework, deployFolder):
    if not os.path.exists(framework):
        raise IOError(f'no framework found at: {framework}') 
    if os.path.exists(deployFolder):
        name = os.path.basename(framework)
        deployPath = os.path.join(deployFolder, name)
        console(f'Deploying framework to {deployPath}')
        execute(f'rm -rf {deployPath}')
        shutil.copytree(framework, deployPath)
        return True
    return False
Beispiel #14
0
 def after_load(self):
     if self.config.no_specific_target():
         first_changed = next(
             (c for c in self.children if c.should_rebuild), None)
         if first_changed and not self.should_rebuild:
             self.should_rebuild = True
             if self.config.print:
                 console(
                     f'  - Target {self.name: <16}   BUILD [{first_changed.name} changed]'
                 )
             self.create_build_dir_if_needed()  # in case we just cleaned
Beispiel #15
0
    def clean(self):
        if self.config.print:
            console(
                f'  - Target {self.name: <16}   CLEAN  {self.config.build_folder()}'
            )

        if self.build_dir == '/' or not os.path.exists(self.build_dir):
            return

        self.target.clean()  # Customization point
        shutil.rmtree(self.build_dir, ignore_errors=True)
Beispiel #16
0
 def reclone_wipe(self):
     if self.dep.config.print:
         console(f'  - Target {self.dep.name: <16}   RECLONE WIPE')
     if os.path.exists(self.dep.dep_dir):
         if System.windows:  # chmod everything to user so we can delete:
             for root, dirs, files in os.walk(self.dep.dep_dir):
                 for d in dirs:
                     os.chmod(os.path.join(root, d), stat.S_IWUSR)
                 for f in files:
                     os.chmod(os.path.join(root, f), stat.S_IWUSR)
         shutil.rmtree(self.dep.dep_dir)
Beispiel #17
0
 def find_ninja_build(self):
     ninja_executables = [
         os.getenv('NINJA'), 
         find_executable_from_system('ninja'),
         '/Projects/ninja.exe'
     ]
     for ninja_exe in ninja_executables:        
         if ninja_exe and os.path.isfile(ninja_exe):
             if self.verbose: console(f'Found Ninja Build System: {ninja_exe}')
             return ninja_exe
     return ''
Beispiel #18
0
    def _execute_run_tasks(self):
        if self.is_test_target():
            test_args = self.config.test.lstrip()
            if self.config.print:
                console(f'  - Testing {self.name} {test_args}')
            self.test(test_args)

        if self.dep.is_root and self.config.start:
            start_args = self.config.start.lstrip()
            if self.config.print:
                console(f'  - Starting {self.name} {start_args}')
            self.start(start_args)
Beispiel #19
0
 def _execute_tasks(self):
     if self.dep.already_executed:
         return
     try:
         self.dep.already_executed = True
         self._execute_build_tasks()
         self._execute_deploy_tasks()
         self._execute_run_tasks()
     except Exception as err:
         import traceback
         tb = traceback.format_exc().splitlines(True)
         tb = tb[-3] + tb[-2] if len(tb) >= 3 else ''.join(tb)
         console(
             f'  [BUILD FAILED]  {self.dep.name}  \n{err}\n\nError Source:\n{tb}'
         )
         exit(-1)  # exit without stack trace
Beispiel #20
0
    def get_msvc_tools_path(self):
        if self._msvctools_path:
            return self._msvctools_path
        if not System.windows:
            raise EnvironmentError('MSVC tools not available on this platform!')

        tools_root = f"{self.get_visualstudio_path()}\\VC\\Tools\\MSVC"
        tools = os.listdir(tools_root)
        if not tools:
            raise EnvironmentError('Could not detect MSVC Tools')

        tools_path = os.path.join(tools_root, tools[0])
        #tools_path = forward_slashes(tools_path)
        self._msvctools_path = tools_path
        if self.verbose: console(f'Detected MSVC Tools: {tools_path}')
        return tools_path
Beispiel #21
0
    def install_clang6(self):
        if System.windows: raise OSError('Install Visual Studio 2019 with Clang support')
        if System.macos:   raise OSError('Install Xcode to get Clang on macOS')
        
        suffix = '1404'
        try:
            dist = distro.info()
            if dist['id'] != "ubuntu": raise OSError('install_clang6 only supports Ubuntu')
            majorVersion = int(dist['version_parts']['major'])
            if majorVersion >= 16:
                suffix = '1604'
            console(f'Choosing {suffix} for kernel major={majorVersion}')
        except Exception as err:
            console(f'Failed to parse linux distro; falling back to {suffix}: {err}')

        self.install_clang(clang_major='6', clang_ver='6.0', suffix=suffix)
Beispiel #22
0
    def init_ndk_path(self):
        paths = []
        self.append_env_path(paths, 'ANDROID_HOME')
        if System.windows: paths += [f'{os.getenv("LOCALAPPDATA")}\\Android\\Sdk']
        elif System.linux: paths += [f'{os.getenv("HOME")}/Android/Sdk', '/usr/bin/android-sdk', '/opt/android-sdk']
        elif System.macos: paths += [f'{os.getenv("HOME")}/Library/Android/sdk']
        ext = '.cmd' if System.windows else ''
        for sdk_path in paths:
            if os.path.exists(f'{sdk_path}/ndk-bundle/ndk-build{ext}'):
                self.android_sdk_path = sdk_path
                self.android_ndk_path = sdk_path  + '/ndk-bundle'
                self.android_ndk_release = 'r16b'
                if self.print: console(f'Found Android NDK: {self.android_ndk_path}')
                return
        raise EnvironmentError(f'''Could not detect any Android NDK installations. 
Default search paths: {paths} 
Define env ANDROID_HOME with path to Android SDK with NDK at ${{ANDROID_HOME}}/ndk-bundle.''')
Beispiel #23
0
 def install_clang(self, clang_major, clang_ver, suffix):
     clang_major = '11'
     clang_ver = '11.0'
     clangpp = f'clang++{clang_major}'
     clang_zip = download_file(f'http://ateh10.net/dev/{clangpp}-{suffix}.zip', tempfile.gettempdir())
     console(f'Installing to /usr/local/{clangpp}')
     execute(f'sudo rm -rf /usr/local/{clangpp}') # get rid of any old stuff
     execute(f'cd /usr/local && sudo unzip -oq {clang_zip}') # extract /usr/local/clang++11/
     os.remove(clang_zip)
     execute(f'sudo ln -sf /usr/local/{clangpp}/lib/libc++.so.1    /usr/lib')
     execute(f'sudo ln -sf /usr/local/{clangpp}/lib/libc++abi.so.1 /usr/lib')
     execute(f'sudo ln -sf /usr/local/{clangpp}/bin/clang      /usr/bin/clang-{clang_ver}')
     execute(f'sudo ln -sf /usr/local/{clangpp}/bin/clang++    /usr/bin/clang++-{clang_ver}')
     execute(f'sudo ln -sf /usr/local/{clangpp}/include/c++/v1 /usr/include/c++/v1')
     execute(f'sudo update-alternatives --install /usr/bin/clang   clang   /usr/bin/clang-{clang_ver}   100')
     execute(f'sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-{clang_ver} 100')
     execute(f'sudo update-alternatives --set clang   /usr/bin/clang-{clang_ver}')
     execute(f'sudo update-alternatives --set clang++ /usr/bin/clang++-{clang_ver}')
Beispiel #24
0
def run_with_timeout(executable, argstring, workingDir, timeoutSeconds=None):
    args = [executable]
    args += shlex.split(argstring)
    start = time.time()
    proc = subprocess.Popen(args, shell=True, cwd=workingDir)
    try:
        proc.wait(timeout=timeoutSeconds)
        console(f'{executable} elapsed: {round(time.time()-start, 1)}s')
    except subprocess.TimeoutExpired:
        console('TIMEOUT, sending break signal')
        if System.windows:
            proc.send_signal(subprocess.signal.CTRL_C_EVENT)
        else:
            proc.send_signal(subprocess.signal.SIGINT)
        raise
    if proc.returncode == 0:
        return
    raise subprocess.CalledProcessError(proc.returncode, ' '.join(args))
Beispiel #25
0
def copy_files(fromFolder, toFolder, fileNames):
    for file in fileNames:
        sourceFile = os.path.join(fromFolder, file)
        if not os.path.exists(sourceFile):
            continue
        destFile = os.path.join(toFolder, os.path.basename(file))
        destFileExists = os.path.exists(destFile)
        if destFileExists and is_file_modified(sourceFile, destFile):
            console(f"skipping copy '{destFile}'")
            continue
        console(f"copyto '{toFolder}'  '{sourceFile}'")
        if System.windows and destFileExists: # note: windows crashes if dest file is in use
            tempCopy = f'{destFile}.{random.randrange(1000)}.deleted'
            shutil.move(destFile, tempCopy)
            try:
                os.remove(tempCopy)
            except Exception:
                pass
        shutil.copy2(sourceFile, destFile) # copy while preserving metadata
Beispiel #26
0
    def _print_exports(self):
        if not self.config.print:
            return
        if not (self.exported_includes and self.exported_libs
                and self.exported_syslibs and self.exported_assets):
            return

        console(f'  - Package {self.name}')
        for include in self.exported_includes:
            self._print_ws_path('<I>', include)
        for library in self.exported_libs:
            self._print_ws_path('[L]', library)
        for library in self.exported_syslibs:
            self._print_ws_path('[S]', library, check_exists=False)
        if self.config.deploy:
            for asset in self.exported_assets:
                self._print_ws_path('[A]', str(asset), check_exists=False)
        elif self.exported_assets:
            assets = 'assets' if len(self.exported_assets) > 1 else 'asset'
            console(f'    [A]  ({len(self.exported_assets)} {assets})')
Beispiel #27
0
    def get_msbuild_path(self):
        if self._msbuild_path:
            return self._msbuild_path
        
        paths = [ find_executable_from_system('msbuild') ]
        if System.windows:
            vswhere = '"C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -nologo -property installationPath'
            paths.append(f"{execute_piped(vswhere)}\\MSBuild\\Current\\Bin\\MSBuild.exe")
            paths.append(f"{execute_piped(vswhere)}\\MSBuild\\15.0\\Bin\\amd64\\MSBuild.exe")
            
            vs_variants = [ 'Enterprise', 'Professional', 'Community' ]
            for variant in vs_variants:
                paths.append(f'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\{variant}\\MSBuild\\Current\\Bin\\MSBuild.exe')
                paths.append(f'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\{variant}\\MSBuild\\15.0\\Bin\\amd64\\MSBuild.exe')

        for path in paths:
            if path and os.path.exists(path):
                self._msbuild_path = path
                if self.verbose: console(f'Detected MSBuild: {path}')
                return path
        raise EnvironmentError('Failed to find MSBuild from system PATH. You can easily configure msbuild by running `mama install-msbuild`.')
Beispiel #28
0
    def init_raspi_path(self):
        paths = []
        self.append_env_path(paths, 'RASPI_HOME')
        self.append_env_path(paths, 'RASPBERRY_HOME')
        if System.windows: paths += ['/SysGCC/raspberry']
        elif System.linux: paths += ['/usr/bin/raspberry', '/usr/local/bin/raspberry', '/opt/raspberry']
        compiler = ''
        if System.windows: compiler = 'bin/arm-linux-gnueabihf-gcc.exe'
        elif System.linux: compiler = 'arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc'
        for raspi_path in paths:
            if os.path.exists(f'{raspi_path}/{compiler}'):
                if not System.windows:
                    raspi_path = f'{raspi_path}/arm-bcm2708/arm-linux-gnueabihf/'
                self.raspi_compilers = f'{raspi_path}/bin/'
                self.raspi_system    = f'{raspi_path}/arm-linux-gnueabihf/sysroot'
                self.raspi_include_paths = [f'{raspi_path}/arm-linux-gnueabihf/lib/include']
                if self.print: console(f'Found RASPI TOOLS: {self.raspi_compilers}\n    sysroot: {self.raspi_system}')
                return
        raise EnvironmentError(f'''No Raspberry PI toolchain compilers detected! 
Default search paths: {paths} 
Define env RASPI_HOME with path to Raspberry tools.''')
Beispiel #29
0
 def clone_or_pull(self, wiped=False):
     if is_dir_empty(self.dep.src_dir):
         if not wiped and self.dep.config.print:
             console(
                 f"  - Target {self.dep.name: <16}   CLONE because src is missing"
             )
         branch = self.branch_or_tag()
         if branch: branch = f" --branch {self.branch_or_tag()}"
         execute(
             f"git clone --recurse-submodules --depth 1 {branch} {self.url} {self.dep.src_dir}",
             self.dep.config.verbose)
         self.checkout_current_branch()
     else:
         if self.dep.config.print:
             console(
                 f"  - Pulling {self.dep.name: <16}  SCM change detected")
         self.checkout_current_branch()
         execute("git submodule update --init --recursive")
         if not self.tag:  # pull if not a tag
             self.run_git("reset --hard -q")
             self.run_git("pull")
Beispiel #30
0
 def ms_build(self, projectfile, properties: dict = dict()):
     """
     Invokes MSBuild on the specificied projectfile and passes specified
     properties to MSBuild.
     ```
     def build(self):
         self.cmake_build()
         self.ms_build('extras/csharp/CSharpTests.sln', {
             'Configuration': 'Debug',
             'Platform': 'Any CPU',
         })
     ```
     Default properties set by Mama if not specified via properties dict:
     /p:PreferredToolArchitecture=x64
     /p:Configuration=Release
     /p:Platform=x64
     """
     if self.config.print:
         console('\n#########################################')
         console(f'MSBuild {self.name} {projectfile}')
     msbuild_build(self.config, self.source_dir(projectfile), properties)