OpenPIV / openpiv-c--qt

C++ with Qt frontend (superfast) version of OpenPIV
http://www.openpiv.net
GNU General Public License v3.0
20 stars 17 forks source link

export symbols to enable msvc build #45

Open timdewhirst opened 3 months ago

ErichZimmer commented 3 months ago

One method for exporting symbols on the Meson MSVC build is to compile a static library, export all symbols from that static library, then compile the dll using the .def file and the object files from the static library (or recompile the object files, I forgot which one). This method apparently works enough that some use it at their workplace and has the added benefit of not requiring __declspec(dllexport).

ErichZimmer commented 3 months ago

Exporting of symbols is done through dumpbin /exports or dumpbin /linkermember.

ErichZimmer commented 3 months ago

I put __declspec(dllexport) on c++ classes with source files and it seems that Meson is able to produce .lib files on its own. However, I get a link error like such:

FAILED: tests/grid_test.exe "link" /MACHINE:x64 /OUT:tests/grid_test.exe tests/grid_test.exe.p/grid_test.cpp.obj "/nologo" "/release" "/nologo" "/OPT:REF" "openpiv\openpiv.lib" "subprojects\tiff-4.4.0\libtiff\tiff4.lib" "subprojects\Catch2-3.4.0\src/catch2\libCatch2.a" "subprojects\Catch2-3.4.0\src/catch2\libCatch2Main.a" "/SUBSYSTEM:CONSOLE" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "comdlg32.lib" "advapi32.lib" Creating library tests\grid_test.lib and object tests\grid_test.exp grid_test.cpp.obj : error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits > & cdecl openpiv::core::operator<<(class std::basic_ostream<char,struct std::char_traits > &,class openpiv::core::rect const &)" (??6core@openpiv@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AEAV23@AEBVrect@01@@Z) referenced in function "public: struct Catch::MessageBuilder && cdecl Catch::MessageBuilder::operator<<<class std::vector<class openpiv::core::rect,class std::allocator > >(class std::vector<class openpiv::core::rect,class std::allocator > const &)&& " (??$?6V?$vector@Vrect@core@openpiv@@V?$allocator@Vrect@core@openpiv@@@std@@@std@@@MessageBuilder@Catch@@QEHAA$$QEAU01@AEBV?$vector@Vrect@core@openpiv@@V?$allocator@Vrect@core@openpiv@@@std@@@std@@@Z) tests\grid_test.exe : fatal error LNK1120: 1 unresolved externals

timdewhirst commented 3 months ago

From memory there are two parts to this problem:

  1. mark up functions and classes with declspec(dllexport) and declspec(dllimport) - this is usually achieved by wrapping in some macros to ensure we export when building the DLL, and import otherwise
  2. tell the build system that you need to produce both a .lib and .dll

Of course the alternative is just to build a fully static library... there's not much downside to this as the core functionality is pretty small, and in fact it should give a small performance improvement.

ErichZimmer commented 3 months ago

Static compilation has the following error

../tests/image_algos_test.cpp(30): FAILED: REQUIRE( save_to_file( "fft-input.pgm", im ) ) due to unexpected exception with message: failed to find image writer

This error also occurs for the tif image loader.

../tests/image_algos_test.cpp(132): FAILED: due to unexpected exception with message: failed to find loader for corr_a.tiff

Additionally, the link error on the dll when compiling dynamically seems to be caused by https://github.com/OpenPIV/openpiv-c--qt/blob/8bdf76ee10cf8298dd7f366a79aa079af94e0040/openpiv/core/rect.h#L77 The issue could be caused by the overload not being exported since it is not part of a class member.

ErichZimmer commented 3 months ago

Exporting operator << overloads fixes the problem! Compiles sucessfully with MS Visual Studio 2019 and 2022.

ErichZimmer commented 3 months ago

I encountered an unexpected side effect of using Meson's dl export functionality. Although all executables compile and link properly, the executables are exporting symbols as such:

dumpbin /exports image_test.exe
Microsoft (R) COFF/PE Dumper Version 14.34.31937.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file image_test.exe

File Type: EXECUTABLE IMAGE

Section contains the following exports for image_test.exe

00000000 characteristics
FFFFFFFF time date stamp
    0.00 version
       1 ordinal base
      39 number of functions
      39 number of names

