[SOLVED] .lib file of external module is not build

Hello,

when I try to build (ENABLE_SHARED) an external module the compiling is fine until the TestDriver and the HeaderTest are compiled. They are looking for an itkORA.lib file that is not created in the itk/lib/Debug folder.

LNK1104 cannot open file 'C:\TK\ITK-413\msvc2015_64\lib\Debug\itkORA-4.13.lib' ORATestDriver

The src/CMakeList.txt is as follows:

set(ORA_SRCS
  oraProjectionGeometry.cxx
  oraStringTools.cxx
  )

itk_module_add_library(ORA ${ORA_SRCS})

Nothing spectacular. ITK and VTK are compile with the same configurations. The *.dll files are created inside the itk build tree /bin/Debug/ directory. Inside the ORA-Build tree is neither a *.dll file nor a *.lib file.

In C:\TK\ITK-413\msvc2015_64\lib\cmake\ITK-4.13\Modules a ORA.cmake file is created:

set(ORA_LOADED 1)
set(ORA_ENABLE_SHARED "1")
set(ORA_DEPENDS "ITKCommon;ITKImageGrid;ITKImageSources;ITKVtkGlue;RTK")
set(ORA_PUBLIC_DEPENDS "ITKCommon;ITKImageGrid;ITKVtkGlue;RTK")
set(ORA_TRANSITIVE_DEPENDS "ITKCommon;ITKImageGrid;ITKImageSources;ITKVtkGlue;RTK")
set(ORA_PRIVATE_DEPENDS "")
set(ORA_LIBRARIES "ORA")
set(ORA_INCLUDE_DIRS "C:/TK/src/ora/include;C:/TK/ora/msvc2015_64/include")
set(ORA_LIBRARY_DIRS "")
set(ORA_RUNTIME_LIBRARY_DIRS "C:/TK/ITK-413/msvc2015_64/bin")
set(ORA_TARGETS_FILE "C:/TK/ITK-413/msvc2015_64/lib/cmake/ITK-4.13/Modules/Targets/ORATargets.cmake")
set(ORA_FACTORY_NAMES "")

The ORA_LIBRARIES value is empty. Which module creates this file? I guess the missing library name is a hint. An earlier projects has a library name filled in.
What could be a reason for not generating a LIB file?

CMake generated another file in C:\TK\ITK-413\msvc2015_64\lib\cmake\ITK-4.13\Modules\Targets:

ORATargets.cmake
# Generated by CMake

if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5)
   message(FATAL_ERROR "CMake >= 2.6.0 required")
endif()
cmake_policy(PUSH)
cmake_policy(VERSION 2.6)
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------

# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)

# Protect against multiple inclusion, which would fail when already imported targets are added once more.
set(_targetsDefined)
set(_targetsNotDefined)
set(_expectedTargets)
foreach(_expectedTarget ORA)
  list(APPEND _expectedTargets ${_expectedTarget})
  if(NOT TARGET ${_expectedTarget})
    list(APPEND _targetsNotDefined ${_expectedTarget})
  endif()
  if(TARGET ${_expectedTarget})
    list(APPEND _targetsDefined ${_expectedTarget})
  endif()
endforeach()
if("${_targetsDefined}" STREQUAL "${_expectedTargets}")
  unset(_targetsDefined)
  unset(_targetsNotDefined)
  unset(_expectedTargets)
  set(CMAKE_IMPORT_FILE_VERSION)
  cmake_policy(POP)
  return()
endif()
if(NOT "${_targetsDefined}" STREQUAL "")
  message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n")
endif()
unset(_targetsDefined)
unset(_targetsNotDefined)
unset(_expectedTargets)


# Create imported target ORA
add_library(ORA SHARED IMPORTED)

set_target_properties(ORA PROPERTIES
  INTERFACE_LINK_LIBRARIES "ITKCommon;ITKCommon;ITKStatistics;ITKTransform;ITKVtkGlue;RTK"
)

