1#!/usr/bin/python 2# 3# Copyright (c) 2009-2021, Google LLC 4# All rights reserved. 5# 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. 16# 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. 27 28"""TODO(haberman): DO NOT SUBMIT without one-line documentation for make_cmakelists. 29 30TODO(haberman): DO NOT SUBMIT without a detailed description of make_cmakelists. 31""" 32 33from __future__ import absolute_import 34from __future__ import division 35from __future__ import print_function 36 37import sys 38import textwrap 39import os 40 41def StripColons(deps): 42 return map(lambda x: x[1:], deps) 43 44def IsSourceFile(name): 45 return name.endswith(".c") or name.endswith(".cc") 46 47class BuildFileFunctions(object): 48 def __init__(self, converter): 49 self.converter = converter 50 51 def _add_deps(self, kwargs, keyword=""): 52 if "deps" not in kwargs: 53 return 54 self.converter.toplevel += "target_link_libraries(%s%s\n %s)\n" % ( 55 kwargs["name"], 56 keyword, 57 "\n ".join(StripColons(kwargs["deps"])) 58 ) 59 60 def load(self, *args): 61 pass 62 63 def cc_library(self, **kwargs): 64 if kwargs["name"].endswith("amalgamation"): 65 return 66 if kwargs["name"] == "upbc_generator": 67 return 68 if kwargs["name"] == "lupb": 69 return 70 files = kwargs.get("srcs", []) + kwargs.get("hdrs", []) 71 found_files = [] 72 for file in files: 73 if os.path.isfile(file): 74 found_files.append("../" + file) 75 elif os.path.isfile("cmake/" + file): 76 found_files.append("../cmake/" + file) 77 else: 78 print("Warning: no such file: " + file) 79 80 if list(filter(IsSourceFile, files)): 81 # Has sources, make this a normal library. 82 self.converter.toplevel += "add_library(%s\n %s)\n" % ( 83 kwargs["name"], 84 "\n ".join(found_files) 85 ) 86 self._add_deps(kwargs) 87 else: 88 # Header-only library, have to do a couple things differently. 89 # For some info, see: 90 # http://mariobadr.com/creating-a-header-only-library-with-cmake.html 91 self.converter.toplevel += "add_library(%s INTERFACE)\n" % ( 92 kwargs["name"] 93 ) 94 self._add_deps(kwargs, " INTERFACE") 95 96 def cc_binary(self, **kwargs): 97 pass 98 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" % ( 102 # kwargs["name"], 103 # "\n ".join(kwargs["srcs"]) 104 # ) 105 # self.converter.toplevel += "add_test(NAME %s COMMAND %s)\n" % ( 106 # kwargs["name"], 107 # kwargs["name"], 108 # ) 109 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 119 # )) 120 121 # self._add_deps(kwargs) 122 pass 123 124 def py_library(self, **kwargs): 125 pass 126 127 def py_binary(self, **kwargs): 128 pass 129 130 def lua_proto_library(self, **kwargs): 131 pass 132 133 def sh_test(self, **kwargs): 134 pass 135 136 def make_shell_script(self, **kwargs): 137 pass 138 139 def exports_files(self, files, **kwargs): 140 pass 141 142 def proto_library(self, **kwargs): 143 pass 144 145 def cc_proto_library(self, **kwargs): 146 pass 147 148 def generated_file_staleness_test(self, **kwargs): 149 pass 150 151 def upb_amalgamation(self, **kwargs): 152 pass 153 154 def upb_proto_library(self, **kwargs): 155 pass 156 157 def upb_proto_library_copts(self, **kwargs): 158 pass 159 160 def upb_proto_reflection_library(self, **kwargs): 161 pass 162 163 def upb_proto_srcs(self, **kwargs): 164 pass 165 166 def genrule(self, **kwargs): 167 pass 168 169 def config_setting(self, **kwargs): 170 pass 171 172 def upb_fasttable_enabled(self, **kwargs): 173 pass 174 175 def select(self, arg_dict): 176 return [] 177 178 def glob(self, *args): 179 return [] 180 181 def licenses(self, *args): 182 pass 183 184 def filegroup(self, **kwargs): 185 pass 186 187 def map_dep(self, arg): 188 return arg 189 190 191class WorkspaceFileFunctions(object): 192 def __init__(self, converter): 193 self.converter = converter 194 195 def load(self, *args): 196 pass 197 198 def workspace(self, **kwargs): 199 self.converter.prelude += "project(%s)\n" % (kwargs["name"]) 200 self.converter.prelude += "set(CMAKE_C_STANDARD 99)\n" 201 202 def http_archive(self, **kwargs): 203 pass 204 205 def git_repository(self, **kwargs): 206 pass 207 208 def new_git_repository(self, **kwargs): 209 pass 210 211 def bazel_version_repository(self, **kwargs): 212 pass 213 214 def upb_deps(self): 215 pass 216 217 def rules_fuzzing_dependencies(self): 218 pass 219 220 def rules_fuzzing_init(self): 221 pass 222 223 def system_python(self, **kwargs): 224 pass 225 226 227class Converter(object): 228 def __init__(self): 229 self.prelude = "" 230 self.toplevel = "" 231 self.if_lua = "" 232 233 def convert(self): 234 return self.template % { 235 "prelude": converter.prelude, 236 "toplevel": converter.toplevel, 237 } 238 239 template = textwrap.dedent("""\ 240 # This file was generated from BUILD using tools/make_cmakelists.py. 241 242 cmake_minimum_required(VERSION 3.1) 243 244 if(${CMAKE_VERSION} VERSION_LESS 3.12) 245 cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) 246 else() 247 cmake_policy(VERSION 3.12) 248 endif() 249 250 cmake_minimum_required (VERSION 3.0) 251 cmake_policy(SET CMP0048 NEW) 252 253 %(prelude)s 254 255 # Prevent CMake from setting -rdynamic on Linux (!!). 256 SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") 257 SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") 258 259 # Set default build type. 260 if(NOT CMAKE_BUILD_TYPE) 261 message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") 262 set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING 263 "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." 264 FORCE) 265 endif() 266 267 # When using Ninja, compiler output won't be colorized without this. 268 include(CheckCXXCompilerFlag) 269 CHECK_CXX_COMPILER_FLAG(-fdiagnostics-color=always SUPPORTS_COLOR_ALWAYS) 270 if(SUPPORTS_COLOR_ALWAYS) 271 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") 272 endif() 273 274 # Implement ASAN/UBSAN options 275 if(UPB_ENABLE_ASAN) 276 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") 277 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") 278 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") 279 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") 280 endif() 281 282 if(UPB_ENABLE_UBSAN) 283 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") 284 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") 285 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") 286 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") 287 endif() 288 289 include_directories(..) 290 include_directories(../cmake) 291 include_directories(${CMAKE_CURRENT_BINARY_DIR}) 292 293 if(APPLE) 294 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup -flat_namespace") 295 elseif(UNIX) 296 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id") 297 endif() 298 299 enable_testing() 300 301 %(toplevel)s 302 303 """) 304 305data = {} 306converter = Converter() 307 308def GetDict(obj): 309 ret = {} 310 ret["UPB_DEFAULT_COPTS"] = [] # HACK 311 for k in dir(obj): 312 if not k.startswith("_"): 313 ret[k] = getattr(obj, k); 314 return ret 315 316globs = GetDict(converter) 317 318exec(open("WORKSPACE").read(), GetDict(WorkspaceFileFunctions(converter))) 319exec(open("BUILD").read(), GetDict(BuildFileFunctions(converter))) 320 321with open(sys.argv[1], "w") as f: 322 f.write(converter.convert()) 323