def get_extension(EXTENSION_NAME, DEFINE_MACROS, MATLAB_LIBRARY_DIRS, MATLAB_LIBRARIES, CPP_LIBRARIES, MATLAB_INCLUDE_DIRS): """ We have to do this due to a bug in the compiler that means that if the runtime library directories get passed AT ALL to the build command then the binary fails to build on windows """ args = [EXTENSION_NAME, ['mlabwrap/mlabraw.cpp']] kwargs = { 'define_macros': DEFINE_MACROS, 'library_dirs': MATLAB_LIBRARY_DIRS, 'libraries': MATLAB_LIBRARIES + CPP_LIBRARIES, 'include_dirs': MATLAB_INCLUDE_DIRS + [np.get_include()] } if not isWindows(): kwargs['runtime_library_dirs'] = MATLAB_LIBRARY_DIRS return Extension(*args, **kwargs)
def get_matlab_output(matlab_bin): """ Check output doesn't exist in Python < 2.7 so we need to use the old communicate way. This doesn't poll and assumes that program writes output and then exits. """ command = [matlab_bin, '-r', 'get_version', '-nosplash', '-nodesktop'] # On Windows we can't actually write to stdout apparently so we use the # logfile trick and just sit and wait until Matlab is finished # loading the popup command window if isWindows(): subprocess.call(command + ['-wait', '-logfile', 'out.txt']) with open('out.txt', 'r+') as f: return f.read() else: if sys.version_info[1] < 7: return subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0] else: return subprocess.check_output(command)
def main(args): ### SETUP BASE VARIABLES MATLAB_ROOT = args.matlab_root MATLAB_BIN = os.path.join(MATLAB_ROOT, 'bin') MATLAB_BINARY = os.path.join(MATLAB_BIN, 'matlab') # Add .exe if windows if isWindows(): MATLAB_BINARY = '{0}.exe'.format(MATLAB_BINARY) # Let's check that we DEFINITELY have a Matlab binary to use if not os.path.exists(MATLAB_BINARY): raise Exception( 'Unable to find Matlab binary at {0}'.format(MATLAB_BINARY)) # Now we come against the hardest part of all - finding the Matlab version. # I can think of 3 valid ways to do this: # 1. Parse the install directory and use a hard-coded table. However, # complicated by the fact that there are SP versions and that every OS # stores the directory in a different manner. # e.g. 'R2013a' could be parsed in to '2013' and 'a' and this implies V8.1 # (take a look at http://en.wikipedia.org/wiki/MATLAB#Release_history) # 2. Parse the Help command (matlab -h). # Doesn't technically run Matlab but is a pain and I can't guarantee # that all Matlab versions print the EXACT same message. # e.g. R2013a doesn't print any version information using 'matlab -h' # 3. Run Matlab itself and query it's 'version' command. Matlab # documentation tells me that this command exists at least as far back # as R14. This is the method I've chosen as it also allows me to query # the 'computer' command which says which architecture Matlab is # running (32 bit/64 bit). I created a short Matlab script to print # the appropriate output to stdout MATLAB_INFO = get_matlab_info(MATLAB_BINARY) if None in MATLAB_INFO: raise Exception( 'Unable to correctly parse Matlab information. ' 'Found Matlab Version = {0}, Matlab Release = {1}, ' 'Matlab Architecture = {2}.'.format(*MATLAB_INFO)) else: [MATLAB_VERSION, MATLAB_RELEASE, MATLAB_ARCH] = MATLAB_INFO # Setup include and lib directories for building the extension MATLAB_INCLUDE_DIRS = [os.path.join(MATLAB_ROOT, 'extern', 'include')] if isWindows(): EXTENSION_NAME = 'mlabraw' # Strip off PC from PCWIN## PLATFORM_DIR = MATLAB_ARCH.lower()[2:] CPP_LIBRARIES = [] MATLAB_LIBRARIES = ['libeng', 'libmx'] MATLAB_LIBRARY_DIRS = [ os.path.join(MATLAB_ROOT, 'extern', 'lib', PLATFORM_DIR, 'microsoft')] lib_dirs = msvc_library_dirs() inc_dirs = msvc_library_dirs() if lib_dirs: MATLAB_LIBRARY_DIRS.extend(lib_dirs) if inc_dirs: MATLAB_INCLUDE_DIRS.extend(inc_dirs) else: # Linux/OSX EXTENSION_NAME = 'mlabrawmodule' PLATFORM_DIR = MATLAB_ARCH.lower() CPP_LIBRARIES = ['stdc++'] # Version >= 6.5 if cmp(MATLAB_VERSION, VERSION_6_5) >= 0: MATLAB_LIBRARIES = ['eng', 'mx', 'mat', 'ut'] else: MATLAB_LIBRARIES = ['eng', 'mx', 'mat', 'mi', 'ut'] # Version >= 7.0 if cmp(MATLAB_VERSION, VERSION_7_0) >= 0: MATLAB_LIBRARY_DIRS = [os.path.join(MATLAB_BIN, PLATFORM_DIR)] else: MATLAB_LIBRARY_DIRS = [ os.path.join(MATLAB_ROOT, 'extern', 'lib', PLATFORM_DIR)] # Version dependent defines DEFINE_MACROS = [] # Version >= 6.5 if cmp(MATLAB_VERSION, VERSION_6_5) >= 0: DEFINE_MACROS.append(('_V6_5_OR_LATER', 1)) # Version >= 7.3 if cmp(MATLAB_VERSION, VERSION_7_3) >= 0: DEFINE_MACROS.append(('_V7_3_OR_LATER', 1)) setup( name="mlabwrap", version='1.2', description="A high-level bridge to matlab", author="Alexander Schmolck", author_email="*****@*****.**", url='http://mlabwrap.sourceforge.net', packages=['mlabwrap', 'mlabwrap_utils'], ext_package='mlabwrap', ext_modules=[ get_extension(EXTENSION_NAME, DEFINE_MACROS, MATLAB_LIBRARY_DIRS, MATLAB_LIBRARIES, CPP_LIBRARIES, MATLAB_INCLUDE_DIRS) ], use_2to3=True )