Skip to content

std.Build: Deprecate Step.Compile APIs that mutate the root module #22587

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 26, 2025

Conversation

castholm
Copy link
Contributor

@castholm castholm commented Jan 23, 2025

Not only are Step.Compile methods like linkLibC() redundant because Module exposes the same APIs, it also might not be immediately obvious to users that these methods modify the underlying root module, which can be a footgun and lead to unintended results if the module is exported to package consumers or shared by multiple compile steps. For example, I personally almost ran in to this:

// module exported to package consumers, doesn't require libc
const mod = b.addModule("mymodule", .{
    .root_source_file = b.path("main.zig"),
    .target = target,
    .optimize = optimize,
});

// some unit tests require libc
const tests = b.addTest(.{ .root_module = mod });
tests.linkLibC(); // uh-oh! now the exported module requires libc!

const run_tests = b.addRunArtifact(tests);

const test_step = b.step("test", "Run tests");
test_step.dependOn(&run_tests.step);

Using compile.root_module.link_libc = true or compile.root_module.linkLibrary(lib) makes it more clear to users which of the compile step and the module owns which options.

Suggested release notes (if you think deprecation notices are relevant):

Deprecated std.Build.Step.Compile APIs

The following std.Build.Step.Compile methods have been deprecated in favor of their std.Build.Module equivalents and are slated for removal during the next release cycle:

  • addAfterIncludePath
  • addAssemblyFile
  • addCSourceFile
  • addCSourceFiles
  • addConfigHeader
  • addEmbedPath
  • addFrameworkPath
  • addIncludePath
  • addLibraryPath
  • addObject
  • addObjectFile
  • addRPath
  • addSystemFrameworkPath
  • addSystemIncludePath
  • addWin32ResourceFile
  • linkFramework
  • linkLibC
  • linkLibCpp
  • linkLibrary
  • linkSystemLibrary
  • linkSystemLibrary2

Upgrade guide:

 // Most uses can be migrated by inserting `root_module` before the method call
-exe.linkLibrary(lib);
+exe.root_module.linkLibrary(lib);

 // Set the corresponding field directly
-exe.linkLibC();
-exe.linkLibCpp();
+exe.root_module.link_libc = true;
+exe.root_module.link_libcpp = true;

 // Pass '.{}' as the second argument
-exe.linkSystemLibrary("foo");
+exe.root_module.linkSystemLibrary("foo", .{});

 // Omit the '2' from the method name
-exe.linkSystemLibrary2("foo", .{ .needed = false });
+exe.root_module.linkSystemLibrary("foo", .{ .needed = false });

@alexrp alexrp added this to the 0.14.0 milestone Jan 30, 2025
@alexrp alexrp added the release notes This PR should be mentioned in the release notes. label Feb 9, 2025
@alexrp alexrp requested a review from mlugg February 9, 2025 03:21
@alexrp
Copy link
Member

alexrp commented Feb 9, 2025

@mlugg would you mind reviewing this (considering #20388/#18752)? Also @BratishkaErik.

Copy link
Member

@andrewrk andrewrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, let's make this depend on #22822 yeah?

@castholm
Copy link
Contributor Author

@andrewrk Updating these APIs to make use of @deprecated is blocked by the fact that @deprecated does not seem to work as envisioned. I opened a topic on Zulip with more details but the gist of the problem is that if you have a function marked with @deprecated, it becomes an error if the context in which it is declared forbids deprecations, when it should be the context from which it is called. Because Compile.linkLibrary etc. reside in the std module, which is configured with fno-allow-deprecated by default, this means that it becomes a compile error to use them even from a dependency's build.zig module which is configured with -fallow-deprecated. This makes it painful to depend on "legacy packages" that haven't been updated to use the module APIs and seems contrary to the spirit of soft-deprecating the APIs in the first place (instead of simply removing them right here and now).

@castholm castholm force-pushed the deprecate-compile-apis branch 3 times, most recently from a8cfdb5 to 8d7acbe Compare February 28, 2025 04:15
@castholm castholm requested a review from andrewrk February 28, 2025 17:50
@andrewrk andrewrk removed this from the 0.14.0 milestone Mar 1, 2025
@castholm castholm force-pushed the deprecate-compile-apis branch from 8d7acbe to 137094d Compare March 3, 2025 21:44
@castholm
Copy link
Contributor Author

castholm commented Mar 3, 2025

This did not make the 0.14 cutoff. I've removed references to version numbers from the doc comments so this can be merged whenever you feel is appropriate.

@castholm castholm force-pushed the deprecate-compile-apis branch 2 times, most recently from 28049d3 to cc1ab4e Compare March 27, 2025 23:48
@castholm castholm force-pushed the deprecate-compile-apis branch 4 times, most recently from 42a65c4 to 04c283c Compare July 25, 2025 20:29
@mlugg
Copy link
Member

mlugg commented Jul 26, 2025

This looks good to me. Note that reaching through to exe.root_module is probably not actually great style -- I would say it's nicer to construct the module separately in most non-trivial cases -- but certainly for a simple migration it's a fine approach.

One last request, sorry. Would it be possible to add /// Remove after the 0.15.0 release. to all of the deprecation comments? This just makes it easier to spot them by grepping the standard library in the future, so helps stop us accidentally leaving deprecated stuff hanging around for a long time.

If you can amend the first commit with that, I'll then be happy to press the big green button -- you can give me a ping on Zulip to make sure I don't miss it.

cheesecakeycat added a commit to Gota7/zig-sdl3 that referenced this pull request Jul 26, 2025
castholm added 2 commits July 26, 2025 12:06
Not only are `Step.Compile` methods like `linkLibC()` redundant because
`Module` exposes the same APIs, it also might not be immediately obvious
to users that these methods modify the underlying root module, which can
be a footgun and lead to unintended results if the module is exported to
package consumers or shared by multiple compile steps.

Using `compile.root_module.link_libc = true` makes it more clear to
users which of the compile step and the module owns which options.
@castholm castholm force-pushed the deprecate-compile-apis branch from 04c283c to 154bd2f Compare July 26, 2025 10:06
@castholm
Copy link
Contributor Author

I would say it's nicer to construct the module separately in most non-trivial cases -- but certainly for a simple migration it's a fine approach.

I agree that it's the better and more hygienic style to construct and configure the module separately since modifying exe.root_module could still inadvertently modify a module shared by two compile steps, it just makes it more obvious that the option resides in the module. It's difficult to fit guidance about the preferred way of constructing modules/compile steps in the deprecation notices but I could try to add a mention of it to the release notes draft if you think that sounds good.

Copy link
Member

@mlugg mlugg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, thanks very much. You can add a mention to the release notes of the fact that directly using exe.root_module (etc) is discouraged if you would like to, but it's not that important, so don't worry too much.

@mlugg mlugg enabled auto-merge July 26, 2025 10:59
@mlugg mlugg merged commit a51cdf3 into ziglang:master Jul 26, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release notes This PR should be mentioned in the release notes.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants