It looks like the Windows cross-builds are failing after that change. The error is that functions that are marked as dllimport cannot be defined in the same compilation unit.
The approach for “visibility” settings is slightly different on Windows and Linux. On Windows, functions are not only marked as “dllexport” in compilation units that define those functions. They are also marked as “dllimport” in compilation units where they are used (but not defined).
Definitions cannot be marked as “dllimport”. Only declarations can.
Template instantiations are declarations in that sense. Template specializations (that include a function body) are definitions.
That behavior might also help to get the flags right on Linux. IMHO, there is not much point exporting a symbol if it is defined in every compilation unit that is using it anyway.
Edit:
Untested as of now. But we could probably remove the API flags from the template definitions that are included in each compilation unit that instantiates them.
That might fix the compilation error for Windows targets. And it shouldn’t make a difference on other platforms IIUC.
MSparse-visibility.patch (3.8 KB)
Edit:
With those changes, cross-compiling for Windows still fails for me while linking liboctinterp with the following errors:
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: /home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: DWARF error: could not find variable specification at offset df154
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: DWARF error: could not find variable specification at offset df162
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: DWARF error: could not find variable specification at offset df172
libinterp/octave-value/.libs/liboctave-value.a(liboctave_value_la-ov-cx-sparse.o): in function `MSparse<bool>::~MSparse()':
/home/osboxes/Documents/Repositories/Octave/mxe-octave/tmp-default-octave/octave-7.0.0/liboctave/array/MSparse.h:75: undefined reference to `__imp__ZTV7MSparseIbE'
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: /home/osboxes/Documents/Repositories/Octave/mxe-octave/tmp-default-octave/octave-7.0.0/liboctave/array/MSparse.h:75: undefined reference to `__imp__ZTV7MSparseIbE'
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: libinterp/octave-value/.libs/liboctave-value.a(liboctave_value_la-ov-cx-sparse.o): in function `MSparse<bool>::~MSparse()':
/home/osboxes/Documents/Repositories/Octave/mxe-octave/tmp-default-octave/octave-7.0.0/liboctave/array/MSparse.h:75: undefined reference to `__imp__ZTV7MSparseIbE'
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: libinterp/octave-value/.libs/liboctave-value.a(liboctave_value_la-ov-cx-sparse.o): in function `MSparse<bool>::~MSparse()':
/home/osboxes/Documents/Repositories/Octave/mxe-octave/tmp-default-octave/octave-7.0.0/liboctave/array/MSparse.h:75: undefined reference to `__imp__ZTV7MSparseIbE'
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: libinterp/octave-value/.libs/liboctave-value.a(liboctave_value_la-ov-cx-sparse.o): in function `MSparse<bool>::MSparse(Sparse<bool> const&)':
/home/osboxes/Documents/Repositories/Octave/mxe-octave/tmp-default-octave/octave-7.0.0/liboctave/array/MSparse.h:57: undefined reference to `__imp__ZTV7MSparseIbE'
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: /home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: DWARF error: could not find variable specification at offset dc804
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: DWARF error: could not find variable specification at offset dc812
/home/osboxes/Documents/Repositories/Octave/mxe-octave/usr/bin/x86_64-w64-mingw32-ld: DWARF error: could not find variable specification at offset dc822
libinterp/octave-value/.libs/liboctave-value.a(liboctave_value_la-ov-re-sparse.o):/home/osboxes/Documents/Repositories/Octave/mxe-octave/tmp-default-octave/octave-7.0.0/liboctave/array/MSparse.h:75: more undefined references to `__imp__ZTV7MSparseIbE' follow
collect2: error: ld returned 1 exit status
make[5]: *** [Makefile:13186: libinterp/liboctinterp.la] Error 1
__imp__ZTV7MSparseIbE
demangled is __imp_vtable for MSparse<bool>
. The __imp_
-prefix is for functions that have dllimport
/dllexport
attributes.
Where do we even use MSparse<bool>
? I thought we only had MSparse<double>
and MSparse<Complex>
…
Edit:
I tried to explicitly instantiate MSparse<bool>
and that fails like so:
n file included from ../liboctave/array/MSparse.h:129,
from ../liboctave/array/MSparse-b.cc:30:
../liboctave/array/MSparse.cc: In instantiation of ‘MSparse<T> quotient(const MSparse<T>&, const MSparse<T>&) [with T = bool]’:
../liboctave/array/MSparse-b.cc:34:1: required from here
../liboctave/array/MSparse.cc:551:11: error: call of overloaded ‘MSparse(octave_idx_type&, octave_idx_type&, int)’ is ambiguous
551 | r = MSparse<T> (a_nr, a_nc, (Zero / Zero));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../liboctave/array/MSparse-b.cc:30:
../liboctave/array/MSparse.h:75:3: note: candidate: ‘MSparse<T>::MSparse(octave_idx_type, octave_idx_type, octave_idx_type) [with T = bool; octave_idx_type = long int]’
75 | MSparse (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz)
| ^~~~~~~
../liboctave/array/MSparse.h:70:12: note: candidate: ‘MSparse<T>::MSparse(octave_idx_type, octave_idx_type, T) [with T = bool; octave_idx_type = long int]’
70 | explicit MSparse (octave_idx_type r, octave_idx_type c, T val)
| ^~~~~~~
In file included from ../liboctave/array/MSparse.h:129,
from ../liboctave/array/MSparse-b.cc:30:
../liboctave/array/MSparse.cc: In instantiation of ‘MSparse<T> product(const MSparse<T>&, const MSparse<T>&) [with T = bool]’:
../liboctave/array/MSparse-b.cc:34:1: required from here
../liboctave/array/MSparse.cc:405:39: warning: ‘*’ in boolean context, suggest ‘&&’ instead [-Wint-in-bool-context]
405 | r.data (i) = a.data (0) * r.data (i);
| ~~~~~~~~~~~^~~~~~~~~~~~
../liboctave/array/MSparse.cc:422:39: warning: ‘*’ in boolean context, suggest ‘&&’ instead [-Wint-in-bool-context]
422 | r.data (i) = r.data (i) * b.data (0);
| ~~~~~~~~~~~^~~~~~~~~~~~
../liboctave/array/MSparse.cc:461:49: warning: ‘*’ in boolean context, suggest ‘&&’ instead [-Wint-in-bool-context]
461 | r.data (jx) = a.data (ja) * b.data (jb);
| ~~~~~~~~~~~~^~~~~~~~~~~~~
config.status: executing build-aux/subst-config-vals.sh commands
make[2]: *** [Makefile:22148: liboctave/array/libarray_la-MSparse-b.lo] Error 1
That makes the reason for the vtable
error clearer.
The question still remains: Where do we implicitly instantiate MSparse<bool>
?
Edit:
Possible candidate for an implicit instantiation could be this template in MatrixType.h
:
template <typename T>
OCTAVE_API
MatrixType (const MSparse<T> &a);
There is no specialization for SparseBoolMatrix
afaics.
Does that mean that this template is used with T is bool
for something like this command in Octave?
matrix_type(logical(speye(3)))