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

export symbols to enable msvc build #45

Open
timdewhirst opened this issue Mar 24, 2024 · 11 comments
Open

export symbols to enable msvc build #45

timdewhirst opened this issue Mar 24, 2024 · 11 comments
Assignees

Comments

@timdewhirst
Copy link
Member

No description provided.

@ErichZimmer
Copy link
Contributor

ErichZimmer commented Mar 24, 2024

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
Copy link
Contributor

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

@ErichZimmer
Copy link
Contributor

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
Copy link
Member Author

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
Copy link
Contributor

ErichZimmer commented Mar 26, 2024

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

std::ostream& operator<<( std::ostream& os, const rect& r );

The issue could be caused by the overload not being exported since it is not part of a class member.

@ErichZimmer
Copy link
Contributor

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

@ErichZimmer
Copy link
Contributor

ErichZimmer commented Mar 27, 2024

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
Copy link
Contributor

Issue is now fixed with preprocessor directives.

@ErichZimmer
Copy link
Contributor

ErichZimmer commented Mar 28, 2024

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
Copy link
Contributor

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
Copy link
Contributor

Linking pull request for this feature (#46)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants