0

I am including SDL and SDL_image as project dependencies via git submodules. SDL_image contains multiple external dependencies itself, including the problematic jpeg library. The overall project structure looks like this:

│   CMakeLists.txt
├───build
├───src
└───external
    ├───SDL (git submodule)
    └───SDL_image (git submodule)
        │   CMakeLists.txt
        └───external
            ├───jpeg-9d
            ├───libpng-1.6.37
            ├───libwebp-1.0.3
            ├───tiff-4.2.0
            └───zlib-1.2.11

I am using the following top level CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(GameTemplate    VERSION 1.0.0
                        LANGUAGES CXX)

# define common SOURCES variable as all files within src
file(GLOB_RECURSE SOURCES src/*)

# add main executable (entry point + SOURCES)
# in windows, WIN32 property adds /SUBSYSTEM:WINDOWS compiler flag 
# required for GUI applications
add_executable(${PROJECT_NAME} WIN32 ${SOURCES})

# SDL (shared only)
# NOTE: setting SDL_STATIC to ON has no effect on jpeg output,
# it just prevents building the SDLstatic target unnecessarily
set(SDL_STATIC OFF CACHE BOOL "build SDL static lib" FORCE)
add_subdirectory(external/SDL EXCLUDE_FROM_ALL)
add_subdirectory(external/SDL_image EXCLUDE_FROM_ALL)

# includes
target_include_directories(GameTemplate
    PRIVATE external/SDL/include
    PRIVATE external/SDL_image
    PRIVATE src)

# linker
target_link_libraries(GameTemplate
    PRIVATE SDL2main
    PRIVATE SDL2
    PRIVATE SDL2_image)

The following build steps are successful on macOS:

$ cd build
$ cmake ..
$ make

The equivalent MSVC build steps fail with the error below while attempting to build the SDL_image target

$ cd build
$ cmake ..
$ MSBuild.exe .\GameTemplate.sln
...
Link:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30037\bin\HostX64\x64\link.exe /ERRORREPOR
  T:QUEUE /OUT:"C:\Users\colev\workspace\game-template\build\external\SDL_image\Debug\SDL2_image.dll" /INCREMENTAL /ILK:"SDL2_i
  mage.dir\Debug\SDL2_image.ilk" /NOLOGO "external\jpeg-9d\Debug\jpeg.lib" "external\libpng-1.6.37\Debug\libpng16d.lib" ..\SDL\
  Debug\SDL2d.lib "external\zlib-1.2.11\Debug\zlibd.lib" kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib o
  leaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /D
  EBUG /PDB:"C:/Users/colev/workspace/game-template/build/external/SDL_image/Debug/SDL2_image.pdb" /SUBSYSTEM:CONSOLE /TLBID:1
  /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:/Users/colev/workspace/game-template/build/external/SDL_image/Debug/SDL2_image.lib" /MACHIN
  E:X64  /machine:x64 /DLL SDL2_image.dir\Debug\IMG.obj
  SDL2_image.dir\Debug\IMG_png.obj
  SDL2_image.dir\Debug\IMG_bmp.obj
  SDL2_image.dir\Debug\IMG_gif.obj
  SDL2_image.dir\Debug\IMG_jpg.obj
  SDL2_image.dir\Debug\IMG_lbm.obj
  SDL2_image.dir\Debug\IMG_pcx.obj
  SDL2_image.dir\Debug\IMG_pnm.obj
  SDL2_image.dir\Debug\IMG_svg.obj
  SDL2_image.dir\Debug\IMG_tga.obj
  SDL2_image.dir\Debug\IMG_tif.obj
  SDL2_image.dir\Debug\IMG_webp.obj
  SDL2_image.dir\Debug\IMG_WIC.obj
  SDL2_image.dir\Debug\IMG_xcf.obj
  SDL2_image.dir\Debug\IMG_xpm.obj
  SDL2_image.dir\Debug\IMG_xv.obj
  SDL2_image.dir\Debug\IMG_xxx.obj
LINK : fatal error LNK1104: cannot open file 'external\jpeg-9d\Debug\jpeg.lib' [C:\Users\me\workspace\game-template\build\ex
ternal\SDL_image\SDL2_image.vcxproj]

Sure enough, that file is not there in build\external\SDL_image\external\jpeg-9d\Debug, only the .dll. The .lib is there for all the other SDL_image external deps though...

$ ls build\external\SDL_image\external\jpeg-9d\Debug\
-a----          7/2/2021   2:19 PM         513024 jpeg.dll
-a----          7/2/2021   2:19 PM        1232896 jpeg.pdb

$ ls build\external\SDL_image\external\libpng-1.6.37\Debug\
-a----          7/2/2021   2:19 PM         423424 libpng16d.dll
-a----          7/2/2021   2:19 PM          33612 libpng16d.exp
-a----          7/2/2021   2:19 PM          56196 libpng16d.lib
-a----          7/2/2021   2:19 PM        1200128 libpng16d.pdb

If I cd into external\SDL_image\external\jpeg-9d\ and build jpeg by itself it does generate a .lib file, but my understanding of windows is that .lib can be either a static link libary OR an export library for a corresponding .dll. I assume when building jpeg by itself I am building the static link library, and the .lib that my main build actually needs is the export library.

If this is the case, why doesn't jpeg also build the export lib when built with BUILD_SHARED_LIBS? Isn't building a dll kind of useless with no export lib?

EDIT: I just found this answer indicating .lib files are not produced if a library does not export any symbols. I think that is unlikely since jpeg is a popular library, but is there a way I can check to be sure? https://stackoverflow.com/a/7615698/1800023

EDIT2: I found DUMPBIN and confirmed that there are no files exported by jpeg.dll... How could that be?

EDIT3: Disabling JPG results in building SDL2_image.dll but it also exports no symbols (causing link failure in main project build).

thedarklord47
  • 3,183
  • 3
  • 26
  • 55
  • "I found DUMPBIN and confirmed that there are no files exported by jpeg.dll... How could that be?" - It depends what sources for SDL_image you are using and whether its `external/jpeg-9d` subfolder supports building with CMake (instead of autotools, which don't work on Windows). – Tsyvarev Jul 03 '21 at 07:02
  • `external/jpeg-9d` does contain a CMakeLists.txt which adds the library. I can build it by itself but it still doesn’t export anything – thedarklord47 Jul 03 '21 at 15:26
  • I did find that disabling JPG results in an SDL2_image.dll with the same problem (no exports). – thedarklord47 Jul 03 '21 at 15:28
  • Are you sure that you have SDL_image sources which are actually suitable for building under Windows (without MinGW)? Where have you obtained that sources? – Tsyvarev Jul 03 '21 at 15:30
  • I didn't realize that there were separate sources. I am using https://github.com/libsdl-org/SDL_image – thedarklord47 Jul 04 '21 at 00:07
  • I don't think that these sources correctly support building on Windows with dllexport. Yes, their header [SDL_image.h](https://github.com/libsdl-org/SDL_image/blob/main/SDL_image.h) uses `DECLSPEC` macro when declare the functions. But definitions of this macro they take from the header [begin_code.h](https://github.com/libsdl-org/SDL/blob/main/include/begin_code.h) which is created for SDL, not for SDL_image. From my understanding, two dependent libraries shouldn't share a macro expanded into `dllexport`, otherwise building SDL_image pretend to build SDL too, which is wrong. – Tsyvarev Jul 04 '21 at 08:29
  • Not sure I follow the pretending to build bit. Why couldn’t it be built solo assuming you have access to SDL lib and includes? – thedarklord47 Jul 04 '21 at 15:15
  • @Tsyvarev do you mind elaborating on that last part regarding sharing a `dllexport` macro? – thedarklord47 Jul 06 '21 at 21:28
  • I am not sure whether my understanding is correct, but still... When SDL library is built, then `DECLSPEC` is expected to be expanded into `__declspec(dllexport)`. That way the linker understands that functions marked with given macro are exported by the library itself and should not be searched elsewhere. In case of `SDL_image` the things are similar: `DECLSPEC` should be non-empty when build `SDL_image` library. But `SDL_image.h` **includes** `SDL.h`. So linker would assume that `SDL_image` defines not only functions in `SDL_image.h` but also functions in `SDL.h`, which is not true. – Tsyvarev Jul 06 '21 at 21:52

0 Answers0