wdas / ptex

Per-Face Texture Mapping for Production Rendering https://wdas.github.io/ptex

Home Page:https://www.disneyanimation.com/open-source/ptex/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Linking issues on Windows

KelSolaar opened this issue · comments

Hello,

I'm trying to build OpenImageIO with Ptex support and I'm having linking issues:

ptexinput.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl Ptex::v2_3::String::~String(void)" (__imp_??1String@v2_3@Ptex@@QEAA@XZ) referenced in function "public: virtual bool __cdecl OpenImageIO_v2_2::PtexInput::open(class std::basic_string<char,struct std::char_traits<char>
,class std::allocator<char> > const &,class OpenImageIO_v2_2::ImageSpec &)" (?open@PtexInput@OpenImageIO_v2_2@@UEAA_NAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAVImageSpec@2@@Z) [...\openimageio\build\platform-windows\arch-AMD64\msvc-19.1\python-3.7\qt-5.15.
2.rf1\oiio\src\libOpenImageIO\OpenImageIO.vcxproj]

ptexinput.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static class Ptex::v2_3::PtexTexture * __cdecl Ptex::v2_3::PtexTexture::open(char const *,class Ptex::v2_3::String &,bool)" (__imp_?open@PtexTexture@v2_3@Ptex@@SAPEAV123@PEBDAEAVString@23@_N@Z) referenced in function "public:
 virtual bool __cdecl OpenImageIO_v2_2::PtexInput::open(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class OpenImageIO_v2_2::ImageSpec &)" (?open@PtexInput@OpenImageIO_v2_2@@UEAA_NAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAVImageSpec@2@@Z
) [...\openimageio\build\platform-windows\arch-AMD64\msvc-19.1\python-3.7\qt-5.15.2.rf1\oiio\src\libOpenImageIO\OpenImageIO.vcxproj]
...\openimageio\build\platform-windows\arch-AMD64\msvc-19.1\python-3.7\qt-5.15.2.rf1\oiio\bin\Release\OpenImageIO.dll : fatal error LNK1120: 2 unresolved externals [...\openimageio\build\platform-windows\arch-AMD64\msvc-19.1\python-3.7\qt-5.15.2.rf1\
oiio\src\libOpenImageIO\OpenImageIO.vcxproj]

I looked at the exported symbols in my built Ptex.dll and there are small differences between what OpenImagIO is looking for and what is being exported:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC>dumpbin /exports H:\Documents\Development\ThirdParty\Ptex\build\platform-windows\arch-AMD64\msvc-19.1\release\lib\Ptex.dll
Microsoft (R) COFF/PE Dumper Version 14.00.24245.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file H:\Documents\Development\ThirdParty\Ptex\build\platform-windows\arch-AMD64\msvc-19.1\release\lib\Ptex.dll

