Skip to content

Commit

Permalink
[workspace] Straighten out repo rules for MOSEK, TBB, OpenUSD (RobotL…
Browse files Browse the repository at this point in the history
…ocomotion#21155)

Now deprecated: calling mosek_repository() without providing mirrors.

Split up MOSEK repository rule into separate, more cohesive files:
- repository.bzl for the version pin and checksums
- repository_impl.bzl for the arch-specific downloading and paths
- package.BUILD.bazel for the C++ rules

Improve the MOSEK repository rule features:
- Add linuxaarch64 support.
- Add mirroring support.
- Use a deeper strip_prefix to discard stuff we don't need.
- Fix use of install_name_tool to skip symlinks and set rpaths properly.
- Remove hard-coded version numbers in the BUILD file.
- Use cc_import (the canonical Bazel spelling for prebuilt shared libraries).
- Provide separate rules for TBB and MOSEK.

When WITH_USD is ON:
- Provide the TBB shared libraries to pydrake (via libdrake.so).
- Install the OneTBB license.

Fix typo in our skylark cc_import forwarder.
  • Loading branch information
jwnimmer-tri authored Mar 21, 2024
1 parent 9d8e868 commit 8518e84
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 186 deletions.
12 changes: 12 additions & 0 deletions tools/install/libdrake/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,17 @@ cc_library(
}),
)

# Depend on TBB shared library iff USD is enabled.
cc_library(
name = "usd_deps",
deps = select({
"//tools:with_usd": [
"@mosek//:tbb",
],
"//conditions:default": [],
}),
)

