summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2018-12-08 09:54:09 +0100
committerJoshua Haberman <jhaberman@gmail.com>2018-12-08 09:54:09 +0100
commit14c96a143c63a01c1080a23d9e1c0196d06f0e5e (patch)
treef59388c3d84b175c335581a0f065e2c31d22834a /tools
parente77ab811ba3e1ed069822cb5dccb4d643d3e56d3 (diff)
parent35fa3df8ecc3f451af0512e70a03f89ee407c85c (diff)
Merge branch 'cmake-mac-fixes' into defcleanup
Diffstat (limited to 'tools')
-rw-r--r--tools/make_c_api.lua2
-rwxr-xr-xtools/make_cmakelists.py240
-rw-r--r--tools/staleness_test.py30
-rw-r--r--tools/staleness_test_lib.py158
-rw-r--r--tools/upbc.lua22
5 files changed, 446 insertions, 6 deletions
diff --git a/tools/make_c_api.lua b/tools/make_c_api.lua
index c333ff0..9da4c1f 100644
--- a/tools/make_c_api.lua
+++ b/tools/make_c_api.lua
@@ -381,7 +381,7 @@ local function write_h_file(filedef, append)
local msgname = to_cident(msg:full_name())
append('extern const upb_msglayout %s_msginit;\n', msgname)
append('UPB_INLINE %s *%s_new(upb_arena *arena) {\n', msgname, msgname)
- append(' return upb_msg_new(&%s_msginit, arena);\n', msgname)
+ append(' return (%s *)upb_msg_new(&%s_msginit, arena);\n', msgname, msgname)
append('}\n')
append('UPB_INLINE %s *%s_parsenew(upb_stringview buf, upb_arena *arena) {\n',
msgname, msgname)
diff --git a/tools/make_cmakelists.py b/tools/make_cmakelists.py
new file mode 100755
index 0000000..b8f46b9
--- /dev/null
+++ b/tools/make_cmakelists.py
@@ -0,0 +1,240 @@
+#!/usr/bin/env python
+
+"""TODO(haberman): DO NOT SUBMIT without one-line documentation for make_cmakelists.
+
+TODO(haberman): DO NOT SUBMIT without a detailed description of make_cmakelists.
+"""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import sys
+import textwrap
+
+def StripColons(deps):
+ return map(lambda x: x[1:], deps)
+
+def IsSourceFile(name):
+ return name.endswith(".c") or name.endswith(".cc")
+
+class BuildFileFunctions(object):
+ def __init__(self, converter):
+ self.converter = converter
+
+ def _add_deps(self, kwargs, keyword=""):
+ if "deps" not in kwargs:
+ return
+ self.converter.toplevel += "target_link_libraries(%s%s\n %s)\n" % (
+ kwargs["name"],
+ keyword,
+ "\n ".join(StripColons(kwargs["deps"]))
+ )
+
+ def load(self, *args):
+ pass
+
+ def cc_library(self, **kwargs):
+ if kwargs["name"] == "amalgamation" or kwargs["name"] == "upbc_generator":
+ return
+ files = kwargs.get("srcs", []) + kwargs.get("hdrs", [])
+
+ if filter(IsSourceFile, files):
+ # Has sources, make this a normal library.
+ self.converter.toplevel += "add_library(%s\n %s)\n" % (
+ kwargs["name"],
+ "\n ".join(files)
+ )
+ self._add_deps(kwargs)
+ else:
+ # Header-only library, have to do a couple things differently.
+ # For some info, see:
+ # http://mariobadr.com/creating-a-header-only-library-with-cmake.html
+ self.converter.toplevel += "add_library(%s INTERFACE)\n" % (
+ kwargs["name"]
+ )
+ self._add_deps(kwargs, " INTERFACE")
+
+ def cc_binary(self, **kwargs):
+ pass
+
+ def cc_test(self, **kwargs):
+ self.converter.toplevel += "add_executable(%s\n %s)\n" % (
+ kwargs["name"],
+ "\n ".join(kwargs["srcs"])
+ )
+ self.converter.toplevel += "add_test(NAME %s COMMAND %s)\n" % (
+ kwargs["name"],
+ kwargs["name"],
+ )
+
+ if "data" in kwargs:
+ for data_dep in kwargs["data"]:
+ self.converter.toplevel += textwrap.dedent("""\
+ add_custom_command(
+ TARGET %s POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_SOURCE_DIR}/%s
+ ${CMAKE_CURRENT_BINARY_DIR}/%s)\n""" % (
+ kwargs["name"], data_dep, data_dep
+ ))
+
+ self._add_deps(kwargs)
+
+ def py_library(self, **kwargs):
+ pass
+
+ def py_binary(self, **kwargs):
+ pass
+
+ def lua_cclibrary(self, **kwargs):
+ pass
+
+ def lua_library(self, **kwargs):
+ pass
+
+ def lua_binary(self, **kwargs):
+ pass
+
+ def lua_test(self, **kwargs):
+ pass
+
+ def sh_test(self, **kwargs):
+ pass
+
+ def make_shell_script(self, **kwargs):
+ pass
+
+ def exports_files(self, files, **kwargs):
+ pass
+
+ def proto_library(self, **kwargs):
+ pass
+
+ def generated_file_staleness_test(self, **kwargs):
+ pass
+
+ def upb_amalgamation(self, **kwargs):
+ pass
+
+ def upb_proto_library(self, **kwargs):
+ pass
+
+ def genrule(self, **kwargs):
+ pass
+
+ def glob(*args):
+ return []
+
+
+class WorkspaceFileFunctions(object):
+ def __init__(self, converter):
+ self.converter = converter
+
+ def load(self, *args):
+ pass
+
+ def workspace(self, **kwargs):
+ self.converter.prelude += "project(%s)\n" % (kwargs["name"])
+
+ def http_archive(self, **kwargs):
+ pass
+
+ def git_repository(self, **kwargs):
+ pass
+
+
+class Converter(object):
+ def __init__(self):
+ self.prelude = ""
+ self.toplevel = ""
+ self.if_lua = ""
+
+ def convert(self):
+ return self.template % {
+ "prelude": converter.prelude,
+ "toplevel": converter.toplevel,
+ }
+
+ template = textwrap.dedent("""\
+ # This file was generated from BUILD using tools/make_cmakelists.py.
+
+ cmake_minimum_required(VERSION 3.1)
+
+ if(${CMAKE_VERSION} VERSION_LESS 3.12)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+ else()
+ cmake_policy(VERSION 3.12)
+ endif()
+
+ cmake_minimum_required (VERSION 3.0)
+ cmake_policy(SET CMP0048 NEW)
+
+ %(prelude)s
+
+ # Prevent CMake from setting -rdynamic on Linux (!!).
+ SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+ SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+ # Set default build type.
+ if(NOT CMAKE_BUILD_TYPE)
+ message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.")
+ set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
+ "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
+ FORCE)
+ endif()
+
+ # When using Ninja, compiler output won't be colorized without this.
+ include(CheckCXXCompilerFlag)
+ CHECK_CXX_COMPILER_FLAG(-fdiagnostics-color=always SUPPORTS_COLOR_ALWAYS)
+ if(SUPPORTS_COLOR_ALWAYS)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
+ endif()
+
+ # Implement ASAN/UBSAN options
+ if(UPB_ENABLE_ASAN)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
+ endif()
+
+ if(UPB_ENABLE_UBSAN)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
+ endif()
+
+ include_directories(.)
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ if(APPLE)
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup -flat_namespace")
+ elseif(UNIX)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id")
+ endif()
+
+ enable_testing()
+
+ %(toplevel)s
+
+ """)
+
+data = {}
+converter = Converter()
+
+def GetDict(obj):
+ ret = {}
+ for k in dir(obj):
+ if not k.startswith("_"):
+ ret[k] = getattr(obj, k);
+ return ret
+
+globs = GetDict(converter)
+
+execfile("WORKSPACE", GetDict(WorkspaceFileFunctions(converter)))
+execfile("BUILD", GetDict(BuildFileFunctions(converter)))
+
+with open(sys.argv[1], "w") as f:
+ f.write(converter.convert())
diff --git a/tools/staleness_test.py b/tools/staleness_test.py
new file mode 100644
index 0000000..045cd1a
--- /dev/null
+++ b/tools/staleness_test.py
@@ -0,0 +1,30 @@
+"""The py_test() script for generated_file_staleness_test() rules.
+
+Note that this file is preprocessed! The INSERT_<...> text below is replaced
+with the actual list of files before we actually run the script.
+"""
+
+from __future__ import absolute_import
+
+from tools import staleness_test_lib
+import unittest
+import sys
+
+file_list = """
+ INSERT_FILE_LIST_HERE
+""".split()
+
+config = staleness_test_lib.Config(file_list)
+
+
+class TestFilesMatch(unittest.TestCase):
+
+ def testFilesMatch(self):
+ errors = staleness_test_lib.CheckFilesMatch(config)
+ self.assertFalse(errors, errors)
+
+
+if len(sys.argv) > 1 and sys.argv[1] == "--fix":
+ staleness_test_lib.FixFiles(config)
+else:
+ unittest.main()
diff --git a/tools/staleness_test_lib.py b/tools/staleness_test_lib.py
new file mode 100644
index 0000000..6d5c3d3
--- /dev/null
+++ b/tools/staleness_test_lib.py
@@ -0,0 +1,158 @@
+"""Shared code for validating generated_file_staleness_test() rules.
+
+This code is used by test scripts generated from
+generated_file_staleness_test() rules.
+"""
+
+from __future__ import absolute_import
+from __future__ import print_function
+
+import os
+from shutil import copyfile
+
+
+class _FilePair(object):
+ """Represents a single (target, generated) file pair."""
+
+ def __init__(self, target, generated):
+ self.target = target
+ self.generated = generated
+
+
+class Config(object):
+ """Represents the configuration for a single staleness test target."""
+
+ def __init__(self, file_list):
+ # Duplicate to avoid modifying our arguments.
+ file_list = list(file_list)
+
+ # The file list contains a few other bits of information at the end.
+ # This is packed by the code in build_defs.bzl.
+ self.target_name = file_list.pop()
+ self.package_name = file_list.pop()
+ self.pattern = file_list.pop()
+
+ self.file_list = file_list
+
+
+def _GetFilePairs(config):
+ """Generates the list of file pairs.
+
+ Args:
+ config: a Config object representing this target's config.
+
+ Returns:
+ A list of _FilePair objects.
+ """
+
+ ret = []
+
+ has_bazel_genfiles = os.path.exists("bazel-genfiles")
+
+ for filename in config.file_list:
+ target = os.path.join(config.package_name, filename)
+ generated = os.path.join(config.package_name, config.pattern % filename)
+ if has_bazel_genfiles:
+ generated = os.path.join("bazel-genfiles", generated)
+
+ # Generated files should always exist. Blaze should guarantee this before
+ # we are run.
+ if not os.path.isfile(generated):
+ print("Generated file '%s' does not exist." % generated)
+ print("Please run this command to generate it:")
+ print(" bazel build %s:%s" % (config.package_name, config.target_name))
+ ret.append(_FilePair(target, generated))
+
+ return ret
+
+
+def _GetMissingAndStaleFiles(file_pairs):
+ """Generates lists of missing and stale files.
+
+ Args:
+ file_pairs: a list of _FilePair objects.
+
+ Returns:
+ missing_files: a list of _FilePair objects representing missing files.
+ These target files do not exist at all.
+ stale_files: a list of _FilePair objects representing stale files.
+ These target files exist but have stale contents.
+ """
+
+ missing_files = []
+ stale_files = []
+
+ for pair in file_pairs:
+ if not os.path.isfile(pair.target):
+ missing_files.append(pair)
+ continue
+
+ generated = open(pair.generated).read()
+ target = open(pair.target).read()
+ if generated != target:
+ stale_files.append(pair)
+
+ return missing_files, stale_files
+
+
+def _CopyFiles(file_pairs):
+ """Copies all generated files to the corresponding target file.
+
+ The target files must be writable already.
+
+ Args:
+ file_pairs: a list of _FilePair objects that we want to copy.
+ """
+
+ for pair in file_pairs:
+ target_dir = os.path.dirname(pair.target)
+ if not os.path.isdir(target_dir):
+ os.makedirs(target_dir)
+ copyfile(pair.generated, pair.target)
+
+
+def FixFiles(config):
+ """Implements the --fix option: overwrites missing or out-of-date files.
+
+ Args:
+ config: the Config object for this test.
+ """
+
+ file_pairs = _GetFilePairs(config)
+ missing_files, stale_files = _GetMissingAndStaleFiles(file_pairs)
+
+ _CopyFiles(stale_files + missing_files)
+
+
+def CheckFilesMatch(config):
+ """Checks whether each target file matches the corresponding generated file.
+
+ Args:
+ config: the Config object for this test.
+
+ Returns:
+ None if everything matches, otherwise a string error message.
+ """
+
+ diff_errors = []
+
+ file_pairs = _GetFilePairs(config)
+ missing_files, stale_files = _GetMissingAndStaleFiles(file_pairs)
+
+ for pair in missing_files:
+ diff_errors.append("File %s does not exist" % pair.target)
+ continue
+
+ for pair in stale_files:
+ diff_errors.append("File %s is out of date" % pair.target)
+
+ if diff_errors:
+ error_msg = "Files out of date!\n\n"
+ error_msg += "To fix run THIS command:\n"
+ error_msg += " bazel-bin/%s/%s --fix\n\n" % (config.package_name,
+ config.target_name)
+ error_msg += "Errors:\n"
+ error_msg += " " + "\n ".join(diff_errors)
+ return error_msg
+ else:
+ return None
diff --git a/tools/upbc.lua b/tools/upbc.lua
index 8ac4f73..adea373 100644
--- a/tools/upbc.lua
+++ b/tools/upbc.lua
@@ -13,11 +13,17 @@ local make_c_api = require "make_c_api"
local upb = require "upb"
local generate_upbdefs = false
+local outdir = "."
-for _, argument in ipairs(arg) do
+i = 1
+while i <= #arg do
+ argument = arg[i]
if argument.sub(argument, 1, 2) == "--" then
if argument == "--generate-upbdefs" then
generate_upbdefs = true
+ elseif argument == "--outdir" then
+ i = i + 1
+ outdir = arg[i]
else
print("Unknown flag: " .. argument)
return 1
@@ -29,6 +35,7 @@ for _, argument in ipairs(arg) do
end
src = argument
end
+ i = i + 1
end
if not src then
@@ -40,6 +47,11 @@ function strip_proto(filename)
return string.gsub(filename, '%.proto$','')
end
+local function open(filename)
+ local full_name = outdir .. "/" .. filename
+ return assert(io.open(full_name, "w"), "couldn't open " .. full_name)
+end
+
-- Open input/output files.
local f = assert(io.open(src, "r"), "couldn't open input file " .. src)
local descriptor = f:read("*all")
@@ -67,8 +79,8 @@ for _, file in ipairs(files) do
if generate_upbdefs then
-- Legacy generated defs.
- local hfile = assert(io.open(hfilename, "w"), "couldn't open " .. hfilename)
- local cfile = assert(io.open(cfilename, "w"), "couldn't open " .. cfilename)
+ local hfile = open(hfilename)
+ local cfile = open(cfilename)
local happend = dump_cinit.file_appender(hfile)
local cappend = dump_cinit.file_appender(cfile)
@@ -90,8 +102,8 @@ for _, file in ipairs(files) do
print(string.format(" cfilename=%s", cfilename))
end
- local hfile = assert(io.open(hfilename, "w"), "couldn't open " .. hfilename)
- local cfile = assert(io.open(cfilename, "w"), "couldn't open " .. cfilename)
+ local hfile = open(hfilename)
+ local cfile = open(cfilename)
local happend = dump_cinit.file_appender(hfile)
local cappend = dump_cinit.file_appender(cfile)
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback