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