def _generate_swig_wrappers(interface_files, output_directory): """ Generates SWIG Wrapper files (.cxx) and python modules that can be compiled into a shared library by distutils. :raises: ``EnvironmentError`` if swig is not installed. """ if swig_path is None: raise EnvironmentError("No swig executable found.") output_directory = _utils.resolve_path(output_directory) for current_file in interface_files: module_name = _utils.file_name(current_file) output_file = os.path.join( output_directory, "%s_wrap.cxx" % (module_name, ) ) # Let swig generate the wrapper files. subprocess.check_call( [swig_path, "-c++", "-python", "-o", output_file, current_file], cwd = output_directory, stdout = _utils.DEVNULL, stderr = subprocess.STDOUT )
def _generate_swig_interface(file_path, output_directory): """ Generates a SWIG Interface file (.i) that can be compiled with SWIG to a shared library file that can be imported into python for testing. """ file_path = _utils.resolve_path(file_path) output_directory = _utils.resolve_path(output_directory) # Figure out what this module will be named by getting just the filename # (minus extension) of the code file. module_name = _utils.file_name(file_path) # -MM flag returns all dependencies needed to compile file. gpp_process = subprocess.Popen( ["g++", "-MM", file_path], stdout = subprocess.PIPE, stderr = subprocess.STDOUT ) gpp_output = gpp_process.communicate()[0] # Get dependencies, minus the .o file and the white space gpp_output = gpp_output.split(":")[1].strip() dependencies = [i.strip() for i in gpp_output.split(" ") if i.strip() != "\\"] necessary_includes = [] for include in dependencies: necessary_includes.append("#include \"%s\"" % (include)) # TODO: Add comment describing what's going on here. if ".h" in include: include = include.replace(".hpp", ".h") include = include.replace(".h", ".cpp") if file_path not in include and os.path.isfile(include): necessary_includes.append("#include \"%s\"" % (include)) with open(os.path.join(output_directory, module_name + ".i"), "w") as f: f.write("%%module %s\n\n" % (module_name, )) # Ensure we include all of the special swig interface files that allow # us to interop with the C++ Standard Library. for interface in STD_INTERFACES: f.write("%%include \"%s\"\n" % (interface, )) # Write directives inside and out of wrapper for consistency in wrapped # file. f.write("\n".join(EXPOSURE_DIRECTIVES) + "\n") f.write("using namespace std;\n\n") f.write("%{\n") f.write("\n".join(EXPOSURE_DIRECTIVES) + "\n") for include in necessary_includes: f.write("%s\n" % include) f.write("%}\n\n") # SWIG cannot import global include like iostream, but it does need # all local includes local_includes = \ (include for include in necessary_includes if '<' not in include) for include in local_includes: f.write("%s\n" % include.replace("#", "%")) return module_name