From 111f77dd499df79c2d821bd4c1133ecdb4326e3b Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 7 Feb 2024 19:08:54 -0800 Subject: [PATCH] Pass link flags to Rust more consistently Passing `LDFLAGS` is no longer always enough. Pass link flags as `-C link-arg=...` in `RUSTFLAGS` as well. --- metapkg/packages/base.py | 21 ++++----- metapkg/packages/python.py | 4 +- metapkg/targets/base.py | 90 ++++++++++++++++++++---------------- metapkg/targets/deb/build.py | 13 ++++-- 4 files changed, 72 insertions(+), 56 deletions(-) diff --git a/metapkg/packages/base.py b/metapkg/packages/base.py index 3fdce8c..f6f34b2 100644 --- a/metapkg/packages/base.py +++ b/metapkg/packages/base.py @@ -338,7 +338,7 @@ def _get_sources(cls, version: str | None) -> list[af_sources.BaseSource]: if "version" not in extras: extras["version"] = version else: - extras = {"version": version} + extras = af_sources.SourceExtraDecl({"version": version}) if "vcs_version" not in extras: extras["vcs_version"] = cls.to_vcs_version( @@ -1037,29 +1037,28 @@ def configure_dependency( ) if var_prefix: - build.sh_append_flags( + build.sh_append_quoted_flags( configure_flags, f"{var_prefix}_CFLAGS", - f"-I{rel_path}/include/", + [f"-I{rel_path}/include/"], ) - build.sh_append_flags( + build.sh_append_quoted_flags( configure_flags, f"{var_prefix}_LIBS", dep_ldflags, ) else: - build.sh_append_flags( + build.sh_append_quoted_flags( configure_flags, "CFLAGS", - f"-I{rel_path}/include/", + [f"-I{rel_path}/include/"], ) - build.sh_append_flags( + build.sh_append_quoted_ldflags( configure_flags, - f"LDFLAGS", dep_ldflags, ) - ldflags = f"-L{rel_path}/lib/" + ldflags = [f"-L{rel_path}/lib/"] if platform.system() == "Darwin": # In case ./configure tries to compile and test a program @@ -1067,9 +1066,9 @@ def configure_dependency( # at its install_name location. configure_flags["DYLD_FALLBACK_LIBRARY_PATH"] = root else: - ldflags += f'" "-Wl,-rpath-link,{rel_path}/lib' + ldflags.append(f"-Wl,-rpath-link,{rel_path}/lib") - build.sh_append_flags(configure_flags, f"LDFLAGS", ldflags) + build.sh_append_quoted_ldflags(configure_flags, ldflags) elif build.is_stdlib(pkg): configure_flags[f"{var_prefix}_CFLAGS"] = ( diff --git a/metapkg/packages/python.py b/metapkg/packages/python.py index f481832..f814e5e 100644 --- a/metapkg/packages/python.py +++ b/metapkg/packages/python.py @@ -388,7 +388,7 @@ def get_build_script(self, build: targets.Build) -> str: ) if cflags: - build.sh_append_flags(env, "CFLAGS", cflags) + build.sh_append_quoted_flags(env, "CFLAGS", cflags) ldflags = build.sh_get_bundled_shlibs_ldflags( build_deps, @@ -396,7 +396,7 @@ def get_build_script(self, build: targets.Build) -> str: ) if ldflags: - build.sh_append_flags(env, "LDFLAGS", ldflags) + build.sh_append_quoted_ldflags(env, ldflags) binary = True diff --git a/metapkg/targets/base.py b/metapkg/targets/base.py index 529d2ae..2e001d5 100644 --- a/metapkg/targets/base.py +++ b/metapkg/targets/base.py @@ -1173,7 +1173,7 @@ def prepare_tools(self) -> None: if bundled_tools: self._tools.update(bundled_tools) - source_dirs = [pathlib.Path(helpers_pkg.__path__[0])] + source_dirs = [pathlib.Path(next(iter(helpers_pkg.__path__)))] mod_file = sys.modules[self.__module__].__file__ assert mod_file is not None specific_helpers = pathlib.Path(mod_file).parent / "_helpers" @@ -1465,17 +1465,23 @@ def sh_join_flags( ) -> str: return '" "'.join(filter(None, flags)) + def sh_quote_flags( + self, + flags: list[str] | tuple[str, ...], + ) -> list[str]: + return [shlex.quote(f) for f in flags if f] + def sh_format_flags( self, flags: list[str] | tuple[str, ...], ) -> str: - return self.sh_join_flags([shlex.quote(f) for f in flags if f]) + return self.sh_join_flags(self.sh_quote_flags(flags)) def sh_get_bundled_shlib_ldflags( self, pkg: mpkg_base.BasePackage, relative_to: Location = "pkgbuild", - ) -> str: + ) -> list[str]: flags = [] assert self.is_bundled(pkg) @@ -1501,32 +1507,32 @@ def sh_get_bundled_shlib_ldflags( ) for shlib in pkg.get_shlibs(self): - flags.append(f"-l{shlib}") + flags.append(f"-l{shlex.quote(shlib)}") - return self.sh_join_flags(flags) + return flags def sh_get_bundled_shlibs_ldflags( self, deps: Iterable[mpkg_base.BasePackage], relative_to: Location = "pkgbuild", - ) -> str: + ) -> list[str]: flags = [] for pkg in deps: if self.is_bundled(pkg): - flags.append( + flags.extend( self.sh_get_bundled_shlib_ldflags( pkg, relative_to=relative_to ) ) - return self.sh_join_flags(flags) + return flags def sh_get_bundled_shlib_cflags( self, pkg: mpkg_base.BasePackage, relative_to: Location = "pkgbuild", - ) -> str: + ) -> list[str]: flags = [] assert self.is_bundled(pkg) @@ -1536,61 +1542,41 @@ def sh_get_bundled_shlib_cflags( inc_path = root_path / include_path.relative_to("/") flags.append(f"-I$(pwd -P)/{shlex.quote(str(inc_path))}") - return self.sh_join_flags(flags) + return flags def sh_get_bundled_shlibs_cflags( self, deps: Iterable[mpkg_base.BasePackage], relative_to: Location = "pkgbuild", - ) -> str: + ) -> list[str]: flags = [] for pkg in deps: if self.is_bundled(pkg): - flags.append( + flags.extend( self.sh_get_bundled_shlib_cflags( pkg, relative_to=relative_to ) ) - return self.sh_join_flags(flags) + return flags def sh_append_global_flags( self, args: Mapping[str, str | pathlib.Path | None] | None = None, - flag_names: Mapping[str, str] | None = None, ) -> dict[str, str | pathlib.Path | None]: global_cflags = self.target.get_global_cflags(self) global_cxxflags = self.target.get_global_cxxflags(self) global_ldflags = self.target.get_global_ldflags(self) if args is None: args = {} - flag_name_map = { - "CFLAGS": "CFLAGS", - "CXXFLAGS": "CXXFLAGS", - "LDFLAGS": "LDFLAGS", - "RUSTFLAGS": "RUSTFLAGS", - } - flag_name_map.update(flag_names or {}) conf_args = dict(args) if global_cflags: - self.sh_append_flags( - conf_args, flag_name_map["CFLAGS"], global_cflags - ) + self.sh_append_flags(conf_args, "CFLAGS", global_cflags) if global_cxxflags: - self.sh_append_flags( - conf_args, flag_name_map["CXXFLAGS"], global_cxxflags - ) + self.sh_append_flags(conf_args, "CXXFLAGS", global_cxxflags) if global_ldflags: - self.sh_append_flags( - conf_args, flag_name_map["LDFLAGS"], global_ldflags - ) - rust_ldflags = [] - for f in global_ldflags: - rust_ldflags.extend(["-C", f"link-arg={f}"]) - self.sh_append_flags( - conf_args, flag_name_map["RUSTFLAGS"], rust_ldflags - ) + self.sh_append_ldflags(conf_args, global_ldflags) return conf_args def sh_append_run_time_ldflags( @@ -1607,9 +1593,9 @@ def sh_append_run_time_ldflags( ) ) if ldflags: - self.sh_append_flags(args, "LDFLAGS", ldflags) + self.sh_append_quoted_ldflags(args, ldflags) - def sh_append_flags( + def sh_append_quoted_flags( self, args: dict[str, str | pathlib.Path | None], key: str, @@ -1618,7 +1604,7 @@ def sh_append_flags( if isinstance(flags, str): flags_line = flags else: - flags_line = self.sh_format_flags(flags) + flags_line = self.sh_join_flags(flags) existing_flags = args.get(key) if existing_flags: assert isinstance(existing_flags, str) @@ -1630,6 +1616,32 @@ def sh_append_flags( else: args[key] = "!" + flags_line + def sh_append_flags( + self, + args: dict[str, str | pathlib.Path | None], + key: str, + flags: list[str] | tuple[str, ...], + ) -> None: + self.sh_append_quoted_flags(args, key, self.sh_quote_flags(flags)) + + def sh_append_quoted_ldflags( + self, + args: dict[str, str | pathlib.Path | None], + flags: list[str] | tuple[str, ...], + ) -> None: + self.sh_append_quoted_flags(args, "LDFLAGS", flags) + rust_ldflags = [] + for f in flags: + rust_ldflags.extend(["-C", f"link-arg={f}"]) + self.sh_append_quoted_flags(args, "RUSTFLAGS", rust_ldflags) + + def sh_append_ldflags( + self, + args: dict[str, str | pathlib.Path | None], + flags: list[str] | tuple[str, ...], + ) -> None: + self.sh_append_quoted_ldflags(args, self.sh_quote_flags(flags)) + def sh_configure( self, path: str | pathlib.Path, diff --git a/metapkg/targets/deb/build.py b/metapkg/targets/deb/build.py index 7cf47d9..e96ce3b 100644 --- a/metapkg/targets/deb/build.py +++ b/metapkg/targets/deb/build.py @@ -11,6 +11,8 @@ import subprocess import textwrap +from cleo.io.outputs import stream_output as cleo_io_stream_output + from metapkg import packages from metapkg import targets from metapkg import tools @@ -598,12 +600,15 @@ def _dpkg_buildpackage(self) -> None: else: workdir = self.get_source_abspath() + output = self._io.output + assert isinstance(output, cleo_io_stream_output.StreamOutput) + tools.cmd( "apt-get", "update", env=env, cwd=str(workdir), - stdout=self._io.output.stream, + stdout=output.stream, stderr=subprocess.STDOUT, ) @@ -616,7 +621,7 @@ def _dpkg_buildpackage(self) -> None: "devscripts", env=env, cwd=str(workdir), - stdout=self._io.output.stream, + stdout=output.stream, stderr=subprocess.STDOUT, ) @@ -628,7 +633,7 @@ def _dpkg_buildpackage(self) -> None: str(self._debroot / "control"), env=env, cwd="/tmp", - stdout=self._io.output.stream, + stdout=output.stream, stderr=subprocess.STDOUT, ) @@ -640,7 +645,7 @@ def _dpkg_buildpackage(self) -> None: "dpkg-buildpackage", *args, cwd=str(workdir), - stdout=self._io.output.stream, + stdout=output.stream, stderr=subprocess.STDOUT, )