MiB_Coder
MiB_Coder

Reputation: 915

Octave: how to specify arguments for mkoctfile

Im am using octave under windows (native) and try to compile a c++ program into a mex file and link some libraries to it:

% compile for octave
cmd = sprintf("mex main.cpp -I\"%s\\Winnt\\Include\" -L\"%s\\Winnt\\lib_x64\\msc\" -lvisa64.lib", ...
getenv('VXIPNPPATH'), getenv('VXIPNPPATH'))
eval(cmd);

When run, the output of the command is:

>> mex main.cpp -I'C:\Program Files (x86)\IVI Foundation\VISA\\Winnt\Include' -L'C:\Program Files (x86)\IVI Foundation\VISA\\Winnt\lib_x64\msc' -lvisa64.lib
g++: error: Files: No such file or directory
g++: error: (x86)\IVI: No such file or directory
g++: error: Foundation\VISA\\Winnt\lib_x64\msc: No such file or directory
warning: mkoctfile: building exited with failure status

I also tried to run the string directly from the command line:

mex main.cpp -I'C:\Program Files (x86)\IVI Foundation\VISA\\Winnt\Include' -L'C:\Program Files (x86)\IVI Foundation\VISA\\Winnt\lib_x64\msc' -lvisa64.lib

with the same result. While the -I command appears to work well, why does the -L argument causes problems? What would be the right way to escape the path names with spaces? Double quotes also won't work.

EDIT Based on the answers, I am using mex() in its functional form, but the result is still the same:

vxipath = getenv('VXIPNPPATH');
params={};
params{1} = sprintf('-I%s', fullfile(vxipath, 'Winnt', 'Include'));
params{2} = sprintf('-L%s', fullfile(vxipath, 'Winnt', 'lib_x64', 'msc'));
params{3} = sprintf('-lvisa64.lib');

