Add the initializes attribute inference (#117104)
[llvm-project.git] / libcxx / cmake / Modules / HandleLibCXXABI.cmake
blob52236f473f35de42fda90ca8d411d7ad66408e62
1 #===============================================================================
2 # Define targets for linking against the selected ABI library
4 # After including this file, the following targets are defined:
5 # - libcxx-abi-headers: An interface target that allows getting access to the
6 #                       headers of the selected ABI library.
7 # - libcxx-abi-shared: A target representing the selected shared ABI library.
8 # - libcxx-abi-static: A target representing the selected static ABI library.
10 # Furthermore, some ABI libraries also define the following target:
11 # - libcxx-abi-shared-objects: An object library representing a set of object files
12 #                              constituting the ABI library, suitable for bundling
13 #                              into a shared library.
14 # - libcxx-abi-static-objects: An object library representing a set of object files
15 #                              constituting the ABI library, suitable for bundling
16 #                              into a static library.
17 #===============================================================================
19 include(GNUInstallDirs)
21 # This function copies the provided headers to a private directory and adds that
22 # path to the given INTERFACE target. That target can then be linked against to
23 # get access to those headers (and only those).
25 # The problem this solves is that when building against a system-provided ABI library,
26 # the ABI headers might live side-by-side with an actual C++ Standard Library
27 # installation. For that reason, we can't just add `-I <path-to-ABI-headers>`,
28 # since we would end up also adding the system-provided C++ Standard Library to
29 # the search path. Instead, what we do is copy just the ABI library headers to
30 # a private directory and add just that path when we build libc++.
31 function(import_private_headers target include_dirs headers)
32   foreach(header ${headers})
33     set(found FALSE)
34     foreach(incpath ${include_dirs})
35       if (EXISTS "${incpath}/${header}")
36         set(found TRUE)
37         message(STATUS "Looking for ${header} in ${incpath} - found")
38         get_filename_component(dstdir ${header} PATH)
39         get_filename_component(header_file ${header} NAME)
40         set(src ${incpath}/${header})
41         set(dst "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}/${header_file}")
43         add_custom_command(OUTPUT ${dst}
44             DEPENDS ${src}
45             COMMAND ${CMAKE_COMMAND} -E make_directory "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}"
46             COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
47             COMMENT "Copying C++ ABI header ${header}")
48         list(APPEND abilib_headers "${dst}")
49       else()
50         message(STATUS "Looking for ${header} in ${incpath} - not found")
51       endif()
52     endforeach()
53     if (NOT found)
54       message(WARNING "Failed to find ${header} in ${include_dirs}")
55     endif()
56   endforeach()
58   # Work around https://gitlab.kitware.com/cmake/cmake/-/issues/18399
59   add_library(${target}-generate-private-headers OBJECT ${abilib_headers})
60   set_target_properties(${target}-generate-private-headers PROPERTIES LINKER_LANGUAGE CXX)
62   target_link_libraries(${target} INTERFACE ${target}-generate-private-headers)
63   target_include_directories(${target} INTERFACE "${LIBCXX_BINARY_DIR}/private-abi-headers")
64 endfunction()
66 # This function creates an imported static library named <target>.
67 # It imports a library named <name> searched at the given <path>.
68 function(import_static_library target path name)
69   add_library(${target} STATIC IMPORTED GLOBAL)
70   find_library(file
71     NAMES "${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}"
72     PATHS "${path}"
73     NO_CACHE)
74   set_target_properties(${target} PROPERTIES IMPORTED_LOCATION "${file}")
75 endfunction()
77 # This function creates an imported shared (interface) library named <target>
78 # for the given library <name>.
79 function(import_shared_library target name)
80   add_library(${target} INTERFACE IMPORTED GLOBAL)
81   set_target_properties(${target} PROPERTIES IMPORTED_LIBNAME "${name}")
82 endfunction()
84 # Link against a system-provided libstdc++
85 if ("${LIBCXX_CXX_ABI}" STREQUAL "libstdc++")
86   if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS)
87     message(FATAL_ERROR "LIBCXX_CXX_ABI_INCLUDE_PATHS must be set when selecting libstdc++ as an ABI library")
88   endif()
90   add_library(libcxx-abi-headers INTERFACE)
91   import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}"
92     "cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h")
93   target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBSTDCXX" "-D__GLIBCXX__")
95   import_shared_library(libcxx-abi-shared stdc++)
96   target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
98   import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" stdc++)
99   target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
101 # Link against a system-provided libsupc++
102 elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libsupc++")
103   if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS)
104     message(FATAL_ERROR "LIBCXX_CXX_ABI_INCLUDE_PATHS must be set when selecting libsupc++ as an ABI library")
105   endif()
107   add_library(libcxx-abi-headers INTERFACE)
108   import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}"
109     "cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h")
110   target_compile_definitions(libcxx-abi-headers INTERFACE "-D__GLIBCXX__")
112   import_shared_library(libcxx-abi-shared supc++)
113   target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
115   import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" supc++)
116   target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
118 # Link against the in-tree libc++abi
119 elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxabi")
120   add_library(libcxx-abi-headers INTERFACE)
121   target_link_libraries(libcxx-abi-headers INTERFACE cxxabi-headers)
122   target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI")
124   if (TARGET cxxabi_shared)
125     add_library(libcxx-abi-shared INTERFACE)
126     target_link_libraries(libcxx-abi-shared INTERFACE cxxabi_shared)
128     # When using the in-tree libc++abi as an ABI library, libc++ re-exports the
129     # libc++abi symbols (on platforms where it can) because libc++abi is only an
130     # implementation detail of libc++.
131     target_link_libraries(libcxx-abi-shared INTERFACE cxxabi-reexports)
133     # Populate the OUTPUT_NAME property of libcxx-abi-shared because that is used when
134     # generating a linker script.
135     get_target_property(_output_name cxxabi_shared OUTPUT_NAME)
136     set_target_properties(libcxx-abi-shared PROPERTIES "OUTPUT_NAME" "${_output_name}")
137   endif()
139   if (TARGET cxxabi_static)
140     add_library(libcxx-abi-static ALIAS cxxabi_static)
141   endif()
143   if (TARGET cxxabi_shared_objects)
144     add_library(libcxx-abi-shared-objects ALIAS cxxabi_shared_objects)
145   endif()
147   if (TARGET cxxabi_static_objects)
148     add_library(libcxx-abi-static-objects ALIAS cxxabi_static_objects)
149   endif()
151 # Link against a system-provided libc++abi
152 elseif ("${LIBCXX_CXX_ABI}" STREQUAL "system-libcxxabi")
153   if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS)
154     message(FATAL_ERROR "LIBCXX_CXX_ABI_INCLUDE_PATHS must be set when selecting system-libcxxabi as an ABI library")
155   endif()
157   add_library(libcxx-abi-headers INTERFACE)
158   import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" "cxxabi.h;__cxxabi_config.h")
159   target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI")
161   import_shared_library(libcxx-abi-shared c++abi)
162   target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
164   import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" c++abi)
165   target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
167 # Link against a system-provided libcxxrt
168 elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxrt")
169   if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS)
170     message(STATUS "LIBCXX_CXX_ABI_INCLUDE_PATHS not set, using /usr/include/c++/v1")
171     set(LIBCXX_CXX_ABI_INCLUDE_PATHS "/usr/include/c++/v1")
172   endif()
173   add_library(libcxx-abi-headers INTERFACE)
174   import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}"
175     "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h")
176   target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXXRT")
178   import_shared_library(libcxx-abi-shared cxxrt)
179   target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
181   import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" cxxrt)
182   target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
184 # Link against a system-provided vcruntime
185 # FIXME: Figure out how to configure the ABI library on Windows.
186 elseif ("${LIBCXX_CXX_ABI}" STREQUAL "vcruntime")
187   add_library(libcxx-abi-headers INTERFACE)
188   add_library(libcxx-abi-shared INTERFACE)
189   add_library(libcxx-abi-static INTERFACE)
191 # Don't link against any ABI library
192 elseif ("${LIBCXX_CXX_ABI}" STREQUAL "none")
193   add_library(libcxx-abi-headers INTERFACE)
194   target_compile_definitions(libcxx-abi-headers INTERFACE "-D_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY")
196   add_library(libcxx-abi-shared INTERFACE)
197   target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
199   add_library(libcxx-abi-static INTERFACE)
200   target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
201 endif()