1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
cmake_minimum_required(VERSION 3.10)
project(CompatibleInterface)
include(GenerateExportHeader)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(iface1 INTERFACE)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL
BOOL_PROP1
BOOL_PROP2
BOOL_PROP3
BOOL_PROP4
BOOL_PROP5
)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING
STRING_PROP1
STRING_PROP2
STRING_PROP3
STRING_PROP4
)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_NUMBER_MIN
NUMBER_MIN_PROP1
NUMBER_MIN_PROP2
NUMBER_MIN_PROP3
NUMBER_MIN_PROP4
NUMBER_MIN_PROP5
NUMBER_MIN_PROP6
)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_NUMBER_MAX
NUMBER_MAX_PROP1
NUMBER_MAX_PROP2
NUMBER_MAX_PROP3
NUMBER_MAX_PROP4
)
set(CMAKE_DEBUG_TARGET_PROPERTIES
BOOL_PROP1 BOOL_PROP2 BOOL_PROP3 BOOL_PROP4 BOOL_PROP5
STRING_PROP1 STRING_PROP2 STRING_PROP3 STRING_PROP4
NUMBER_MIN_PROP1 NUMBER_MIN_PROP2 NUMBER_MIN_PROP3 NUMBER_MIN_PROP4 NUMBER_MIN_PROP5 NUMBER_MIN_PROP6
NUMBER_MAX_PROP1 NUMBER_MAX_PROP2 NUMBER_MAX_PROP3 NUMBER_MAX_PROP4
)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP1 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP2 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP5 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP1 prop1)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP2 prop2)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP4 prop4)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP1 100)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP2 200)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP3 0x10)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP4 0x10)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP5 5)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP6 6)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP1 100)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP2 200)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP3 3)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP4 4)
add_executable(CompatibleInterface main.cpp)
target_link_libraries(CompatibleInterface iface1)
add_library(foo STATIC foo.cpp)
add_library(bar SHARED bar.cpp)
set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SOMEPROP)
set_property(TARGET foo PROPERTY INTERFACE_SOMEPROP ON)
# Use LINK_ONLY to suppress usage requirements and allow the check to pass.
set_property(TARGET bar PROPERTY INTERFACE_LINK_LIBRARIES $<LINK_ONLY:foo>)
set_property(TARGET CompatibleInterface PROPERTY SOMEPROP OFF)
target_link_libraries(CompatibleInterface bar)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP2 ON)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP3 ON)
set_property(TARGET CompatibleInterface PROPERTY STRING_PROP2 prop2)
set_property(TARGET CompatibleInterface PROPERTY STRING_PROP3 prop3)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP1 50)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP2 250)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP3 0xa)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP4 0x1A)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MAX_PROP1 50)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MAX_PROP2 250)
target_compile_definitions(CompatibleInterface
PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP1>>:BOOL_PROP1>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP2>>:BOOL_PROP2>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP3>>:BOOL_PROP3>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP1>,prop1>:STRING_PROP1>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP2>,prop2>:STRING_PROP2>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP3>,prop3>:STRING_PROP3>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP1>,50>:NUMBER_MIN_PROP1=50>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP2>,200>:NUMBER_MIN_PROP2=200>
$<$<EQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP3>,0xA>:NUMBER_MIN_PROP3=0xA>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP4>,0x10>:NUMBER_MIN_PROP4=0x10>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP5>,5>:NUMBER_MIN_PROP5=5>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MAX_PROP1>,100>:NUMBER_MAX_PROP1=100>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MAX_PROP2>,250>:NUMBER_MAX_PROP2=250>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MAX_PROP3>,3>:NUMBER_MAX_PROP3=3>
# Static libraries compute COMPATIBLE_INTERFACE_ properties transitively.
$<$<BOOL:$<TARGET_PROPERTY:static1,BOOL_PROP1>>:STATIC1_BOOL_PROP1>
$<$<STREQUAL:$<TARGET_PROPERTY:static1,STRING_PROP1>,prop1>:STATIC1_STRING_PROP1>
$<$<EQUAL:$<TARGET_PROPERTY:static1,NUMBER_MAX_PROP3>,3>:STATIC1_NUMBER_MAX_PROP3>
$<$<EQUAL:$<TARGET_PROPERTY:static1,NUMBER_MIN_PROP5>,5>:STATIC1_NUMBER_MIN_PROP5>
# Object libraries do not compute COMPATIBLE_INTERFACE_ properties transitively.
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:object1,BOOL_PROP1>,>>:OBJECT1_BOOL_PROP1>
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:object1,STRING_PROP1>,>>:OBJECT1_STRING_PROP1>
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:object1,NUMBER_MAX_PROP3>,>>:OBJECT1_NUMBER_MAX_PROP3>
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:object1,NUMBER_MIN_PROP5>,>>:OBJECT1_NUMBER_MIN_PROP5>
# Interface libraries do not compute COMPATIBLE_INTERFACE_ properties transitively.
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:iface3,BOOL_PROP1>,>>:IFACE3_BOOL_PROP1>
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:iface3,STRING_PROP1>,>>:IFACE3_STRING_PROP1>
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:iface3,NUMBER_MAX_PROP3>,>>:IFACE3_NUMBER_MAX_PROP3>
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:iface3,NUMBER_MIN_PROP5>,>>:IFACE3_NUMBER_MIN_PROP5>
# Static libraries compute COMPATIBLE_INTERFACE_ properties transitively.
$<$<BOOL:$<TARGET_PROPERTY:static1,BOOL_PROP5>>:STATIC1_BOOL_PROP5>
$<$<STREQUAL:$<TARGET_PROPERTY:static1,STRING_PROP4>,prop4>:STATIC1_STRING_PROP4>
$<$<EQUAL:$<TARGET_PROPERTY:static1,NUMBER_MIN_PROP6>,6>:STATIC1_NUMBER_MIN_PROP6>
$<$<EQUAL:$<TARGET_PROPERTY:static1,NUMBER_MAX_PROP4>,4>:STATIC1_NUMBER_MAX_PROP4>
# Object libraries do not compute COMPATIBLE_INTERFACE_ properties transitively,
# but can have properties set on them.
$<$<BOOL:$<TARGET_PROPERTY:object1,BOOL_PROP5>>:OBJECT1_BOOL_PROP5>
$<$<STREQUAL:$<TARGET_PROPERTY:object1,STRING_PROP4>,prop4>:OBJECT1_STRING_PROP4>
$<$<EQUAL:$<TARGET_PROPERTY:object1,NUMBER_MIN_PROP6>,7>:OBJECT1_NUMBER_MIN_PROP6>
$<$<EQUAL:$<TARGET_PROPERTY:object1,NUMBER_MAX_PROP4>,1>:OBJECT1_NUMBER_MAX_PROP4>
# Interface libraries do not compute COMPATIBLE_INTERFACE_ properties transitively,
# but can have properties set on them.
$<$<BOOL:$<TARGET_PROPERTY:iface3,BOOL_PROP5>>:IFACE3_BOOL_PROP5>
$<$<STREQUAL:$<TARGET_PROPERTY:iface3,STRING_PROP4>,prop4>:IFACE3_STRING_PROP4>
$<$<EQUAL:$<TARGET_PROPERTY:iface3,NUMBER_MIN_PROP6>,7>:IFACE3_NUMBER_MIN_PROP6>
$<$<EQUAL:$<TARGET_PROPERTY:iface3,NUMBER_MAX_PROP4>,1>:IFACE3_NUMBER_MAX_PROP4>
)
add_library(iface2 SHARED iface2.cpp)
generate_export_header(iface2)
set_property(TARGET iface2 APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING
Iface2_PROP
)
# For the LINK_LIBRARIES and related properties, we should not evaluate
# properties defined only in the interface - they should be implicitly zero
set_property(TARGET iface2
APPEND PROPERTY
LINK_INTERFACE_LIBRARIES $<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP4>>:nonexistent>
)
target_link_libraries(CompatibleInterface iface2
$<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:nonexistent>
)
# Test that this does not segfault:
target_compile_definitions(CompatibleInterface
PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:SOME_DEFINE>
)
# The COMPATIBLE_INTERFACE_* properties are only read from dependencies
# in the interface. Populating it on the CompatibleInterface target does
# not have any effect on the interpretation of the INTERFACE variants
# in dependencies.
set_property(TARGET iface1 PROPERTY
INTERFACE_NON_RELEVANT_PROP ON
)
set_property(TARGET iface2 PROPERTY
INTERFACE_NON_RELEVANT_PROP ON
)
set_property(TARGET CompatibleInterface APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL
NON_RELEVANT_PROP
)
add_library(static1 STATIC foo.cpp)
set_property(TARGET static1 PROPERTY BOOL_PROP5 ON)
set_property(TARGET static1 PROPERTY STRING_PROP4 prop4)
set_property(TARGET static1 PROPERTY NUMBER_MIN_PROP6 7)
set_property(TARGET static1 PROPERTY NUMBER_MAX_PROP4 1)
target_link_libraries(static1 PUBLIC iface1)
add_library(object1 OBJECT foo.cpp)
set_property(TARGET object1 PROPERTY BOOL_PROP5 ON)
set_property(TARGET object1 PROPERTY STRING_PROP4 prop4)
set_property(TARGET object1 PROPERTY NUMBER_MIN_PROP6 7)
set_property(TARGET object1 PROPERTY NUMBER_MAX_PROP4 1)
target_link_libraries(object1 PUBLIC iface1)
add_library(iface3 INTERFACE)
set_property(TARGET iface3 PROPERTY BOOL_PROP5 ON)
set_property(TARGET iface3 PROPERTY STRING_PROP4 prop4)
set_property(TARGET iface3 PROPERTY NUMBER_MIN_PROP6 7)
set_property(TARGET iface3 PROPERTY NUMBER_MAX_PROP4 1)
target_link_libraries(iface3 INTERFACE iface1)
# Test COMPATIBLE_INTERFACE_* property evaluation outside of usage requirements.
add_custom_target(check ALL VERBATIM
COMMAND CompatibleInterface
# expect actual
"1" "$<TARGET_PROPERTY:CompatibleInterface,BOOL_PROP1>"
"prop1" "$<TARGET_PROPERTY:CompatibleInterface,STRING_PROP1>"
"3" "$<TARGET_PROPERTY:CompatibleInterface,NUMBER_MAX_PROP3>"
"5" "$<TARGET_PROPERTY:CompatibleInterface,NUMBER_MIN_PROP5>"
"1" "$<TARGET_PROPERTY:static1,BOOL_PROP1>"
"prop1" "$<TARGET_PROPERTY:static1,STRING_PROP1>"
"3" "$<TARGET_PROPERTY:static1,NUMBER_MAX_PROP3>"
"5" "$<TARGET_PROPERTY:static1,NUMBER_MIN_PROP5>"
"" "$<TARGET_PROPERTY:object1,BOOL_PROP1>"
"" "$<TARGET_PROPERTY:object1,STRING_PROP1>"
"" "$<TARGET_PROPERTY:object1,NUMBER_MAX_PROP3>"
"" "$<TARGET_PROPERTY:object1,NUMBER_MIN_PROP5>"
"" "$<TARGET_PROPERTY:iface3,BOOL_PROP1>"
"" "$<TARGET_PROPERTY:iface3,STRING_PROP1>"
"" "$<TARGET_PROPERTY:iface3,NUMBER_MAX_PROP3>"
"" "$<TARGET_PROPERTY:iface3,NUMBER_MIN_PROP5>"
"ON" "$<TARGET_PROPERTY:static1,BOOL_PROP5>"
"prop4" "$<TARGET_PROPERTY:static1,STRING_PROP4>"
"6" "$<TARGET_PROPERTY:static1,NUMBER_MIN_PROP6>"
"4" "$<TARGET_PROPERTY:static1,NUMBER_MAX_PROP4>"
"ON" "$<TARGET_PROPERTY:object1,BOOL_PROP5>"
"prop4" "$<TARGET_PROPERTY:object1,STRING_PROP4>"
"7" "$<TARGET_PROPERTY:object1,NUMBER_MIN_PROP6>"
"1" "$<TARGET_PROPERTY:object1,NUMBER_MAX_PROP4>"
"ON" "$<TARGET_PROPERTY:iface3,BOOL_PROP5>"
"prop4" "$<TARGET_PROPERTY:iface3,STRING_PROP4>"
"7" "$<TARGET_PROPERTY:iface3,NUMBER_MIN_PROP6>"
"1" "$<TARGET_PROPERTY:iface3,NUMBER_MAX_PROP4>"
)
|