% replace \ with /
for i1=1:length(params)
  s = params{i1};
  s(s=='\') = '/';
  params{i1} = s;
end

params
mex("main.cpp", params{:});

Gives the output:

params =
{
  [1,1] = -IC:/Program Files (x86)/IVI Foundation/VISA/Winnt/Include
  [1,2] = -LC:/Program Files (x86)/IVI Foundation/VISA/Winnt/lib_x64/msc
  [1,3] = -lvisa64.lib
}

g++: error: Files: No such file or directory
g++: error: (x86)/IVI: No such file or directory
g++: error: Foundation/VISA/Winnt/lib_x64/msc: No such file or directory
warning: mkoctfile: building exited with failure status

Which is the same result as before. Additional observations are:

I also tried it directly from the bash shell with the corresponding command with the same result.

Upvotes: 1

Views: 646

Answers (3)

MiB_Coder
MiB_Coder

Reputation: 915

mkoctfile does not escape the arguments properly if they contain spaces and it does not like backslashes in Octave's own paths. It creates the following two commands:

g++ -c -I/release/mxe-octave-w64/usr/x86_64-w64-mingw32/include  -IC:\Octave\OCTAVE~1.0\\mingw64\include\octave-5.1.0\octave\.. -IC:\Octave\OCTAVE~1.0\\mingw64\include\octave-5.1.0\octave -IC:\Octave\OCTAVE~1.0\\mingw64\include   -fopenmp -g -O2   -I. "-IC:\Program Files (x86)\IVI Foundation\VISA\Winnt\Include"  -DMEX_DEBUG main.cpp -o C:\Octave\OCTAVE~1.0\tmp/oct-u4r15I.o
g++ -IC:\Octave\OCTAVE~1.0\\mingw64\include\octave-5.1.0\octave\.. -IC:\Octave\OCTAVE~1.0\\mingw64\include\octave-5.1.0\octave -IC:\Octave\OCTAVE~1.0\\mingw64\include   -fopenmp -g -O2 -shared -Wl,-rpath-link,/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/qt5/lib -Wl,--export-all-symbols  -o main.mex  C:\Octave\OCTAVE~1.0\tmp/oct-u4r15I.o  -lvisa64.lib  -LC:\Program Files (x86)\IVI Foundation\VISA\Winnt\lib_x64\msc -LC:\Octave\OCTAVE~1.0\\mingw64\lib\octave\5.1.0 -LC:\Octave\OCTAVE~1.0\\mingw64\lib -LC:\Octave\OCTAVE~1.0\\mingw64\lib\octave\5.1.0 -loctinterp -loctave  -Wl,-rpath-link,/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/qt5/lib -Wl,--export-all-symbols 

When I change it to the following:

  • replace \ with /
  • specify the library name without .lib extension
  • escape -LC:\Program Files... to "-LC:\Program Files..."
g++ -c -I/release/mxe-octave-w64/usr/x86_64-w64-mingw32/include  -IC:/Octave/OCTAVE~1.0//mingw64/include/octave-5.1.0/octave/.. -IC:/Octave/OCTAVE~1.0//mingw64/include/octave-5.1.0/octave -IC:/Octave/OCTAVE~1.0//mingw64/include   -fopenmp -g -O2   -I. "-IC:/Program Files (x86)/IVI Foundation/VISA/Winnt/Include"  -DMEX_DEBUG main.cpp -o C:/Octave/OCTAVE~1.0/tmp/oct-u4r15I.o  
g++ -IC:/Octave/OCTAVE~1.0//mingw64/include/octave-5.1.0/octave/.. -IC:/Octave/OCTAVE~1.0//mingw64/include/octave-5.1.0/octave -IC:/Octave/OCTAVE~1.0//mingw64/include   -fopenmp -g -O2 -shared -Wl,-rpath-link,/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/qt5/lib -Wl,--export-all-symbols  -o main.mex  C:/Octave/OCTAVE~1.0/tmp/oct-u4r15I.o "-LC:/Program Files (x86)/IVI Foundation/VISA/Winnt/lib_x64/msc" -lvisa64 -LC:/Octave/OCTAVE~1.0//mingw64/lib/octave/5.1.0 -LC:/Octave/OCTAVE~1.0//mingw64/lib -LC:/Octave/OCTAVE~1.0//mingw64/lib/octave/5.1.0 -loctinterp -loctave  -Wl,-rpath-link,/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/lib -L/release/mxe-octave-w64/usr/x86_64-w64-mingw32/qt5/lib -Wl,--export-all-symbols 

It will compile without error.

Upvotes: 1

Cris Luengo
Cris Luengo

Reputation: 60514

This doesn't answer the how to fix it, as rahnema1 already did that. But I'll show you how to simplify your code.

  1. Do not use eval. eval is evil.

    Instead of evaluating a string function paramA paramB, call function directly with string input arguments. function paramA paramB is translated by the interpreter to a call function('paramA','paramB'). But it is a lot easier to generate the latter form, and you get to avoid eval to boot:

    params = {};
    params{1} = '-IC:/Program Files (x86)/IVI Foundation/VISA//Winnt/Include';
    params{2} = '-LC:/Program Files (x86)/IVI Foundation/VISA//Winnt/lib_x64/msc';
    params{2} = '-lvisa64.lib';
    mex('main.cpp', params{:});
    
  2. Properly generate paths using fullfile. It adds / or \ depending on which platform you're on, plus I find it easier to read:

    include_path = fullfile(getenv('VXIPNPPATH'), 'Winnt', 'Include');
    params{1} = ['-I', include_path];
    

Upvotes: 1

rahnema1
rahnema1

Reputation: 15837

Replace backslashes with slashes and place each argument inside single quotes.

mex 'main.cpp' '-IC:/Program Files (x86)/IVI Foundation/VISA//Winnt/Include' '-LC:/Program Files (x86)/IVI Foundation/VISA//Winnt/lib_x64/msc' '-lvisa64.lib'

or

mex ('main.cpp', '-IC:/Program Files (x86)/IVI Foundation/VISA//Winnt/Include', '-LC:/Program Files (x86)/IVI Foundation/VISA//Winnt/lib_x64/msc', '-lvisa64.lib')

Upvotes: 1

Related Questions