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