diff --git a/.gitignore b/.gitignore
index f25a9c0114f653c281cd0517b259fba4de89fbde..22b4eccd162dfe114956c248d57ba52f9ef908f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,7 +31,7 @@ Thumbs.db
 
 # Ignore CMake cache and build directiories (assume build*/)
 CmakeCache.txt
-build*/
+/build*/
 **/CMakeFiles
 
 # Ignore pycache folder
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d2b1d7c649ef821b9c414a9ac9141fae07af55a9..b21b2c5954d325cb0c0d95841b2e3f07762d1f57 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,7 +10,7 @@ set(HYDRA_MODULE_NAME "HIP")
 find_package(CUDA REQUIRED)
 find_package(OpenMP REQUIRED)
 
-find_package(Matlab)
+find_package(Matlab COMPONENTS MAIN_PROGRAM)
 find_package(Python COMPONENTS Development NumPy)
 
 # Setup backend Hydra CUDA library (static) for cuda building
diff --git a/src/MATLAB/+HIP/BuildScript.m b/src/MATLAB/+HIP/BuildScript.m
deleted file mode 100644
index 3cb91f573345d303756ccc1fd4426826d8fc1bee..0000000000000000000000000000000000000000
--- a/src/MATLAB/+HIP/BuildScript.m
+++ /dev/null
@@ -1,141 +0,0 @@
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Set List of Files to Exclude               %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-clear mex
-excludeList = ...
-    {'Cuda.m';
-     'DeviceCount.m';
-     'DeviceStats.m'};
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-% remember curent path
-curPath = pwd();
-
-% find where the image processing package is
-cudaPath = fileparts(which('HIP.BuildMexObject'));
-cd(cudaPath)
-
-% create the m files that correspond to the commands in the mex interface
-HIP.BuildMexObject(fullfile('..','..','c',['Mex.' mexext]),'Cuda','HIP');
-
-packagePath = cudaPath;
-cudaPath = fullfile(cudaPath,'@Cuda');
-
-% get a list of all of the functions in the class
-dList = dir(fullfile(cudaPath,'*.m'));
-
-% wrap each function
-numFunctions = 0;
-for i=1:length(dList)
-    if (any(strcmpi(excludeList,dList(i).name)))
-        continue;
-    end
-
-    % copy the file from the class to the package
-    newFile = fullfile(packagePath,dList(i).name);
-%     if (exist(newFile,'file') && ~strcmpi(dList(i).name,'Help.m') && ~strcmpi(dList(i).name,'Info.m'))
-%         % fprintf(1,'File exist: %s\n',newFile);
-%         continue;
-%     end
-%     fprintf(1,'Making undetected file: %s\n',newFile);
-
-    % get all of the lines
-    f = fopen(fullfile(cudaPath,dList(i).name),'rt');
-    curLine = fgetl(f);
-    textLines = {};
-    while ischar(curLine)
-        textLines = [textLines;{curLine}];
-        curLine = fgetl(f);
-    end
-    fclose(f);
-
-    % write out the new data
-    f = fopen(newFile,'wt');
-    funcCallFilled = '';
-    for j=1:length(textLines)
-        curLine = textLines{j};
-
-        % check for comment line
-        if (strcmpi(curLine(1),'%'))
-            %check if it is the protype line
-            protoLineExpr = '\.Cuda\.';
-            protoIdx = regexpi(curLine,protoLineExpr);
-            if (~isempty(protoIdx))
-                % remove the class part of the path
-                fprintf(f, '%s\n',curLine([1:protoIdx,protoIdx+6:end]));
-                continue;
-            end
-            % doesn't me other searches write as is
-            fprintf(f,'%s\n',curLine);
-            continue;
-        end
-
-        % figure out if this is the function line
-        funcLineExpr = 'function (?<out>.*) = (?<name>\w+)\((?<param>.*)\)';
-        funcCall = regexpi(curLine,funcLineExpr,'names');
-        if (~isempty(funcCall))
-            funcCallFilled = funcCall;
-            fprintf(f,'\nfunction %s = %s(%s)\n',funcCall.out,funcCall.name,funcCall.param);
-            fprintf(f,'    try\n');
-            fprintf(f,'        %s = HIP.Cuda.%s(%s);\n',funcCall.out,funcCall.name,funcCall.param);
-            fprintf(f,'    catch errMsg\n');
-            localFuctionCall = sprintf('%s = HIP.Local.%s(%s)',funcCall.out,funcCall.name,funcCall.param);
-            fprintf(f,'        warning(errMsg.message);\n');
-            fprintf(f,'        %s;\n', localFuctionCall);
-            fprintf(f,'    end\n');
-            continue;
-        end
-
-        mexCallExpr = '\.Mex';
-        mexPos = regexpi(curLine,mexCallExpr);
-        if (~isempty(mexPos))
-            % this was written above in the Cuda version of the function
-            continue
-        end
-
-        % does not meet any criteria, write as is
-        fprintf(f, '%s\n',curLine);
-    end
-    fclose(f);
-    
-    numFunctions = numFunctions +1;
-
-    %place the local function call stub here
-    if (isempty(funcCallFilled))
-        continue
-    end
-    
-    if (~exist(fullfile(packagePath,'+Local'),'dir'))
-        mkdir(fullfile(packagePath,'+Local'));
-    end
-    
-    localFuncFileName = fullfile(packagePath,'+Local',[funcCallFilled.name,'.m']);
-    if (~exist(localFuncFileName,'file'))
-        f = fopen(localFuncFileName,'wt');
-        fprintf(f, 'function %s = %s(%s,suppressWarning)\n',funcCallFilled.out,funcCallFilled.name,funcCallFilled.param);
-        fprintf(f, '     error(''%s not yet implemented in MATLAB!''); %%delete this line when implemented\n',funcCallFilled.name);
-        fprintf(f, '     if (~exist(''suppressWarning'',''var'') || isempty(suppressWarning) || ~suppressWarning)\n');
-        fprintf(f, '         warning(''Falling back to matlab.'');\n');
-        fprintf(f, '     end\n');
-        fprintf(f, '     \n');
-        fprintf(f, '     if (~exist(''numIterations'',''var'') || isempty(numIterations))\n');
-        fprintf(f, '         numIterations = 1;\n');
-        fprintf(f, '     end\n');
-        fprintf(f, '     \n');
-        fprintf(f, '     arrayOut = arrayIn;\n');
-        fprintf(f, '     for t=1:size(arrayIn,5)\n');
-        fprintf(f, '         for c=1:size(arrayIn,4)\n');
-        fprintf(f, '             for i=1:numIterations\n');
-        fprintf(f, '                 %% implement this function here\n');
-        fprintf(f, '                 arrayOut(:,:,:,c,t) = arrayIn(:,:,:,c,t);\n');
-        fprintf(f, '             end\n');
-        fprintf(f, '         end\n');
-        fprintf(f, '     end\n');
-        fprintf(f, 'end\n');
-        fclose(f);
-    end
-end
-
-fprintf('HIP BuildScript wrote %d functions\n',numFunctions);
-% go back to the original directory
-cd(curPath)
diff --git a/src/MATLAB/+HIP/BuildMexObject.m b/src/MATLAB/build-scripts/BuildMexClass.m
similarity index 64%
rename from src/MATLAB/+HIP/BuildMexObject.m
rename to src/MATLAB/build-scripts/BuildMexClass.m
index 214bc94d68108de6ef68923256609bfcd5e04e60..d336eb5751e177fe32ed0a596734f395eb60dfd7 100644
--- a/src/MATLAB/+HIP/BuildMexObject.m
+++ b/src/MATLAB/build-scripts/BuildMexClass.m
@@ -1,4 +1,4 @@
-function BuildMexObject(mexFile, objectName, parentPackage)
+function BuildMexClass(mexFile, packagePath, className, parentPackage)
     oldPath = pwd();
     cleanupObj = onCleanup(@()(cleanupFunc(oldPath)));
 
