1
2cmake_minimum_required(VERSION 2.8.12)
3
4project(TargetIncludeDirectories)
5
6macro(create_header _name)
7  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_name}")
8  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_name}/${_name}.h" "/* ${_name}.h */\n")
9endmacro()
10
11create_header(bar)
12create_header(bat)
13create_header(foo)
14create_header(baz)
15create_header(bang)
16create_header(bing)
17create_header(bung)
18create_header(arguments)
19create_header(list)
20create_header(target1)
21create_header(target2)
22
23set(CMAKE_INCLUDE_CURRENT_DIR ON)
24
25include_directories("${CMAKE_CURRENT_BINARY_DIR}/bar")
26include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/bang>")
27
28add_executable(TargetIncludeDirectories main.cpp)
29
30set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bat")
31set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foo")
32set_property(TARGET TargetIncludeDirectories APPEND PROPERTY
33    INCLUDE_DIRECTORIES "$<1:${CMAKE_CURRENT_BINARY_DIR}/bing>")
34
35include_directories("${CMAKE_CURRENT_BINARY_DIR}/baz")
36include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/bung>")
37include_directories("sing$<1:/ting>")
38
39include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/arguments;${CMAKE_CURRENT_BINARY_DIR}/list>")
40
41create_header(fee)
42create_header(fiy)
43create_header(foh)
44create_header(fum)
45
46file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp" "#include \"fee.h\"\n")
47add_library(lib1 "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp")
48set_property(TARGET lib1 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fee")
49set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy")
50set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:${CMAKE_CURRENT_BINARY_DIR}/foh>")
51
52file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp" "#include \"fiy.h\"\n")
53add_library(lib2 "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp")
54set_property(TARGET lib2 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fum;$<TARGET_PROPERTY:lib1,INTERFACE_INCLUDE_DIRECTORIES>")
55set_property(TARGET lib2 APPEND PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:lib1,INTERFACE_INCLUDE_DIRECTORIES>")
56
57file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n#include \"fum.h\"\nint main(int,char**) { return 0; }\n")
58add_executable(exe3 "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp")
59set_property(TARGET exe3 APPEND PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:lib2,INTERFACE_INCLUDE_DIRECTORIES>")
60
61# Test cycles
62file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n")
63add_library(lib3 "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp")
64set_property(TARGET lib3 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy;$<TARGET_PROPERTY:lib4,INTERFACE_INCLUDE_DIRECTORIES>")
65set_property(TARGET lib3 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy;$<TARGET_PROPERTY:lib4,INTERFACE_INCLUDE_DIRECTORIES>")
66
67file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n")
68add_library(lib4 "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp")
69set_property(TARGET lib4 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foh;$<TARGET_PROPERTY:lib3,INTERFACE_INCLUDE_DIRECTORIES>")
70set_property(TARGET lib4 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foh;$<TARGET_PROPERTY:lib3,INTERFACE_INCLUDE_DIRECTORIES>")
71
72add_library(somelib::withcolons UNKNOWN IMPORTED)
73set_property(TARGET somelib::withcolons PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/target1")
74set_property(TARGET somelib::withcolons PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/target1")
75
76set_property(TARGET TargetIncludeDirectories
77  APPEND PROPERTY INCLUDE_DIRECTORIES
78  "$<TARGET_PROPERTY:somelib::withcolons,INTERFACE_INCLUDE_DIRECTORIES>"
79)
80
81add_library(somelib_aliased UNKNOWN IMPORTED GLOBAL)
82set_property(TARGET somelib_aliased PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/target2")
83add_library(somelib::withcolons2 ALIAS somelib_aliased)
84
85set_property(TARGET TargetIncludeDirectories
86  APPEND PROPERTY INCLUDE_DIRECTORIES
87  "$<TARGET_PROPERTY:somelib::withcolons2,INTERFACE_INCLUDE_DIRECTORIES>"
88)
89
90add_custom_target(test_custom_target
91        "some_bogus_custom_tool"
92        $<TARGET_PROPERTY:TargetIncludeDirectories,COMPILE_DEFINITIONS>
93        WORKING_DIRECTORY
94        "${CMAKE_CURRENT_SOURCE_DIR}")
95
96file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bad")
97file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/bad/common.h" "#error Should not be included\n")
98file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/good")
99file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/good/common.h" "#include \"othergood.h\"\n")
100file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/othergood")
101file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/othergood/othergood.h" "/* No error */\n")
102
103file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libothergood.cpp" "// No content \n")
104add_library(libothergood "${CMAKE_CURRENT_BINARY_DIR}/libothergood.cpp")
105set_property(TARGET libothergood APPEND PROPERTY
106  INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/othergood"
107)
108
109file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libgood.cpp" "// No content \n")
110add_library(libgood "${CMAKE_CURRENT_BINARY_DIR}/libgood.cpp")
111set_property(TARGET libgood APPEND PROPERTY
112  INTERFACE_INCLUDE_DIRECTORIES
113    "${CMAKE_CURRENT_BINARY_DIR}/good;$<TARGET_PROPERTY:libothergood,INTERFACE_INCLUDE_DIRECTORIES>"
114)
115
116file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libbad.cpp" "// No content \n")
117add_library(libbad "${CMAKE_CURRENT_BINARY_DIR}/libbad.cpp")
118set_property(TARGET libbad APPEND PROPERTY
119  INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bad"
120)
121
122add_library(lib6 SHARED other.cpp)
123add_library(lib7 SHARED other.cpp)
124target_link_libraries(lib7 $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:lib6>)
125target_include_directories(lib7 PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:/lib7/include>)
126add_custom_target(head_target_test "some_bogus_custom_tool \"$<TARGET_PROPERTY:lib7,INCLUDE_DIRECTORIES>$<TARGET_PROPERTY:lib7,INTERFACE_INCLUDE_DIRECTORIES>\"")
127
128add_library(includes_source_good empty.cpp)
129target_include_directories(includes_source_good
130  INTERFACE
131    "${CMAKE_CURRENT_BINARY_DIR}/good"
132    "${CMAKE_CURRENT_BINARY_DIR}/othergood/"
133)
134add_library(includes_source_bad empty.cpp)
135target_include_directories(includes_source_bad
136  INTERFACE
137    "${CMAKE_CURRENT_BINARY_DIR}/bad"
138)
139
140add_library(includes_proxy SHARED empty.cpp)
141target_link_libraries(includes_proxy includes_source_good)
142target_link_libraries(includes_proxy LINK_INTERFACE_LIBRARIES includes_source_bad)
143add_executable(copy_includes copy_includes.cpp)
144target_include_directories(copy_includes PRIVATE $<TARGET_PROPERTY:includes_proxy,INCLUDE_DIRECTORIES>)
145
146
147file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp" "#include \"common.h\"\n")
148add_library(lib5 "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp")
149
150# Assuming the link order must be:
151target_link_libraries(lib5 libbad libgood)
152
153# Oops!.
154# As include directory order and link order are the same when using target_link_libraries, we have to
155# get the libgood includes in before the libbad includes.
156# We do that with this command:
157target_include_directories(lib5
158  BEFORE PRIVATE $<TARGET_PROPERTY:libgood,INTERFACE_INCLUDE_DIRECTORIES>
159)
160
161file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat")
162file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat/prefix_foo_bar_bat.h" "/* prefix_foo_bar_bat.h */\n")
163
164target_include_directories(TargetIncludeDirectories PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix_$<JOIN:foo;bar;bat,/prefix_>")
165
166# Test that the language generator expressions work
167set_property(TARGET TargetIncludeDirectories
168  APPEND PROPERTY INCLUDE_DIRECTORIES
169  "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:${CMAKE_CURRENT_BINARY_DIR}/bad>"
170  "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:${CMAKE_CURRENT_BINARY_DIR}/good>"
171  "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:${CMAKE_CURRENT_BINARY_DIR}/othergood/>"
172)
173
174add_executable(TargetIncludeDirectories_C main.c)
175set_property(TARGET TargetIncludeDirectories_C
176  APPEND PROPERTY INCLUDE_DIRECTORIES
177  "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:${CMAKE_CURRENT_BINARY_DIR}/bad>"
178  "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:${CMAKE_CURRENT_BINARY_DIR}/good>"
179  "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:${CMAKE_CURRENT_BINARY_DIR}/othergood/>"
180)
181