slice2cpp and LNK1189 with Ice 3.6.2 and VS2013 or 2015

rleighrleigh Member Roger LeighOrganization: University of DundeeProject: OMERO (Open Microscopy Environment)
[461/718] Linking CXX shared library components\tools\OmeroCpp\omero-ice.dll
FAILED: cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_dll --intdir=components\tools\OmeroCpp\CMakeFiles\omero-ice.dir --manifests  -- C:\PROGRA~2\MI0E91~1.0\VC\bin\amd64\link.exe /nologo @CMakeFiles/omero-ice.rsp  /out:components\tools\OmeroCpp\omero-ice.dll /implib:components\tools\OmeroCpp\omero-ice.lib /pdb:components\tools\OmeroCpp\omero-ice.pdb /dll /version:5.3 /machine:x64 /debug /INCREMENTAL /INCREMENTAL:NO   && cd ."
LINK : fatal error LNK1189: library limit of 65535 objects exceeded
LINK Pass 1 failed. with 1189
ninja: build stopped: subcommand failed

We had this problem with the upgrade to Ice 3.5, and are now hitting it again with Ice 3.6. The code generated by slice2cpp contains more symbols in the new release, and this breaks creation of the DLL. For Ice 3.5, we were able to split the library into two separate libraries after careful dependency analysis, but this might not be possible to repeat a second time

While it's not a bug, it's definitely a problem! I was wondering if there was any way to reduce the symbol count in the compiled code, either through slice2cpp options or compiler defines when building. For example, is there any "legacy" functionality which we could opt out of using in order to squeeze the slice2cpp-generated code into these symbol count limits?

Thanks,
Roger

Tagged:

Best Answer

  • bernardbernard Jupiter, FLBernard NormierOrganization: ZeroC, Inc.Project: Ice ZeroC Staff
    Accepted Answer

    Hi Roger,

    Were you able to find a work-around and link successfully omero-ice.dll with Ice 3.6?

    In Ice 3.5 and earlier releases, the generated code was selectively dll-exporting proxy member functions instead of the whole proxy classes. See for example:
    https://github.com/zeroc-ice/ice/blob/3.5/cpp/src/slice2cpp/Gen.cpp#L2166

    This worked because our dll-exporting didn't support the GCC and clang symbol-visibility options.

    Then, in Ice 3.6, we added support for these GCC and clang symbol-visibility options:
    https://doc.zeroc.com/display/Ice36/New+Features+in+Ice+3.6#NewFeaturesinIce3.6-Supportfor-fvisibility=hiddenwithGCCandclang

    With GCC/clang, you need to export the whole class to export the vtable correctly, so we got rid of this selective member function exporting. We are now exporting the full proxy classes:
    https://github.com/zeroc-ice/ice/blob/3.6/cpp/src/slice2cpp/Gen.cpp#L1695

    We were not aware of this Visual Studio export-symbol-limit, so we didn't worry about it. It's unfortunate you didn't report this issue when you hit it with Ice 3.5.

    Visual Studio is particularly bad when exporting full classes because it exports everything, including inline member functions. And our generated code for proxies provides numerous inline functions!

    With GCC/clang, inline member functions aren't exported, so the "whole proxy class export" doesn't cause as much export-symbol bloat.

    On our master branch, we fixed this problem a couple months ago by reworking our dll macros: the generated code exports full classes with GCC/clang, and selectively export member functions with Visual Studio:
    https://github.com/zeroc-ice/ice/commit/90cddd47c69828336cffa343754e8688099bcad3

    This fix reduced the size of our DLLs on Windows, and dramatically reduced the number of symbols exported:

    Before After
    ice 4398 3687
    icegrid 2685 1363
    ice++11 3663 2363
    icegrid++11 1609 496

    I also added a test to make sure this selective exporting doesn't break dynamic_cast (and fortunately it doesn't):
    https://github.com/zeroc-ice/ice/tree/master/cpp/test/Ice/library

    If you didn't find a satisfactory work-around, we could look into backporting this fix to 3.6 and include it in Ice 3.6.3. It wouldn't be a trivial backport as 3.6 needs to maintain binary compatibility with prior 3.6 releases.

    Cheers,
    Bernard

