@@ -597,6 +597,10 @@ std::string canonical_compile_flags(const mcpp::manifest::Manifest& m) {
597597 s += " cxxflag:" ;
598598 s += flag;
599599 }
600+ for (auto const & flag : m.buildConfig .ldflags ) {
601+ s += " ldflag:" ;
602+ s += flag;
603+ }
600604 return s;
601605}
602606
@@ -623,6 +627,10 @@ std::string canonical_package_build_metadata(
623627 s += " cxxflag:" ;
624628 s += flag;
625629 }
630+ for (auto const & flag : pkg.manifest .buildConfig .ldflags ) {
631+ s += " ldflag:" ;
632+ s += flag;
633+ }
626634 for (auto const & [path, content] : pkg.manifest .buildConfig .generatedFiles ) {
627635 s += " genfile:" ;
628636 s += path.generic_string ();
@@ -1541,6 +1549,7 @@ prepare_build(bool print_fingerprint,
15411549 std::string source; // "version" | "path" | "git" — for type-clash check
15421550 std::size_t depIndex = 0 ; // index into dep_manifests/packages-1 (for in-place re-fetch)
15431551 std::vector<std::filesystem::path> includeDirsAdded; // entries appended to m->buildConfig.includeDirs by this dep
1552+ std::vector<std::string> linkFlagsAdded; // entries appended to m->buildConfig.ldflags by this dep
15441553 };
15451554 std::map<ResolvedKey, ResolvedRecord> resolved;
15461555
@@ -1824,6 +1833,48 @@ prepare_build(bool print_fingerprint,
18241833 }
18251834 };
18261835
1836+ auto normalizeDepLdflag = [](const std::filesystem::path& depRoot,
1837+ const std::string& flag) {
1838+ auto absolute_path = [&](std::string_view raw) {
1839+ std::filesystem::path p{std::string (raw)};
1840+ if (p.is_absolute () || raw.starts_with (" $" )) return p;
1841+ return depRoot / p;
1842+ };
1843+
1844+ if (flag.starts_with (" -L" ) && flag.size () > 2 ) {
1845+ return " -L" + absolute_path (std::string_view (flag).substr (2 )).string ();
1846+ }
1847+
1848+ constexpr std::string_view rpathPrefix = " -Wl,-rpath," ;
1849+ if (flag.starts_with (rpathPrefix) && flag.size () > rpathPrefix.size ()) {
1850+ return std::string (rpathPrefix)
1851+ + absolute_path (std::string_view (flag).substr (rpathPrefix.size ())).string ();
1852+ }
1853+
1854+ return flag;
1855+ };
1856+
1857+ auto propagateLinkFlags = [&](const std::filesystem::path& depRoot,
1858+ const mcpp::manifest::Manifest& depManifest)
1859+ -> std::vector<std::string>
1860+ {
1861+ std::vector<std::string> added;
1862+ for (auto const & flag : depManifest.buildConfig .ldflags ) {
1863+ auto normalized = normalizeDepLdflag (depRoot, flag);
1864+ m->buildConfig .ldflags .push_back (normalized);
1865+ added.push_back (std::move (normalized));
1866+ }
1867+ return added;
1868+ };
1869+
1870+ auto removeLinkFlags = [&](const std::vector<std::string>& flags) {
1871+ auto & ldflags = m->buildConfig .ldflags ;
1872+ for (auto const & flag : flags) {
1873+ auto pos = std::find (ldflags.begin (), ldflags.end (), flag);
1874+ if (pos != ldflags.end ()) ldflags.erase (pos);
1875+ }
1876+ };
1877+
18271878 // Stage a dep's source files into a fresh directory, rewriting their
18281879 // module / import declarations against `rename`. Used by the multi-
18291880 // version mangling fallback (Level 1) so two cross-major copies of
@@ -2065,6 +2116,7 @@ prepare_build(bool print_fingerprint,
20652116 });
20662117 packages.push_back ({secStage, *dep_manifests.back ()});
20672118 auto added = propagateIncludeDirs (secStage, *dep_manifests.back ());
2119+ auto linkFlagsAdded = propagateLinkFlags (secStage, *dep_manifests.back ());
20682120
20692121 ResolvedKey mangledKey{key.ns , mangled};
20702122 resolved[mangledKey] = ResolvedRecord{
@@ -2074,6 +2126,7 @@ prepare_build(bool print_fingerprint,
20742126 .source = " version" ,
20752127 .depIndex = dep_manifests.size () - 1 ,
20762128 .includeDirsAdded = std::move (added),
2129+ .linkFlagsAdded = std::move (linkFlagsAdded),
20772130 };
20782131
20792132 mcpp::ui::info (" Mangled" ,
@@ -2136,7 +2189,9 @@ prepare_build(bool print_fingerprint,
21362189 }
21372190
21382191 removeIncludeDirs (it->second .includeDirsAdded );
2192+ removeLinkFlags (it->second .linkFlagsAdded );
21392193 auto added = propagateIncludeDirs (newRoot, newManifest);
2194+ auto linkFlagsAdded = propagateLinkFlags (newRoot, newManifest);
21402195
21412196 // Replace in dep_manifests + packages. depIndex is the slot
21422197 // in dep_manifests; packages = [main, dep_0, dep_1, …], so
@@ -2147,6 +2202,7 @@ prepare_build(bool print_fingerprint,
21472202
21482203 it->second .version = *merged;
21492204 it->second .includeDirsAdded = std::move (added);
2205+ it->second .linkFlagsAdded = std::move (linkFlagsAdded);
21502206 if (it->second .depIndex < dep_cache_identities.size ())
21512207 dep_cache_identities[it->second .depIndex ].version = *merged;
21522208
@@ -2284,6 +2340,7 @@ prepare_build(bool print_fingerprint,
22842340 // expansion against dep_root) — stash it so a SemVer merge can
22852341 // evict these entries on a re-fetch.
22862342 auto includeDirsAdded = propagateIncludeDirs (dep_root, *dep_manifest);
2343+ auto linkFlagsAdded = propagateLinkFlags (dep_root, *dep_manifest);
22872344
22882345 // Move the manifest into stable storage so we can later look it up
22892346 // by depIndex (the SemVer merger needs to overwrite the slot).
@@ -2307,6 +2364,7 @@ prepare_build(bool print_fingerprint,
23072364 .source = sourceKind,
23082365 .depIndex = dep_manifests.size () - 1 ,
23092366 .includeDirsAdded = std::move (includeDirsAdded),
2367+ .linkFlagsAdded = std::move (linkFlagsAdded),
23102368 };
23112369
23122370 // Recurse: the dep's own [dependencies] become new worklist items.
0 commit comments