3 # Copyright (c) 2009-2021, Google LLC
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above copyright
11 # notice, this list of conditions and the following disclaimer in the
12 # documentation and/or other materials provided with the distribution.
13 # * Neither the name of Google LLC nor the
14 # names of its contributors may be used to endorse or promote products
15 # derived from this software without specific prior written permission.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 # DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
21 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 """TODO(haberman): DO NOT SUBMIT without one-line documentation for make_cmakelists.
30 TODO(haberman): DO NOT SUBMIT without a detailed description of make_cmakelists.
33 from __future__ import absolute_import
34 from __future__ import division
35 from __future__ import print_function
41 def StripColons(deps):
42 return map(lambda x: x[1:], deps)
44 def IsSourceFile(name):
45 return name.endswith(".c") or name.endswith(".cc")
47 class BuildFileFunctions(object):
48 def __init__(self, converter):
49 self.converter = converter
51 def _add_deps(self, kwargs, keyword=""):
52 if "deps" not in kwargs:
54 self.converter.toplevel += "target_link_libraries(%s%s\n %s)\n" % (
57 "\n ".join(StripColons(kwargs["deps"]))
60 def load(self, *args):
63 def cc_library(self, **kwargs):
64 if kwargs["name"].endswith("amalgamation"):
66 if kwargs["name"] == "upbc_generator":
68 if kwargs["name"] == "lupb":
70 files = kwargs.get("srcs", []) + kwargs.get("hdrs", [])
73 if os.path.isfile(file):
74 found_files.append("../" + file)
75 elif os.path.isfile("cmake/" + file):
76 found_files.append("../cmake/" + file)
78 print("Warning: no such file: " + file)
80 if list(filter(IsSourceFile, files)):
81 # Has sources, make this a normal library.
82 self.converter.toplevel += "add_library(%s\n %s)\n" % (
84 "\n ".join(found_files)
86 self._add_deps(kwargs)
88 # Header-only library, have to do a couple things differently.
90 # http://mariobadr.com/creating-a-header-only-library-with-cmake.html
91 self.converter.toplevel += "add_library(%s INTERFACE)\n" % (
94 self._add_deps(kwargs, " INTERFACE")
96 def cc_binary(self, **kwargs):
99 def cc_test(self, **kwargs):
100 # Disable this until we properly support upb_proto_library().
101 # self.converter.toplevel += "add_executable(%s\n %s)\n" % (
103 # "\n ".join(kwargs["srcs"])
105 # self.converter.toplevel += "add_test(NAME %s COMMAND %s)\n" % (
110 # if "data" in kwargs:
111 # for data_dep in kwargs["data"]:
112 # self.converter.toplevel += textwrap.dedent("""\
113 # add_custom_command(
114 # TARGET %s POST_BUILD
115 # COMMAND ${CMAKE_COMMAND} -E copy
116 # ${CMAKE_SOURCE_DIR}/%s
117 # ${CMAKE_CURRENT_BINARY_DIR}/%s)\n""" % (
118 # kwargs["name"], data_dep, data_dep
121 # self._add_deps(kwargs)
124 def py_library(self, **kwargs):
127 def py_binary(self, **kwargs):
130 def lua_proto_library(self, **kwargs):
133 def sh_test(self, **kwargs):
136 def make_shell_script(self, **kwargs):
139 def exports_files(self, files, **kwargs):
142 def proto_library(self, **kwargs):
145 def cc_proto_library(self, **kwargs):
148 def generated_file_staleness_test(self, **kwargs):
151 def upb_amalgamation(self, **kwargs):
154 def upb_proto_library(self, **kwargs):
157 def upb_proto_library_copts(self, **kwargs):
160 def upb_proto_reflection_library(self, **kwargs):
163 def upb_proto_srcs(self, **kwargs):
166 def genrule(self, **kwargs):
169 def config_setting(self, **kwargs):
172 def upb_fasttable_enabled(self, **kwargs):
175 def select(self, arg_dict):
178 def glob(self, *args):
181 def licenses(self, *args):
184 def filegroup(self, **kwargs):
187 def map_dep(self, arg):
191 class WorkspaceFileFunctions(object):
192 def __init__(self, converter):
193 self.converter = converter
195 def load(self, *args):
198 def workspace(self, **kwargs):
199 self.converter.prelude += "project(%s)\n" % (kwargs["name"])
200 self.converter.prelude += "set(CMAKE_C_STANDARD 99)\n"
202 def http_archive(self, **kwargs):
205 def git_repository(self, **kwargs):
208 def new_git_repository(self, **kwargs):
211 def bazel_version_repository(self, **kwargs):
218 class Converter(object):
225 return self.template % {
226 "prelude": converter.prelude,
227 "toplevel": converter.toplevel,
230 template = textwrap.dedent("""\
231 # This file was generated from BUILD using tools/make_cmakelists.py.
233 cmake_minimum_required(VERSION 3.1)
235 if(${CMAKE_VERSION} VERSION_LESS 3.12)
236 cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
238 cmake_policy(VERSION 3.12)
241 cmake_minimum_required (VERSION 3.0)
242 cmake_policy(SET CMP0048 NEW)
246 # Prevent CMake from setting -rdynamic on Linux (!!).
247 SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
248 SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
250 # Set default build type.
251 if(NOT CMAKE_BUILD_TYPE)
252 message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.")
253 set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
254 "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
258 # When using Ninja, compiler output won't be colorized without this.
259 include(CheckCXXCompilerFlag)
260 CHECK_CXX_COMPILER_FLAG(-fdiagnostics-color=always SUPPORTS_COLOR_ALWAYS)
261 if(SUPPORTS_COLOR_ALWAYS)
262 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
265 # Implement ASAN/UBSAN options
267 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
268 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
269 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
270 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
274 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
275 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
276 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
277 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
280 include_directories(..)
281 include_directories(../cmake)
282 include_directories(${CMAKE_CURRENT_BINARY_DIR})
285 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup -flat_namespace")
287 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id")
297 converter = Converter()
301 ret["UPB_DEFAULT_COPTS"] = [] # HACK
303 if not k.startswith("_"):
304 ret[k] = getattr(obj, k);
307 globs = GetDict(converter)
309 exec(open("WORKSPACE").read(), GetDict(WorkspaceFileFunctions(converter)))
310 exec(open("BUILD").read(), GetDict(BuildFileFunctions(converter)))
312 with open(sys.argv[1], "w") as f:
313 f.write(converter.convert())