ordinal hint RVA      name

      1    0 000038D0 ??0image_loader@core@openpiv@@QEAA@AEBV012@@Z
      2    1 000038D0 ??0image_loader@core@openpiv@@QEAA@XZ
      3    2 00003980 ??0rect@core@openpiv@@QEAA@$$QEAV012@@Z
      4    3 00003980 ??0rect@core@openpiv@@QEAA@AEBV012@@Z
      5    4 000039A0 ??0rect@core@openpiv@@QEAA@XZ
      6    5 000039F0 ??0size@core@openpiv@@QEAA@$$QEAV012@@Z
      7    6 000039F0 ??0size@core@openpiv@@QEAA@AEBV012@@Z
      8    7 00003A00 ??0size@core@openpiv@@QEAA@II@Z
      9    8 00003A10 ??0size@core@openpiv@@QEAA@XZ
     10    9 00004220 ??1image_loader@core@openpiv@@UEAA@XZ
     11    A 00004370 ??4image_loader@core@openpiv@@QEAAAEAV012@AEBV012@@Z
     12    B 00004370 ??4image_loader_registry@core@openpiv@@QEAAAEAV012@$$QEAV012@@Z
     13    C 00004370 ??4image_loader_registry@core@openpiv@@QEAAAEAV012@AEBV012@@Z
     14    D 00004380 ??4rect@core@openpiv@@QEAAAEAV012@$$QEAV012@@Z
     15    E 00004380 ??4rect@core@openpiv@@QEAAAEAV012@AEBV012@@Z
     16    F 000043A0 ??4size@core@openpiv@@QEAAAEAV012@$$QEAV012@@Z
     17   10 000043A0 ??4size@core@openpiv@@QEAAAEAV012@AEBV012@@Z
     18   11 000043B0 ??8size@core@openpiv@@QEBA_NAEBV012@@Z
     19   12 000043C0 ??9size@core@openpiv@@QEBA_NAEBV012@@Z
     20   13 0005EB00 ??_7image_loader@core@openpiv@@6B@
     21   14 00009B60 ?area@rect@core@openpiv@@QEBAIXZ
     22   15 00009B70 ?area@size@core@openpiv@@QEBAIXZ
     23   16 00009CF0 ?bottom@rect@core@openpiv@@QEBAHXZ
     24   17 00009D00 ?components@size@core@openpiv@@QEBA?AV?$array@I$01@std@@XZ
     25   18 00009E40 ?height@rect@core@openpiv@@QEBAIXZ
     26   19 00009CF0 ?height@size@core@openpiv@@QEBAIXZ
     27   1A 00009E50 ?height_@size@core@openpiv@@AEAAAEAIXZ
     28   1B 00009E50 ?height_@size@core@openpiv@@AEBAAEBIXZ
     29   1C 00009EB0 ?left@rect@core@openpiv@@QEBAHXZ
     30   1D 00009FA0 ?load@image_loader@core@openpiv@@UEAA_NAEAV?$basic_istream@DU?$char_traits@D@std@@@std@@AEAV?$image@U?$g@G@core@openpiv@@@23@@Z
     31   1E 00009FF0 ?load@image_loader@core@openpiv@@UEAA_NAEAV?$basic_istream@DU?$char_traits@D@std@@@std@@AEAV?$image@U?$g@N@core@openpiv@@@23@@Z
     32   1F 0000A040 ?load@image_loader@core@openpiv@@UEAA_NAEAV?$basic_istream@DU?$char_traits@D@std@@@std@@AEAV?$image@U?$rgba@G@core@openpiv@@@23@@Z
     33   20 0000A670 ?right@rect@core@openpiv@@QEBAHXZ
     34   21 0000AB60 ?size@rect@core@openpiv@@QEBAAEBV023@XZ
     35   22 0000BDB0 ?top@rect@core@openpiv@@QEBAHXZ
     36   23 0000C180 ?width@rect@core@openpiv@@QEBAIXZ
     37   24 00009EB0 ?width@size@core@openpiv@@QEBAIXZ
     38   25 00004370 ?width_@size@core@openpiv@@AEAAAEAIXZ
     39   26 00004370 ?width_@size@core@openpiv@@AEBAAEBIXZ

  Summary

    5000 .data
    5000 .pdata
   1B000 .rdata
    1000 .reloc
   5D000 .text

This could be eliminated using .def files with all symbols to create the dynamic library instead of dll exports, however the import lib would be much more messier due to lots of symbols being exported through libopenpivcore (very similar to CMake's WINDOWS_EXPORT_ALL_SYMBOLS).

Here is the executable symbol table using CMake's WINDOWS_EXPORT_ALL_SYMBOLS

  dumpbin /exports image_test.exe
  Microsoft (R) COFF/PE Dumper Version 14.34.31937.0
  Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file image_test.exe

File Type: EXECUTABLE IMAGE

  Summary

    4000 .data
    5000 .pdata
   19000 .rdata
    1000 .reloc
    1000 .rsrc
   5A000 .text
ErichZimmer commented 3 months ago

Issue is now fixed with preprocessor directives.

ErichZimmer commented 3 months ago

Here is an interesting performance test. I wonder why GCC is so much faster (especially because I did not set any simd or mtune flags)?

Performance of MSVC (Visual Studio 2022) compared to GCC 10 in release build (average of 10 runs) Compiler Time / IW in microseconds)
msvc 10.22
gcc 6.79
ErichZimmer commented 3 months ago

It seems that I broke the Linux build again (-_-) See here for the segmentation violation fault. Other than that, Windows using Visual Studio (I'll have to update the CI to use Visual Studio instead of GCC) and Mac OS build tests pass.

ErichZimmer commented 2 months ago

Linking pull request for this feature (#46)