%% Build 32-bit DLL on 64-bit Windows(R) Platform Using MSVC Toolchain 
%
% Register and use a Microsoft(R) Visual C/C++ (MSVC) toolchain
% running on a 64-bit Windows(R) platform to compile a 32-bit dynamic link library (DLL).
% This example uses a Microsoft(R) compiler. However, the concepts and programming interface
% apply for other toolchains. Once you register the toolchain, you can select it from a
% list of toolchains, and the code generator generates a makefile to build the code
% by using that toolchain.  A toolchain consists of several tools, such as a compiler, linker, and 
% archiver with multiple different configuration options. The toolchain compiles, 
% links, and runs code on a specified platform. To access the files that this 
% example uses, click *Open Script*.

% Copyright 2017 The MathWorks, Inc.

%% Check Platform and Determine MSVC Version
% This code checks that the platform is supported and that 
% you have a supported version of Microsoft(R) Visual C/C++. 
% The |my_msvc_32bit_tc.m| toolchain definition can use the Microsoft(R) 
% Visual Studio versions 9.0, 10.0, 11.0, 12.0, 14.0, or 15.0. 
%
% If you are not using a Windows(R) platform, or if you do not have a supported version of Microsoft(R) Visual 
% C/C++, the example generates only code and a makefile, without running the generated makefile.
VersionNumbers = {'14.0'}; % Placeholder value 
if ~ispc
    supportedCompilerInstalled = false;
else
    installed_compilers = mex.getCompilerConfigurations('C', 'Installed');
    MSVC_InstalledVersions = regexp({installed_compilers.Name}, 'Microsoft Visual C\+\+ 20\d\d');
    MSVC_InstalledVersions = cellfun(@(a)~isempty(a), MSVC_InstalledVersions);
    if ~any(MSVC_InstalledVersions)
        supportedCompilerInstalled = false;
    else
        VersionNumbers = {installed_compilers(MSVC_InstalledVersions).Version}';
        supportedCompilerInstalled = true;
    end
end

%% Function for the Dynamic Link Library
% The example function for the dynamic link library, |myMatlabFunction.m|,
% multiplies a number by two.
%
% <include>myMatlabFunction.m</include>
%
%% Create and Configure an MSVC Toolchain
% The |my_msvc_32bit_tc.m| toolchain definition function takes in
% an argument containing the Visual Studio version number. In this example, the 
% commands that create and configure this toolchain are:
tc = my_msvc_32bit_tc(VersionNumbers{end});
save my_msvc_32bit_tc tc;

%% Register the Toolchain
% Before the code generator can use a toolchain for the build process, the |RTW.TargetRegistry|
% must contain the toolchain registration. This registration can come from any |rtwTargetInfo.m|
% file on the MATLAB path. MATLAB will load a new registration if the |RTW.TargetRegistry| is reset.
%
% Create the |rtwTargetInfo.m| file from the corresponding text file |myRtwTargetInfo.txt|.
%
% <include>myRtwTargetInfo.txt</include>
%
copyfile myRtwTargetInfo.txt rtwTargetInfo.m
RTW.TargetRegistry.getInstance('reset');

%% Create Code Generation Configuration Object
% To generate the 32-bit dynamic link library (DLL), create a |'dll'| code generation configuration
% object. Specifying |'dll'| directs the linker (a build tool in the toolchain)
% to use "Shared Library" linker commands.
cfg = coder.config('dll');

%% Configure Code Generation for 32-bit Hardware
% To successfully generate code that is compatible with 32-bit hardware,
% the generated code must use the correct underlying C types (for example, |int|, |signed char|,
% and others). These types are the basis for |typedef| statements for sized types (for example,
% |uint8|, |int16|, and others). Set the configuration with the command:
cfg.HardwareImplementation.ProdHWDeviceType = ...
    'Generic->Unspecified (assume 32-bit Generic)';

%% Configure Code Generation to Use the 32-bit Toolchain
% Set the name of the |Toolchain| property to match the |Name| that you specify in the |rtwTargetInfo.m|
% file. 
cfg.Toolchain = ...
    'Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)';

%% Select Verbose Status Reporting
% To provide confirmation of compiler flags that the toolchain uses to build the DLL, 
% select verbose status reporting. 
cfg.Verbose = true;

%% Determine Whether to Generate Code Only
% When the Microsoft(R) compilers are not installed, the code generator generates only
% code and the makefile. When the supported compilers are installed, the code generator builds 
% the 32-bit binary file. 
if supportedCompilerInstalled
    cfg.GenCodeOnly = false;
else
    cfg.GenCodeOnly = true;
end

%% Generate Code and Build a DLL
% To use the toolchain for code generation and build the DLL (if build is
% enabled), at the command prompt, enter:
codegen -config cfg myMatlabFunction -args { double(1.0) };

%% Build and Run an Executable
% If you have a supported version of the compiler installed,
% you can build the 32-bit executable by using a C main function. You can use the
% executable to test that the generated code works as expected.
cfge = coder.config('exe');
cfge.CustomInclude = pwd;
cfge.CustomSource = 'myMatlabFunction_main.c';
cfge.GenCodeOnly = cfg.GenCodeOnly;
cfge.Verbose = true;
cfge.Toolchain = ...
    'Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)';
codegen -config cfge myMatlabFunction -args { double(1.0) };
if supportedCompilerInstalled
    pause(5); %wait for EXE to get generated
    system('myMatlabFunction 3.1416'); % Expected output: myMatlabFunction(3.1416) = 6.2832
end

%% Optional Step: Unregister the toolchain
% To unregister the toolchain, enter:
delete ./rtwTargetInfo.m
RTW.TargetRegistry.getInstance('reset');
