Begin
Recently i had the pleasure to compile a lot of C++ code for a release and it was kind of painful to switch back and forth between windows and linux.
The work-flow was as following. Writing code and testing under Linux, using CMake to generate a Visual Studio project, compile a static library, use matlabs mex to generate a mex file for use with simulink. Every single step in this process was as painful as it sounds and most importantly bugs might occur in every stage described. A nice way out of this misery seemed to be using a cross-compiler for generating a static library which could be used under windows.
Little did I know, it was possible to completely generate a .mexw32/.mexw64 file which could be directly used in simulink.
During my search for cross-compiling I found out that I needed a toolchain for compiling.
With debian the following toolchain can be used for 32-bit applications
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_SYSTEM_PROCESSOR "32")
# which compilers to use for C and C++
SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32 )
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
and for 64-bit application the following toolchain should be valid:
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_SYSTEM_PROCESSOR "64")
# which compilers to use for C and C++
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32/ )
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Note that CMAKE_SYSTEM_PROCESSOR is misused here for later on deciding between 32- and 64-bit systems.
The following CMakeLists.txt can be used to generate a .mex file:
cmake_minimum_required (VERSION 2.6)
OPTION (BUILD_SIMULINK_INTERFACE "Build simulink interfaces" OFF)
### set path to matlab here
SET(MATLAB_WINDOWS_DIRECTORY "MATLAB-NOT-FOUND" CACHE PATH "Path to Matlab" )
if (BUILD_SIMULINK_INTERFACE)
### needed link directory for matlab
LINK_DIRECTORIES( ${CMAKE_LIBRARY_PATH} ${MATLAB_WINDOWS_DIRECTORY}/bin/win${TARGET_BIT}/ )
### simulink paths
INCLUDE_DIRECTORIES(${PATH_TO_MATLAB}/rtw/c/src ${PATH_TO_MATLAB}/stateflow/c/mex/include ${PATH_TO_MATLAB}/simulink/include)
### a lot of libraries that are needed for matlab and mingw
SET(SIMULINK_LIBRARIES mex mx mwlapack mwblas eng advapi32 user32 gdi32 kernel32 mingwex)
### This tells simulink we are building an s-function
ADD_DEFINITIONS(-DMATLAB_MEX_FILE)
### .mex* is a nothing more than a shared library, therefore we set this SHARED
ADD_LIBRARY(simulinkLib SHARED ${S_FUNCTION_FILES_HERE} )
TARGET_LINK_LIBRARIES (simulinkLib ${DIFFERENT_LIBRARIES_HERE} ${SIMULINK_LIBRARIES})
endif(BUILD_SIMULINK_INTERFACE)
The generation of the code can be toggled with the option BUILD_SIMULINK_INTERFACE and one has to set the path to the windows matlab directory. If one does not want to have a full blown matlab/simulink installation running the following directories from the matlab root directory should be sufficient:
- /bin/win32 or /bin/win64
- /rtw/c/src
- /stateflow/c/mex/include
- /simulink/include