form_build_command.template.m

Back to Orphans

matlab/

% Description: Forms a mex-build-command.
% Documentation: building_timmatlab.txt

function commandSet = form_build_command(fileSet, varargin)

% Determine the bitness of the running Matlab version
% (not of the operating system or the computer).
[ignore, maxArraySize] = computer;
bits = 32;
if maxArraySize >= 2^32
    bits = 64;
end

% Add Pastel to Matlab path so that
% process_options is available.
addpath(['${PastelDirectory}', '/matlab']);

% Optional input arguments
mode = 'release';
verbose = 'off';
run = false;
defineSet = {};
librarySet = {};
outputDirectory = '.';
libraryDirectorySet = {};
includeDirectorySet = {};
outputLibraryName = '';
eval(pastelmatlab.process_options(...
    {'includeDirectorySet', 'libraryDirectorySet', ...
    'defineSet', 'outputDirectory', 'librarySet', ...
    'mode', 'verbose', 'run', 'outputLibraryName'}, ...
    varargin));

modeSet = {'debug', 'release', 'relwithdebinfo'};
if ~ismember(mode, modeSet)
    error(['MODE must be one of debug, release, or relwithdebinfo.']);
end

verboseSet = {'on', 'off'};
if ~ismember(verbose, verboseSet)
    error(['VERBOSE must be one on or off.']);
end

printOutputLibraryName = outputLibraryName;
if isempty(outputLibraryName)
    printOutputLibraryName = '<default-name>';
end

disp(' ');
disp(['Building a mex file for ', ...
    printOutputLibraryName, ...
    ' in ', ...
    num2str(bits), '-bit ', ...
    mode, ' mode.']);
disp(' ');

generatedBits = ${GENERATOR_BITS};
if bits ~= generatedBits
    error(['Build file is ', num2str(generatedBits), '-bit, but ', ...
        'Matlab is ', num2str(bits), '-bit. ', ...
        'Switch to ', num2str(bits), '-bit Matlab, or regenerate the build-file with a ', ...
        num2str(bits), '-bit CMake generator.'])
end

% Handle semicolon-separated lists
% --------------------------------

function resultSet = breakSemicolons(stringSet)
    resultSet = {};
    for i = 1 : numel(stringSet)
        string = stringSet{i};
        splitSet = regexp(string, ';', 'split');
        resultSet = [resultSet, splitSet];
    end
end

includeDirectorySet = breakSemicolons(includeDirectorySet);
libraryDirectorySet = breakSemicolons(libraryDirectorySet);
librarySet = breakSemicolons(librarySet);

% Preprocessor definitions 
% ------------------------

defineSet{end + 1} = '_ITERATOR_DEBUG_LEVEL=0';

% Form the build-command
% ----------------------

commandSet = {};
commandSet{end + 1} = 'mex';
for i = 1 : numel(fileSet)
    commandSet{end + 1} = [' ', fileSet{i}];
end

% Add preprocessor definitions.
for i = 1 : numel(defineSet)
    commandSet{end + 1} = [' -D', defineSet{i}];
end

% Add include paths.
for i = 1 : numel(includeDirectorySet)
    commandSet{end + 1} = [' -I''', includeDirectorySet{i}, ''''];
end

% Add library directories.
for i = 1 : numel(libraryDirectorySet)
    libraryDirectory = libraryDirectorySet{i};
    if isempty(libraryDirectory)
        % No directory was specified; skip it.
        continue;
    end

    [iStart, iEnd] = regexp(libraryDirectory, '\.framework$');
    if ~isempty(iStart) && ismac()
        % This is a framework directory.
        commandSet{end + 1} = [' LDFLAGS=''$LDFLAGS -F ', libraryDirectory, ''''];
    else
        % This is a normal library directory.
        commandSet{end + 1} = [' -L''', libraryDirectory, ''''];
    end
end

% Add output path.
commandSet{end + 1} = [' -outdir ''', outputDirectory, ''''];

% Add output name.
if ~isempty(outputLibraryName)
    commandSet{end + 1} = [' -output ''', outputLibraryName, ''''];
end

% Add libraries.
for i = 1 : numel(librarySet)
    library = librarySet{i};
    if isempty(library)
        % No library was specified; skip it.
        continue;
    end

    [iStart, iEnd] = regexp(library, '\.framework$');
    if ~isempty(iStart) && ismac()
        % This is a framework (Mac OS X).

        % Get the framework name by stripping out the
        % trailing '.framework'.
        frameworkName = library(1 : iStart - 1);

        % Mex does not have a direct flag to specify
        % frameworks. Instead, we embed it directly
        % into compiler flags.
        commandSet{end + 1} = [' CXXLIBS=''$CXXLIBS -framework ', frameworkName, ''''];
    else
        % This is a normal library.
        commandSet{end + 1} = [' -l', librarySet{i}];
    end
end

% Other flags.
if strcmp(mode, 'debug')
    if strcmp('${CompilerId}', 'msvc')
        % Use debug-mode C++ standard library.
        commandSet{end + 1} = ' -g COMPFLAGS="$COMPFLAGS /MDd"';
    else
        commandSet{end + 1} = ' -g';
    end
end

if strcmp(mode, 'relwithdebinfo') 
    commandSet{end + 1} = ' -g';
end

if strcmp(verbose, 'on')
    commandSet{end + 1} = ' -v';
end

% Run the build-command
% ---------------------

if run
    % Print the executed build-command in pretty form.
    for i = 1 : numel(commandSet)
        disp(commandSet{i});
    end

    % Run the command.
    buildCommand = [commandSet{:}];
    eval(buildCommand);
end

end