aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xcompile.sh2
-rw-r--r--src/tools/xcode/realpath/BUILD11
-rw-r--r--src/tools/xcode/realpath/README14
-rw-r--r--src/tools/xcode/realpath/realpath.c103
4 files changed, 130 insertions, 0 deletions
diff --git a/compile.sh b/compile.sh
index 12bfc2fac2..9523edf1bb 100755
--- a/compile.sh
+++ b/compile.sh
@@ -123,6 +123,8 @@ if [ $DO_TOOLS_COMPILATION ]; then
tools/objc/precomp_xcodegen_deploy.jar
bazel_bootstrap //src/tools/xcode/stdredirect:StdRedirect.dylib \
tools/objc/StdRedirect.dylib
+ bazel_bootstrap //src/tools/xcode/realpath:realpath \
+ tools/objc/realpath
fi
fi
diff --git a/src/tools/xcode/realpath/BUILD b/src/tools/xcode/realpath/BUILD
new file mode 100644
index 0000000000..0dc2455a81
--- /dev/null
+++ b/src/tools/xcode/realpath/BUILD
@@ -0,0 +1,11 @@
+package(default_visibility = ["//src:__subpackages__"])
+
+# This target will only build on a Mac.
+genrule(
+ name = "realpath_genrule",
+ srcs = ["realpath.c"],
+ outs = ["realpath"],
+ cmd = "/usr/bin/xcrun clang -o $@ $<",
+ output_to_bindir = 1,
+ visibility = ["//visibility:public"],
+)
diff --git a/src/tools/xcode/realpath/README b/src/tools/xcode/realpath/README
new file mode 100644
index 0000000000..66ab1795cc
--- /dev/null
+++ b/src/tools/xcode/realpath/README
@@ -0,0 +1,14 @@
+realpath is a simple implementation of the realpath utility:
+http://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html
+since Mac OS X does not have anything equivalent.
+
+This version takes no options.
+
+This is based on the default GNU/Linux implementation that allows the last
+component to not exist. This is different than the Debian implementation that
+requires the last component to exist. Supporting the GNU/Linux implementation
+makes writing scripts that depend on realpath much easier, and is probably
+closer to what Apple may actually ship as a realpath implementation in the
+future.
+
+realpath only builds/runs on Darwin.
diff --git a/src/tools/xcode/realpath/realpath.c b/src/tools/xcode/realpath/realpath.c
new file mode 100644
index 0000000000..06addf38c7
--- /dev/null
+++ b/src/tools/xcode/realpath/realpath.c
@@ -0,0 +1,103 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// realpath.c
+//
+// A simple implementation of realpath for Mac OS X.
+// This implementation follows gnu/linux conventions and allows the last
+// component to not exist:
+// http://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html
+// Debian requires all components to exist.
+//
+
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// Print a simple error message and exit.
+static void PrintError(const char *argv[]) {
+ fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+ exit(1);
+}
+
+// Concatenate two paths together adding a '/' if appropriate.
+// Returned pointer is owned by client and should be freed.
+static char *JoinPaths(const char *path1, const char* path2) {
+ size_t len1 = strlen(path1);
+ size_t len2 = strlen(path2);
+ // +1 for '/' and +1 for '\0'
+ size_t totalSize = len1 + 1 + len2 + 1;
+ char *outPath = malloc(totalSize);
+ if (outPath == NULL) {
+ return NULL;
+ }
+ strlcpy(outPath, path1, totalSize);
+ if (len1 > 0 && len2 > 0) {
+ if (path1[len1 - 1] != '/' && path2[0] != '/') {
+ strlcat(outPath, "/", totalSize);
+ }
+ }
+ strlcat(outPath, path2, totalSize);
+ return outPath;
+}
+
+// Since this is a simple utility that quits immediately, we are not worrying
+// about making the code more complex by freeing up any memory allocations.
+int main(int argc, const char *argv[]) {
+ if (argc != 2) {
+ fprintf(stderr, "realpath <path>\n");
+ return 1;
+ }
+ const char *path = argv[1];
+ char *goodPath = realpath(path, NULL);
+ if (goodPath == NULL) {
+ if ((errno != ENOENT) || (strlen(path) == 0)) {
+ PrintError(argv);
+ }
+
+ // If only the last element is missing, then call realpath on the parent
+ // dir and append the basename back onto it.
+
+ // Technically the strdup is not required on Mac OS X, but this
+ // keeps things compatible with other basename/dirname implementations
+ // that do require a string they can modify.
+ char *dirCopy = strdup(path);
+ char *baseCopy = strdup(path);
+ if (dirCopy == NULL || baseCopy == NULL) {
+ PrintError(argv);
+ }
+ char *dir = dirname(dirCopy);
+ if (dir == NULL) {
+ PrintError(argv);
+ }
+ char *base = basename(baseCopy);
+ if (base == NULL) {
+ PrintError(argv);
+ }
+ char *realdir = realpath(dir, NULL);
+ if (realdir == NULL) {
+ PrintError(argv);
+ }
+ goodPath = JoinPaths(realdir, base);
+ if (goodPath == NULL) {
+ PrintError(argv);
+ }
+ }
+ fprintf(stdout, "%s\n", goodPath);
+ return 0;
+}