1# 2# Copyright 2017 The Abseil Authors. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# https://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17include(CMakeParseArguments) 18include(AbseilConfigureCopts) 19include(AbseilDll) 20include(AbseilInstallDirs) 21 22# The IDE folder for Abseil that will be used if Abseil is included in a CMake 23# project that sets 24# set_property(GLOBAL PROPERTY USE_FOLDERS ON) 25# For example, Visual Studio supports folders. 26set(ABSL_IDE_FOLDER Abseil) 27 28# absl_cc_library() 29# 30# CMake function to imitate Bazel's cc_library rule. 31# 32# Parameters: 33# NAME: name of target (see Note) 34# HDRS: List of public header files for the library 35# SRCS: List of source files for the library 36# DEPS: List of other libraries to be linked in to the binary targets 37# COPTS: List of private compile options 38# DEFINES: List of public defines 39# LINKOPTS: List of link options 40# PUBLIC: Add this so that this library will be exported under absl:: 41# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal. 42# TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake. 43# 44# Note: 45# By default, absl_cc_library will always create a library named absl_${NAME}, 46# and alias target absl::${NAME}. The absl:: form should always be used. 47# This is to reduce namespace pollution. 48# 49# absl_cc_library( 50# NAME 51# awesome 52# HDRS 53# "a.h" 54# SRCS 55# "a.cc" 56# ) 57# absl_cc_library( 58# NAME 59# fantastic_lib 60# SRCS 61# "b.cc" 62# DEPS 63# absl::awesome # not "awesome" ! 64# PUBLIC 65# ) 66# 67# absl_cc_library( 68# NAME 69# main_lib 70# ... 71# DEPS 72# absl::fantastic_lib 73# ) 74# 75# TODO: Implement "ALWAYSLINK" 76function(absl_cc_library) 77 cmake_parse_arguments(ABSL_CC_LIB 78 "DISABLE_INSTALL;PUBLIC;TESTONLY" 79 "NAME" 80 "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS" 81 ${ARGN} 82 ) 83 84 if(ABSL_CC_LIB_TESTONLY AND NOT ABSL_RUN_TESTS) 85 return() 86 endif() 87 88 if(ABSL_ENABLE_INSTALL) 89 set(_NAME "${ABSL_CC_LIB_NAME}") 90 else() 91 set(_NAME "absl_${ABSL_CC_LIB_NAME}") 92 endif() 93 94 # Check if this is a header-only library 95 # Note that as of February 2019, many popular OS's (for example, Ubuntu 96 # 16.04 LTS) only come with cmake 3.5 by default. For this reason, we can't 97 # use list(FILTER...) 98 set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}") 99 foreach(src_file IN LISTS ABSL_CC_SRCS) 100 if(${src_file} MATCHES ".*\\.(h|inc)") 101 list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}") 102 endif() 103 endforeach() 104 105 if("${ABSL_CC_SRCS}" STREQUAL "") 106 set(ABSL_CC_LIB_IS_INTERFACE 1) 107 else() 108 set(ABSL_CC_LIB_IS_INTERFACE 0) 109 endif() 110 111 # Determine this build target's relationship to the DLL. It's one of four things: 112 # 1. "dll" -- This target is part of the DLL 113 # 2. "dll_dep" -- This target is not part of the DLL, but depends on the DLL. 114 # Note that we assume any target not in the DLL depends on the 115 # DLL. This is not a technical necessity but a convenience 116 # which happens to be true, because nearly every target is 117 # part of the DLL. 118 # 3. "shared" -- This is a shared library, perhaps on a non-windows platform 119 # where DLL doesn't make sense. 120 # 4. "static" -- This target does not depend on the DLL and should be built 121 # statically. 122 if (${ABSL_BUILD_DLL}) 123 absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll) 124 if (${_in_dll}) 125 # This target should be replaced by the DLL 126 set(_build_type "dll") 127 set(ABSL_CC_LIB_IS_INTERFACE 1) 128 else() 129 # Building a DLL, but this target is not part of the DLL 130 set(_build_type "dll_dep") 131 endif() 132 elseif(BUILD_SHARED_LIBS) 133 set(_build_type "shared") 134 else() 135 set(_build_type "static") 136 endif() 137 138 if(NOT ABSL_CC_LIB_IS_INTERFACE) 139 if(${_build_type} STREQUAL "dll_dep") 140 # This target depends on the DLL. When adding dependencies to this target, 141 # any depended-on-target which is contained inside the DLL is replaced 142 # with a dependency on the DLL. 143 add_library(${_NAME} STATIC "") 144 target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) 145 absl_internal_dll_targets( 146 DEPS ${ABSL_CC_LIB_DEPS} 147 OUTPUT _dll_deps 148 ) 149 target_link_libraries(${_NAME} 150 PUBLIC ${_dll_deps} 151 PRIVATE 152 ${ABSL_CC_LIB_LINKOPTS} 153 ${ABSL_DEFAULT_LINKOPTS} 154 ) 155 156 if (ABSL_CC_LIB_TESTONLY) 157 set(_gtest_link_define "GTEST_LINKED_AS_SHARED_LIBRARY=1") 158 else() 159 set(_gtest_link_define) 160 endif() 161 162 target_compile_definitions(${_NAME} 163 PUBLIC 164 ABSL_CONSUME_DLL 165 "${_gtest_link_define}" 166 ) 167 168 elseif(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared") 169 add_library(${_NAME} "") 170 target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) 171 target_link_libraries(${_NAME} 172 PUBLIC ${ABSL_CC_LIB_DEPS} 173 PRIVATE 174 ${ABSL_CC_LIB_LINKOPTS} 175 ${ABSL_DEFAULT_LINKOPTS} 176 ) 177 else() 178 message(FATAL_ERROR "Invalid build type: ${_build_type}") 179 endif() 180 181 # Linker language can be inferred from sources, but in the case of DLLs we 182 # don't have any .cc files so it would be ambiguous. We could set it 183 # explicitly only in the case of DLLs but, because "CXX" is always the 184 # correct linker language for static or for shared libraries, we set it 185 # unconditionally. 186 set_property(TARGET ${_NAME} PROPERTY LINKER_LANGUAGE "CXX") 187 188 target_include_directories(${_NAME} 189 PUBLIC 190 "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>" 191 $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}> 192 ) 193 target_compile_options(${_NAME} 194 PRIVATE ${ABSL_CC_LIB_COPTS}) 195 target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES}) 196 197 # Add all Abseil targets to a a folder in the IDE for organization. 198 if(ABSL_CC_LIB_PUBLIC) 199 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}) 200 elseif(ABSL_CC_LIB_TESTONLY) 201 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) 202 else() 203 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal) 204 endif() 205 206 # INTERFACE libraries can't have the CXX_STANDARD property set 207 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD}) 208 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) 209 210 # When being installed, we lose the absl_ prefix. We want to put it back 211 # to have properly named lib files. This is a no-op when we are not being 212 # installed. 213 if(ABSL_ENABLE_INSTALL) 214 set_target_properties(${_NAME} PROPERTIES 215 OUTPUT_NAME "absl_${_NAME}" 216 ) 217 endif() 218 else() 219 # Generating header-only library 220 add_library(${_NAME} INTERFACE) 221 target_include_directories(${_NAME} 222 INTERFACE 223 "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>" 224 $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}> 225 ) 226 227 if (${_build_type} STREQUAL "dll") 228 set(ABSL_CC_LIB_DEPS abseil_dll) 229 endif() 230 231 target_link_libraries(${_NAME} 232 INTERFACE 233 ${ABSL_CC_LIB_DEPS} 234 ${ABSL_CC_LIB_LINKOPTS} 235 ${ABSL_DEFAULT_LINKOPTS} 236 ) 237 target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES}) 238 endif() 239 240 # TODO currently we don't install googletest alongside abseil sources, so 241 # installed abseil can't be tested. 242 if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL) 243 install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets 244 RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR} 245 LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR} 246 ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR} 247 ) 248 endif() 249 250 add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME}) 251endfunction() 252 253# absl_cc_test() 254# 255# CMake function to imitate Bazel's cc_test rule. 256# 257# Parameters: 258# NAME: name of target (see Usage below) 259# SRCS: List of source files for the binary 260# DEPS: List of other libraries to be linked in to the binary targets 261# COPTS: List of private compile options 262# DEFINES: List of public defines 263# LINKOPTS: List of link options 264# 265# Note: 266# By default, absl_cc_test will always create a binary named absl_${NAME}. 267# This will also add it to ctest list as absl_${NAME}. 268# 269# Usage: 270# absl_cc_library( 271# NAME 272# awesome 273# HDRS 274# "a.h" 275# SRCS 276# "a.cc" 277# PUBLIC 278# ) 279# 280# absl_cc_test( 281# NAME 282# awesome_test 283# SRCS 284# "awesome_test.cc" 285# DEPS 286# absl::awesome 287# gmock 288# gtest_main 289# ) 290function(absl_cc_test) 291 if(NOT ABSL_RUN_TESTS) 292 return() 293 endif() 294 295 cmake_parse_arguments(ABSL_CC_TEST 296 "" 297 "NAME" 298 "SRCS;COPTS;DEFINES;LINKOPTS;DEPS" 299 ${ARGN} 300 ) 301 302 set(_NAME "absl_${ABSL_CC_TEST_NAME}") 303 304 add_executable(${_NAME} "") 305 target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS}) 306 target_include_directories(${_NAME} 307 PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} 308 PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} 309 ) 310 311 if (${ABSL_BUILD_DLL}) 312 target_compile_definitions(${_NAME} 313 PUBLIC 314 ${ABSL_CC_TEST_DEFINES} 315 ABSL_CONSUME_DLL 316 GTEST_LINKED_AS_SHARED_LIBRARY=1 317 ) 318 319 # Replace dependencies on targets inside the DLL with abseil_dll itself. 320 absl_internal_dll_targets( 321 DEPS ${ABSL_CC_TEST_DEPS} 322 OUTPUT ABSL_CC_TEST_DEPS 323 ) 324 else() 325 target_compile_definitions(${_NAME} 326 PUBLIC 327 ${ABSL_CC_TEST_DEFINES} 328 ) 329 endif() 330 target_compile_options(${_NAME} 331 PRIVATE ${ABSL_CC_TEST_COPTS} 332 ) 333 334 target_link_libraries(${_NAME} 335 PUBLIC ${ABSL_CC_TEST_DEPS} 336 PRIVATE ${ABSL_CC_TEST_LINKOPTS} 337 ) 338 # Add all Abseil targets to a folder in the IDE for organization. 339 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) 340 341 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD}) 342 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) 343 344 add_test(NAME ${_NAME} COMMAND ${_NAME}) 345endfunction() 346 347 348function(check_target my_target) 349 if(NOT TARGET ${my_target}) 350 message(FATAL_ERROR " ABSL: compiling absl requires a ${my_target} CMake target in your project, 351 see CMake/README.md for more details") 352 endif(NOT TARGET ${my_target}) 353endfunction() 354