368 lines · plain
1#===-- cmake/modules/AddFlangRT.cmake --------------------------------------===#2#3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4# See https://llvm.org/LICENSE.txt for license information.5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6#7#===------------------------------------------------------------------------===#8 9# Builds a library with common options for Flang-RT.10#11# Usage:12#13# add_flangrt_library(name sources ...14# SHARED15# Build a dynamic (.so/.dll) library16# STATIC17# Build a static (.a/.lib) library18# OBJECT19# Always create an object library.20# Without SHARED/STATIC, build only the object library.21# INSTALL_WITH_TOOLCHAIN22# Install library into Clang's resource directory so it can be found by the23# Flang driver during compilation, including tests24# EXCLUDE_FROM_ALL25# Do not build library by default; typically used for libraries needed for26# testing only, no install27# LINK_TO_LLVM28# Library requires include path and linking to LLVM's Support component29# ADDITIONAL_HEADERS30# May specify header files for IDE generators.31# INCLUDE_DIRECTORIES32# Additional target_include_directories for all added targets33# LINK_LIBRARIES34# Additional target_link_libraries for all added targets35# TARGET_PROPERTIES36# Set target properties of all added targets37# )38function (add_flangrt_library name)39 set(options STATIC SHARED OBJECT INSTALL_WITH_TOOLCHAIN EXCLUDE_FROM_ALL LINK_TO_LLVM)40 set(multiValueArgs ADDITIONAL_HEADERS INCLUDE_DIRECTORIES LINK_LIBRARIES TARGET_PROPERTIES)41 cmake_parse_arguments(ARG42 "${options}"43 ""44 "${multiValueArgs}"45 ${ARGN})46 47 if (ARG_INSTALL_WITH_TOOLCHAIN AND ARG_EXCLUDE_FROM_ALL)48 message(SEND_ERROR "add_flangrt_library(${name} ...):49 INSTALL_WITH_TOOLCHAIN and EXCLUDE_FROM_ALL are in conflict. When50 installing an artifact it must have been built first in the 'all' target.51 ")52 endif ()53 54 # Internal names of libraries. If called with just single type option, use55 # the default name for it. Name of targets must only depend on function56 # arguments to be predictable for callers.57 set(name_static "${name}.static")58 set(name_shared "${name}.shared")59 set(name_object "obj.${name}")60 if (ARG_STATIC AND NOT ARG_SHARED)61 set(name_static "${name}")62 elseif (NOT ARG_STATIC AND ARG_SHARED)63 set(name_shared "${name}")64 elseif (NOT ARG_STATIC AND NOT ARG_SHARED AND ARG_OBJECT)65 set(name_object "${name}")66 elseif (NOT ARG_STATIC AND NOT ARG_SHARED AND NOT ARG_OBJECT)67 # Only one of them will actually be built.68 set(name_static "${name}")69 set(name_shared "${name}")70 endif ()71 72 # Determine what to build. If not explicitly specified, honor73 # BUILD_SHARED_LIBS (e.g. for unittest libraries). If can build static and74 # shared, use ENABLE_STATIC/ENABLE_SHARED setting.75 if (ARG_STATIC AND ARG_SHARED)76 set(build_static ${FLANG_RT_ENABLE_STATIC})77 set(build_shared ${FLANG_RT_ENABLE_SHARED})78 else ()79 set(build_static ${ARG_STATIC})80 set(build_shared ${ARG_SHARED})81 endif ()82 if (NOT ARG_STATIC AND NOT ARG_SHARED AND NOT ARG_OBJECT)83 if (BUILD_SHARED_LIBS)84 set(build_shared ON)85 else ()86 set(build_static ON)87 endif ()88 endif ()89 90 # Build an object library if building multiple libraries at once or if91 # explicitly requested.92 set(build_object OFF)93 if (ARG_OBJECT)94 set(build_object ON)95 elseif (build_static AND build_shared)96 set(build_object ON)97 endif ()98 99 # srctargets: targets that contain source files100 # libtargets: static/shared if they are built101 # alltargets: any add_library target added by this function102 set(srctargets "")103 set(libtargets "")104 set(alltargets "")105 if (build_static)106 list(APPEND srctargets "${name_static}")107 list(APPEND libtargets "${name_static}")108 list(APPEND alltargets "${name_static}")109 endif ()110 if (build_shared)111 list(APPEND srctargets "${name_shared}")112 list(APPEND libtargets "${name_shared}")113 list(APPEND alltargets "${name_shared}")114 endif ()115 if (build_object)116 set(srctargets "${name_object}")117 list(APPEND alltargets "${name_object}")118 endif ()119 120 set(extra_args "")121 if (ARG_EXCLUDE_FROM_ALL)122 list(APPEND extra_args EXCLUDE_FROM_ALL)123 endif ()124 125 # Also add header files to IDEs to list as part of the library.126 set_source_files_properties(${ARG_ADDITIONAL_HEADERS} PROPERTIES HEADER_FILE_ONLY ON)127 128 # Create selected library types.129 if (build_object)130 add_library("${name_object}" OBJECT ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})131 set_target_properties(${name_object} PROPERTIES132 POSITION_INDEPENDENT_CODE ON133 FOLDER "Flang-RT/Object Libraries"134 )135 136 # Replace arguments for the libraries we are going to create.137 set(ARG_ADDITIONAL_HEADERS "")138 set(ARG_UNPARSED_ARGUMENTS "$<TARGET_OBJECTS:${name_object}>")139 endif ()140 if (build_static)141 add_library("${name_static}" STATIC ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})142 target_link_libraries("${name_static}" PRIVATE flang-rt-libcxx-headers flang-rt-libc-headers flang-rt-libc-static)143 endif ()144 if (build_shared)145 add_library("${name_shared}" SHARED ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})146 target_link_libraries("${name_shared}" PRIVATE flang-rt-libcxx-headers flang-rt-libc-headers flang-rt-libc-shared)147 if (Threads_FOUND) 148 target_link_libraries(${name_shared} PUBLIC Threads::Threads)149 endif ()150 151 # Special dependencies handling for shared libraries only:152 #153 # flang-rt libraries must not depend on libc++/libstdc++,154 # so set the linker language to C to avoid the unnecessary155 # library dependence. Note that libc++/libstdc++ may still156 # come through CMAKE_CXX_IMPLICIT_LINK_LIBRARIES.157 set_target_properties(${name_shared} PROPERTIES LINKER_LANGUAGE C)158 # Use --as-needed to avoid unnecessary dependencies.159 if (LINKER_AS_NEEDED_OPT)160 target_link_options(${name_shared} BEFORE PRIVATE161 "${LINKER_AS_NEEDED_OPT}"162 )163 endif()164 endif ()165 166 if (libtargets)167 # Provide a default alias which exists in either setting.168 if (BUILD_SHARED_LIBS)169 if (build_shared)170 set(default_target "${name_shared}")171 else ()172 set(default_target "${name_static}")173 endif ()174 else ()175 if (build_static)176 set(default_target "${name_static}")177 else ()178 set(default_target "${name_shared}")179 endif ()180 endif ()181 add_library(${name}.default ALIAS "${default_target}")182 183 # Provide a build target that builds any enabled library.184 # Not intended for target_link_libraries. Either use the ${name}.static,185 # ${name}.shared variants, or ${name}.default to let BUILD_SHARED_LIBS186 # decide.187 if (NOT TARGET ${name})188 add_custom_target(${name})189 add_dependencies(${name} ${libtargets})190 endif ()191 endif ()192 193 foreach (tgtname IN LISTS libtargets)194 if (NOT WIN32)195 # Use same stem name for .a and .so. Common in UNIX environments.196 # Not possible in Windows environments.197 set_target_properties(${tgtname} PROPERTIES OUTPUT_NAME "${name}")198 endif ()199 200 if (ARG_INSTALL_WITH_TOOLCHAIN)201 set_target_properties(${tgtname} PROPERTIES FOLDER "Flang-RT/Toolchain Libraries")202 else ()203 set_target_properties(${tgtname} PROPERTIES FOLDER "Flang-RT/Libraries")204 endif ()205 endforeach ()206 207 set(TARGET_FLAGS)208 if(APPLE)209 set(DARWIN_EMBEDDED_PLATFORMS)210 set(DARWIN_osx_BUILTIN_MIN_VER 10.7)211 set(DARWIN_osx_BUILTIN_MIN_VER_FLAG212 -mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER})213 endif()214 215 # Define how to compile and link the library.216 # Some conceptionally only apply to ${srctargets} or ${libtargets}, but we217 # apply them to ${alltargets}. In worst case, they are ignored by CMake.218 foreach (tgtname IN LISTS alltargets)219 # Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else.220 target_compile_features(${tgtname} PRIVATE cxx_std_17)221 222 # When building the flang runtime if LTO is enabled the archive file223 # contains LLVM IR rather than object code. Currently flang is not224 # LTO aware so cannot link this file to compiled Fortran code.225 if (FLANG_RT_HAS_FNO_LTO_FLAG)226 target_compile_options(${tgtname} PRIVATE -fno-lto)227 endif ()228 229 # Use compiler-specific options to disable exceptions and RTTI.230 if (LLVM_COMPILER_IS_GCC_COMPATIBLE)231 target_compile_options(${tgtname} PRIVATE232 $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -funwind-tables -fno-asynchronous-unwind-tables>233 )234 235 # We define our own _GLIBCXX_THROW_OR_ABORT here because, as of236 # GCC 15.1, the libstdc++ header file <bits/c++config> uses237 # (void)_EXC in its definition of _GLIBCXX_THROW_OR_ABORT to238 # silence a warning.239 #240 # This is a problem for us because some compilers, specifically241 # clang, do not always optimize away that (void)_EXC even though242 # it is unreachable since it occurs after a call to243 # _builtin_abort(). Because _EXC is typically an object derived244 # from std::exception, (void)_EXC, when not optimized away,245 # calls std::exception methods defined in the libstdc++ shared246 # library. We shouldn't link against that library since our247 # build version may conflict with the version used by a hybrid248 # Fortran/C++ application.249 #250 # Redefining _GLIBCXX_THROW_OR_ABORT in this manner is not251 # supported by the maintainers of libstdc++, so future changes252 # to libstdc++ may require future changes to this build script253 # and/or future changes to the Fortran runtime source code.254 target_compile_options(${tgtname} PUBLIC "-D_GLIBCXX_THROW_OR_ABORT(_EXC)=(__builtin_abort())")255 elseif (MSVC)256 target_compile_options(${tgtname} PRIVATE257 $<$<COMPILE_LANGUAGE:CXX>:/EHs-c- /GR->258 )259 elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL")260 target_compile_options(${tgtname} PRIVATE261 $<$<COMPILE_LANGUAGE:CXX>:-qnoeh -qnortti>262 )263 endif ()264 265 # Add target specific options if necessary.266 if ("${LLVM_RUNTIMES_TARGET}" MATCHES "^amdgcn")267 target_compile_options(${tgtname} PRIVATE268 $<$<COMPILE_LANGUAGE:CXX>:-nogpulib -flto -fvisibility=hidden>269 )270 elseif ("${LLVM_RUNTIMES_TARGET}" MATCHES "^nvptx")271 target_compile_options(${tgtname} PRIVATE272 $<$<COMPILE_LANGUAGE:CXX>:-nogpulib -flto -fvisibility=hidden -Wno-unknown-cuda-version --cuda-feature=+ptx63>273 )274 elseif (APPLE)275 # Clang on Darwin enables non-POSIX extensions by default.276 # This causes some macros to leak, such as HUGE from <math.h>, which277 # causes some conflicts with Flang symbols (but not with Flang-RT, for278 # now).279 # It also causes some Flang-RT extensions to be disabled, such as fdate,280 # that checks for _POSIX_C_SOURCE.281 # Setting _POSIX_C_SOURCE avoids these issues.282 target_compile_options(${tgtname} PRIVATE283 $<$<COMPILE_LANGUAGE:CXX>:${DARWIN_osx_BUILTIN_MIN_VER_FLAG} -D_POSIX_C_SOURCE=200809>284 )285 endif ()286 287 # Also for CUDA source when compiling with FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT=CUDA288 if (CMAKE_CUDA_COMPILER_ID MATCHES "NVIDIA")289 # Assuming gcc as host compiler.290 target_compile_options(${tgtname} PRIVATE291 $<$<COMPILE_LANGUAGE:CUDA>:--no-exceptions -Xcompiler -fno-rtti -Xcompiler -fno-unwind-tables -Xcompiler -fno-asynchronous-unwind-tables>292 )293 else ()294 # Assuming a clang-compatible CUDA compiler.295 target_compile_options(${tgtname} PRIVATE296 $<$<COMPILE_LANGUAGE:CUDA>:-fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables>297 )298 endif ()299 300 # Flang-RT's public headers301 target_include_directories(${tgtname} PUBLIC "${FLANG_RT_SOURCE_DIR}/include")302 303 # For ISO_Fortran_binding.h to be found by the runtime itself (Accessed as #include "flang/ISO_Fortran_binding.h")304 # User applications can use #include <ISO_Fortran_binding.h>305 target_include_directories(${tgtname} PUBLIC "${FLANG_SOURCE_DIR}/include")306 307 # For Flang-RT's configured config.h to be found308 target_include_directories(${tgtname} PRIVATE "${FLANG_RT_BINARY_DIR}")309 310 # Disable libstdc++/libc++ assertions, even in an LLVM_ENABLE_ASSERTIONS311 # build, to avoid an unwanted dependency on libstdc++/libc++.so.312 target_compile_definitions(${tgtname} PUBLIC _GLIBCXX_NO_ASSERTIONS)313 if (FLANG_RT_SUPPORTS_UNDEFINE_FLAG)314 target_compile_options(${tgtname} PUBLIC315 "$<$<COMPILE_LANGUAGE:CXX>:-Wp,-U_GLIBCXX_ASSERTIONS>")316 target_compile_options(${tgtname} PUBLIC317 "$<$<COMPILE_LANGUAGE:CXX>:-Wp,-U_LIBCPP_ENABLE_ASSERTIONS>")318 endif ()319 320 # Non-GTest unittests depend on LLVMSupport321 if (ARG_LINK_TO_LLVM)322 if (LLVM_LINK_LLVM_DYLIB)323 set(llvm_libs LLVM)324 else()325 llvm_map_components_to_libnames(llvm_libs Support)326 endif()327 target_link_libraries(${tgtname} PUBLIC ${llvm_libs})328 target_include_directories(${tgtname} PUBLIC ${LLVM_INCLUDE_DIRS})329 endif ()330 331 if (ARG_INCLUDE_DIRECTORIES)332 target_include_directories(${tgtname} ${ARG_INCLUDE_DIRECTORIES})333 endif ()334 335 if (ARG_LINK_LIBRARIES)336 target_link_libraries(${tgtname} PUBLIC ${ARG_LINK_LIBRARIES})337 endif ()338 endforeach ()339 340 foreach (tgtname IN LISTS libtargets)341 # If this is part of the toolchain, put it into the compiler's resource342 # directory. Otherwise it is part of testing and is not installed at all.343 # TODO: Consider multi-configuration builds (MSVC_IDE, "Ninja Multi-Config")344 if (ARG_INSTALL_WITH_TOOLCHAIN)345 set_target_properties(${tgtname}346 PROPERTIES347 ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"348 LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"349 )350 351 install(TARGETS ${tgtname}352 ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"353 LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"354 )355 endif ()356 357 if (ARG_TARGET_PROPERTIES)358 set_target_properties(${tgtname} PROPERTIES ${ARG_TARGET_PROPERTIES})359 endif ()360 361 # flang-rt should build all the Flang-RT targets that are built in an362 # 'all' build.363 if (NOT ARG_EXCLUDE_FROM_ALL)364 add_dependencies(flang-rt ${tgtname})365 endif ()366 endforeach ()367endfunction (add_flangrt_library)368