Answers

  • benoitbenoit Rennes, FranceAdministrators, ZeroC Staff Benoit FoucherOrganization: ZeroC, Inc.Project: Ice ZeroC Staff

    Hi Roger,

    I'm afraid there's currently no easy way to reduce the generated code. My understanding is that this limit applies to the library for export symbols. Can you perhaps reduce the number of exported symbols to not hit this limit?

    Cheers,
    Benoit.

  • bernardbernard Jupiter, FLAdministrators, ZeroC Staff Bernard NormierOrganization: ZeroC, Inc.Project: Ice ZeroC Staff
    Accepted Answer

    Hi Roger,

    Were you able to find a work-around and link successfully omero-ice.dll with Ice 3.6?

    In Ice 3.5 and earlier releases, the generated code was selectively dll-exporting proxy member functions instead of the whole proxy classes. See for example:
    https://github.com/zeroc-ice/ice/blob/3.5/cpp/src/slice2cpp/Gen.cpp#L2166

    This worked because our dll-exporting didn't support the GCC and clang symbol-visibility options.

    Then, in Ice 3.6, we added support for these GCC and clang symbol-visibility options:
    https://doc.zeroc.com/display/Ice36/New+Features+in+Ice+3.6#NewFeaturesinIce3.6-Supportfor-fvisibility=hiddenwithGCCandclang

    With GCC/clang, you need to export the whole class to export the vtable correctly, so we got rid of this selective member function exporting. We are now exporting the full proxy classes:
    https://github.com/zeroc-ice/ice/blob/3.6/cpp/src/slice2cpp/Gen.cpp#L1695

    We were not aware of this Visual Studio export-symbol-limit, so we didn't worry about it. It's unfortunate you didn't report this issue when you hit it with Ice 3.5.

    Visual Studio is particularly bad when exporting full classes because it exports everything, including inline member functions. And our generated code for proxies provides numerous inline functions!

    With GCC/clang, inline member functions aren't exported, so the "whole proxy class export" doesn't cause as much export-symbol bloat.

    On our master branch, we fixed this problem a couple months ago by reworking our dll macros: the generated code exports full classes with GCC/clang, and selectively export member functions with Visual Studio:
    https://github.com/zeroc-ice/ice/commit/90cddd47c69828336cffa343754e8688099bcad3

    This fix reduced the size of our DLLs on Windows, and dramatically reduced the number of symbols exported:

    Before After
    ice 4398 3687
    icegrid 2685 1363
    ice++11 3663 2363
    icegrid++11 1609 496

    I also added a test to make sure this selective exporting doesn't break dynamic_cast (and fortunately it doesn't):
    https://github.com/zeroc-ice/ice/tree/master/cpp/test/Ice/library

    If you didn't find a satisfactory work-around, we could look into backporting this fix to 3.6 and include it in Ice 3.6.3. It wouldn't be a trivial backport as 3.6 needs to maintain binary compatibility with prior 3.6 releases.

    Cheers,
    Bernard

  • rleighrleigh Member Roger LeighOrganization: University of DundeeProject: OMERO (Open Microscopy Environment)

    Dear Bernard,

    Thanks for the followup; it's great to see how things will be improved for Ice 3.7.

    We didn't report this for Ice 3.5 because at the time we felt this was a problem on our side--the sheer number of Ice slice interfaces and implementations was pushing the symbol count past the limit, and so splitting into two DLLs seemed like the pragmatic choice at the time.

    Regarding backporting, we will try to build our code against current Ice git and see if that helps, so we will know whether or not that is a viable possibility, or if we will need to do some additional restructuring as well.

    Thanks,
    Roger

Sign In or Register to comment.