Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mingw enhancement #548

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions doc/DevelopersDocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,42 @@ From Visual Studio, you can open the project file `JSBSim.vcxproj` to open a pro

For more detailed instructions on using Visual Studio project files and CMake via Visual Studio to build JSBSim take a look at the following documentation link - [Building using Visual Studio](https://jsbsim-team.github.io/jsbsim-reference-manual/mypages/quickstart-building-using-visualstudio/).

### Building with MinGW toolset

With the help of cmake, you can build JSBSim under Windows using MinGW toolset. The whole configuration and building command is
as simple as that in unix bash:

```bash
> cd jsbsim-code
> mkdir build
> cd build
> cmake ..
> mingw32-make
```

#### Building python module with MinGW toolset
If cython executable is installed in your PATH enviroment or provided to cmake command, the python module will be built as well.
Usually, there is nothing special with MinGW toolset. But if you get `cannot find -lmsvcrt140`, you may need to modify your cygwinccompiler.py,
which is in distutils folder (In anaconda, it should be `Anaconda3\lib\distutils\cygwinccompiler.py`)

```python
elif int(msc_ver) >= 1900:
# VS2015 / MSVC 14.0
# return ['msvcr140']
return ['vcruntime140']
```
Comment on lines +125 to +130
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot find this code in Python official distutils: https://github.com/python/cpython/blob/576e38f9db61ca09ca6dc57ad13b02a7bf9d370a/Lib/distutils/cygwinccompiler.py#L61 so I am a bit skeptical that a user can follow successfully the steps you are describing ?


And then copy `vcruntime140.dll` to `/path/to/mingw-w64/lib`. This problem is due to msvc runtime library naming convention broken after VS2015. See [here](https://stackoverflow.com/questions/52943590/cython-missing-msvcr140-dll).
Comment on lines +120 to +132
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting the user to perform manual modifications to their Python installation is not our way to handle platform specific cases.

Actually, we are going to great length to avoid this and instead we are automatically handling such situations by overloading distutils compilers such as in python/setup.py.in

jsbsim/python/setup.py.in

Lines 78 to 106 in d9df845

# distutils assumes that all the files must be compiled with the same compiler
# flags regardless of their file extension .c or .cpp.
# JSBSim C++ files must be compiled with -std=c++1x but compilation on MacOSX
# fails when trying to compile C files with -std=c++1x.
# The class C_CxxCompiler adds C++ flags to compilation flags for C++ files only.
class C_CxxCompiler(UnixCCompiler):
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
_cc_args = cc_args
# Add the C++ flags to the compile flags if we are dealing with a C++
# source file.
if os.path.splitext(src)[-1] in ('.cpp', '.cxx', '.cc'):
_cc_args = cpp_compile_flag + cc_args
UnixCCompiler._compile(self, obj, src, ext, _cc_args,
extra_postargs, pp_opts)
# The class BuildC_CxxExtension intercepts the build of the Python module and
# replaces the compiler by an instance of C_CxxCompiler that select the compile
# flags depending on whether it is a C++ source file or not.
class BuildC_CxxExtension(build_ext):
def build_extension(self, ext):
if self.compiler.compiler_type == 'unix':
old_compiler = self.compiler
self.compiler = C_CxxCompiler()
# Copy the attributes to the new compiler instance
for attr, value in old_compiler.__dict__.items():
setattr(self.compiler, attr, value)
return build_ext.build_extension(self, ext)


#### Building matlab mex file with MinGW toolset
To compile matlab mex file, gcc major version needs to be greater than 8 to support c++14 language features. The official matlab support MinGW-w64
version is 6.3, so you have to set your own MinGW toolset environment:
* Download a newer MinGW-w64 toolset in your local machine
* Set `MW_MINGW64_LOC` environment variable in your local machine or in matlab command shell
* Run matlab command `mex -setup` to set up toolset

After setting up your Mingw-w64 toolset in matlab, you can build the JSBSim mex file running `JSBSimSimulinkCompile.m`.

## Testing JSBSim

JSBSim comes with a test suite to automatically check that the build is correct. This test suite is located in the `tests` directory and is coded in Python so you need to [build the Python module of JSBSim](#building-the-python-module-of-jsbsim) first.
Expand Down
4 changes: 3 additions & 1 deletion matlab/JSBSimSimulinkCompile.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
disp('Compiling S-function from JSBSim...');
% For Linux:
mex -v -R2017b CXXFLAGS='$CXXFLAGS -std=c++14' ./matlab/JSBSim_SFunction.cpp ./matlab/JSBSimInterface.cpp -I./src -L./src/.libs -lJSBSim
% For Windows:
% For Windows MSVC:
%mex -v -R2017b COMPFLAGS='$COMPFLAGS' ./matlab/JSBSim_SFunction.cpp ./matlab/JSBSimInterface.cpp -I".\out\install\x64-Release\include\JSBSim" -L".\out\install\x64-Release\lib" -lJSBSim wsock32.lib ws2_32.lib
% For Windows MinGW
%mex -v -R2017b CXXFLAGS='$CXXFLAGS -std=c++14' COMPFLAGS='$COMPFLAGS' ./matlab/JSBSim_SFunction.cpp ./matlab/JSBSimInterface.cpp -I".\out\install\x64-Release\include\JSBSim" -L".\out\install\x64-Release\lib" -lJSBSim -L"/path/to/mingw/lib" -lwsock32 -lws2_32
disp('Finished.')

% -v verbose
Expand Down
2 changes: 1 addition & 1 deletion python/fpectl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ else()

add_custom_command(OUTPUT ${FPECTL_PYTHON_MODULE}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fpectlmodule.h ${CMAKE_CURRENT_SOURCE_DIR}/fpectlmodule.cpp ${CMAKE_SOURCE_DIR}/python/ExceptionManagement.h
COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build_ext -b ${CMAKE_BINARY_DIR}/tests
COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build_ext -b ${CMAKE_BINARY_DIR}/tests $<IF:$<BOOL:${MINGW}>,--compiler,> $<IF:$<BOOL:${MINGW}>,mingw32,>
COMMENT "Building fpectl module...")

add_custom_target(fpectl ALL DEPENDS ${FPECTL_PYTHON_MODULE})
Expand Down
6 changes: 3 additions & 3 deletions python/fpectl/fpectlmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
#include <signal.h>
#include <iostream>

#if defined(_MSC_VER)
#if defined(_WIN32)
# include <float.h>
static unsigned int fp_flags = 0;
#elif (defined(__GNUC__) || defined(__clang__)) && !defined(sgi)
Expand Down Expand Up @@ -139,7 +139,7 @@ static void sigfpe_handler(int signo)

static PyObject *turnon_sigfpe(PyObject *self, PyObject *args)
{
#ifdef _MSC_VER
#ifdef _WIN32
_clearfp();
fp_flags = _controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW),
_MCW_EM);
Expand All @@ -164,7 +164,7 @@ static PyObject *turnon_sigfpe(PyObject *self, PyObject *args)

static PyObject *turnoff_sigfpe(PyObject *self, PyObject *args)
{
#ifdef _MSC_VER
#ifdef _WIN32
_controlfp(fp_flags, _MCW_EM);

#elif defined(__clang__)
Expand Down
3 changes: 3 additions & 0 deletions python/fpectl/setup.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ compiler = new_compiler(compiler=compiler_name)
if compiler.compiler_type == 'unix':
cpp_compile_flags = ['-std=c++11']
cpp_link_flags = []
elif compiler.compiler_type == 'mingw32':
cpp_compile_flags = ['-std=c++11', '-D_hypot=hypot']
Copy link
Member

@bcoconni bcoconni Dec 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I ask why you are requesting the flag -D_hypot=hypot since AFAICT ::hypot is not used in JSBSim ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review.

I use this macro as Python.h header file declares ::hypot function. I'm using anaconda with python 3.6, whose distutils may contain some modification code.

I close this PR for the moment. My branch will be working in progress for better MinGW compability support, to pass the CI python module building. If any new findings, I will be back here.:grin:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha OK, I did not think to check Python.h. That's a good point 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we'll be more than happy to provide you some help so do not hesitate to re-open this PR if you need some support.

cpp_link_flags = []
elif compiler.compiler_type == 'msvc':
# These flags are equivalent to a RelWithDebInfo configuration.
# Since the module fpectl is not supposed to be used in production, these
Expand Down
4 changes: 4 additions & 0 deletions python/setup.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ if compiler.compiler_type == 'unix':
cpp_compile_flag = ['-std=c++14']
cpp_link_flags = []
link_libraries = [${JSBSIM_LINK_LIBRARIES}]
elif compiler.compiler_type == 'mingw32':
cpp_compile_flag = ['-std=c++14', '-D_hypot=hypot']
Copy link
Member

@bcoconni bcoconni Dec 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: why are you requesting the flag -D_hypot=hypot ?

cpp_link_flags = ['-Wl,-Bstatic']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of this linker flags ?

link_libraries = ['wsock32', 'ws2_32']
elif compiler.compiler_type == 'msvc':
if args.config in ('Debug', 'RelWithDebInfo'):
# These flags are equivalent to a RelWithDebInfo configuration.
Expand Down