Bug 1459764 - Build libraries in their FINAL_TARGET location rather than installing them during the build. r=firefox-build-system-reviewers,ahochheiden

Like bug 1255485, but for libraries.

Original patch by Chris Manchester.

Differential Revision: https://phabricator.services.mozilla.com/D63281
This commit is contained in:
Mike Hommey 2024-04-30 23:29:46 +00:00
parent 5753351e60
commit cf328a56ac
23 changed files with 197 additions and 40 deletions

8
Cargo.lock generated
View File

@ -1462,6 +1462,13 @@ dependencies = [
"syn",
]
[[package]]
name = "dist-bin"
version = "0.1.0"
dependencies = [
"mozbuild",
]
[[package]]
name = "dllservices-gtest"
version = "0.1.0"
@ -3810,6 +3817,7 @@ dependencies = [
"bytes",
"cc",
"chrono",
"dist-bin",
"env_logger",
"flate2",
"futures-channel",

View File

@ -0,0 +1,11 @@
[package]
name = "dist-bin"
version = "0.1.0"
edition = "2021"
license = "MPL-2.0"
[lib]
path = "lib.rs"
[build-dependencies]
mozbuild = "0.1"

View File

@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
fn main() {
// Hack around the lack of dist/bin in the search path set up by
// various third party crates for nss. Bug 1892894.
println!(
"cargo:rustc-link-search=native={}",
mozbuild::TOPOBJDIR
.join("dist")
.join("bin")
.to_str()
.unwrap()
);
}

View File

@ -0,0 +1,3 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

View File

@ -20,6 +20,7 @@ arrayvec = { version = "0.7", features = ["serde"], optional = true }
bitflags = { version = "2", features = ["serde", "std"], optional = true }
bytes = { version = "1", optional = true }
chrono = { version = "0.4", features = ["serde"], optional = true }
dist-bin = { path = "../rust/dist-bin", optional = true }
env_logger = { version = "0.10", default-features = false, features = ["color"], optional = true }
flate2 = { version = "1", optional = true }
futures-channel = { version = "0.3", features = ["sink"], optional = true }
@ -190,7 +191,7 @@ crashreporter = ["dep:env_logger", "dep:hyper", "dep:log", "dep:serde_json", "de
geckodriver = ["dep:bitflags", "dep:bytes", "dep:cc", "dep:chrono", "dep:flate2", "dep:futures-channel", "dep:futures-core", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:hyper", "dep:indexmap", "dep:log", "dep:memchr", "dep:mio", "dep:num-integer", "dep:num-traits", "dep:once_cell", "dep:regex", "dep:semver", "dep:serde_json", "dep:smallvec", "dep:time", "dep:tokio", "dep:tokio-util", "dep:tracing", "dep:url", "dep:uuid", "dep:windows-sys"]
gkrust = ["dep:arrayvec", "dep:bindgen", "dep:bitflags", "dep:bytes", "dep:cc", "dep:chrono", "dep:env_logger", "dep:flate2", "dep:futures-channel", "dep:futures-core", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:log", "dep:memchr", "dep:nom", "dep:num-integer", "dep:num-traits", "dep:once_cell", "dep:regex", "dep:scopeguard", "dep:semver", "dep:serde_json", "dep:smallvec", "dep:time", "dep:url", "dep:uuid", "dep:windows-sys"]
gkrust-gtest = ["gkrust"]
http3server = ["dep:arrayvec", "dep:bindgen", "dep:bitflags", "dep:bytes", "dep:chrono", "dep:env_logger", "dep:futures-channel", "dep:futures-core", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:hyper", "dep:indexmap", "dep:log", "dep:memchr", "dep:mio", "dep:nom", "dep:num-integer", "dep:num-traits", "dep:once_cell", "dep:regex", "dep:serde_json", "dep:smallvec", "dep:time", "dep:tokio", "dep:tokio-util", "dep:tracing", "dep:url", "dep:windows-sys"]
http3server = ["dep:arrayvec", "dep:bindgen", "dep:bitflags", "dep:bytes", "dep:chrono", "dep:env_logger", "dep:futures-channel", "dep:futures-core", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:hyper", "dep:indexmap", "dep:log", "dep:memchr", "dep:mio", "dep:nom", "dep:num-integer", "dep:num-traits", "dep:once_cell", "dep:regex", "dep:serde_json", "dep:smallvec", "dep:time", "dep:tokio", "dep:tokio-util", "dep:tracing", "dep:url", "dep:windows-sys", "dep:dist-bin"]
ipcclientcerts-static = ["dep:bindgen", "dep:bitflags", "dep:memchr", "dep:nom", "dep:regex"]
jsrust = ["dep:arrayvec", "dep:cc", "dep:env_logger", "dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:log", "dep:memchr", "dep:num-traits", "dep:once_cell", "dep:semver", "dep:smallvec", "dep:url"]
mozwer_s = ["dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:once_cell", "dep:serde_json", "dep:uuid", "dep:windows-sys"]

View File

@ -14,16 +14,6 @@ PROGRAMS_TARGET := target
INSTALL_TARGETS += PROGRAMS
endif
ifdef SHARED_LIBRARY
SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
ifndef SHARED_LIBRARY_TARGET
SHARED_LIBRARY_TARGET = target
endif
INSTALL_TARGETS += SHARED_LIBRARY
endif # SHARED_LIBRARY
ifdef WASM_LIBRARY
WASM_LIBRARY_FILES = $(WASM_LIBRARY)
WASM_LIBRARY_DEST ?= $(FINAL_TARGET)

View File

@ -279,7 +279,7 @@ endif
ifeq ($(OS_ARCH),Darwin)
ifneq (,$(SHARED_LIBRARY))
_LOADER_PATH := @rpath
EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$@ -compatibility_version 1 -current_version 1
EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$(@F) -compatibility_version 1 -current_version 1
endif
endif
@ -534,11 +534,11 @@ endif
# symlinks back to the originals. The symlinks are a no-op for stabs debugging,
# so no need to conditionalize on OS version or debugging format.
$(SHARED_LIBRARY): $(OBJS) $(call resfile,$(SHARED_LIBRARY)) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
$(SHARED_LIBRARY): $(OBJS) $(call resfile,$(SHARED_LIBRARY)) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS) $(call mkdir_deps,$(FINAL_TARGET))
$(REPORT_BUILD)
$(call BUILDSTATUS,START_SharedLib $@)
$(RM) $@
$(MKSHLIB) $($@_OBJS) $(filter %.res,$^) $(RELRHACK_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS)
$(MKSHLIB) $(if $(filter _WINNT,$(GNU_CC)_$(OS_ARCH)),-IMPLIB:$(basename $(@F)).lib )$($(notdir $@)_OBJS) $(filter %.res,$^) $(RELRHACK_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS)
$(call py_action,check_binary,$@)
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))

View File

@ -1366,7 +1366,10 @@ class RecursiveMakeBackend(MakeBackend):
backend_file.write_once("LIBRARY_NAME := %s\n" % libdef.basename)
backend_file.write("FORCE_SHARED_LIB := 1\n")
backend_file.write("IMPORT_LIBRARY := %s\n" % libdef.import_name)
backend_file.write("SHARED_LIBRARY := %s\n" % libdef.lib_name)
backend_file.write(
"SHARED_LIBRARY := %s\n"
% self._pretty_path(libdef.output_path, backend_file)
)
if libdef.soname:
backend_file.write("DSO_SONAME := %s\n" % libdef.soname)
if libdef.symbols_file:
@ -1376,10 +1379,6 @@ class RecursiveMakeBackend(MakeBackend):
backend_file.write("LIB_IS_C_ONLY := 1\n")
if libdef.output_category:
self._process_non_default_target(libdef, libdef.lib_name, backend_file)
# Override the install rule target for this library. This is hacky,
# but can go away as soon as we start building libraries in their
# final location (bug 1459764).
backend_file.write("SHARED_LIBRARY_TARGET := %s\n" % libdef.output_category)
def _process_static_library(self, libdef, backend_file):
backend_file.write_once("LIBRARY_NAME := %s\n" % libdef.basename)
@ -1427,15 +1426,13 @@ class RecursiveMakeBackend(MakeBackend):
)
def _process_linked_libraries(self, obj, backend_file):
def pretty_relpath(lib, name):
return os.path.normpath(
mozpath.join(mozpath.relpath(lib.objdir, obj.objdir), name)
)
def pretty_relpath(path):
return os.path.normpath(mozpath.relpath(path, obj.objdir))
objs, shared_libs, os_libs, static_libs = self._expand_libs(obj)
obj_target = obj.name
if isinstance(obj, Program):
if isinstance(obj, (Program, SharedLibrary)):
obj_target = self._pretty_path(obj.output_path, backend_file)
objs_ref = " \\\n ".join(os.path.relpath(o, obj.objdir) for o in objs)
@ -1485,7 +1482,7 @@ class RecursiveMakeBackend(MakeBackend):
for lib in shared_libs:
assert obj.KIND != "host" and obj.KIND != "wasm"
backend_file.write_once(
"SHARED_LIBS += %s\n" % pretty_relpath(lib, lib.import_name)
"SHARED_LIBS += %s\n" % pretty_relpath(lib.import_path)
)
# We have to link any Rust libraries after all intermediate static
@ -1497,7 +1494,7 @@ class RecursiveMakeBackend(MakeBackend):
(l for l in static_libs if isinstance(l, BaseRustLibrary)),
):
backend_file.write_once(
"%s += %s\n" % (var, pretty_relpath(lib, lib.import_name))
"%s += %s\n" % (var, pretty_relpath(lib.import_path))
)
for lib in os_libs:

View File

@ -391,6 +391,15 @@ class Linkable(ContextDerived):
self.lib_defines = Defines(context, OrderedDict())
self.sources = defaultdict(list)
@property
def output_path(self):
if self.installed:
return ObjDirPath(
self._context, "!/" + mozpath.join(self.install_target, self.name)
)
else:
return ObjDirPath(self._context, "!" + self.name)
def link_library(self, obj):
assert isinstance(obj, BaseLibrary)
if obj.KIND != self.KIND:
@ -481,15 +490,6 @@ class BaseProgram(Linkable):
self.program = program
self.is_unit_test = is_unit_test
@property
def output_path(self):
if self.installed:
return ObjDirPath(
self._context, "!/" + mozpath.join(self.install_target, self.program)
)
else:
return ObjDirPath(self._context, "!" + self.program)
def __repr__(self):
return "<%s: %s/%s>" % (type(self).__name__, self.relobjdir, self.program)
@ -637,6 +637,10 @@ class BaseLibrary(Linkable):
def name(self):
return self.lib_name
@property
def import_path(self):
return mozpath.join(self.objdir, self.import_name)
class Library(BaseLibrary):
"""Context derived container object for a library"""
@ -873,6 +877,16 @@ class SharedLibrary(Library):
elif context.config.substs.get("GCC_USE_GNU_LD"):
self.symbols_link_arg = "-Wl,--version-script," + self.symbols_file
@property
def import_path(self):
if self.config.substs.get("OS_ARCH") == "WINNT":
# We build import libs on windows in a library's objdir
# to avoid cluttering up dist/bin.
return mozpath.join(self.objdir, self.import_name)
return mozpath.join(
mozpath.dirname(self.output_path.full_path), self.import_name
)
class HostSharedLibrary(HostMixin, Library):
"""Context derived container object for a host shared library.

View File

@ -179,6 +179,15 @@ CONFIGS = defaultdict(
"BIN_SUFFIX": ".prog",
},
},
"shared-lib-paths": {
"defines": {},
"substs": {
"COMPILE_ENVIRONMENT": "1",
"LIB_SUFFIX": "a",
"DLL_PREFIX": "lib",
"DLL_SUFFIX": ".so",
},
},
"linkage": {
"defines": {},
"substs": {

View File

@ -0,0 +1,4 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
SharedLibrary("dist-bin")

View File

@ -0,0 +1,5 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
DIST_SUBDIR = "foo"
SharedLibrary("dist-subdir")

View File

@ -0,0 +1,5 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
FINAL_TARGET = "final/target"
SharedLibrary("final-target")

View File

@ -0,0 +1,16 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def SharedLibrary(name):
FORCE_SHARED_LIB = True
LIBRARY_NAME = name
DIRS += [
"dist-bin",
"dist-subdir",
"final-target",
"not-installed",
]

View File

@ -0,0 +1,5 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
DIST_INSTALL = False
SharedLibrary("not-installed")

View File

@ -1203,23 +1203,23 @@ class TestRecursiveMakeBackend(BackendTester):
env = self._consume("linkage", RecursiveMakeBackend)
expected_linkage = {
"prog": {
"SHARED_LIBS": ["qux/qux.so", "../shared/baz.so"],
"SHARED_LIBS": ["../dist/bin/qux.so", "../dist/bin/baz.so"],
"STATIC_LIBS": ["../real/foo.a"],
"OS_LIBS": ["-lfoo", "-lbaz", "-lbar"],
},
"shared": {
"OS_LIBS": ["-lfoo"],
"SHARED_LIBS": ["../prog/qux/qux.so"],
"SHARED_LIBS": ["../dist/bin/qux.so"],
"STATIC_LIBS": [],
},
"static": {
"STATIC_LIBS": ["../real/foo.a"],
"OS_LIBS": ["-lbar"],
"SHARED_LIBS": ["../prog/qux/qux.so"],
"SHARED_LIBS": ["../dist/bin/qux.so"],
},
"real": {
"STATIC_LIBS": [],
"SHARED_LIBS": ["../prog/qux/qux.so"],
"SHARED_LIBS": ["../dist/bin/qux.so"],
"OS_LIBS": ["-lbaz"],
},
}
@ -1326,6 +1326,28 @@ class TestRecursiveMakeBackend(BackendTester):
][0]
self.assertEqual(program, expected_program)
def test_shared_lib_paths(self):
"""SHARED_LIBRARYs with various moz.build settings that change the destination should
produce the expected paths in backend.mk."""
env = self._consume("shared-lib-paths", RecursiveMakeBackend)
expected = [
("dist-bin", "$(DEPTH)/dist/bin/libdist-bin.so"),
("dist-subdir", "$(DEPTH)/dist/bin/foo/libdist-subdir.so"),
("final-target", "$(DEPTH)/final/target/libfinal-target.so"),
("not-installed", "libnot-installed.so"),
]
prefix = "SHARED_LIBRARY := "
for subdir, expected_shared_lib in expected:
with io.open(os.path.join(env.topobjdir, subdir, "backend.mk"), "r") as fh:
lines = fh.readlines()
shared_lib = [
line.rstrip().split(prefix, 1)[1]
for line in lines
if line.startswith(prefix)
][0]
self.assertEqual(shared_lib, expected_shared_lib)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,4 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
SharedLibrary("dist-bin")

View File

@ -0,0 +1,5 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
DIST_SUBDIR = "foo"
SharedLibrary("dist-subdir")

View File

@ -0,0 +1,5 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
FINAL_TARGET = "final/target"
SharedLibrary("final-target")

View File

@ -0,0 +1,16 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def SharedLibrary(name):
FORCE_SHARED_LIB = True
LIBRARY_NAME = name
DIRS += [
"dist-bin",
"dist-subdir",
"final-target",
"not-installed",
]

View File

@ -0,0 +1,5 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
DIST_INSTALL = False
SharedLibrary("not-installed")

View File

@ -782,6 +782,22 @@ class TestEmitterBasic(unittest.TestCase):
],
)
def test_shared_lib_paths(self):
"""Various moz.build settings that change the destination of SHARED_LIBRARY
should be accurately reflected in Program.output_path."""
reader = self.reader("shared-lib-paths")
objs = self.read_topsrcdir(reader)
prog_paths = [o.output_path for o in objs if isinstance(o, SharedLibrary)]
self.assertEqual(
prog_paths,
[
"!/dist/bin/libdist-bin.so",
"!/dist/bin/foo/libdist-subdir.so",
"!/final/target/libfinal-target.so",
"!libnot-installed.so",
],
)
def test_host_program_paths(self):
"""The destination of a HOST_PROGRAM (almost always dist/host/bin)
should be accurately reflected in Program.output_path."""

View File

@ -28,7 +28,7 @@ if CONFIG["COMPILE_ENVIRONMENT"]:
"dependentlibs.list.gtest",
script="dependentlibs.py",
entry_point="gen_list",
inputs=["!%s" % full_libname],
inputs=["!/dist/bin/%s" % full_libname],
)
FINAL_TARGET_FILES += ["!dependentlibs.list", "!dependentlibs.list.gtest"]