Skip to content
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

Run libtool without symlinking if possible #11958

Closed
wants to merge 13 commits into from
8 changes: 8 additions & 0 deletions tools/objc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ sh_binary(
data = [
":make_hashed_objlist.py",
":xcrunwrapper",
":libtool_check_unique",
],
)

cc_binary(
name = "libtool_check_unique",
michaeleisel marked this conversation as resolved.
Show resolved Hide resolved
srcs = [
"libtool_check_unique.cc",
],
)

Expand Down
18 changes: 11 additions & 7 deletions tools/objc/libtool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ fi

WRAPPER="${MY_LOCATION}/xcrunwrapper.sh"

# Ensure 0 timestamping for hermetic results.
export ZERO_AR_DATE=1

if $(/usr/bin/dirname "$0")/libtool_check_unique "$@"; then
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry I missed this before--is it possible to refer to this relative to $MY_LOCATION?

Given that this script may be invoked in multiple contexts (according to the logic above), it might be prudent to refer to this in a canonical way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

# If there are no duplicate .o basenames, libtool can be invoked with the original arguments
"${WRAPPER}" libtool "$@"
exit
fi

echo "Duplicate .o basenames detected, taking slow path"
michaeleisel marked this conversation as resolved.
Show resolved Hide resolved

TEMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/libtool.XXXXXXXX")"
trap "rm -rf \"${TEMPDIR}\"" EXIT

Expand Down Expand Up @@ -111,11 +122,4 @@ while [[ $# -gt 0 ]]; do
esac
done

# Ensure 0 timestamping for hermetic results.
export ZERO_AR_DATE=1

"${WRAPPER}" libtool "${ARGS[@]}"

# Prevents a pre-Xcode-8 bug in which passing zero-date archive files to ld
# would cause ld to error.
touch "$OUTPUTFILE"
michaeleisel marked this conversation as resolved.
Show resolved Hide resolved
56 changes: 56 additions & 0 deletions tools/objc/libtool_check_unique.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <iostream>
#include <regex>
#include <fstream>
#include <unordered_set>

using namespace std;

static unordered_set<string> sBasenames;
michaeleisel marked this conversation as resolved.
Show resolved Hide resolved

string getBasename(string path) {
michaeleisel marked this conversation as resolved.
Show resolved Hide resolved
auto idx = path.find_last_of("/");
michaeleisel marked this conversation as resolved.
Show resolved Hide resolved
if (idx == string::npos) {
return path;
}
return path.substr(idx + 1);
}

// Returns 0 if there are no duplicate basenames in the object files (both via -filelist as well as shell args),
// 1 otherwise
int main(int argc, const char * argv[]) {
regex no_arg_flags = regex("-static|-s|-a|-c|-L|-T|-no_warning_for_no_symbols");
regex single_arg_flags = regex("-arch_only|-syslibroot|-o");
// Set i to 1 to skip executable path
for (int i = 1; argv[i] != nullptr; i++) {
string arg = argv[i];
if (arg == "-filelist") {
ifstream list(argv[i + 1]);
for (string line; getline(list, line); ) {
string basename = getBasename(line);
auto pair = sBasenames.insert(basename);
if (!pair.second) {
return 1;
}
}
list.close();
i++;
} else if (regex_match(arg, no_arg_flags)) {
// No arg flags
} else if (regex_match(arg, single_arg_flags)) {
// Single-arg flags
i++;
} else if (arg[0] == '-') {
return 1;
// Unrecognized flag, let the wrapper deal with it
} else if (regex_match(arg, regex(".*\\.a$"))) {
michaeleisel marked this conversation as resolved.
Show resolved Hide resolved
// Archive inputs can remain untouched, as they come from other targets.
} else {
string basename = getBasename(arg);
auto pair = sBasenames.insert(basename);
if (!pair.second) {
return 1;
}
}
}
return 0;
}