error building an external module: cannot open input file 'ITKCommon.lib'

cmake
external-module

(Edwin Bennink) #1

Dear all,

I am trying to build an external ITK module, but linking the new module to the ITK libraries fails. It appears that CMake added the dependent ITK libraries as ITKCommon.lib and ITKSpatialObjects.lib to the link command, whereas these should have had the ITK version number included, i.e. ITKCommon-4.13.lib and ITKSpatialObjects-4.13.lib.

I am using ITK 4.13, built in Release mode and BUILD_SHARED_LIBS=ON. Windows 10, MSVC 2015, CMake version 3.10.2.

My itk-module.cmake looks like:

get_filename_component(MY_CURRENT_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
file(READ "${MY_CURRENT_DIR}/README.rst" DOCUMENTATION)

itk_module(IsiToolkitLabelModule
  DEPENDS
    ITKCommon
	ITKSpatialObjects
  DESCRIPTION
    "${DOCUMENTATION}"
  EXCLUDE_FROM_DEFAULT
  ENABLE_SHARED
)

Any thoughts on what could go wrong?

Cheers,
Edwin


(Matt McCormick) #2

Hi Edwin,

Do ITKCommon.lib and ITKSpatialObjects.lib have full paths on the link line?

Does the external module have the following code in its top level CMakeLists.txt file?

Thanks,
Matt


(Edwin Bennink) #3

Hi Matt,

Do ITKCommon.lib and ITKSpatialObjects.lib have full paths on the link line?

No, the link line looks like this:

C:\PROGRA~2\MICROS~2.0\VC\bin\amd64\link.exe @CMakeFiles\IsiToolkitLabelModule.dir\objects1.rsp /out:D:\develop\isitk-core-new\build\ITK\build\bin\itkIsiToolkitLabelModule-4.13.dll /implib:D:\develop\isitk-core-new\build\ITK\build\lib\itkIsiToolkitLabelModule-4.13.lib /pdb:D:\develop\isitk-core-new\build\ITK\build\bin\itkIsiToolkitLabelModule-4.13.pdb /dll /version:1.0 /machine:x64 /INCREMENTAL:NO ITKCommon.lib ITKSpatialObjects.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:D:\develop\isitk-core-new\build\ITK\build\bin\itkIsiToolkitLabelModule-4.13.dll.manifest

The compile lines, however, do include the full paths (compiling works).

Does the external module have the following code in its top level CMakeLists.txt file?

Yes, the CMakeLists.txt file looks like this:

cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
cmake_policy(VERSION 3.10.2)

project(IsiToolkitLabelModule)

if(NOT ITK_SOURCE_DIR)
  find_package(ITK REQUIRED)
  list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR})
  include(ITKModuleExternal)
else()
  itk_module_impl()
endif()

(Jon Haitz Legarreta Gorroño) #4

I am using ITK 4.13, built in Release mode and BUILD_SHARED_LIBS=ON.

Is it an issue of mixing dynamic and static linking? If you built ITK with BUILD_SHARED_LIBS=ON, then your module should link against the .dll files, instead of the .lib files.


(Dženan Zukić) #5

I don’t think this is the case. Even when needing to use DLLs, you need to link against their import libraries, .lib files.

I remember this problem of missing version number occurring before, but I don’t remember either the cause or the solution :frowning:

Edit: trying a clean build of both ITK and the external module might help.


(Edwin Bennink) #6

Ok. I will try a clean build of ITK and the module.


(Edwin Bennink) #7

Now, after a clean build of ITK, something different happened. Both ITK and my external module were build with BUILD_SHARED_LIBS=ON, but my external module was statically linked to ITK. The resulting external module library has no dependencies on any ITK shared libraries, such as ITKCommon-4.13.dll, whereas the internal ITK module libraries do have these dependencies.
FYI: I also built SimpleITK and those libraries DO depend on the ITK shared libraries.


(Dženan Zukić) #8

Why do you think this? Have you examined the external module’s DLLs using Dependency Walker?


(Edwin Bennink) #9

Hi Dzenan,
Yes, I indeed used Dependency Walker to check it because the build output doesn’t show the full link command when there are no errors.


(Dženan Zukić) #10

Is your external module’s library big, file size wise? Does it appear as a static or dynamic library (.lib or .lib+.dll)? Have you tried linking a simple application to it and invoking some function, .e.g construct a class from the library? Does that work?

Edit: turn on showing full paths in Dependency Walker, different DLLs might be picked up than what you thought.


(Edwin Bennink) #11

I have a feeling that I’m beginning to understand what’s going on here. As my external module is made up of templated code only (just a .hxx file), the DLL is just an empty shell. I expected that the ITK build process would pre-process all templated code, compile all of it, and put it into a shared library, but this is apparently not the case.
So, correct me if I’m wrong, but for compiling the ITK Python package (for example) there is no benefit in building shared libraries, is there? The collection of ITK shared libraries has a size of just 20 MB, whereas the Python ITK libraries are 467 MB in total.


(Dženan Zukić) #12

This is called explicit template instantiation. You can read more about it here. Enabling this requires extra work on the developer’s side.

@matt.mccormick or @blowekamp would be better able to answer the part of the question about Python packages.


(Edwin Bennink) #13

Thanks! Good to know :slight_smile: