Matlab: Removing dependency on OS env PATH variable for gcc

Hi

We have started experimenting with acados using the Matlab interface and we are in general happy with the setup. We have however bumped into a constraint which is causing us trouble.

When generating a Simulink s-function a number of c-files are compiled using the mex compilation setup and these are linked with a library containing the casadi_ext_fun. The compilation of this library does not use mex compilation, but is rather a system call directly to the compiler. For this to work it is required that the compiler used by mex is added to the OS PATH environment variable.

As we need to have another (incompatible) version of gcc in our OS PATH environment variable acados will use this incompatible gcc version to compile the cadasdi_ext_fun library and the linking will subsequently fail.

To fix this I have implemented the below change on top of the v0.1.8 commit. The change is to extract the path to the compiler mex uses and temporariy add it to the environment PATH variable in the current Matlab session.

Also I’m not sure if similar changes are needed elsewhere in the code-base?

The below change works in our use-case, but is only tested using minGW on Windows. Question is if you agree with this fix and if so if you want me rebase a to latest master and make a pull request?

Simulink: gcc: No longer necessary to have gcc in OS environment variable path

Modified building of casadi_ext_fun library such that the gcc version configured for building mex files is used.
This avoids a linking error which happens when a version of gcc different than configured for mex building is in the OS environment PATH variable.

diff --git a/interfaces/acados_matlab_octave/ocp_generate_casadi_ext_fun.m b/interfaces/acados_matlab_octave/ocp_generate_casadi_ext_fun.m
index 14a8cb8c..c6a251d3 100644
--- a/interfaces/acados_matlab_octave/ocp_generate_casadi_ext_fun.m
+++ b/interfaces/acados_matlab_octave/ocp_generate_casadi_ext_fun.m
@@ -208,6 +208,9 @@ end
 
 ext_fun_compile_flags = opts_struct.ext_fun_compile_flags;
 
+%Store the current PATH environment variable value
+origEnvPath=getenv('PATH');
+
 if use_msvc
     % get env vars for MSVC
     msvc_env = fullfile(mexOpts.Location, 'VC\Auxiliary\Build\vcvars64.bat');
@@ -223,6 +226,13 @@ if use_msvc
     % build
     compile_command = sprintf('"%s" & %s', msvc_env, build_cmd);
 else % gcc
+    %Read the mex C compiler configuration and extract the location
+    cCompilerConfig = mex.getCompilerConfigurations('C');
+    pathToCompilerLocation = cCompilerConfig.Location;
+    %Modify the environment PATH varuable for this Matlab session such that 
+    %the mex C compiler takes priority ensuring calls to gcc uses the
+    %configured mex compiler
+    setenv('PATH', [fullfile(pathToCompilerLocation,'bin') ';' origEnvPath]);
     % set includes
     acados_include = ['-I' acados_folder];
     blasfeo_include = ['-I' fullfile(acados_folder, 'external' , 'blasfeo', 'include')];
@@ -236,11 +246,22 @@ else % gcc
                        ' ', strjoin(unique(c_files_path), ' '), ' -o ', out_lib];
 end
 
+
 compile_status = system(compile_command);
+
+%Store the PATH environment variable used during compile for error reporting
+envPath=getenv('PATH');
+
+%Reset the environment path variable to its original value
+%This is done before potentially raising an error to ensure that the path
+%environment variable is clean
+setenv('PATH',origEnvPath);
+
 if compile_status ~= 0
-    error('Compilation of model functions failed! %s %s\n%s\n\n', ...
+    error('Compilation of model functions failed! %s\n%s\n%s\n%s\n%s\n\n', ...
         'Please check the compile command above and the flags therein closely.',...
-        'Compile command was:', compile_command);
+        'Compile command was:', compile_command, ...
+        'Environment path was: ', envPath);
 end
 
 end


Hi,

Great to hear!

I think, the change you propose makes sense!

Probably this file should be changed similarly: acados/sim_generate_casadi_ext_fun.m at master · acados/acados · GitHub

This example tests both the integrator and OCP solver in Simulink: acados/simulink_example_advanced.m at master · acados/acados · GitHub

Other than this, if you already have a solution for something like this, a PR is always welcome!

Ideally, you apply the change also in the other file and rebase onto the latest version.

We have CI tests for Simulink on Linux on Github Actions, which will run on the PR.
I think those should be sufficient to test the compatibility.

Best,
Jonathan