# Import target "ORA" for configuration "Debug"
set_property(TARGET ORA APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(ORA PROPERTIES
  IMPORTED_IMPLIB_DEBUG "C:/TK/ITK-413/msvc2015_64/lib/Debug/itkORA-4.13.lib"
  IMPORTED_LOCATION_DEBUG "C:/TK/ITK-413/msvc2015_64/bin/Debug/itkORA-4.13.dll"
  )

# Import target "ORA" for configuration "Release"
set_property(TARGET ORA APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(ORA PROPERTIES
  IMPORTED_IMPLIB_RELEASE "C:/TK/ITK-413/msvc2015_64/lib/Release/itkORA-4.13.lib"
  IMPORTED_LOCATION_RELEASE "C:/TK/ITK-413/msvc2015_64/bin/Release/itkORA-4.13.dll"
  )

# Import target "ORA" for configuration "MinSizeRel"
set_property(TARGET ORA APPEND PROPERTY IMPORTED_CONFIGURATIONS MINSIZEREL)
set_target_properties(ORA PROPERTIES
  IMPORTED_IMPLIB_MINSIZEREL "C:/TK/ITK-413/msvc2015_64/lib/MinSizeRel/itkORA-4.13.lib"
  IMPORTED_LOCATION_MINSIZEREL "C:/TK/ITK-413/msvc2015_64/bin/MinSizeRel/itkORA-4.13.dll"
  )

# Import target "ORA" for configuration "RelWithDebInfo"
set_property(TARGET ORA APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
set_target_properties(ORA PROPERTIES
  IMPORTED_IMPLIB_RELWITHDEBINFO "C:/TK/ITK-413/msvc2015_64/lib/RelWithDebInfo/itkORA-4.13.lib"
  IMPORTED_LOCATION_RELWITHDEBINFO "C:/TK/ITK-413/msvc2015_64/bin/RelWithDebInfo/itkORA-4.13.dll"
  )

# This file does not depend on other imported targets which have
# been exported from the same project but in a separate export set.

# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)

That seems to be without any problems.

Hi @Gordian, how are you compiling the external module? SHARED_ENABLED is not a standard itk or cmake option.

I would recommend to start in a clean-state, delete the build folder of you external module and re-configure with cmake. Just for sanity.

Hi @phcerdan,

I recompiled it after deleting the build folder. Still the same problem. The runtime library (itkORA-4.13.dll) is created and the lib-file isn’t generated. The repository branch is here.
My build system is Win10, Visual Studio 2015, ITK 4.13, VTK 8.0, RTK 1.4

The includes from ITK and ORA used in the cxx files are not found. Are the header files not automatically linked to the cxx files listed in the src/CMakeList.txt?

Do I need to export classes or functions?

Correction: I meant ENABLE_SHARED.

Thanks in advance,
Gordian

ENABLE_SHARED is not a cmake option in ITK either, are you using a cmake gui to enable the options? Try to use the cmake option: BUILD_SHARED_LIBS=ON in your module build to enable shared libraries.

I guess both ITK and your module, should have the same value for that option.

I am using the BUILD_SHARED_LIBS=ON option. This is from my external module:


This is the cmake-gui for ITK:

In the itk-module.cmake the option is listed as ENABLE_SHARED.

Thanks for the link to you project, looking good! And great initiative to create an External Module.

So, just for clarification ENABLE_SHARED in the itk-module.cmake allows ‘listening’ to the BUILD_SHARED_LIBS. but if BUILD_SHARED_LIBS is OFF, no shared libraries will be generated.

I am not a Windows user, but googling a little bit about the missing .lib, but the .dll being there: https://stackoverflow.com/questions/7614286/how-do-i-get-cmake-to-create-a-dll-and-its-matching-lib-file

There is a cmake post about it: https://blog.kitware.com/create-dlls-on-windows-without-declspec-using-new-cmake-export-all-feature/

And a related change in ITK classes in this review: http://review.source.kitware.com/#/c/20020

This is beyond my knowledge to make any advice with confident and I have no windows machine at hand right now to test. But you might try:

template<class TFixedImage, class TMovingImage, class TGradientPixelType>
class ORA_EXPORT GradientDifferenceImageToImageMetric :
    public itk::ImageToImageMetric<TFixedImage, TMovingImage>

and compile with the CMake option: CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS:BOOL=ON

It is a long shot, maybe somebody can suggest the best approach. Tricky stuff.

By the way, with BUILD_SHARED_LIBS:BOOL=OFF, does it work?

When I set BUILD_SHARED_LIBS:BOOL=OFF a lib file is generated and the project compiles without any problems. Even the test are fine as far as I can see.

I am not sure what are the consequences I have to face if I build this project without shared libs. I dont think it complies with ITK guidelines.
I do not have a deep background on programming enviroments and with the complexity of CMake it becomes sometime a struggle. :slight_smile: But with the help of the nice people in this forum i can move forward… :+1:

I will try to implement the ORA_EXPORT macro. The ITK_EXPORT does not define anything. Its the one I should use? Whereas the RTK_EXPORT defines a lot more if its used with Windows.

ITK Export Macro

#define ITK_EXPORT

RTK Export Macro

#if (defined(_WIN32) || defined(WIN32)) && defined(RTK_BUILD_SHARED_LIBS) 
# if defined(RTK_EXPORTS) || defined(__CUDACC__)
#  define RTK_EXPORT __declspec(dllexport)
# else
#  define RTK_EXPORT __declspec(dllimport)
# endif  /* RTK_EXPORT */
#else
/* unix needs nothing */
#define RTK_EXPORT 
#endif

You do not have a “lib” file because you don’t have anything “exported”. As you noticed you need missing export specification for you methods.

You will need to include the header “ITKORAExport.h”

For your none template classes and functions you should be using ITKORA_EXPORT. This is necessary on windows. For some advanced cases such as native python wrapping and other odd reasons, ITK_TEMPLATE_EXPORT should be used on templated classes. The IOImageBase module may be a good example:

2 Likes

This was the right hint. I included the header in all *.h files and added ORA_EXPORT to the non-template classes. I guess that the functions of those classes are implicit also exported?

I would try to run some tests before I mark this thread as solved. The build passed in DEBUG and RelWithDebInfo mode. The tests passed aswell. Seems to work.

As a further note: The ORAExport.h file is automatically created and can be found in the build tree.(path\to\module\build\tree\include).

Thank you @blowekamp, @phcerdan for your time and tips.