0

I'm trying to create a project, that will create an executable MyExec.exe, which will depends on another library Niftilib, which itself depends on zlib.

What I did is that I used cmake and created a superbuild, using ExternalProject_Add to download and compile zlib:

ExternalProject_Add(Zlib
    SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/zlib"
    BINARY_DIR "${PROJECT_BINARY_DIR}/deps/zlib-build"
    INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/zlib-install"
    GIT_REPOSITORY "${git_protocol}://github.com/madler/zlib.git"
    GIT_TAG "50893291621658f355bc5b4d450a8d06a563053d"
    CMAKE_ARGS
        -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
        -DINSTALL_BIN_DIR=<INSTALL_DIR>/bin
        -DINSTALL_INC_DIR=<INSTALL_DIR>/include
        -DINSTALL_LIB_DIR=<INSTALL_DIR>/lib
        -DINSTALL_MAN_DIR=<INSTALL_DIR>/share/man
        -DINSTALL_PKGCONFIG_DIR=<INSTALL_DIR>/share/pkgconfig)

I did the same for Nifticlib:

ExternalProject_Add(Nifticlib
    SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib"
    BINARY_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-build"
    INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-install"
    GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/nifticlib.git"
    GIT_TAG "9f427b39eb6a16822c6ed34454f87eb751b23220"
    CMAKE_ARGS
        -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
        -DZLIB_INCLUDE_DIR=${ZLIB_INC_DIR}
        -DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibd.lib
    DEPENDS Zlib)

Then I did the same for MyExec:

ExternalProject_Add(MyExec
    SOURCE_DIR "${PROJECT_BINARY_DIR}/MyExec"
    BINARY_DIR "${PROJECT_BINARY_DIR}/MyExec-build"
    INSTALL_DIR "${PROJECT_BINARY_DIR}/MyExec-install"
    GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/MyExec.git"
    GIT_TAG "8514aacf5422f1111602e24ea73b229556293b8c"
    CMAKE_ARGS
        -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
        -DBOOST_INC_DIR=${Boost_INCLUDE_DIRS}
        -DBOOST_LIB_DIR=${Boost_LIBRARY_DIRS}
        -DZLIB_INC_DIR=${ZLIB_INC_DIR}
        -DZLIB_LIB_DIR=${ZLIB_LIB_DIR}
        -DNIFTI_INC_DIR=${NIFTI_INC_DIR}
        -DNIFTI_LIB_DIR=${NIFTI_LIB_DIR}
    DEPENDS Nifticlib)

And in my CMakeLists of MyExec project, I have this:

cmake_minimum_required(VERSION 3.6)

project(MyExec)

include_directories(${BOOST_INC_DIR} ${ZLIB_INC_DIR} ${NIFTI_INC_DIR})
link_directories(${BOOST_LIB_DIR} ${ZLIB_LIB_DIR} ${NIFTI_LIB_DIR})

add_subdirectory(DataStructure)
add_subdirectory(FileHandler)
add_subdirectory(Parser)

add_executable(${PROJECT_NAME} MyExec.cc)
target_link_libraries(${PROJECT_NAME} zlibd znz nifticdf niftiio DataStructure FileHandler Parser)

install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)

My goal is to be able to distribute MyExec.exe without having all the required libraries (except boost). I want nifticlib library to be embedded in my exec.

If I compile this way, it doesn't work, because it says that zlibd.dll is missing. I find out that I had to link my executable to zlibstaticd instead of zlibd.

But my question is, should I also change -DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibd.lib to -DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibstaticd.lib in Nifticlib project ?

Or does it only matter in the executable project ? Why does nifticlib require me to provide the path to the zlib library, if it's build as a static library and doesn't do any linking ?

Thank you.

Edit: If I dont link the zlib to my executable, I get these errors:

5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzdopen referenced in function znzdopen
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzread referenced in function znzread
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzwrite referenced in function znzwrite
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzputs referenced in function znzputs
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzgets referenced in function znzgets
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzputc referenced in function znzputc
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzgetc referenced in function znzgetc
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzflush referenced in function znzflush
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzeof referenced in function znzeof
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzclose referenced in function Xznzclose
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzopen referenced in function znzopen
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzseek referenced in function znzseek
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gztell referenced in function znztell

znz is part of nifticlib. It is the part using the zlib library.

Edit 2: To make it simpler, my question is does the linking happen like Linking 1 or Linking 2 (knowing that nifticlib depends on zlib, both compiled as static libraries):

  Linking 1                           Linking 2
--------------           --------------      ---------------
|    zlib    |           |    zlib    |      |  nifticlib  |
--------------           --------------      ---------------
      |                         \                   /
--------------                   \                 /
| nifticlib  |                    \               /
--------------                     \             /
      |                          -------------------
--------------                   |   MyExec.exe    |
| MyExec.exe |                   -------------------
--------------
whiteShadow
  • 369
  • 4
  • 19
  • If I understand correctly, _Niftilib_ depends on _zlib_ and you want to link your application with _Niftilib_. Than, no, it does not matter in exec. project, but it matters in the _Niftilib_ lib. as well. I do not use CMake, however, in VS, when you create a static link, which is dependent on another static link, you can link it (zlib in Niftilib project) via Configuration Properties -> Librarian -> General -> Additional Dependencies. So I think, yes, you should change it and probably skip in exec. project. Hope this helped ;-) – Dom Aug 10 '16 at 23:14
  • I think if I skip it in exec, the MyExec project doesn't compile. It failed at link step, because it cannot find symbols. My question is, if I compile niftilib, which depends on zlib, will zlib symbols be included in niftilib.lib or not ? Do I need to link it to MyExec also ? Thank you. – whiteShadow Aug 11 '16 at 10:43
  • Did you try to skip it in exec? If you do not call zlib functions directly from exec, it should be linked in niftlib only and should not be set in exec, I think so... unfortunately I am not sure... :-/ try it. – Dom Aug 11 '16 at 13:09
  • I tried, but it doesn't work. I got some missing symbols error. – whiteShadow Aug 11 '16 at 19:11
  • Could you post whole error list? – Dom Aug 11 '16 at 20:04
  • I added the errors in the post. – whiteShadow Aug 11 '16 at 20:52
  • Hmm... I've briefly checked the code... Why don't you simply add the sources to your project and compile the sources as they are? Why do you need to build static libraries? It would simplify your intention... – Dom Aug 11 '16 at 21:15
  • zlib and niftilib already exists, I didn't created them. Putting everything in the same project would complicate things in the future as it won't be modular. – whiteShadow Aug 12 '16 at 04:27
  • Why did I get a -1 ??? – whiteShadow Aug 16 '16 at 04:46

1 Answers1

1

The usual way is that linking is only done when an executable binary is generated. This includes for example normal executables, but also dynamic libraries (.dll, .so). Linking is not done for static libraries (.lib, .a).

That means if you build a static library of "nifticlib" it does not need to be linked to "zlib".

You should definitly change the dependency from the dynamic one to the static one, because CMake carries dependencies from static libraries over to the final binary. In this case it should not matter though, because you don't specify a real CMake dependency, just some variable for the library.

Note: In Visual Studio you can pretty easily "link" static libraries into each other. What it does is just concatenation of all functions into one .lib file. CMake does not use this feature though and instead carries dependencies over like mentioned above when doing "TARGET_LINK_LIBRARIES" on a static library target.

typ1232
  • 5,535
  • 6
  • 35
  • 51
  • Ok, thank you. So it's more like Linking 2. It makes sense now. I check nifticlib and why it asked me for zlibd.lib, but I think it's because nifticlib is compiling some unit tests (executables), so it need to link them to zlib too. So even if I don't use these executables, they are compiled. – whiteShadow Aug 12 '16 at 21:45
  • @whiteShadow Ups... sorry, I did not realized, linking is regarding dynamic libraries. This answer must be correct. – Dom Aug 16 '16 at 22:03
  • @Dom no it was about static libraries – whiteShadow Aug 16 '16 at 22:44