@@ -6,49 +6,48 @@ function BuildMexObject(mexFile, objectName, parentPackage)
     cd(mexPath);
 
     mexFunc = str2func(mexName);
-	commandList = mexFunc('Info');
+    commandList = mexFunc('Info');
 
-    cd(oldPath);
+    cd(packagePath);
     
     % Delete old function definitions
-    if ( exist(['@' objectName], 'dir') )
-        delete(fullfile(['@' objectName], '*.m'));
+    if ( exist(['@' className], 'dir') )
+        delete(fullfile(['@' className], '*.m'));
     end
     
-    makeClassdef(objectName, mexName, commandList);
+    makeClassdef(className, mexName, commandList);
     for i=1:length(commandList)
-        makeStaticMethod(objectName, mexName, commandList(i), parentPackage);
+        makeStaticMethod(className, mexName, commandList(i), parentPackage);
     end
 
-    copyfile(mexFile, ['@' objectName]);
-    clear mex
+    copyfile(mexFile, ['@' className]);
 end
 
-function makeClassdef(objectName, mexName, commandList)
-    if ( ~exist(['@' objectName],'dir') )
-        mkdir(['@' objectName]);
+function makeClassdef(className, mexName, commandList)
+    if ( ~exist(['@' className],'dir') )
+        mkdir(['@' className]);
     end
