make_cmakelists.py 9.0 KB

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