diff --git a/modules/qdldl/0.1.7/MODULE.bazel b/modules/qdldl/0.1.7/MODULE.bazel new file mode 100644 index 00000000000..01bf6736e62 --- /dev/null +++ b/modules/qdldl/0.1.7/MODULE.bazel @@ -0,0 +1,8 @@ +module( + name = "qdldl", + version = "0.1.7", + compatibility_level = 1, +) + +bazel_dep(name = "platforms", version = "0.0.8") +bazel_dep(name = "rules_cc", version = "0.0.9") diff --git a/modules/qdldl/0.1.7/patches/add_build_file.patch b/modules/qdldl/0.1.7/patches/add_build_file.patch new file mode 100644 index 00000000000..6176f376b7e --- /dev/null +++ b/modules/qdldl/0.1.7/patches/add_build_file.patch @@ -0,0 +1,70 @@ +diff --git BUILD.bazel BUILD.bazel +new file mode 100644 +index 0000000..aabba4f +--- /dev/null ++++ BUILD.bazel +@@ -0,0 +1,64 @@ ++load("@rules_cc//cc:defs.bzl", "cc_library") ++ ++load( ++ "//bazel:cmake_configure_file.bzl", ++ "cmake_configure_file", ++) ++ ++licenses(["notice"]) ++ ++package( ++ default_visibility = ["//visibility:public"], ++) ++ ++cmake_configure_file( ++ name = "configure_file_types", ++ src = "configure/qdldl_types.h.in", ++ out = "include/qdldl_types.h", ++ # https://github.com/osqp/qdldl/blob/v0.1.6/README.md#custom-types-for-integer-floats-and-booleans ++ defines = [ ++ "QDLDL_BOOL_TYPE=unsigned char", ++ # Keep the `int` type sync'd with the build of @osqp_internal and ++ # @scs_internal. See drake/tools/workspace/qdldl_internal/README.md. ++ "QDLDL_INT_TYPE=int", ++ "QDLDL_LONG=0", ++ # Keep the `int` type sync'd with the build of @osqp_internal and ++ # @scs_internal. See drake/tools/workspace/qdldl_internal/README.md. ++ "QDLDL_FLOAT_TYPE=double", ++ "QDLDL_FLOAT=0", ++ # Match this to QDLDL_INT_TYPE above. ++ "QDLDL_INT_TYPE_MAX=INT_MAX", ++ ], ++ visibility = ["//visibility:private"], ++) ++ ++cmake_configure_file( ++ name = "configure_file_version", ++ src = "configure/qdldl_version.h.in", ++ out = "include/qdldl_version.h", ++ cmakelists = [ ++ "CMakeLists.txt", ++ ], ++ visibility = ["//visibility:private"], ++) ++ ++cc_library( ++ name = "qdldl", ++ hdrs = [ ++ "include/qdldl.h", ++ ":include/qdldl_types.h", ++ ":include/qdldl_version.h", ++ ], ++ srcs = [ ++ "src/qdldl.c", ++ ], ++ copts = [ ++ "-fvisibility=hidden", ++ ] + select({ ++ "@platforms//os:windows": [], ++ "//conditions:default": ["-Werror=incompatible-pointer-types"], ++ }), ++ includes = [ ++ "include", ++ ], ++) diff --git a/modules/qdldl/0.1.7/patches/add_cmake_configure_file.patch b/modules/qdldl/0.1.7/patches/add_cmake_configure_file.patch new file mode 100644 index 00000000000..1e133c9f7ee --- /dev/null +++ b/modules/qdldl/0.1.7/patches/add_cmake_configure_file.patch @@ -0,0 +1,336 @@ +diff --git bazel/BUILD.bazel bazel/BUILD.bazel +new file mode 100644 +index 0000000..e5d9278 +--- /dev/null ++++ bazel/BUILD.bazel +@@ -0,0 +1,5 @@ ++py_binary( ++ name = "cmake_configure_file", ++ srcs = ["cmake_configure_file.py"], ++ visibility = ["//visibility:public"], ++) +\ No newline at end of file +diff --git bazel/cmake_configure_file.bzl bazel/cmake_configure_file.bzl +new file mode 100644 +index 0000000..08d9fdd +--- /dev/null ++++ bazel/cmake_configure_file.bzl +@@ -0,0 +1,86 @@ ++# -*- python -*- ++ ++# Copied from the Drake project: ++# https://github.com/RobotLocomotion/drake/blob/17423f8fb6f292b4af0b4cf3c6c0f157273af501/tools/workspace/cmake_configure_file.bzl ++ ++# Defines the implementation actions to cmake_configure_file. ++def _cmake_configure_file_impl(ctx): ++ arguments = [ ++ "--input", ++ ctx.file.src.path, ++ "--output", ++ ctx.outputs.out.path, ++ ] ++ for item in ctx.attr.defines: ++ arguments += ["-D" + item] ++ for item in ctx.attr.undefines: ++ arguments += ["-U" + item] ++ for item in ctx.files.cmakelists: ++ arguments += ["--cmakelists", item.path] ++ ctx.actions.run( ++ inputs = [ctx.file.src] + ctx.files.cmakelists, ++ outputs = [ctx.outputs.out], ++ arguments = arguments, ++ env = ctx.attr.env, ++ executable = ctx.executable.cmake_configure_file_py, ++ ) ++ return [] ++ ++# Defines the rule to cmake_configure_file. ++_cmake_configure_file_gen = rule( ++ attrs = { ++ "src": attr.label( ++ allow_single_file = True, ++ mandatory = True, ++ ), ++ "out": attr.output(mandatory = True), ++ "defines": attr.string_list(), ++ "undefines": attr.string_list(), ++ "cmakelists": attr.label_list(allow_files = True), ++ "cmake_configure_file_py": attr.label( ++ cfg = "exec", ++ executable = True, ++ default = Label("//bazel:cmake_configure_file"), ++ ), ++ "env": attr.string_dict( ++ mandatory = True, ++ allow_empty = True, ++ ), ++ }, ++ output_to_genfiles = True, ++ implementation = _cmake_configure_file_impl, ++) ++ ++def cmake_configure_file( ++ name, ++ src = None, ++ out = None, ++ defines = None, ++ undefines = None, ++ cmakelists = None, ++ **kwargs): ++ """Creates a rule to generate an out= file from a src= file, using CMake's ++ configure_file substitution semantics. This implementation is incomplete, ++ and may not produce the same result as CMake in all cases. ++ Definitions optionally can be passed in directly as defines= strings (with ++ the usual defines= convention of either a name-only "HAVE_FOO", or a ++ key-value "MYSCALAR=DOUBLE"). ++ Definitions optionally can be read from simple CMakeLists files that ++ contain statements of the form "set(FOO_MAJOR_VERSION 1)" and similar. ++ Variables that are known substitutions but which should be undefined can be ++ passed as undefines= strings. ++ See cmake_configure_file.py for our implementation of the configure_file ++ substitution rules. ++ The CMake documentation of the configure_file macro is: ++ https://cmake.org/cmake/help/latest/command/configure_file.html ++ """ ++ _cmake_configure_file_gen( ++ name = name, ++ src = src, ++ out = out, ++ defines = defines, ++ undefines = undefines, ++ cmakelists = cmakelists, ++ env = {}, ++ **kwargs ++ ) +diff --git bazel/cmake_configure_file.py bazel/cmake_configure_file.py +new file mode 100644 +index 0000000..7097821 +--- /dev/null ++++ bazel/cmake_configure_file.py +@@ -0,0 +1,226 @@ ++"""A re-implementation of CMake's configure_file substitution semantics. This ++implementation is incomplete, and may not produce the same result as CMake in ++all (or even many) cases. ++ ++The CMake documentation of the configure_file macro is: ++https://cmake.org/cmake/help/latest/command/configure_file.html ++ ++""" ++ ++import argparse ++import os ++import re ++import sys ++ ++from collections import OrderedDict ++ ++# Looks like "#cmakedefine VAR ..." or "#cmakedefine01 VAR". ++_cmakedefine = re.compile(r'^(\s*)#cmakedefine(01)? ([^ \r\n]+)(.*?)([\r\n]+)') ++ ++# Looks like "@VAR@" or "${VAR}". ++_varsubst = re.compile(r'^(.*?)(@[^ ]+?@|\$\{[^ ]+?\})(.*)([\r\n]*)') ++ ++ ++# Transform a source code line per CMake's configure_file semantics. ++# ++# The 'definitions' provides values for CMake variables. The dict's keys are ++# the variable names to substitute, and the dict's values are the values to ++# substitute. (The values can be None, for known-but-undefined variable keys.) ++# ++# The configuration semantics are as follows: ++# ++# - An input line 'cmakedefine VAR' turns into '#define VAR VALUE' if and only ++# if the 'definitions' dict has a non-None value VALUE for VAR, otherwise it ++# turns into '/* #undef VAR */'. When in strict mode, it is an error if ++# there is no such key in the dict. ++# ++# - An input line 'cmakedefine01 VAR' turns into '#define VAR 1' if and only if ++# the 'definitions' dict has a non-None value for VAR, otherwise it turns ++# into '#define VAR 0'. When in strict mode, it is an error if there is no ++# such key in the dict. ++# ++# - An input line with a substitution '@VAR@' or '${VAR}' replaces the ++# substitution token with the value in 'definitions' dict for that VAR, or ++# else the empty string if the value is None. It is an error if there is no ++# such key in the dict. ++def _transform_cmake(*, line, definitions, strict): ++ used_vars = set() ++ ++ # Replace define statements. ++ match = _cmakedefine.match(line) ++ if match: ++ blank, maybe01, var, rest, newline = match.groups() ++ if var not in definitions: ++ defined = False ++ if strict: ++ raise KeyError(var) ++ else: ++ defined = definitions[var] is not None ++ used_vars.add(var) ++ if maybe01: ++ line = blank + '#define ' + var + [' 0', ' 1'][defined] + newline ++ return line, used_vars ++ elif defined: ++ line = blank + '#define ' + var + rest + newline ++ else: ++ line = blank + '/* #undef ' + var + ' */' + newline ++ return line, used_vars ++ ++ # Replace variable substitutions. ++ while True: ++ match = _varsubst.match(line) ++ if not match: ++ break ++ before, xvarx, after, newline = match.groups() ++ if xvarx[0] == '$': ++ assert len(xvarx) >= 4 ++ assert xvarx[1] == '{' ++ assert xvarx[-1] == '}' ++ var = xvarx[2:-1] ++ elif xvarx[0] == '@': ++ assert len(xvarx) >= 3 ++ assert xvarx[-1] == '@' ++ var = xvarx[1:-1] ++ assert len(var) > 0 ++ ++ if var not in definitions: ++ raise KeyError(var) ++ used_vars.add(var) ++ value = definitions.get(var) ++ if value is None: ++ value = '' ++ line = before + value + after + newline ++ ++ return line, used_vars ++ ++ ++# Looks like "#undef VAR". ++_autoconf_undef = re.compile(r'^(\s*)#undef +([^ \r\n]+)([\r\n]+)') ++ ++ ++# Transform a source code line using autoconf format. ++# The 'definitions' provides variable values, just like _transform_cmake above. ++def _transform_autoconf(*, line, definitions, strict): ++ used_vars = set() ++ match = _autoconf_undef.match(line) ++ if match: ++ blank, var, newline = match.groups() ++ if var in definitions: ++ used_vars.add(var) ++ value = definitions[var] ++ if value is not None: ++ line = blank + f'#define {var} {value}' + newline ++ else: ++ line = blank + f'/* undef {var} */' + newline ++ elif strict: ++ raise KeyError(f"Missing define or undefine decision for {var}" ++ " when running in strict=True mode") ++ else: ++ line = blank + f'/* missing {var} */' + newline ++ return line, used_vars ++ ++ ++# Looks like "set(VAR value)". ++_set_var = re.compile(r'^\s*set\s*\(\s*(.+)\s+(.+)\s*\)\s*$') ++ ++ ++# From a line of CMakeLists.txt, return a set(...) key-value pair, if found. ++def _extract_definition(line, prior_definitions): ++ match = _set_var.match(line) ++ if not match: ++ return dict() ++ var, value = match.groups() ++ try: ++ value, _ = _transform_cmake( ++ line=value, ++ definitions=prior_definitions, ++ strict=False) ++ except KeyError: ++ return dict() ++ if value.startswith('"'): ++ assert value.endswith('"') ++ value = value[1:-1] ++ return {var: value} ++ ++ ++# Load our definitions dict, given the command-line args: ++# - A command-line '-Dfoo' will add ('foo', '1') to the result. ++# - A command-line '-Dfoo=bar' will add ('foo', 'bar') to the result. ++# - A command-line '-Ufoo' will add ('foo', None) to the result. ++def _setup_definitions(args): ++ result = OrderedDict() ++ for item in args.defines: ++ if '=' in item: ++ key, value = item.split('=', 1) ++ result[key] = value ++ else: ++ result[item] = '1' ++ ++ for item in args.undefines: ++ result[item] = None ++ ++ cmakelist_keys = set() ++ for filename in args.cmakelists: ++ with open(filename, 'r') as cmakelist: ++ for line in cmakelist.readlines(): ++ definition = _extract_definition(line, result) ++ result.update(definition) ++ cmakelist_keys.update(definition.keys()) ++ ++ return result, cmakelist_keys ++ ++ ++def main(): ++ parser = argparse.ArgumentParser() ++ parser.add_argument( ++ '--input', metavar='FILE', action='append', default=[]) ++ parser.add_argument( ++ '--output', metavar='FILE', action='append', default=[]) ++ parser.add_argument( ++ '-D', metavar='NAME', dest='defines', action='append', default=[]) ++ parser.add_argument( ++ '-U', metavar='NAME', dest='undefines', action='append', default=[]) ++ parser.add_argument( ++ '--autoconf', action='store_true', ++ help='The input file is in autoconf format, not cmake format.') ++ parser.add_argument( ++ '--cmakelists', action='append', default=[]) ++ parser.add_argument( ++ '--strict', action='store_true') ++ args = parser.parse_args() ++ if len(args.input) == 0: ++ parser.error("There must be at least one --input") ++ if len(args.input) != len(args.output): ++ parser.error("The number of --input and --output must be congruent") ++ definitions, cmakelist_keys = _setup_definitions(args) ++ ++ transformer = _transform_autoconf if args.autoconf else _transform_cmake ++ total_used_vars = set() ++ missing_vars = set() ++ for input_path, output_path in zip(args.input, args.output): ++ with open(input_path, 'r') as input_file: ++ with open(output_path + '.tmp', 'w') as output_file: ++ for input_line in input_file.readlines(): ++ try: ++ output_line, used_vars = transformer( ++ line=input_line, ++ definitions=definitions, ++ strict=args.strict) ++ output_file.write(output_line) ++ total_used_vars |= used_vars ++ except KeyError as e: ++ missing_vars.add(e.args[0]) ++ if missing_vars: ++ raise RuntimeError(f"The definitions of {sorted(missing_vars)} were" ++ " required, but missing.") ++ unused_vars = definitions.keys() - cmakelist_keys - total_used_vars ++ if unused_vars: ++ raise RuntimeError(f"The definitions of {sorted(unused_vars)} were" ++ " ignored and therefore seem like dead code;" ++ " remove them from defines= or undefines=.") ++ for output_path in args.output: ++ os.rename(output_path + '.tmp', output_path) ++ ++ ++if __name__ == '__main__': ++ main() diff --git a/modules/qdldl/0.1.7/patches/module_dot_bazel.patch b/modules/qdldl/0.1.7/patches/module_dot_bazel.patch new file mode 100644 index 00000000000..5a8fd0a9705 --- /dev/null +++ b/modules/qdldl/0.1.7/patches/module_dot_bazel.patch @@ -0,0 +1,14 @@ +diff --git MODULE.bazel MODULE.bazel +new file mode 100644 +index 0000000..01bf673 +--- /dev/null ++++ MODULE.bazel +@@ -0,0 +1,8 @@ ++module( ++ name = "qdldl", ++ version = "0.1.7", ++ compatibility_level = 1, ++) ++ ++bazel_dep(name = "platforms", version = "0.0.8") ++bazel_dep(name = "rules_cc", version = "0.0.9") diff --git a/modules/qdldl/0.1.7/presubmit.yml b/modules/qdldl/0.1.7/presubmit.yml new file mode 100644 index 00000000000..dfb02c8ad36 --- /dev/null +++ b/modules/qdldl/0.1.7/presubmit.yml @@ -0,0 +1,15 @@ +matrix: + platform: + - debian10 + - ubuntu2004 + - macos + - macos_arm64 + - windows + bazel: [6.x, 7.x] +tasks: + verify_targets: + name: Verify build targets + platform: ${{ platform }} + bazel: ${{ bazel }} + build_targets: + - "@qdldl//:qdldl" diff --git a/modules/qdldl/0.1.7/source.json b/modules/qdldl/0.1.7/source.json new file mode 100644 index 00000000000..7bf2c51365d --- /dev/null +++ b/modules/qdldl/0.1.7/source.json @@ -0,0 +1,11 @@ +{ + "url": "https://github.com/osqp/qdldl/archive/refs/tags/v0.1.7.tar.gz", + "integrity": "sha256-YxrmXzZ4Wfoe+t4WVuS6IrfaeJwG4BDM64spZWv2V1c=", + "strip_prefix": "qdldl-0.1.7", + "patches": { + "add_build_file.patch": "sha256-pEBWcLi9c2DOUtDgju2dMnL86H7yKth86RqwzEylNqk=", + "add_cmake_configure_file.patch": "sha256-qge+NoLlQcrPkS5AR0TbJKkhE3FETgjuzvj9O0WqWwc=", + "module_dot_bazel.patch": "sha256-YHOoqz6XUJQGUmFyoJ9icG2a4Z/4zO8K5zEX4IU8e2Y=" + }, + "patch_strip": 0 +} diff --git a/modules/qdldl/metadata.json b/modules/qdldl/metadata.json new file mode 100644 index 00000000000..f19d96e967b --- /dev/null +++ b/modules/qdldl/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/osqp/qdldl", + "maintainers": [ + { + "email": "daisuke.nishimatsu1021@gmail.com", + "github": "wep21", + "name": "Daisuke Nishimatsu" + } + ], + "repository": [ + "github:osqp/qdldl" + ], + "versions": [ + "0.1.7" + ], + "yanked_versions": {} +}