File Type: DLL

  Section contains the following exports for Ptex.dll

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

    ordinal hint RVA      name

          1    0 0001E030 ??1String@v2_3@Ptex@@QEAA@XZ
          2    1 0001E040 ??4String@v2_3@Ptex@@QEAAAEAV012@PEBD@Z
          3    2 0001E640 ?BorderModeName@v2_3@Ptex@@YAPEBDW4BorderMode@12@@Z
          4    3 0001E660 ?ConvertFromFloat@v2_3@Ptex@@YAXPEAXPEBMW4DataType@12@H@Z
          5    4 0001E960 ?ConvertToFloat@v2_3@Ptex@@YAXPEAMPEBXW4DataType@12@H@Z
          6    5 0001EAD0 ?DataTypeName@v2_3@Ptex@@YAPEBDW4DataType@12@@Z
          7    6 0001EAF0 ?EdgeFilterModeName@v2_3@Ptex@@YAPEBDW4EdgeFilterMode@12@@Z
          8    7 0001EB10 ?EdgeIdName@v2_3@Ptex@@YAPEBDW4EdgeId@12@@Z
          9    8 0001EB30 ?MeshTypeName@v2_3@Ptex@@YAPEBDW4MeshType@12@@Z
         10    9 0001EB50 ?MetaDataTypeName@v2_3@Ptex@@YAPEBDW4MetaDataType@12@@Z
         11    A 00024B20 ?applyEdits@PtexWriter@v2_3@Ptex@@SA_NPEBDAEAVString@23@@Z
         12    B 00001FC0 ?create@PtexCache@v2_3@Ptex@@SAPEAV123@H_K_NPEAVPtexInputHandler@23@PEAVPtexErrorHandler@23@@Z
         13    C 00025180 ?edit@PtexWriter@v2_3@Ptex@@SAPEAV123@PEBD_NW4MeshType@23@W4DataType@23@HHHAEAVString@23@1@Z
         14    D 00077000 ?f2hTable@PtexHalf@v2_3@Ptex@@2PAGA
         15    E 00004C80 ?fromFloat_except@PtexHalf@v2_3@Ptex@@CAGI@Z
         16    F 00004920 ?getFilter@PtexFilter@v2_3@Ptex@@SAPEAV123@PEAVPtexTexture@23@AEBUOptions@123@@Z
         17   10 00037000 ?h2fTable@PtexHalf@v2_3@Ptex@@2PAIA
         18   11 0000AE80 ?open@PtexTexture@v2_3@Ptex@@SAPEAV123@PEBDAEAVString@23@_N@Z
         19   12 00026CE0 ?open@PtexWriter@v2_3@Ptex@@SAPEAV123@PEBDW4MeshType@23@W4DataType@23@HHHAEAVString@23@_N@Z

  Summary

       46000 .data
        3000 .pdata
        B000 .rdata
        1000 .reloc
        1000 .rsrc
       2B000 .text
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC>undname ??1String@v2_3@Ptex@@QEAA@XZ
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "??1String@v2_3@Ptex@@QEAA@XZ"
is :- "public: __cdecl Ptex::v2_3::String::~String(void) __ptr64"
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC>undname ?open@PtexTexture@v2_3@Ptex@@SAPEAV123@PEBDAEAVString@23@_N@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?open@PtexTexture@v2_3@Ptex@@SAPEAV123@PEBDAEAVString@23@_N@Z"
is :- "public: static class Ptex::v2_3::PtexTexture * __ptr64 __cdecl Ptex::v2_3::PtexTexture::open(char const * __ptr64,class Ptex::v2_3::String & __ptr64,bool)"
  • OIIO: public: __cdecl Ptex::v2_3::String::~String(void)
  • Ptex: public: __cdecl Ptex::v2_3::String::~String(void) __ptr64
  • OIIO: public: static class Ptex::v2_3::PtexTexture * __cdecl Ptex::v2_3::PtexTexture::open(char const *,class Ptex::v2_3::String &,bool)
  • Ptex: public: static class Ptex::v2_3::PtexTexture * __ptr64 __cdecl Ptex::v2_3::PtexTexture::open(char const * __ptr64,class Ptex::v2_3::String & __ptr64,bool)

As far as I can tell, the only difference is __ptr64, I'm building everything for x64 and I'm unclear if it is an OIIO issue at this point or Ptex. Paging @lgritz just in case he has an idea!

Cheers,

Thomas

