summaryrefslogtreecommitdiffstats
path: root/Tests/InterfaceLinkLibrariesDirect
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2022-01-12 22:14:40 (GMT)
committerBrad King <brad.king@kitware.com>2022-01-29 11:48:13 (GMT)
commitf3ad061858d03cc2a0569f903df3560152106050 (patch)
treebe604880c112a5b7b6eeee586cf2238c4e952c3e /Tests/InterfaceLinkLibrariesDirect
parent193a999cd5ed345d79b91dae1fd284248ec93ba2 (diff)
downloadCMake-f3ad061858d03cc2a0569f903df3560152106050.zip
CMake-f3ad061858d03cc2a0569f903df3560152106050.tar.gz
CMake-f3ad061858d03cc2a0569f903df3560152106050.tar.bz2
Add usage requirements to update direct link dependencies
Link line construction starts with `LINK_LIBRARIES` and appends dependencies from the transitive closure of `INTERFACE_LINK_LIBRARIES`. Only the entries of `LINK_LIBRARIES` are considered direct link dependencies. In some advanced use cases, particularly involving static libraries and static plugins, usage requirements need to update the list of direct link dependencies. This may mean adding new items, removing existing items, or both. Add target properties to encode these usage requirements: * INTERFACE_LINK_LIBRARIES_DIRECT * INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE Fixes: #22496
Diffstat (limited to 'Tests/InterfaceLinkLibrariesDirect')
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/CMakeLists.txt156
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/ExePlugin.c21
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c18
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/a_always.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_for_exe.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_optional.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_for_exe.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_optional.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/direct_from_A.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe_poison.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional_poison.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/direct_from_A_poison.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_private.c23
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_public.c23
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/main.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_A.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_B.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_B_poison.c6
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_C.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_C_poison.c11
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_D.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_D_poison.c16
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_E.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_E_poison.c21
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_F.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_F_poison.c26
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_G.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_G_poison.c31
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_H.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_H_poison.c36
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_I.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_I_poison.c41
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_J.c3
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_J_poison.c46
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/order_main.c6
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/static_A_private.c16
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/static_A_public.c16
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testExePluginHelperObj.c4
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.c12
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.cmake7
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testSharedLibHelperObj.c4
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.c7
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.cmake6
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.c6
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.cmake14
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testStaticLibPluginExtra.c5
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin1.c4
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin2.c4
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad1.c6
-rw-r--r--Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad2.c7
54 files changed, 703 insertions, 0 deletions
diff --git a/Tests/InterfaceLinkLibrariesDirect/CMakeLists.txt b/Tests/InterfaceLinkLibrariesDirect/CMakeLists.txt
new file mode 100644
index 0000000..b06a2fb
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/CMakeLists.txt
@@ -0,0 +1,156 @@
+cmake_minimum_required(VERSION 3.21)
+project(InterfaceLinkLibrariesDirect C)
+
+include(testStaticLibPlugin.cmake)
+add_executable(InterfaceLinkLibrariesDirect main.c)
+target_link_libraries(InterfaceLinkLibrariesDirect PRIVATE testStaticLibWithPlugin)
+
+include(testSharedLibWithHelper.cmake)
+add_executable(UseSharedLibWithHelper UseSharedLibWithHelper.c)
+target_link_libraries(UseSharedLibWithHelper PRIVATE testSharedLibWithHelper testSharedLibHelperExclude)
+
+include(testExeWithPluginHelper.cmake)
+add_library(ExePlugin MODULE ExePlugin.c)
+target_link_libraries(ExePlugin PRIVATE testExeWithPluginHelper testExePluginHelperExclude)
+
+#----------------------------------------------------------------------------
+
+# Offer usage requirements and symbols to be used through static libs below.
+add_library(A STATIC
+ a_always.c
+
+ # Good symbols that direct_from_A libraries poison if incorrectly used.
+ a_not_direct_from_A.c
+ a_not_direct_from_A_for_exe.c
+ a_not_direct_from_A_optional.c
+
+ # Bad symbols in direct_from_A libraries below to ensure they come first.
+ a_poison_direct_from_A.c
+ a_poison_direct_from_A_for_exe.c
+ a_poison_direct_from_A_optional.c
+ )
+
+# Propagates as usage requirement from A.
+add_library(direct_from_A STATIC direct_from_A.c direct_from_A_poison.c)
+target_compile_definitions(direct_from_A INTERFACE DEF_DIRECT_FROM_A)
+set_property(TARGET A APPEND PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT direct_from_A)
+
+# Propagates as usage requirement from A, but only for executables.
+add_library(direct_from_A_for_exe STATIC direct_from_A_for_exe.c direct_from_A_for_exe_poison.c)
+target_compile_definitions(direct_from_A_for_exe INTERFACE DEF_DIRECT_FROM_A_FOR_EXE)
+set_property(TARGET A APPEND PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT
+ "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:direct_from_A_for_exe>")
+
+# Propagates as usage requirement from A, but only for targets that opt-in.
+add_library(direct_from_A_optional STATIC direct_from_A_optional.c direct_from_A_optional_poison.c)
+target_compile_definitions(direct_from_A_optional INTERFACE DEF_DIRECT_FROM_A_OPTIONAL)
+set_property(TARGET A APPEND PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT
+ "$<$<BOOL:$<TARGET_PROPERTY:A_LINK_OPTIONAL>>:direct_from_A_optional>")
+
+# Uses and propagates A's usage requirements.
+# Does not use the exe-only or optional usage requirements.
+add_library(static_A_public STATIC static_A_public.c)
+target_link_libraries(static_A_public PUBLIC A)
+
+# Uses A's usage requirements, but does not propagate them.
+# Does not use the exe-only usage requirement. Does use the optional one.
+add_library(static_A_private STATIC static_A_private.c)
+target_link_libraries(static_A_private PRIVATE A)
+set_property(TARGET static_A_private PROPERTY A_LINK_OPTIONAL 1)
+
+# Uses A's usage requirements, including an optional one.
+add_executable(exe_use_static_A_public exe_use_static_A_public.c)
+target_link_libraries(exe_use_static_A_public PRIVATE static_A_public)
+set_property(TARGET exe_use_static_A_public PROPERTY A_LINK_OPTIONAL 1)
+
+# Does not use A's usage requirements.
+add_executable(exe_use_static_A_private exe_use_static_A_private.c)
+target_link_libraries(exe_use_static_A_private PRIVATE static_A_private)
+
+#----------------------------------------------------------------------------
+
+# Test how original and injected dependencies get ordered.
+
+# A bunch of static libraries that need to be linked in alphabetic order.
+# Each library has an extra source to poison all symbols meant to be
+# provided by earlier libraries. This enforces ordering on platforms
+# whose linkers re-visit static libraries.
+add_library(order_A STATIC order_A.c)
+add_library(order_B STATIC order_B.c order_B_poison.c)
+add_library(order_C STATIC order_C.c order_C_poison.c)
+add_library(order_D STATIC order_D.c order_D_poison.c)
+add_library(order_E STATIC order_E.c order_E_poison.c)
+add_library(order_F STATIC order_F.c order_F_poison.c)
+add_library(order_G STATIC order_G.c order_G_poison.c)
+add_library(order_H STATIC order_H.c order_H_poison.c)
+add_library(order_I STATIC order_I.c order_I_poison.c)
+add_library(order_J STATIC order_J.c order_J_poison.c)
+
+# An executable to drive linking.
+add_executable(order_main order_main.c)
+
+# In the following diagram, connection by a slash means the top
+# target lists the bottom target in a link interface property:
+#
+# \ => INTERFACE_LINK_LIBRARIES
+# / => INTERFACE_LINK_LIBRARIES_DIRECT
+#
+# The top of each tree represents an entry in the exe's LINK_LIBRARIES.
+# CMake should evaluate this graph to generate the proper link order.
+#
+# D H
+# / \ / \
+# B J F I
+# / / / / \
+# A C E G J
+set_property(TARGET order_main PROPERTY LINK_LIBRARIES order_D order_H)
+set_property(TARGET order_D PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_B)
+set_property(TARGET order_D PROPERTY INTERFACE_LINK_LIBRARIES order_J)
+set_property(TARGET order_B PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_A)
+set_property(TARGET order_J PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_C)
+set_property(TARGET order_H PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_F)
+set_property(TARGET order_H PROPERTY INTERFACE_LINK_LIBRARIES order_I)
+set_property(TARGET order_F PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_E)
+set_property(TARGET order_I PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_G)
+set_property(TARGET order_I PROPERTY INTERFACE_LINK_LIBRARIES order_J)
+
+#----------------------------------------------------------------------------
+
+# Test that the original LINK_LIBRARIES cannot be re-ordered by injection
+# from usage requirements.
+
+# A bunch of static libraries that need to be linked in alphabetic order.
+# Each library has an extra source to poison all symbols meant to be
+# provided by earlier libraries. This enforces ordering on platforms
+# whose linkers re-visit static libraries.
+add_library(force_A STATIC order_A.c)
+add_library(force_B STATIC order_B.c order_B_poison.c)
+add_library(force_C STATIC order_C.c order_C_poison.c)
+add_library(force_D STATIC order_D.c order_D_poison.c)
+add_library(force_E STATIC order_E.c order_E_poison.c)
+add_library(force_F STATIC order_F.c order_F_poison.c)
+add_library(force_G STATIC order_G.c order_G_poison.c)
+add_library(force_H STATIC order_H.c order_H_poison.c)
+add_library(force_I STATIC order_I.c order_I_poison.c)
+add_library(force_J STATIC order_J.c order_J_poison.c)
+
+# An executable to drive linking.
+add_executable(force_main order_main.c)
+
+# The executable explicitly lists all the libraries in the right order.
+target_link_libraries(force_main PRIVATE force_A force_B force_C force_D force_E force_F force_G force_H)
+
+# Add legitimate normal dependencies.
+set_property(TARGET force_D PROPERTY INTERFACE_LINK_LIBRARIES force_J)
+set_property(TARGET force_H PROPERTY INTERFACE_LINK_LIBRARIES force_I)
+set_property(TARGET force_I PROPERTY INTERFACE_LINK_LIBRARIES force_J)
+
+# Add bogus injected direct dependencies to verify that they do not
+# change the original order of LINK_LIBRARIES.
+set_property(TARGET force_A PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_B)
+set_property(TARGET force_B PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_C)
+set_property(TARGET force_C PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_D)
+set_property(TARGET force_D PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_E)
+set_property(TARGET force_E PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_F)
+set_property(TARGET force_F PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_G)
+set_property(TARGET force_G PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_H)
diff --git a/Tests/InterfaceLinkLibrariesDirect/ExePlugin.c b/Tests/InterfaceLinkLibrariesDirect/ExePlugin.c
new file mode 100644
index 0000000..40a261c
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/ExePlugin.c
@@ -0,0 +1,21 @@
+extern int testExePluginHelperObj(int n);
+
+#ifdef testExePluginHelperObj_NO_OBJECT
+int testExePluginHelperObj(int n)
+{
+ return n;
+}
+#endif
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ int testExePluginAPI(int n);
+
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ int testExePlugin(int n)
+{
+ return testExePluginAPI(n) + testExePluginHelperObj(n);
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c b/Tests/InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c
new file mode 100644
index 0000000..832e31f
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c
@@ -0,0 +1,18 @@
+extern int testSharedLibHelperObj(int n);
+
+#ifdef testSharedLibHelperObj_NO_OBJECT
+int testSharedLibHelperObj(int n)
+{
+ return n;
+}
+#endif
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ int testSharedLibWithHelper(int n);
+
+int main(void)
+{
+ return testSharedLibWithHelper(0) + testSharedLibHelperObj(0);
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/a_always.c b/Tests/InterfaceLinkLibrariesDirect/a_always.c
new file mode 100644
index 0000000..007680d
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/a_always.c
@@ -0,0 +1,3 @@
+void a_always(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A.c b/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A.c
new file mode 100644
index 0000000..732d36e
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A.c
@@ -0,0 +1,3 @@
+void not_direct_from_A(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_for_exe.c b/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_for_exe.c
new file mode 100644
index 0000000..9aed296
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_for_exe.c
@@ -0,0 +1,3 @@
+void not_direct_from_A_for_exe(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_optional.c b/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_optional.c
new file mode 100644
index 0000000..3572e51
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/a_not_direct_from_A_optional.c
@@ -0,0 +1,3 @@
+void not_direct_from_A_optional(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A.c b/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A.c
new file mode 100644
index 0000000..6d1963d
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A.c
@@ -0,0 +1,5 @@
+extern void poison_direct_from_A(void);
+void direct_from_A(void)
+{
+ poison_direct_from_A();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_for_exe.c b/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_for_exe.c
new file mode 100644
index 0000000..623fc07
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_for_exe.c
@@ -0,0 +1,5 @@
+extern void poison_direct_from_A_for_exe(void);
+void direct_from_A_for_exe(void)
+{
+ poison_direct_from_A_for_exe();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_optional.c b/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_optional.c
new file mode 100644
index 0000000..0f1328e
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/a_poison_direct_from_A_optional.c
@@ -0,0 +1,5 @@
+extern void poison_direct_from_A_optional(void);
+void direct_from_A_optional(void)
+{
+ poison_direct_from_A_optional();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/direct_from_A.c b/Tests/InterfaceLinkLibrariesDirect/direct_from_A.c
new file mode 100644
index 0000000..d6d0df3
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/direct_from_A.c
@@ -0,0 +1,3 @@
+void direct_from_A(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe.c b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe.c
new file mode 100644
index 0000000..dfa6db1
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe.c
@@ -0,0 +1,3 @@
+void direct_from_A_for_exe(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe_poison.c b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe_poison.c
new file mode 100644
index 0000000..c0ecb0b
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_for_exe_poison.c
@@ -0,0 +1,5 @@
+extern void poison_not_direct_from_A_for_exe(void);
+void not_direct_from_A_for_exe(void)
+{
+ poison_not_direct_from_A_for_exe();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional.c b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional.c
new file mode 100644
index 0000000..affdaeb
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional.c
@@ -0,0 +1,3 @@
+void direct_from_A_optional(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional_poison.c b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional_poison.c
new file mode 100644
index 0000000..c7c3528
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_optional_poison.c
@@ -0,0 +1,5 @@
+extern void poison_not_direct_from_A_optional(void);
+void not_direct_from_A_optional(void)
+{
+ poison_not_direct_from_A_optional();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/direct_from_A_poison.c b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_poison.c
new file mode 100644
index 0000000..b03cdf7
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/direct_from_A_poison.c
@@ -0,0 +1,5 @@
+extern void poison_not_direct_from_A(void);
+void not_direct_from_A(void)
+{
+ poison_not_direct_from_A();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_private.c b/Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_private.c
new file mode 100644
index 0000000..024e96e
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_private.c
@@ -0,0 +1,23 @@
+#ifdef DEF_DIRECT_FROM_A
+# error "DEF_DIRECT_FROM_A incorrectly defined"
+#endif
+#ifdef DEF_DIRECT_FROM_A_FOR_EXE
+# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly defined"
+#endif
+#ifdef DEF_DIRECT_FROM_A_OPTIONAL
+# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly defined"
+#endif
+
+extern void static_A_private(void);
+extern void not_direct_from_A(void);
+extern void not_direct_from_A_for_exe(void);
+extern void not_direct_from_A_optional(void);
+
+int main(void)
+{
+ static_A_private();
+ not_direct_from_A();
+ not_direct_from_A_for_exe();
+ not_direct_from_A_optional();
+ return 0;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_public.c b/Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_public.c
new file mode 100644
index 0000000..b3b0a56
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/exe_use_static_A_public.c
@@ -0,0 +1,23 @@
+#ifndef DEF_DIRECT_FROM_A
+# error "DEF_DIRECT_FROM_A incorrectly not defined"
+#endif
+#ifndef DEF_DIRECT_FROM_A_FOR_EXE
+# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly not defined"
+#endif
+#ifndef DEF_DIRECT_FROM_A_OPTIONAL
+# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly not defined"
+#endif
+
+extern void static_A_public(void);
+extern void direct_from_A(void);
+extern void direct_from_A_for_exe(void);
+extern void direct_from_A_optional(void);
+
+int main(void)
+{
+ static_A_public();
+ direct_from_A();
+ direct_from_A_for_exe();
+ direct_from_A_optional();
+ return 0;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/main.c b/Tests/InterfaceLinkLibrariesDirect/main.c
new file mode 100644
index 0000000..53f0e6d
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/main.c
@@ -0,0 +1,5 @@
+extern int testStaticLibPlugin(void);
+int main(void)
+{
+ return testStaticLibPlugin();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_A.c b/Tests/InterfaceLinkLibrariesDirect/order_A.c
new file mode 100644
index 0000000..2cd4d60
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_A.c
@@ -0,0 +1,5 @@
+extern void order_B(void);
+void order_A(void)
+{
+ order_B();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_B.c b/Tests/InterfaceLinkLibrariesDirect/order_B.c
new file mode 100644
index 0000000..1787f1d
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_B.c
@@ -0,0 +1,5 @@
+extern void order_C(void);
+void order_B(void)
+{
+ order_C();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_B_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_B_poison.c
new file mode 100644
index 0000000..bcb7b4b
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_B_poison.c
@@ -0,0 +1,6 @@
+extern void order_B_poison(void);
+
+void order_A(void)
+{
+ order_B_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_C.c b/Tests/InterfaceLinkLibrariesDirect/order_C.c
new file mode 100644
index 0000000..e67e719
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_C.c
@@ -0,0 +1,5 @@
+extern void order_D(void);
+void order_C(void)
+{
+ order_D();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_C_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_C_poison.c
new file mode 100644
index 0000000..fc31104
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_C_poison.c
@@ -0,0 +1,11 @@
+extern void order_C_poison(void);
+
+void order_A(void)
+{
+ order_C_poison();
+}
+
+void order_B(void)
+{
+ order_C_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_D.c b/Tests/InterfaceLinkLibrariesDirect/order_D.c
new file mode 100644
index 0000000..f5bb2d6
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_D.c
@@ -0,0 +1,5 @@
+extern void order_E(void);
+void order_D(void)
+{
+ order_E();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_D_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_D_poison.c
new file mode 100644
index 0000000..d2d64e6
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_D_poison.c
@@ -0,0 +1,16 @@
+extern void order_D_poison(void);
+
+void order_A(void)
+{
+ order_D_poison();
+}
+
+void order_B(void)
+{
+ order_D_poison();
+}
+
+void order_C(void)
+{
+ order_D_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_E.c b/Tests/InterfaceLinkLibrariesDirect/order_E.c
new file mode 100644
index 0000000..2a56443
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_E.c
@@ -0,0 +1,5 @@
+extern void order_F(void);
+void order_E(void)
+{
+ order_F();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_E_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_E_poison.c
new file mode 100644
index 0000000..7d8b53e
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_E_poison.c
@@ -0,0 +1,21 @@
+extern void order_E_poison(void);
+
+void order_A(void)
+{
+ order_E_poison();
+}
+
+void order_B(void)
+{
+ order_E_poison();
+}
+
+void order_C(void)
+{
+ order_E_poison();
+}
+
+void order_D(void)
+{
+ order_E_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_F.c b/Tests/InterfaceLinkLibrariesDirect/order_F.c
new file mode 100644
index 0000000..d242284
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_F.c
@@ -0,0 +1,5 @@
+extern void order_G(void);
+void order_F(void)
+{
+ order_G();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_F_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_F_poison.c
new file mode 100644
index 0000000..285f247
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_F_poison.c
@@ -0,0 +1,26 @@
+extern void order_F_poison(void);
+
+void order_A(void)
+{
+ order_F_poison();
+}
+
+void order_B(void)
+{
+ order_F_poison();
+}
+
+void order_C(void)
+{
+ order_F_poison();
+}
+
+void order_D(void)
+{
+ order_F_poison();
+}
+
+void order_E(void)
+{
+ order_F_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_G.c b/Tests/InterfaceLinkLibrariesDirect/order_G.c
new file mode 100644
index 0000000..ff71038
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_G.c
@@ -0,0 +1,5 @@
+extern void order_H(void);
+void order_G(void)
+{
+ order_H();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_G_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_G_poison.c
new file mode 100644
index 0000000..3a1fe1d
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_G_poison.c
@@ -0,0 +1,31 @@
+extern void order_G_poison(void);
+
+void order_A(void)
+{
+ order_G_poison();
+}
+
+void order_B(void)
+{
+ order_G_poison();
+}
+
+void order_C(void)
+{
+ order_G_poison();
+}
+
+void order_D(void)
+{
+ order_G_poison();
+}
+
+void order_E(void)
+{
+ order_G_poison();
+}
+
+void order_F(void)
+{
+ order_G_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_H.c b/Tests/InterfaceLinkLibrariesDirect/order_H.c
new file mode 100644
index 0000000..9c62bb1
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_H.c
@@ -0,0 +1,5 @@
+extern void order_I(void);
+void order_H(void)
+{
+ order_I();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_H_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_H_poison.c
new file mode 100644
index 0000000..0c6b84f
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_H_poison.c
@@ -0,0 +1,36 @@
+extern void order_H_poison(void);
+
+void order_A(void)
+{
+ order_H_poison();
+}
+
+void order_B(void)
+{
+ order_H_poison();
+}
+
+void order_C(void)
+{
+ order_H_poison();
+}
+
+void order_D(void)
+{
+ order_H_poison();
+}
+
+void order_E(void)
+{
+ order_H_poison();
+}
+
+void order_F(void)
+{
+ order_H_poison();
+}
+
+void order_G(void)
+{
+ order_H_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_I.c b/Tests/InterfaceLinkLibrariesDirect/order_I.c
new file mode 100644
index 0000000..96152de
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_I.c
@@ -0,0 +1,5 @@
+extern void order_J(void);
+void order_I(void)
+{
+ order_J();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_I_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_I_poison.c
new file mode 100644
index 0000000..3fabe1f
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_I_poison.c
@@ -0,0 +1,41 @@
+extern void order_I_poison(void);
+
+void order_A(void)
+{
+ order_I_poison();
+}
+
+void order_B(void)
+{
+ order_I_poison();
+}
+
+void order_C(void)
+{
+ order_I_poison();
+}
+
+void order_D(void)
+{
+ order_I_poison();
+}
+
+void order_E(void)
+{
+ order_I_poison();
+}
+
+void order_F(void)
+{
+ order_I_poison();
+}
+
+void order_G(void)
+{
+ order_I_poison();
+}
+
+void order_H(void)
+{
+ order_I_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_J.c b/Tests/InterfaceLinkLibrariesDirect/order_J.c
new file mode 100644
index 0000000..49eec47
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_J.c
@@ -0,0 +1,3 @@
+void order_J(void)
+{
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_J_poison.c b/Tests/InterfaceLinkLibrariesDirect/order_J_poison.c
new file mode 100644
index 0000000..9724fd5
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_J_poison.c
@@ -0,0 +1,46 @@
+extern void order_J_poison(void);
+
+void order_A(void)
+{
+ order_J_poison();
+}
+
+void order_B(void)
+{
+ order_J_poison();
+}
+
+void order_C(void)
+{
+ order_J_poison();
+}
+
+void order_D(void)
+{
+ order_J_poison();
+}
+
+void order_E(void)
+{
+ order_J_poison();
+}
+
+void order_F(void)
+{
+ order_J_poison();
+}
+
+void order_G(void)
+{
+ order_J_poison();
+}
+
+void order_H(void)
+{
+ order_J_poison();
+}
+
+void order_I(void)
+{
+ order_J_poison();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/order_main.c b/Tests/InterfaceLinkLibrariesDirect/order_main.c
new file mode 100644
index 0000000..eed2453
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/order_main.c
@@ -0,0 +1,6 @@
+extern void order_A(void);
+int main(void)
+{
+ order_A();
+ return 0;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/static_A_private.c b/Tests/InterfaceLinkLibrariesDirect/static_A_private.c
new file mode 100644
index 0000000..d98a22c
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/static_A_private.c
@@ -0,0 +1,16 @@
+#ifndef DEF_DIRECT_FROM_A
+# error "DEF_DIRECT_FROM_A incorrectly not defined"
+#endif
+#ifdef DEF_DIRECT_FROM_A_FOR_EXE
+# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly defined"
+#endif
+#ifndef DEF_DIRECT_FROM_A_OPTIONAL
+# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly not defined"
+#endif
+
+extern void a_always(void);
+
+void static_A_private(void)
+{
+ a_always();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/static_A_public.c b/Tests/InterfaceLinkLibrariesDirect/static_A_public.c
new file mode 100644
index 0000000..ed88ca6
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/static_A_public.c
@@ -0,0 +1,16 @@
+#ifndef DEF_DIRECT_FROM_A
+# error "DEF_DIRECT_FROM_A incorrectly not defined"
+#endif
+#ifdef DEF_DIRECT_FROM_A_FOR_EXE
+# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly defined"
+#endif
+#ifdef DEF_DIRECT_FROM_A_OPTIONAL
+# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly defined"
+#endif
+
+extern void a_always(void);
+
+void static_A_public(void)
+{
+ a_always();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testExePluginHelperObj.c b/Tests/InterfaceLinkLibrariesDirect/testExePluginHelperObj.c
new file mode 100644
index 0000000..49c495f
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testExePluginHelperObj.c
@@ -0,0 +1,4 @@
+int testExePluginHelperObj(int n)
+{
+ return n;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.c b/Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.c
new file mode 100644
index 0000000..f8787db
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int testExePluginAPI(int n)
+{
+ return n;
+}
+
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.cmake b/Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.cmake
new file mode 100644
index 0000000..97c5b65
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testExeWithPluginHelper.cmake
@@ -0,0 +1,7 @@
+# Logic common to InterfaceLinkLibrariesDirect and ExportImport tests.
+set(src ${CMAKE_CURRENT_LIST_DIR})
+add_executable(testExeWithPluginHelper ${src}/testExeWithPluginHelper.c)
+add_library(testExePluginHelperObj OBJECT ${src}/testExePluginHelperObj.c)
+set_property(TARGET testExeWithPluginHelper PROPERTY ENABLE_EXPORTS 1)
+set_property(TARGET testExeWithPluginHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT $<TARGET_NAME:testExePluginHelperObj>)
+set_property(TARGET testExeWithPluginHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE $<1:testExePluginHelperExclude>)
diff --git a/Tests/InterfaceLinkLibrariesDirect/testSharedLibHelperObj.c b/Tests/InterfaceLinkLibrariesDirect/testSharedLibHelperObj.c
new file mode 100644
index 0000000..9d55fcb
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testSharedLibHelperObj.c
@@ -0,0 +1,4 @@
+int testSharedLibHelperObj(int n)
+{
+ return n;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.c b/Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.c
new file mode 100644
index 0000000..f942b54
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.c
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int testSharedLibWithHelper(int n)
+{
+ return n;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.cmake b/Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.cmake
new file mode 100644
index 0000000..c51751c
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testSharedLibWithHelper.cmake
@@ -0,0 +1,6 @@
+# Logic common to InterfaceLinkLibrariesDirect and ExportImport tests.
+set(src ${CMAKE_CURRENT_LIST_DIR})
+add_library(testSharedLibWithHelper SHARED ${src}/testSharedLibWithHelper.c)
+add_library(testSharedLibHelperObj OBJECT ${src}/testSharedLibHelperObj.c)
+set_property(TARGET testSharedLibWithHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT $<TARGET_NAME:testSharedLibHelperObj>)
+set_property(TARGET testSharedLibWithHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE $<1:testSharedLibHelperExclude>)
diff --git a/Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.c b/Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.c
new file mode 100644
index 0000000..17f643f
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.c
@@ -0,0 +1,6 @@
+extern int testStaticLibWithPlugin1(void);
+extern int testStaticLibPluginExtra(void);
+int testStaticLibPlugin(void)
+{
+ return testStaticLibWithPlugin1() + testStaticLibPluginExtra();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.cmake b/Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.cmake
new file mode 100644
index 0000000..907872f
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testStaticLibPlugin.cmake
@@ -0,0 +1,14 @@
+# Logic common to InterfaceLinkLibrariesDirect and ExportImport tests.
+set(src ${CMAKE_CURRENT_LIST_DIR})
+add_library(testStaticLibWithPlugin STATIC
+ ${src}/testStaticLibWithPlugin1.c # used by testStaticLibPlugin
+ ${src}/testStaticLibWithPlugin2.c # used by testStaticLibPluginExtra
+ ${src}/testStaticLibWithPluginBad1.c # link error if not after testStaticLibPlugin
+ ${src}/testStaticLibWithPluginBad2.c # link error if not after testStaticLibPluginExtra
+ )
+add_library(testStaticLibPluginExtra STATIC ${src}/testStaticLibPluginExtra.c)
+add_library(testStaticLibPlugin STATIC ${src}/testStaticLibPlugin.c)
+target_link_libraries(testStaticLibPlugin PUBLIC testStaticLibWithPlugin testStaticLibPluginExtra)
+target_link_libraries(testStaticLibPluginExtra PUBLIC testStaticLibWithPlugin)
+set_property(TARGET testStaticLibWithPlugin PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT testStaticLibPlugin)
+set_property(TARGET testStaticLibWithPlugin PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE testStaticLibWithPlugin)
diff --git a/Tests/InterfaceLinkLibrariesDirect/testStaticLibPluginExtra.c b/Tests/InterfaceLinkLibrariesDirect/testStaticLibPluginExtra.c
new file mode 100644
index 0000000..11fe0f8
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testStaticLibPluginExtra.c
@@ -0,0 +1,5 @@
+extern int testStaticLibWithPlugin2(void);
+int testStaticLibPluginExtra(void)
+{
+ return testStaticLibWithPlugin2();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin1.c b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin1.c
new file mode 100644
index 0000000..5e75dce
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin1.c
@@ -0,0 +1,4 @@
+int testStaticLibWithPlugin1(void)
+{
+ return 0;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin2.c b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin2.c
new file mode 100644
index 0000000..74ac1ae
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPlugin2.c
@@ -0,0 +1,4 @@
+int testStaticLibWithPlugin2(void)
+{
+ return 0;
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad1.c b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad1.c
new file mode 100644
index 0000000..b41abc9
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad1.c
@@ -0,0 +1,6 @@
+/* Produce an error if if the object compiled from this source is used. */
+extern int testStaticLibWithPlugin_linked_before_testStaticLibPlugin(void);
+int testStaticLibPlugin(void)
+{
+ return testStaticLibWithPlugin_linked_before_testStaticLibPlugin();
+}
diff --git a/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad2.c b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad2.c
new file mode 100644
index 0000000..43337a5
--- /dev/null
+++ b/Tests/InterfaceLinkLibrariesDirect/testStaticLibWithPluginBad2.c
@@ -0,0 +1,7 @@
+/* Produce an error if if the object compiled from this source is used. */
+extern int testStaticLibWithPlugin_linked_before_testStaticLibPluginExtra(
+ void);
+int testStaticLibPluginExtra(void)
+{
+ return testStaticLibWithPlugin_linked_before_testStaticLibPluginExtra();
+}