-
Notifications
You must be signed in to change notification settings - Fork 3
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
Add support for ordering object files during merge #9
Conversation
@@ -148,6 +148,12 @@ pub fn extract_objects<I: IntoParallelIterator<Item = InputLibrary<R>>, R: Read> | |||
}) | |||
} | |||
|
|||
pub fn get_object_name_from_path(path: &std::path::Path) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted from the two uses in filter_deps.rs
Here is an example of the issue and how this PR solves it. Without an order file the merge order is random:
With an order file we can now control it:
|
Thinking about merge order a bit more, do you think we should provide a deterministic merge order for unlisted objects? Right now, because of the use of a HashMap, the merge order is random, which means two invocations of armerge for the exact same inputs will produce different outputs. I think it’s generally valuable to have deterministic outputs. Should we sort unlisted objects by name, so their order is also deterministic (although unspecified)? |
Alright, I was a bit hesitant about whether this tool is the right place to handle initialization order fiasco issues (the modern practice is to try to avoid creating those in the first place, if at all possible!), but ultimately it's not a lot of extra code, so this is reasonable enough to support. I agree a deterministic merge order would have some value. If only for reproducible builds. (Although I don't have much time to work on armerge at the moment) Please also update the usage documentation in the README, but otherwise I'm okay with merging this =) |
Thanks @tux3! Updated the PR with the README changes. Once this PR is merged, I'll open another PR to replace the object file |
This PR adds a new
--order-file
option that allows you to control the order in which some of the object files are passed to the linker, and thus the order in which certain sections and items are laid out in the merged library.The motivating use case here is controlling the order in which static initializers are run on startup on macOS and iOS. Static initializers are listed in the
S_MOD_INIT_FUNC_POINTERS
Mach-O section, and the order in which they appear there is the order in which dyld calls them at runtime.Unfortunately, the Apple linker does not honor the priority value in constructor and destructor attributes across object files, so even if you mark an initializer with
__attribute__((constructor(101))
it might end up being called after an initializer in another object file marked with__attribute__((constructor(102))
. And the-order_file
linker option does not affect the order in which the initializers are listed in the__mod_init_func
section. The order is always based on the order in which the object files are passed to the linker.With this new option, you can now specify an order file that controls the relative order in which
armerge
passes the listed object files to the linker, so you can precisely control the order in which static initializers will be called at runtime. The order file is a simple text file with an entry per line, in the format{INPUT_LIB}@{OBJNAME}
. Any object files not listed are placed after all of the listed objects in an unspecified order, like before. For example: