def run_cmake(self, target=None): r"""Run the cmake command on the source. Args: target (str, optional): Target to build. Raises: RuntimeError: If there is an error in running cmake. """ curdir = os.getcwd() os.chdir(self.sourcedir) if not os.path.isfile('CMakeLists.txt'): os.chdir(curdir) self.cleanup() raise IOError('No CMakeLists.txt file found in %s.' % self.sourcedir) # Configuration if target != 'clean': config_cmd = ['cmake'] + self.cmakeargs config_cmd += ['-H.', self.sourcedir, '-B%s' % self.builddir] self.debug(' '.join(config_cmd)) comp_process = tools.popen_nobuffer(config_cmd) output, err = comp_process.communicate() exit_code = comp_process.returncode if exit_code != 0: os.chdir(curdir) self.cleanup() self.error(backwards.as_unicode(output)) raise RuntimeError("CMake config failed with code %d." % exit_code) self.debug('Config output: \n%s' % output) # Build build_cmd = ['cmake', '--build', self.builddir, '--clean-first'] if self.target is not None: build_cmd += ['--target', self.target] self.info(' '.join(build_cmd)) comp_process = tools.popen_nobuffer(build_cmd) output, err = comp_process.communicate() exit_code = comp_process.returncode if exit_code != 0: # pragma: debug os.chdir(curdir) self.error(backwards.as_unicode(output)) self.cleanup() raise RuntimeError("CMake build failed with code %d." % exit_code) self.debug('Build output: \n%s' % output) self.debug('Make complete') os.chdir(curdir)
def make_target(self, target): r"""Run the make command to make the target. Args: target (str): Target that should be made. Raises: RuntimeError: If there is an error in running the make. """ curdir = os.getcwd() os.chdir(self.makedir) if self.make_command == 'nmake': # pragma: windows make_opts = ['/NOLOGO', '/F'] else: make_opts = ['-f'] make_args = [self.make_command] + make_opts + [self.makefile, target] self.debug(' '.join(make_args)) if not os.path.isfile(self.makefile): os.chdir(curdir) raise IOError("Makefile %s not found" % self.makefile) comp_process = tools.popen_nobuffer(make_args) output, err = comp_process.communicate() exit_code = comp_process.returncode os.chdir(curdir) if exit_code != 0: self.error(output) raise RuntimeError("Make failed with code %d." % exit_code) self.debug('Make complete')
def test_popen_nobuffer(): r"""Test open of process without buffer.""" ans = os.getcwd() # + '\n' # Test w/o shell if platform._is_win: # pragma: windows args = ['cmd', '/c', 'cd'] else: args = ['pwd'] p = tools.popen_nobuffer(args) out, err = p.communicate() res = tools.bytes2str(out).splitlines()[0] assert_equal(res, ans) # Test w/ shell if platform._is_win: # pragma: windows args = 'cd' else: args = 'pwd' p = tools.popen_nobuffer(args, shell=True) out, err = p.communicate() res = tools.bytes2str(out).splitlines()[0] assert_equal(res, ans)
def build_regex_win32(): # pragma: windows r"""Build the regex_win32 library using cmake.""" # Configure project cmd = ['cmake', '-H.', '-Bbuild'] comp_process = tools.popen_nobuffer(cmd, cwd=_regex_win32_dir) output, err = comp_process.communicate() exit_code = comp_process.returncode if exit_code != 0: # pragma: debug print(' '.join(cmd)) tools.print_encoded(output, end="") raise RuntimeError("Could not config regex_win32") # Build project cmd = ['cmake', '--build', 'build', '--clean-first'] comp_process = tools.popen_nobuffer(cmd, cwd=_regex_win32_dir) output, err = comp_process.communicate() exit_code = comp_process.returncode if exit_code != 0: # pragma: debug print(' '.join(cmd)) tools.print_encoded(output, end="") raise RuntimeError("Could not build regex_win32") assert (os.path.isfile(_regex_win32_lib))
def call_link(obj, out=None, flags=[], overwrite=False, verbose=False, cpp=False, shared=False, static=False, working_dir=None): r"""Compile a source file, checking for errors. Args: obj (list): Object files that should be linked. out (str, optional): Full path to output file that should be created. If None, the path will be determined from the path to the first object file provided. Defaults to False. flags (list, optional): Compilation flags. Defaults to []. overwrite (bool, optional): If True, the existing compile file will be overwritten. Otherwise, it will be kept and this function will return without recompiling the source file. verbose (bool, optional): If True, the linking command and any output produced by the command will be displayed on success. Defaults to False. cpp (bool, optional): If True, value is returned assuming the source is written in C++. Defaults to False. shared (bool, optional): If True, the object files are combined into a shared library. Defaults to False. static (bool, optional): If True, the object files are combined into a static library. Defaults to False. working_dir (str, optional): Working directory that input file paths are relative to. Defaults to current working directory. Returns: str: Full path to compiled source. """ # Set defaults if working_dir is None: working_dir = os.getcwd() flags = copy.deepcopy(flags) if not isinstance(obj, list): obj = [obj] # Set path if not provided if out is None: obase = os.path.splitext(obj[0])[0] if platform._is_win: # pragma: windows oext = '.exe' else: oext = '.out' out = obase + oext if not os.path.isabs(out): out = os.path.normpath(os.path.join(working_dir, out)) # Check for file if os.path.isfile(out): if overwrite: os.remove(out) else: return out # Check extension for information about the result if out.endswith('.so') or out.endswith('.dll') or out.endswith('.dylib'): shared = True elif out.endswith('.a') or out.endswith('.lib'): static = True # Get compiler cc = get_cc(shared=shared, static=static, cpp=cpp, linking=True) # Construct arguments args = [cc] if shared: if platform._is_win: # pragma: windows flags.append('/DLL') elif platform._is_mac: flags.append('-dynamiclib') else: flags.append('-shared') args += flags elif static: if platform._is_win: # pragma: windows pass elif platform._is_mac: flags += ['-static'] else: flags += ['-rcs', out] args += flags if platform._is_win: # pragma: windows args += ['/OUT:%s' % out] elif platform._is_mac: if shared: args += ["-o", out] else: args += ["-o", out] else: if static: args += [out] else: args += ["-o", out] args += obj if not (shared or static): args += flags # Call linker comp_process = tools.popen_nobuffer(args) output, err = comp_process.communicate() exit_code = comp_process.returncode if exit_code != 0: # pragma: debug print(' '.join(args)) tools.print_encoded(output, end="") raise RuntimeError("Linking of %s failed with code %d." % (out, exit_code)) if not os.path.isfile(out): # pragma: debug print(' '.join(args)) raise RuntimeError("Linking failed to produce result '%s'" % out) logging.info("Linked %s" % out) if verbose: # pragma: debug print(' '.join(args)) tools.print_encoded(output, end="") return out
def call_compile(src, out=None, flags=[], overwrite=False, verbose=False, cpp=None, working_dir=None): r"""Compile a source file, checking for errors. Args: src (str): Full path to source file. out (str, optional): Full path to the output object file that should be created. Defaults to None and is created from the provided source file. flags (list, optional): Compilation flags. Defaults to []. overwrite (bool, optional): If True, the existing compile file will be overwritten. Otherwise, it will be kept and this function will return without recompiling the source file. verbose (bool, optional): If True, the compilation command and any output produced by the command will be displayed on success. Defaults to False. cpp (bool, optional): If True, value is returned assuming the source is written in C++. Defaults to False. working_dir (str, optional): Working directory that input file paths are relative to. Defaults to current working directory. Returns: str: Full path to compiled source. """ # Set defaults if working_dir is None: working_dir = os.getcwd() flags = copy.deepcopy(flags) if platform._is_win: # pragma: windows flags = ['/W4', '/Zi', "/EHsc"] + flags else: flags = ['-g', '-Wall'] + flags src_base, src_ext = os.path.splitext(src) if cpp is None: cpp = False if src_ext in ['.hpp', '.cpp']: cpp = True if platform._is_win: # pragma: windows if cpp: flags.insert(2, '/TP') else: flags.insert(2, '/TP') # TODO: Currently everything compiled as C++ on windows to allow use of # complex types # flags.insert(2, '/TC') # Add standard library flag std_flag = None for i, a in enumerate(flags): if a.startswith('-std='): std_flag = i break if cpp and (not platform._is_win): if std_flag is None: flags.append('-std=c++11') else: if std_flag is not None: flags.pop(i) # Get compiler command cc = get_cc(cpp=cpp) # Get output if not provided if out is None: if platform._is_win: # pragma: windows out_ext = '.obj' else: out_ext = '.o' out = src_base + '_' + src_ext[1:] + out_ext if not os.path.isabs(out): out = os.path.normpath(os.path.join(working_dir, out)) # Construct arguments args = [cc, "-c"] + flags + [src] if not platform._is_win: args += ["-o", out] else: # pragma: windows args.insert(1, '/Fo%s' % out) # Check for file if os.path.isfile(out): if overwrite: os.remove(out) else: return out # Call compiler comp_process = tools.popen_nobuffer(args) output, err = comp_process.communicate() exit_code = comp_process.returncode if exit_code != 0: # pragma: debug print(' '.join(args)) tools.print_encoded(output, end="") raise RuntimeError("Compilation of %s failed with code %d." % (out, exit_code)) if not os.path.isfile(out): # pragma: debug print(' '.join(args)) raise RuntimeError("Compilation failed to produce result '%s'" % out) logging.info("Compiled %s" % out) if verbose: # pragma: debug print(' '.join(args)) tools.print_encoded(output, end="") return out