# Depend on X11 iff on Ubuntu and not MacOS.
cc_library(
name = "x11_deps",
Expand Down Expand Up @@ -204,6 +215,7 @@ cc_library(
":gurobi_deps",
":ipopt_deps",
":mosek_deps",
":usd_deps",
":x11_deps",
"//common:drake_marker_shared_library",
"@lcm",
Expand Down
2 changes: 1 addition & 1 deletion tools/skylark/cc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def cc_binary(**kwargs):
native.cc_binary(**kwargs)

def cc_import(**kwargs):
native.cc_input(**kwargs)
native.cc_import(**kwargs)

def cc_library(**kwargs):
native.cc_library(**kwargs)
Expand Down
3 changes: 3 additions & 0 deletions tools/workspace/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ _DRAKE_EXTERNAL_PACKAGE_INSTALLS = ["@%s//:install" % p for p in [
}) + select({
"//conditions:default": ["@scs_internal//:install"],
"//tools:no_scs": [],
}) + select({
"//tools:with_usd": ["@onetbb_internal//:install"],
"//conditions:default": [],
})

install(
Expand Down
2 changes: 1 addition & 1 deletion tools/workspace/default.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def add_default_repositories(excludes = [], mirrors = DEFAULT_MIRRORS):
if "meshcat" not in excludes:
meshcat_repository(name = "meshcat", mirrors = mirrors)
if "mosek" not in excludes:
mosek_repository(name = "mosek")
mosek_repository(name = "mosek", mirrors = mirrors)
if "mpmath_py_internal" not in excludes:
mpmath_py_internal_repository(name = "mpmath_py_internal", mirrors = mirrors) # noqa
if "msgpack_internal" not in excludes:
Expand Down
5 changes: 5 additions & 0 deletions tools/workspace/mirrors.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@ DEFAULT_MIRRORS = {
# N.B. ibiblio doesn't offer https.
"http://maven.ibiblio.org/maven2/{fulljar}",
],
"mosek": [
"https://download.mosek.com/{path}",
"https://drake-mirror.csail.mit.edu/mosek/{path}",
"https://s3.amazonaws.com/drake-mirror/mosek/{path}",
],
}
107 changes: 107 additions & 0 deletions tools/workspace/mosek/package.BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# -*- bazel -*-

load("@drake//tools/install:install.bzl", "install", "install_files")
load("@drake//tools/skylark:cc.bzl", "cc_import", "cc_library")

package(default_visibility = ["//visibility:private"])

# We use the the MOSEK™ copy of libtbb, even on Ubuntu which *does* have the
# library already available, because the version in Ubuntu is too old.

# Find the TBB shared library with the major.minor-style version number.
# This will be the spelling with the actual object code.
_TBB_MAJMIN_GLOB = glob([
"bin/libtbb.so.*.*",
"bin/libtbb.*.*.dylib",
])

len(_TBB_MAJMIN_GLOB) == 1 or fail("Glob failure: " + str(glob(["**"])))

# Find the TBB shared library with the major-only-style version number.
# This will be the spelling that's a symlink to the major.minor spelling.
_TBB_MAJ_GLOB = glob([
"bin/libtbb.so.*",
"bin/libtbb.*.dylib",
], exclude = _TBB_MAJMIN_GLOB)

len(_TBB_MAJ_GLOB) == 1 or fail("Glob failure: " + str(glob(["**"])))

cc_import(
name = "import_tbb_majmin",
shared_library = _TBB_MAJMIN_GLOB[0],
)

cc_import(
name = "import_tbb_maj",
shared_library = _TBB_MAJ_GLOB[0],
visibility = ["//visibility:private"],
)

cc_library(
name = "tbb",
deps = [
":import_tbb_maj",
":import_tbb_majmin",
],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
)

# Find the mosek shared library with the major.minor-style version number.
_MOSEK_MAJMIN_GLOB = glob([
"bin/libmosek64.so.*.*",
"bin/libmosek64.*.*.dylib",
])

len(_MOSEK_MAJMIN_GLOB) == 1 or fail("Glob failure: " + str(glob(["**"])))

cc_import(
name = "import_mosek",
shared_library = _MOSEK_MAJMIN_GLOB[0],
deps = [":tbb"],
visibility = ["//visibility:private"],
)

cc_library(
name = "mosek",
hdrs = ["h/mosek.h"],
includes = ["h"],
deps = [":import_mosek"],
visibility = ["//visibility:public"],
)

install_files(
name = "install_tbb_libraries",
dest = "lib",
files = _TBB_MAJMIN_GLOB + _TBB_MAJ_GLOB,
strip_prefix = ["bin"],
visibility = ["//visibility:public"],
)

install_files(
name = "install_mosek_libraries",
dest = "lib",
files = _MOSEK_MAJMIN_GLOB,
strip_prefix = ["bin"],
)

install(
name = "install_licenses",
docs = [
"mosek-eula.pdf",
"@drake//tools/workspace/mosek:drake_mosek_redistribution.txt",
"@drake//tools/workspace/mosek:LICENSE.third_party",
],
doc_strip_prefix = ["tools/workspace/mosek"],
allowed_externals = ["@drake//:.bazelproject"],
)

install(
name = "install",
deps = [
":install_licenses",
":install_mosek_libraries",
":install_tbb_libraries",
],
visibility = ["//visibility:public"],
)
203 changes: 26 additions & 177 deletions tools/workspace/mosek/repository.bzl
Original file line number Diff line number Diff line change
@@ -1,178 +1,27 @@
"""
Downloads and unpacks a MOSEK™ archive and makes its headers and
precompiled shared libraries available to be used as a C/C++
dependency.
Example:
WORKSPACE:
load("@drake//tools/workspace/mosek:repository.bzl", "mosek_repository") # noqa
mosek_repository(name = "foo")
BUILD:
cc_library(
name = "foobar",
deps = ["@foo//:mosek"],
srcs = ["bar.cc"],
)
Argument:
name: A unique name for this rule.
"""

load("//tools/workspace:execute.bzl", "which")

def _impl(repository_ctx):
# When these values are updated:
# - tools/dynamic_analysis/tsan.supp may also need updating
# - LICENSE.third_party may also need updating to match
# https://docs.mosek.com/latest/licensing/license-agreement-info.html
mosek_major_version = 10
mosek_minor_version = 1
mosek_patch_version = 21

os_name = repository_ctx.os.name # 'linux' or 'mac os x' (=> 'darwin')
if os_name == "mac os x":
os_name = "darwin"
os_arch = repository_ctx.os.arch # 'amd64' or 'aarch64'
if os_name == "darwin":
if os_arch == "aarch64":
mosek_platform = "osxaarch64"
sha256 = "f6e862cab171b7897a6f1ad21c3c0fbdf33dc1310f50c792295ab008321950c7" # noqa
else:
mosek_platform = "osx64x86"
sha256 = "3ad45f7e535b6d3bb8be955f403ded30a7f186424057f11024afc57427cbb012" # noqa
else:
# TODO(jwnimmer-tri) We should add linux aarch64 support here.
mosek_platform = "linux64x86"
sha256 = "f37b7b3806e467c64a02e95b2ab009f6fe8430f25ffc72ed56885f7684dec486" # noqa

# TODO(jwnimmer-tri) Port to use mirrors.bzl.
template = "https://download.mosek.com/stable/{}.{}.{}/mosektools{}.tar.bz2" # noqa
url = template.format(
mosek_major_version,
mosek_minor_version,
mosek_patch_version,
mosek_platform,
)
root_path = repository_ctx.path("")
strip_prefix = "mosek/{}.{}".format(
mosek_major_version,
mosek_minor_version,
load("//tools/workspace/mosek:repository_impl.bzl", "repository_impl")

# TODO(jwnimmer-tri) Remove on 2024-07-01 upon completion of deprecation.
load("//tools/workspace:mirrors.bzl", "DEFAULT_MIRRORS")

def mosek_repository(
name,
mirrors = None):
# TODO(jwnimmer-tri) Remove on 2024-07-01 upon completion of deprecation.
if mirrors == None:
print("mosek_repository() now requires a mirrors= argument; passing None is deprecated and will become an error on our after 2024-07-01") # noqa
mirrors = DEFAULT_MIRRORS
repository_impl(
name = name,
# When the version is updated:
# - tools/dynamic_analysis/tsan.supp may also need updating
# - LICENSE.third_party may also need updating to match
# https://docs.mosek.com/latest/licensing/license-agreement-info.html
version = "10.1.21",
sha256 = {
"mosektoolslinuxaarch64.tar.bz2": "f37b7b3806e467c64a02e95b2ab009f6fe8430f25ffc72ed56885f7684dec486", # noqa
"mosektoolslinux64x86.tar.bz2": "f37b7b3806e467c64a02e95b2ab009f6fe8430f25ffc72ed56885f7684dec486", # noqa
"mosektoolsosxaarch64.tar.bz2": "f6e862cab171b7897a6f1ad21c3c0fbdf33dc1310f50c792295ab008321950c7", # noqa
"mosektoolsosx64x86.tar.bz2": "3ad45f7e535b6d3bb8be955f403ded30a7f186424057f11024afc57427cbb012", # noqa
},
mirrors = mirrors,
)

repository_ctx.download_and_extract(
url,
root_path,
sha256 = sha256,
stripPrefix = strip_prefix,
)

platform_prefix = "tools/platform/{}".format(mosek_platform)

if os_name == "darwin":
install_name_tool = which(repository_ctx, "install_name_tool")

files = [
"bin/libtbb.12.dylib",
"bin/libtbb.12.8.dylib",
"bin/libmosek64.{}.{}.dylib".format(
mosek_major_version,
mosek_minor_version,
),
]

for file in files:
file_path = repository_ctx.path(
"{}/{}".format(platform_prefix, file),
)

result = repository_ctx.execute([
install_name_tool,
"-id",
file_path,
file_path,
])

if result.return_code != 0:
fail(
"Could NOT change shared library identification name",
attr = result.stderr,
)

srcs = []

bin_path = repository_ctx.path("{}/bin".format(platform_prefix))

linkopts = [
"-L{}".format(bin_path),
"-lmosek64",
]
else:
files = [
# We use the the MOSEK™ copy of libtbb. The version of libtbb
# available in Ubuntu is too old. Anytime we change this, we must
# also sync our @onetbb_internal version number to match this.
"bin/libtbb.so.12",
"bin/libtbb.so.12.8",
"bin/libmosek64.so.{}.{}".format(
mosek_major_version,
mosek_minor_version,
),
]

linkopts = ["-pthread"]
srcs = ["{}/{}".format(platform_prefix, file) for file in files]

hdrs = ["{}/h/mosek.h".format(platform_prefix)]
includes = ["{}/h".format(platform_prefix)]
files = ["{}/{}".format(platform_prefix, file) for file in files]
libraries_strip_prefix = ["{}/bin".format(platform_prefix)]

file_content = """# DO NOT EDIT: generated by mosek_repository()
load("@drake//tools/install:install.bzl", "install", "install_files")
load("@drake//tools/skylark:cc.bzl", "cc_library")
licenses([
"by_exception_only", # MOSEK
"notice", # fplib AND Zlib
])
package(default_visibility = ["//visibility:public"])
cc_library(
name = "mosek",
srcs = {},
hdrs = {},
includes = {},
linkopts = {},
)
install_files(
name = "install_libraries",
dest = "lib",
files = {},
strip_prefix = {},
visibility = ["//visibility:private"],
)
install(
name = "install",
docs = [
"mosek-eula.pdf",
"@drake//tools/workspace/mosek:drake_mosek_redistribution.txt",
"@drake//tools/workspace/mosek:LICENSE.third_party",
],
doc_strip_prefix = ["tools/workspace/mosek"],
allowed_externals = ["@drake//:.bazelproject"],
deps = [":install_libraries"],
)
""".format(srcs, hdrs, includes, linkopts, files, libraries_strip_prefix)

repository_ctx.file(
"BUILD.bazel",
content = file_content,
executable = False,
)

mosek_repository = repository_rule(implementation = _impl)
Loading

0 comments on commit 8518e84

Please sign in to comment.