CMake library configuration file is linking against both debug and release version of library

41 Views Asked by At

I've edited the CMakeFileLists.txt (and project structure) of CNPY library to automatically generate a cnpy-config.cmake file for importing into my project.

Everything works fine: the library is compiled and .lib, .dll, .cmake files are correctly generated and installed (I've used Debug and Release configurations).

In particular, three configuration files are produced in cmake folder: cnpy-config.cmake, cnpy-config-debug.cmake, cnpy-config-release.cmake`

CMAKE_MINIMUM_REQUIRED(VERSION 3.25 FATAL_ERROR)

if(COMMAND cmake_policy)
    cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)

project(CNPY VERSION 1.0.0)
if(NOT CMAKE_DEBUG_POSTFIX)
  set(CMAKE_DEBUG_POSTFIX d)
endif()
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

# option(ENABLE_STATIC "Build static (.a) library" OFF)

find_package(ZLIB REQUIRED)

add_library(cnpy SHARED)
    target_sources(cnpy PRIVATE src/cnpy.cpp)
    target_link_libraries(cnpy ZLIB::ZLIB)
    target_include_directories(cnpy PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
    target_compile_features(cnpy PUBLIC cxx_std_17)
    install(
        TARGETS cnpy
        EXPORT cnpy_export
        INCLUDES DESTINATION include
    )

    # Install directories
    install (
        DIRECTORY ${PROJECT_SOURCE_DIR}/include/
        DESTINATION include
    )

# Export configuration file
install(EXPORT cnpy_export
        FILE cnpy-config.cmake
        NAMESPACE cnpy::
        # This is always relative to ${CMAKE_PREFIX_INSTALL}
        DESTINATION cmake
)

Now I have my project (very basic right now) that uses cnpy:

CMakeLists.txt

cmake_minimum_required(VERSION 3.25)
project(MyProject)

message("Current configuration: ${CMAKE_BUILD_TYPE}")

find_package(ZLIB REQUIRED)
find_package(CNPY REQUIRED) 

add_executable(MyExe)
target_sources(MyExe PRIVATE main.cpp)
target_link_libraries(MyExe PRIVATE cnpy::cnpy)

main.cpp

#include<cnpy.h>
#include<stdio.h>
#include<string>
int main()
{
    std::string filename("C:\\some\\path\\array.npy");
#ifdef NDEBUG
    printf("I'm in Release mode\n");
#else
    printf("I'm in Debug mode\n");
#endif

    auto arr = cnpy::npy_load(filename);

    std::cout << "Read array of " << arr.as_vec<float>().size() << std::endl;
}

Everything works fine. BUT: main.exe requires both cnpy.dll and cnpyd.dll, no matter whether I'm building in Release or Debug mode.

Digging into cnpy-config.cmake, I noticed the following part of code, that includes ALWAYS both *-debug.cmake and *-release.cmake files.

[...]
file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/cnpy-config-*.cmake")
foreach(_cmake_config_file IN LISTS _cmake_config_files)
  include("${_cmake_config_file}")
endforeach()
unset(_cmake_config_file)
unset(_cmake_config_files)
[...]

The content of the two files follow for clarity:

# cnpy-config-release.cmake
#----------------------------------------------------------------
# Generated CMake target import file for configuration "Release".
#----------------------------------------------------------------

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

# Import target "cnpy::cnpy" for configuration "Release"
set_property(TARGET cnpy::cnpy APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(cnpy::cnpy PROPERTIES
  IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/cnpy.lib"
  IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/cnpy.dll"
  )

list(APPEND _cmake_import_check_targets cnpy::cnpy )
list(APPEND _cmake_import_check_files_for_cnpy::cnpy "${_IMPORT_PREFIX}/lib/cnpy.lib" "${_IMPORT_PREFIX}/bin/cnpy.dll" )

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




# cnpy-config-debug.cmake
#----------------------------------------------------------------
# Generated CMake target import file for configuration "Debug".
#----------------------------------------------------------------

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

# Import target "cnpy::cnpy" for configuration "Debug"
set_property(TARGET cnpy::cnpy APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(cnpy::cnpy PROPERTIES
  IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/cnpyd.lib"
  IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/cnpyd.dll"
  )

list(APPEND _cmake_import_check_targets cnpy::cnpy )
list(APPEND _cmake_import_check_files_for_cnpy::cnpy "${_IMPORT_PREFIX}/lib/cnpyd.lib" "${_IMPORT_PREFIX}/bin/cnpyd.dll" )

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

As far as I understand (I'm not a CMake expert TBH), the two debug and release versions of the library are always included.

Apart from a hack solution of manually editing the master configuration file to check upon configuration, such reported below (I don't like this solution), is there any solution to automatically generate a configuration file that can discern configurations, or help the as is (already generated) configuration file to discern the configuration?

IF (${CMAKE_BUILD_TYPE} MATCHES Debug)
   include("${CMAKE_CURRENT_LIST_DIR}/cnpy-config-debug.cmake")
ELSE()
   include(${CMAKE_CURRENT_LIST_DIR}/cnpy-config-release.cmake")
ENDIF()

Please, I've googled a lot of answers (inside and outside SO), but I've not got anything for this case in particular: If I was missing something and this is a duplicate, I'm really sorry.

0

There are 0 best solutions below