MantisBT - CMake
View Issue Details
0015142CMakeCMakepublic2014-09-08 14:202016-06-10 14:31
Daniele E. Domenichelli 
Kitware Robot 
normalminoralways
closedmoved 
 
 
0015142: Cannot set different INTERFACE_COMPILE_DEFINITIONS for different IMPORTED_CONFIGURATIONS
The INTERFACE_COMPILE_DEFINITIONS target property does not have an IMPORTED_CONFIGURATIONS_<CONFIG> analogue.

This means that it is not possible for imported libraries to use different definitions depending on the configuration of the library being used.
In my opinion it should be possible to do something like this:

add_library(FOO::FOO IMPORTED UNKNOWN)
set_property(TARGET FOO::FOO PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${FOO_INCLUDE_DIRS}")
if(FOO_LIBRARY_RELEASE)
  set_property(TARGET FOO::FOO APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
  set_property(TARGET FOO::FOO PROPERTY IMPORTED_LOCATION_RELEASE "${FOO_LIBRARY_RELEASE}")
  set_property(TARGET FOO::FOO APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS_RELEASE FOO_RELEASE)
endif()
if(FOO_LIBRARY_DEBUG)
  set_property(TARGET FOO::FOO APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
  set_property(TARGET FOO::FOO PROPERTY IMPORTED_LOCATION_DEBUG "${FOO_LIBRARY_DEBUG}")
  set_property(TARGET FOO::FOO APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS_DEBUG FOO_DEBUG)
endif()

And depending on the configuration of the library being used, it should automatically add -DFOO_RELEASE or -DFOO_DEBUG.
No tags attached.
Issue History
2014-09-08 14:20Daniele E. DomenichelliNew Issue
2014-09-08 14:31Brad KingNote Added: 0036750
2014-09-09 05:55Daniele E. DomenichelliNote Added: 0036752
2014-09-09 08:34Brad KingNote Added: 0036754
2014-09-10 06:17Stephen KellyNote Added: 0036768
2014-09-10 12:13Daniele E. DomenichelliNote Added: 0036777
2014-09-10 13:58Stephen KellyNote Added: 0036778
2016-06-10 14:29Kitware RobotNote Added: 0042625
2016-06-10 14:29Kitware RobotStatusnew => resolved
2016-06-10 14:29Kitware RobotResolutionopen => moved
2016-06-10 14:29Kitware RobotAssigned To => Kitware Robot
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0036750)
Brad King   
2014-09-08 14:31   
This is why INTERFACE_COMPILE_DEFINITIONS supports generator expressions. You can do

 $<$<CONFIG:Debug>:FOO_DEBUG>

to get a debug-only definition.
(0036752)
Daniele E. Domenichelli   
2014-09-09 05:55   
I'm not sure if I understood how this works then, please correct me if I'm wrong:

"$<CONFIG:Debug>" is true if the current configuration is "DEBUG", and an imported library might have several "IMPORTED_CONFIGURATIONS" and one is chosen depending on the current configuration.

The configuration chosen from "IMPORTED_CONFIGURATIONS" is not necessarily the same as the current configuration. For example if a library has "IMPORTED_CONFIGURATIONS=RELEASE" configuration, but I'm building in "DEBUG", then, since there is no DEBUG configuration for the imported library, the RELEASE configuration will be chosen and the library will be linked from IMPORTED_LOCATION_RELEASE, but "$<CONFIG:Debug>" will still be FALSE, because I'm building in RELEASE mode. Therefore the "FOO_RELEASE" definition will not be added.

Am I missing something here?
(0036754)
Brad King   
2014-09-09 08:34   
Re 0015142:0036752: Steve?
(0036768)
Stephen Kelly   
2014-09-10 06:17   
My understanding is that MAP_IMPORTED_CONFIG_<CONFIG> must be populated.

However, I didn't try it out. Do you have an sscce?
(0036777)
Daniele E. Domenichelli   
2014-09-10 12:13   
---- BEGIN File CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(Bar LANGUAGES CXX VERSION 1.0.0)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

find_package(Foo)

add_executable(main main.cpp)
target_link_libraries(main FOO::FOO)
---- END File CMakeLists.txt

---- BEGIN File cmake/FindFoo.cmake
# Assuming this are created with some find_library or something else
set(FOO_LIBRARY_RELEASE "/usr/lib/x86_64-linux-gnu/libstdc++.so.6") # Set to an actual library on the system
set(FOO_LIBRARY_DEBUG FOO_LIBRARY_DEBUG-NOTFOUND) # Not found

add_library(FOO::FOO IMPORTED UNKNOWN)
set_property(TARGET FOO::FOO PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${FOO_INCLUDE_DIRS}")
if(FOO_LIBRARY_RELEASE)
  set_property(TARGET FOO::FOO APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
  set_property(TARGET FOO::FOO PROPERTY IMPORTED_LOCATION_RELEASE "${FOO_LIBRARY_RELEASE}")
  set_property(TARGET FOO::FOO APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS $<$<CONFIG:Release>:FOO_RELEASE>)
endif()
if(FOO_LIBRARY_DEBUG)
  set_property(TARGET FOO::FOO APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
  set_property(TARGET FOO::FOO PROPERTY IMPORTED_LOCATION_DEBUG "${FOO_LIBRARY_DEBUG}")
  set_property(TARGET FOO::FOO APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS $<$<CONFIG:Debug>:FOO_DEBUG>)
endif()
---- END File cmake/FindFoo.cmake

---- BEGIN File main.cpp
int main(int argc, char *argv[])
{
    return 0;
}
---- END File main.cpp


# CMAKE_BUILD_TYPE unset
cmake .. -DCMAKE_BUILD_TYPE=""
/usr/bin/c++ -o CMakeFiles/main.dir/main.cpp.o -c /opt/iit/src/examples/cmake_0015142/main.cpp
/usr/bin/c++ CMakeFiles/main.dir/main.cpp.o -o main -rdynamic /usr/lib/x86_64-linux-gnu/libstdc++.so.6


# CMAKE_BUILD_TYPE found
cmake .. -DCMAKE_BUILD_TYPE="Release"
/usr/bin/c++ -DFOO_RELEASE -O3 -DNDEBUG -o CMakeFiles/main.dir/main.cpp.o -c /opt/iit/src/examples/cmake_0015142/main.cpp
/usr/bin/c++ -O3 -DNDEBUG CMakeFiles/main.dir/main.cpp.o -o main -rdynamic /usr/lib/x86_64-linux-gnu/libstdc++.so.6


# CMAKE_BUILD_TYPE not found
cmake .. -DCMAKE_BUILD_TYPE="Debug"
/usr/bin/c++ -g CMakeFiles/main.dir/main.cpp.o -o main -rdynamic /usr/lib/x86_64-linux-gnu/libstdc++.so.6
/usr/bin/c++ -g CMakeFiles/main.dir/main.cpp.o -o main -rdynamic /usr/lib/x86_64-linux-gnu/libstdc++.so.6


# CMAKE_BUILD_TYPE not defined
cmake .. -DCMAKE_BUILD_TYPE="DebugFull"
/usr/bin/c++ -g CMakeFiles/main.dir/main.cpp.o -o main -rdynamic /usr/lib/x86_64-linux-gnu/libstdc++.so.6
/usr/bin/c++ -g CMakeFiles/main.dir/main.cpp.o -o main -rdynamic /usr/lib/x86_64-linux-gnu/libstdc++.so.6




In all these cases -DFOO_RELEASE should be defined when building main.cpp
(0036778)
Stephen Kelly   
2014-09-10 13:58   
The incorrect claim (at least as it relates to the current implementation) seems to be:

 "If the LOCATION_<FOO> of an imported target is used, then the $<CONFIG> must be FOO"

The two elements are not connected in that way. Even though the LOCATION_RELEASE is used (because it is the only one available), the $<CONFIG> is not RELEASE. The LOCATION_RELEASE is used only because it is a fallback in all cases.

Here is what I think you are reporting, and the source of the confusion:

Before CMP0022, If I add
 
 set_property(TARGET FOO::FOO APPEND PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE iface2)

then iface2 is linked by the users of FOO::FOO if the IMPORTED_RELEASE location is chosen. That semantic is independent of the value of the CMAKE_BUILD_TYPE.

However, if I add

 set_property(TARGET FOO::FOO APPEND PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES $<$<CONFIG:Release>:iface2>)

then iface2 is not linked by the users of FOO::FOO.

It might be possible to change that with a policy. I haven't fully investigated why the current semantic is what it is, but it seems like changing it would make sense. CurrentTarget->GetMappedConfig used in ConfigurationTestNode already knows the LOCATION-suffix used.

Here are some commits of interest:

 v2.8.11~289^2~5 (Use mapped config properties to evaluate $<CONFIG>, 2012-12-23)
 v2.8.12~174^2 (Genex: Fix $<CONFIG> with IMPORTED targets and multiple locations., 2013-07-15)
 v2.8.12~64^2 (Genex: Fix evaluation of MAP_IMPORTED_CONFIG_<CONFIG>, 2013-08-27)
(0042625)
Kitware Robot   
2016-06-10 14:29   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.