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("generated_for_cmake/" + file): 51 found_files.append("generated_for_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 generated_file_staleness_test(self, **kwargs): 121 pass 122 123 def upb_amalgamation(self, **kwargs): 124 pass 125 126 def upb_proto_library(self, **kwargs): 127 pass 128 129 def upb_proto_reflection_library(self, **kwargs): 130 pass 131 132 def upb_proto_srcs(self, **kwargs): 133 pass 134 135 def genrule(self, **kwargs): 136 pass 137 138 def config_setting(self, **kwargs): 139 pass 140 141 def select(self, arg_dict): 142 return [] 143 144 def glob(self, *args): 145 return [] 146 147 def licenses(self, *args): 148 pass 149 150 def filegroup(self, **kwargs): 151 pass 152 153 def map_dep(self, arg): 154 return arg 155 156 157class WorkspaceFileFunctions(object): 158 def __init__(self, converter): 159 self.converter = converter 160 161 def load(self, *args): 162 pass 163 164 def workspace(self, **kwargs): 165 self.converter.prelude += "project(%s)\n" % (kwargs["name"]) 166 167 def http_archive(self, **kwargs): 168 pass 169 170 def git_repository(self, **kwargs): 171 pass 172 173 def bazel_version_repository(self, **kwargs): 174 pass 175 176 def upb_deps(self): 177 pass 178 179 180class Converter(object): 181 def __init__(self): 182 self.prelude = "" 183 self.toplevel = "" 184 self.if_lua = "" 185 186 def convert(self): 187 return self.template % { 188 "prelude": converter.prelude, 189 "toplevel": converter.toplevel, 190 } 191 192 template = textwrap.dedent("""\ 193 # This file was generated from BUILD using tools/make_cmakelists.py. 194 195 cmake_minimum_required(VERSION 3.1) 196 197 if(${CMAKE_VERSION} VERSION_LESS 3.12) 198 cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) 199 else() 200 cmake_policy(VERSION 3.12) 201 endif() 202 203 cmake_minimum_required (VERSION 3.0) 204 cmake_policy(SET CMP0048 NEW) 205 206 %(prelude)s 207 208 # Prevent CMake from setting -rdynamic on Linux (!!). 209 SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") 210 SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") 211 212 # Set default build type. 213 if(NOT CMAKE_BUILD_TYPE) 214 message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") 215 set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING 216 "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." 217 FORCE) 218 endif() 219 220 # When using Ninja, compiler output won't be colorized without this. 221 include(CheckCXXCompilerFlag) 222 CHECK_CXX_COMPILER_FLAG(-fdiagnostics-color=always SUPPORTS_COLOR_ALWAYS) 223 if(SUPPORTS_COLOR_ALWAYS) 224 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") 225 endif() 226 227 # Implement ASAN/UBSAN options 228 if(UPB_ENABLE_ASAN) 229 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") 230 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") 231 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") 232 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") 233 endif() 234 235 if(UPB_ENABLE_UBSAN) 236 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") 237 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") 238 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") 239 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") 240 endif() 241 242 include_directories(.) 243 include_directories(generated_for_cmake) 244 include_directories(${CMAKE_CURRENT_BINARY_DIR}) 245 246 if(APPLE) 247 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup -flat_namespace") 248 elseif(UNIX) 249 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id") 250 endif() 251 252 enable_testing() 253 254 %(toplevel)s 255 256 """) 257 258data = {} 259converter = Converter() 260 261def GetDict(obj): 262 ret = {} 263 for k in dir(obj): 264 if not k.startswith("_"): 265 ret[k] = getattr(obj, k); 266 return ret 267 268globs = GetDict(converter) 269 270exec(open("WORKSPACE").read(), GetDict(WorkspaceFileFunctions(converter))) 271exec(open("BUILD").read(), GetDict(BuildFileFunctions(converter))) 272 273with open(sys.argv[1], "w") as f: 274 f.write(converter.convert()) 275