blob: 67b97fe14dfd45e31df9adaa898e05c73dde8289 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001#
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(AbseilInstallDirs)
20
21# The IDE folder for Abseil that will be used if Abseil is included in a CMake
22# project that sets
23# set_property(GLOBAL PROPERTY USE_FOLDERS ON)
24# For example, Visual Studio supports folders.
25set(ABSL_IDE_FOLDER Abseil)
26
27# absl_cc_library()
28#
29# CMake function to imitate Bazel's cc_library rule.
30#
31# Parameters:
32# NAME: name of target (see Note)
33# HDRS: List of public header files for the library
34# SRCS: List of source files for the library
35# DEPS: List of other libraries to be linked in to the binary targets
36# COPTS: List of private compile options
37# DEFINES: List of public defines
38# LINKOPTS: List of link options
39# PUBLIC: Add this so that this library will be exported under absl::
40# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal.
41# TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake.
42#
43# Note:
44# By default, absl_cc_library will always create a library named absl_${NAME},
45# and alias target absl::${NAME}. The absl:: form should always be used.
46# This is to reduce namespace pollution.
47#
48# absl_cc_library(
49# NAME
50# awesome
51# HDRS
52# "a.h"
53# SRCS
54# "a.cc"
55# )
56# absl_cc_library(
57# NAME
58# fantastic_lib
59# SRCS
60# "b.cc"
61# DEPS
62# absl::awesome # not "awesome" !
63# PUBLIC
64# )
65#
66# absl_cc_library(
67# NAME
68# main_lib
69# ...
70# DEPS
71# absl::fantastic_lib
72# )
73#
74# TODO: Implement "ALWAYSLINK"
75function(absl_cc_library)
76 cmake_parse_arguments(ABSL_CC_LIB
77 "DISABLE_INSTALL;PUBLIC;TESTONLY"
78 "NAME"
79 "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS"
80 ${ARGN}
81 )
82
83 if(NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS)
84 if(ABSL_ENABLE_INSTALL)
85 set(_NAME "${ABSL_CC_LIB_NAME}")
86 else()
87 set(_NAME "absl_${ABSL_CC_LIB_NAME}")
88 endif()
89
90 # Check if this is a header-only library
91 # Note that as of February 2019, many popular OS's (for example, Ubuntu
92 # 16.04 LTS) only come with cmake 3.5 by default. For this reason, we can't
93 # use list(FILTER...)
94 set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}")
95 foreach(src_file IN LISTS ABSL_CC_SRCS)
96 if(${src_file} MATCHES ".*\\.(h|inc)")
97 list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}")
98 endif()
99 endforeach()
100 if("${ABSL_CC_SRCS}" STREQUAL "")
101 set(ABSL_CC_LIB_IS_INTERFACE 1)
102 else()
103 set(ABSL_CC_LIB_IS_INTERFACE 0)
104 endif()
105
106 if(NOT ABSL_CC_LIB_IS_INTERFACE)
107 add_library(${_NAME} STATIC "")
108 target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
109 target_include_directories(${_NAME}
110 PUBLIC
111 "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
112 $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
113 )
114 target_compile_options(${_NAME}
115 PRIVATE ${ABSL_CC_LIB_COPTS})
116 target_link_libraries(${_NAME}
117 PUBLIC ${ABSL_CC_LIB_DEPS}
118 PRIVATE
119 ${ABSL_CC_LIB_LINKOPTS}
120 ${ABSL_DEFAULT_LINKOPTS}
121 )
122 target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES})
123
124 # Add all Abseil targets to a a folder in the IDE for organization.
125 if(ABSL_CC_LIB_PUBLIC)
126 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
127 elseif(ABSL_CC_LIB_TESTONLY)
128 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
129 else()
130 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
131 endif()
132
133 # INTERFACE libraries can't have the CXX_STANDARD property set
134 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
135 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
136
137 # When being installed, we lose the absl_ prefix. We want to put it back
138 # to have properly named lib files. This is a no-op when we are not being
139 # installed.
140 set_target_properties(${_NAME} PROPERTIES
141 OUTPUT_NAME "absl_${_NAME}"
142 )
143 else()
144 # Generating header-only library
145 add_library(${_NAME} INTERFACE)
146 target_include_directories(${_NAME}
147 INTERFACE
148 "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
149 $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
150 )
151 target_link_libraries(${_NAME}
152 INTERFACE
153 ${ABSL_CC_LIB_DEPS}
154 ${ABSL_CC_LIB_LINKOPTS}
155 ${ABSL_DEFAULT_LINKOPTS}
156 )
157 target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
158 endif()
159
160 # TODO currently we don't install googletest alongside abseil sources, so
161 # installed abseil can't be tested.
162 if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL)
163 install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets
164 RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
165 LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
166 ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
167 )
168 endif()
169
170 add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})
171 endif()
172endfunction()
173
174# absl_cc_test()
175#
176# CMake function to imitate Bazel's cc_test rule.
177#
178# Parameters:
179# NAME: name of target (see Usage below)
180# SRCS: List of source files for the binary
181# DEPS: List of other libraries to be linked in to the binary targets
182# COPTS: List of private compile options
183# DEFINES: List of public defines
184# LINKOPTS: List of link options
185#
186# Note:
187# By default, absl_cc_test will always create a binary named absl_${NAME}.
188# This will also add it to ctest list as absl_${NAME}.
189#
190# Usage:
191# absl_cc_library(
192# NAME
193# awesome
194# HDRS
195# "a.h"
196# SRCS
197# "a.cc"
198# PUBLIC
199# )
200#
201# absl_cc_test(
202# NAME
203# awesome_test
204# SRCS
205# "awesome_test.cc"
206# DEPS
207# absl::awesome
208# gmock
209# gtest_main
210# )
211function(absl_cc_test)
212 if(NOT ABSL_RUN_TESTS)
213 return()
214 endif()
215
216 cmake_parse_arguments(ABSL_CC_TEST
217 ""
218 "NAME"
219 "SRCS;COPTS;DEFINES;LINKOPTS;DEPS"
220 ${ARGN}
221 )
222
223 set(_NAME "absl_${ABSL_CC_TEST_NAME}")
224 add_executable(${_NAME} "")
225 target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS})
226 target_include_directories(${_NAME}
227 PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}
228 PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
229 )
230 target_compile_definitions(${_NAME}
231 PUBLIC ${ABSL_CC_TEST_DEFINES}
232 )
233 target_compile_options(${_NAME}
234 PRIVATE ${ABSL_CC_TEST_COPTS}
235 )
236 target_link_libraries(${_NAME}
237 PUBLIC ${ABSL_CC_TEST_DEPS}
238 PRIVATE ${ABSL_CC_TEST_LINKOPTS}
239 )
240 # Add all Abseil targets to a a folder in the IDE for organization.
241 set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
242
243 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
244 set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
245
246 add_test(NAME ${_NAME} COMMAND ${_NAME})
247endfunction()
248
249
250function(check_target my_target)
251 if(NOT TARGET ${my_target})
252 message(FATAL_ERROR " ABSL: compiling absl requires a ${my_target} CMake target in your project,
253 see CMake/README.md for more details")
254 endif(NOT TARGET ${my_target})
255endfunction()