-    objFile = fopen(fullfile(['@' objectName],[objectName '.m']), 'wt');
+    classFile = fopen(fullfile(['@' className],[className '.m']), 'wt');
 
-    fprintf(objFile, 'classdef (Abstract,Sealed) %s\n', objectName);
+    fprintf(classFile, 'classdef (Abstract,Sealed) %s\n', className);
 
-    fprintf(objFile, 'methods (Static)\n');
+    fprintf(classFile, 'methods (Static)\n');
     for i=1:length(commandList)
-        fprintf(objFile, '    %s\n', makePrototypeString(commandList(i)));
+        fprintf(classFile, '    %s\n', makePrototypeString(commandList(i)));
     end
-    fprintf(objFile, 'end\n');
+    fprintf(classFile, 'end\n');
 
-    fprintf(objFile, 'methods (Static, Access = private)\n');
-    fprintf(objFile, '    varargout = %s(command, varargin)\n', mexName);
-    fprintf(objFile, 'end\n');
+    fprintf(classFile, 'methods (Static, Access = private)\n');
+    fprintf(classFile, '    varargout = %s(command, varargin)\n', mexName);
+    fprintf(classFile, 'end\n');
 
-    fprintf(objFile, 'end\n');
+    fprintf(classFile, 'end\n');
 
-    fclose(objFile);
+    fclose(classFile);
 end
 
-function makeStaticMethod(objectName, mexName, commandInfo, parentPackage)
-    methodFile = fopen(fullfile(['@' objectName],[commandInfo.command '.m']), 'wt');
+function makeStaticMethod(className, mexName, commandInfo, parentPackage)
+    methodFile = fopen(fullfile(['@' className],[commandInfo.command '.m']), 'wt');
 
     helpLines = strsplit(commandInfo.help, '\n', 'CollapseDelimiters',false);
     validIdx = find(cellfun(@(x)(~isempty(x)), helpLines));
@@ -71,7 +70,7 @@ function makeStaticMethod(objectName, mexName, commandInfo, parentPackage)
     fprintf(methodFile, '%% %s - %s\n', commandInfo.command, summaryString);
 
     % Write call protoype string
-    fprintf(methodFile, '%%    %s\n', makePrototypeString(commandInfo,objectName,parentPackage,true));
+    fprintf(methodFile, '%%    %s\n', makePrototypeString(commandInfo,className,parentPackage,true));
 
     % Write remaining help lines directly
     if ( length(validIdx) > 2 )
@@ -82,13 +81,13 @@ function makeStaticMethod(objectName, mexName, commandInfo, parentPackage)
 
     % Output function body
     fprintf(methodFile, 'function %s\n', makePrototypeString(commandInfo));
-    fprintf(methodFile, '    %s;\n', makeCommandString(objectName, mexName,commandInfo,parentPackage));
+    fprintf(methodFile, '    %s;\n', makeCommandString(className, mexName,commandInfo,parentPackage));
     fprintf(methodFile, 'end\n');
 
     fclose(methodFile);
 end
 
-function commandString = makeCommandString(objectName, mexName, commandInfo, parentPackage)
+function commandString = makeCommandString(className, mexName, commandInfo, parentPackage)
     commandString = '';
     if ( ~isempty(commandInfo.outArgs) )
          commandString = ['[' makeCommaList(commandInfo.outArgs) '] = '];