I'm in critical danger of stepping beyond my windows knowledge, but there are a few common gotchas that I would double check first:

  • That you're not accidentally picking up a set of ptex .h files that don't exactly correspond to the ptex libraries you have? (Sometimes weird things happen if you inadvertently have two different Ptex versions installed.)
  • One library is release, the other is debug? (I think MSVS actually changes ABI slightly between debug and release builds)
  • Mismatch in some other MSVS compiler flags that are required to be the same across all compilation units? (That __ptr64 that's found but not expected is very suspicious.)

Hi Larry/@lgritz,

Thanks for replying!

  • I have only a single Ptex library that I built the same way I build OIIO and all the VFX Reference Platform on Windows.
  • The cmake configuration always use this generator and toolset: -G "Visual Studio 15 2017 Win64" -T v141,host=x64 (I have a variant for Visual Studio 14 2015 Win64 but it is not used for OIIO) and it is build as follows: cmake --build . --config Release --target INSTALL
  • For what its worth, I'm linking OIIO against OpenEXR and Imath just fine and the symbols have the __ptr64 type:
undname ?rgb2hsv_d@Imath_2_5@@YA?AV?$Vec3@N@1@AEBV21@@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?rgb2hsv_d@Imath_2_5@@YA?AV?$Vec3@N@1@AEBV21@@Z"
is :- "class Imath_2_5::Vec3<double> __cdecl Imath_2_5::rgb2hsv_d(class Imath_2_5::Vec3<double> const & __ptr64)"

I too am having this issue, I was curious if you ended up finding anything. My only guess was that OIIO was somehow looking for static ptex even during shared lib linking because of the __declspec(dllimport) prefix in the error and the following snippet in the Ptexture.h file

#if defined(_WIN32) || defined(_WINDOWS) || defined(_MSC_VER)
# ifndef PTEXAPI
#  ifndef PTEX_STATIC
#    ifdef PTEX_EXPORTS
#       define PTEXAPI __declspec(dllexport)
#    else
#       define PTEXAPI __declspec(dllimport)
#    endif
#  else
#    define PTEXAPI
#  endif
# endif
#else
#  ifndef PTEXAPI
#    define PTEXAPI
#  endif
#  ifndef DOXYGEN
#    define PTEX_USE_STDSTRING
#  endif
#endif

But I could not find anything in my OIIO vcxprojs or cmake files to suggest that OIIO is looking for static so I am scratching my head on this as well.

EDIT:
Turns out USD solved this themselves (from their build_usd.py file)

        # Ptex has a bug where the import library for the dynamic library and
        # the static library both get the same name, Ptex.lib, and as a
        # result one clobbers the other. We hack the appropriate CMake
        # file to prevent that. Since we don't need the static library we'll
        # rename that.
        #
        # In addition src\tests\CMakeLists.txt adds -DPTEX_STATIC to the 
        # compiler but links tests against the dynamic library, causing the 
        # links to fail. We patch the file to not add the -DPTEX_STATIC
        PatchFile('src\\ptex\\CMakeLists.txt', 
                  [("set_target_properties(Ptex_static PROPERTIES OUTPUT_NAME Ptex)",
                    "set_target_properties(Ptex_static PROPERTIES OUTPUT_NAME Ptexs)")])
        PatchFile('src\\tests\\CMakeLists.txt',
                  [("add_definitions(-DPTEX_STATIC)", 
                    "# add_definitions(-DPTEX_STATIC)")])

Updating those files fixed it for me

Oh, nice find! We don't actually use the static libs much, and Windows even less, so this is a blind spot for us on Linux where we have libPtex.so and libPtex.a that don't conflict.

We should probably add some notes to the README about the PTEX_BUILD_STATIC_LIBS and PTEX_BUILD_SHARED_LIBS controls that the build system supports. They both default to ON, so disabling one and enabling another explicitly should be a way to fix the build without any build tweaks on Windows.

I'll leave this issue open since we should probably change this so that the static lib are output as libPtex-static.a (aka Ptex-static.lib). That should resolve this issue if I'm understanding this correctly. Does that sound about right?

Heads-up @sunyab ~ hopefully that'll simplify build_usd.py too.

The DLLImport thing is sort of a red herring, it's only there to generate headers for things that link to the DLL and need to know about the class interfaces so the export decls get put on the functions during the build and the headers are generated with the import symbols.

Normally you build the shared and static libs by setting two targets in CMake with different names (not output names), one with static and one with shared linkage... it'll naturally put them in different output directories and use the add_library name as the base name. This is cleaner because it makes CMake auto-sort things into the right places vs trying to find where you buried the output name definition and it allows importing from the project using the shared or static name and having everything else automagically work.

See this -- it's supposed to be controlled with the output directory variables, then whatever wants to link to it uses that structure if it's not integrating with the project CMakeFiles or selects shared vs. static linkage using the variables cmake creates in its caches (see this).