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
16 changes: 9 additions & 7 deletions tools/objc/libtool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ 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

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

Expand Down Expand Up @@ -111,11 +120,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
57 changes: 57 additions & 0 deletions tools/objc/libtool_check_unique.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <iostream>
#include <regex>
#include <fstream>
#include <unordered_set>

using namespace std;

string getBasename(const string &path) {
// Assumes we're on an OS with "/" as the path separator
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[]) {
unordered_set<string> basenames;
const regex libRegex = regex(".*\\.a$");
const regex noArgFlags = regex("-static|-s|-a|-c|-L|-T|-no_warning_for_no_symbols");

This comment was marked as resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

const regex singleArgFlags = 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); ) {
const string basename = getBasename(line);
const auto pair = basenames.insert(basename);
if (!pair.second) {
return 1;
}
}
list.close();
i++;
} else if (regex_match(arg, noArgFlags)) {
// No arg flags
} else if (regex_match(arg, singleArgFlags)) {
// Single-arg flags
i++;
} else if (arg[0] == '-') {
return 1;
// Unrecognized flag, let the wrapper deal with it
} else if (regex_match(arg, libRegex)) {
// Archive inputs can remain untouched, as they come from other targets.
} else {
const string basename = getBasename(arg);
const auto pair = basenames.insert(basename);
if (!pair.second) {
return 1;
}
}
}
return 0;
}