@@ -100,7 +99,7 @@ function commandString = makeCommandString(objectName, mexName, commandInfo, par
         parentPackage = [parentPackage '.'];
     end
 
-    mexCall = [parentPackage objectName '.' mexName];
+    mexCall = [parentPackage className '.' mexName];
     commandString = [commandString mexCall '(''' commandInfo.command ''''];
     if ( ~isempty(commandInfo.inArgs) )
          commandString = [commandString ',' makeCommaList(commandInfo.inArgs)];
@@ -108,9 +107,9 @@ function commandString = makeCommandString(objectName, mexName, commandInfo, par
     commandString = [commandString ')'];
 end
 
-function protoString = makePrototypeString(commandInfo, objectName, parentPackage, leaveOptBrackets)
-    if ( ~exist('objectName','var') )
-        objectName = [];
+function protoString = makePrototypeString(commandInfo, className, parentPackage, leaveOptBrackets)
+    if ( ~exist('className','var') )
+        className = [];
     end
     if ( ~exist('parentPackage','var') )
         parentPackage = [];
@@ -131,8 +130,8 @@ function protoString = makePrototypeString(commandInfo, objectName, parentPackag
         protoString = [protoString ' = '];
     end
 
-    if ( ~isempty(objectName) )
-        protoString = [protoString parentPackage objectName '.'];
+    if ( ~isempty(className) )
+        protoString = [protoString parentPackage className '.'];
     end
 
     protoString = [protoString commandInfo.command '('];
@@ -156,5 +155,4 @@ end
 
 function cleanupFunc(oldPath)
     cd(oldPath);
-    clear mex;
 end
diff --git a/src/MATLAB/build-scripts/autoInstallMex.m b/src/MATLAB/build-scripts/autoInstallMex.m
new file mode 100644
index 0000000000000000000000000000000000000000..80433c19f74ac1a62235a5b2d92ab8f80d702bfa
--- /dev/null
+++ b/src/MATLAB/build-scripts/autoInstallMex.m
@@ -0,0 +1,74 @@
+function autoInstallMex(moduleName, mexFile)
+    className = 'Cuda';
+
+    hipDir = fullfile(pwd(),'..',['+' moduleName]);
+    if ( ~exist(hipDir,'dir') )
+        mkdir(hipDir);
+    end
+
+    BuildMexClass(mexFile, hipDir, className, moduleName);
+    wrapClassFuncs(hipDir, className);
+end
+
+function wrapClassFuncs(packageDir, className)
+    classDir = fullfile(packageDir, ['@' className]);
+
+    % Exclude internal/cuda-specific functions
+    excludeList = {[className '.m'];
+        'DeviceCount.m';
+        'DeviceStats.m'};
+
+    % get a list of all of the functions in the class
+    funcList = dir(fullfile(classDir,'*.m'));
+
+    for i=1:length(funcList)
+        if (any(strcmpi(excludeList, funcList(i).name)))
+            continue;
+        end
+
+        wrapFile = fullfile(packageDir,funcList(i).name);
+        inFile = fullfile(classDir,funcList(i).name);
+
+        inData = fileread(inFile);
+        inLines = strsplit(inData, {'\n','\r\n'});
+
+        wrapLines = updateLines(inLines, className);
+        wrapStr = strjoin(wrapLines, '\n');
+        fid = fopen(wrapFile, 'wt');
+        fprintf(fid,'%s', wrapStr);
+        fclose(fid);
+    end
+end
+
+function outLines = updateLines(inLines, className)
+    outLines = {};
+    for i=1:length(inLines)
+        chkLine = inLines{i};
+
+        classExpr = regexptranslate('escape', ['.' className '.']);
+        commentProtoExpr = ['(%.*?)' classExpr];
+        funcLineExpr = 'function (?<out>.*) = (?<name>\w+)\((?<params>.*)\)';
+
+        commentProto = regexpi(chkLine, commentProtoExpr, 'once');
+        funcLine = regexpi(chkLine, funcLineExpr, 'once');
+        if ( ~isempty(commentProto) )
+            outLines = [outLines; {regexprep(chkLine, commentProtoExpr, '$1.')}];
+        elseif ( ~isempty(funcLine) )
+            funcCall = regexpi(chkLine, funcLineExpr, 'names');
+
+            outLines = [outLines; {sprintf('function %s = %s(%s)', funcCall.out, funcCall.name, funcCall.params)}];
+            outLines = [outLines; {sprintf('    try')}];
+            outLines = [outLines; {sprintf('        %s = HIP.Cuda.%s(%s);',funcCall.out,funcCall.name,funcCall.params)}];
+            outLines = [outLines; {sprintf('    catch errMsg')}];
+            outLines = [outLines; {sprintf('        warning(errMsg.message);')}];
+            outLines = [outLines; {sprintf('        %s = HIP.Local.%s(%s);',funcCall.out,funcCall.name,funcCall.params)}];
+            outLines = [outLines; {sprintf('    end')}];
+            outLines = [outLines; {sprintf('end')}];
+            outLines = [outLines; {''}];
+
+            break;
+        else
+            outLines = [outLines; {chkLine}];
+        end
+    end
+end
diff --git a/src/c/Mex/autoBuildMex.cmake b/src/c/Mex/autoBuildMex.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..eaec3ac7cbe1ed4ebbce0b6c95962a2ca25c1a15
--- /dev/null
+++ b/src/c/Mex/autoBuildMex.cmake
@@ -0,0 +1,6 @@
+add_custom_command(TARGET HydraMex
+    POST_BUILD
+    COMMAND ${Matlab_MAIN_PROGRAM} -nosplash -nodisplay -nodesktop $<$<PLATFORM_ID:Windows>:-wait> -r "autoInstallMex('${HYDRA_MODULE_NAME}', '$<TARGET_FILE:HydraMex>');exit;"
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/MATLAB/build-scripts
+    VERBATIM USES_TERMINAL
+)