From 29a5fee5228447095ced1e1194578555336a762f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20P=C3=B6chtrager?= Date: Sun, 19 Jul 2015 22:28:10 +0200 Subject: [PATCH] * add windows support via cygwin * add openbsd and dragonfly support * replace `` with $() in bash scripts * misc other changes --- CHANGELOG | 9 +- README.md | 10 +- build.sh | 50 +++-- build_compiler_rt.sh | 28 +-- build_gcc.sh | 2 +- patches/cctools-ld64-epath.patch | 343 ++++++++++++++++++++++++++++++ tools/cpucount.c | 6 +- tools/osxcross-macports | 3 +- tools/osxcross_conf.sh | 5 +- tools/tools.sh | 35 ++- wrapper/Makefile | 11 +- wrapper/build.sh | 5 +- wrapper/main.cpp | 7 + wrapper/programs/osxcross-env.cpp | 90 +------- wrapper/target.cpp | 8 + wrapper/tools.cpp | 99 ++++++++- wrapper/tools.h | 4 + 17 files changed, 567 insertions(+), 148 deletions(-) create mode 100644 patches/cctools-ld64-epath.patch diff --git a/CHANGELOG b/CHANGELOG index a3321f9..0ca6878 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,8 +2,15 @@ changed: * improved and colorized wrapper error/warning/debug/info messages +* updated cctools to 870 +* updated ld64 to 242 added: +* Windows support via Cygwin +* OpenBSD and DragonFlyBSD support +* Linux ARM support +* Linux PPC/PPC64 support: Totally untested, but compiles +* gcc compiler support: OSXCross can now be built with gcc * 'osxcross-man' man page tool * p7zip sdk packaging script * a minimalistic xcrun tool @@ -86,7 +93,7 @@ fixed: /******************************* v0.4 *******************************/ added: - * gcc support + * gcc build script * a workaround for buggy unistd.h headers /******************************* v0.3 *******************************/ diff --git a/README.md b/README.md index 627afdd..0d35507 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -## OS X Cross toolchain for Linux, FreeBSD and NetBSD ## +## OS X Cross toolchain for Linux, *BSD and Cygwin ## ### WHAT IS THE GOAL OF OSXCROSS? ### -The goal of OSXCross is to provide a well working OS X cross toolchain for Linux, FreeBSD and NetBSD. +The goal of OSXCross is to provide a well working OS X cross toolchain for Linux, *BSD and Cygwin. ### HOW DOES IT WORK? ### @@ -27,7 +27,7 @@ Please see [README.MACPORTS](https://github.com/tpoechtrager/osxcross/blob/maste Move your packaged SDK to the tarballs/ directory. -Then ensure you have the following installed on your Linux/BSD box: +Then ensure you have the following installed on your system: `Clang 3.2+`, `patch`, `libxml2-devel` (<=10.6 only) and the `bash shell`. @@ -56,7 +56,7 @@ That's it. See usage examples below. ##### Building GCC: ##### If you want to build GCC as well, then you can do this by running: -`[GCC_VERSION=5.1.0] [ENABLE_FORTRAN=1] ./build_gcc.sh`. +`[GCC_VERSION=5.2.0] [ENABLE_FORTRAN=1] ./build_gcc.sh`. \[A gfortran usage example can be found [here](https://github.com/tpoechtrager/osxcross/issues/28#issuecomment-67047134)] @@ -91,7 +91,7 @@ You can turn this behavior off with `OSXCROSS_GCC_NO_STATIC_RUNTIME=1` (env). Step 1. and 2. can be skipped if you have Xcode installed. -##### Packing the SDK on Linux (and others), Method 1 (works with Xcode >= 4.3): ##### +##### Packing the SDK on Linux, Cygwin (and others), Method 1 (works with Xcode >= 4.3): ##### 1. Download Xcode like described in 'Packaging the SDK on Mac OS X' 2. Ensure you have `clang` and `make` installed diff --git a/build.sh b/build.sh index 4289b46..370558d 100755 --- a/build.sh +++ b/build.sh @@ -13,23 +13,23 @@ function guess_sdk_version() file= sdk= guess_sdk_version_result= - sdkcount=`find -L tarballs/ -type f | grep MacOSX | wc -l` + sdkcount=$(find -L tarballs/ -type f | grep MacOSX | wc -l) if [ $sdkcount -eq 0 ]; then echo no SDK found in 'tarballs/'. please see README.md exit 1 elif [ $sdkcount -gt 1 ]; then - sdks=`find -L tarballs/ -type f | grep MacOSX` + sdks=$(find -L tarballs/ -type f | grep MacOSX) for sdk in $sdks; do echo $sdk; done echo 'more than one MacOSX SDK tarball found. please set' echo 'SDK_VERSION environment variable for the one you want' echo '(for example: SDK_VERSION=10.x [OSX_VERSION_MIN=10.x] ./build.sh)' exit 1 else - sdk=`find -L tarballs/ -type f | grep MacOSX` - tmp2=`echo ${sdk/bz2/} | sed s/[^0-9.]//g` - tmp3=`echo $tmp2 | sed s/\\\.*$//g` + sdk=$(find -L tarballs/ -type f | grep MacOSX) + tmp2=$(echo ${sdk/bz2/} | sed s/[^0-9.]//g) + tmp3=$(echo $tmp2 | sed s/\\\.*$//g) guess_sdk_version_result=$tmp3 - echo 'found SDK version' $guess_sdk_version_result 'at tarballs/'`basename $sdk` + echo 'found SDK version' $guess_sdk_version_result 'at tarballs/'$(basename $sdk) fi if [ $guess_sdk_version_result ]; then if [ $guess_sdk_version_result = 10.4 ]; then @@ -44,7 +44,7 @@ function verify_sdk_version() { sdkv=$1 for file in tarballs/*; do - if [ -f "$file" ] && [ `echo $file | grep OSX.*$sdkv` ]; then + if [ -f "$file" ] && [ $(echo $file | grep OSX.*$sdkv) ]; then echo "verified at "$file sdk=$file fi @@ -119,7 +119,6 @@ require clang require patch require sed require gunzip -require cpio pushd $BUILD_DIR &>/dev/null @@ -171,6 +170,11 @@ pushd .. &>/dev/null popd &>/dev/null patch -p0 < $PATCH_DIR/cctools-ld64-1.patch patch -p0 < $PATCH_DIR/cctools-ld64-2.patch +if [ $PLATFORM == "OpenBSD" ] || [ $PLATFORM == "DragonFly" ]; then + pushd .. &>/dev/null + patch -p0 < $PATCH_DIR/cctools-ld64-epath.patch + popd &>/dev/null +fi echo "" CONFFLAGS="--prefix=$TARGET_DIR --target=x86_64-apple-$TARGET" [ -n "$DISABLE_LTO_SUPPORT" ] && CONFFLAGS+=" --enable-lto=no" @@ -180,16 +184,16 @@ $MAKE install -j$JOBS popd &>/dev/null pushd $TARGET_DIR/bin &>/dev/null -CCTOOLS=`find . -name "x86_64-apple-darwin*"` +CCTOOLS=$(find . -name "x86_64-apple-darwin*") CCTOOLS=($CCTOOLS) if [ $X86_64H_SUPPORTED -eq 1 ]; then for CCTOOL in ${CCTOOLS[@]}; do - CCTOOL_X86_64H=`echo "$CCTOOL" | sed 's/x86_64/x86_64h/g'` + CCTOOL_X86_64H=$(echo "$CCTOOL" | sed 's/x86_64/x86_64h/g') ln -sf $CCTOOL $CCTOOL_X86_64H done fi for CCTOOL in ${CCTOOLS[@]}; do - CCTOOL_I386=`echo "$CCTOOL" | sed 's/x86_64/i386/g'` + CCTOOL_I386=$(echo "$CCTOOL" | sed 's/x86_64/i386/g') ln -sf $CCTOOL $CCTOOL_I386 done popd &>/dev/null @@ -204,7 +208,7 @@ ln -sf ../../tools/osxcross-macports osxcross-mp ln -sf ../../tools/osxcross-macports omp popd &>/dev/null -SDK=`ls $TARBALL_DIR/MacOSX$SDK_VERSION*` +SDK=$(ls $TARBALL_DIR/MacOSX$SDK_VERSION*) # XAR if [[ $SDK == *.pkg ]]; then @@ -233,12 +237,12 @@ if [ ! -f "have_cctools_${CCTOOLS_REVHASH}_$TARGET" ]; then function check_cctools() { - [ -f "/$TARGET_DIR/bin/$1-apple-$TARGET-lipo" ] || exit 1 - [ -f "/$TARGET_DIR/bin/$1-apple-$TARGET-ld" ] || exit 1 - [ -f "/$TARGET_DIR/bin/$1-apple-$TARGET-nm" ] || exit 1 - [ -f "/$TARGET_DIR/bin/$1-apple-$TARGET-ar" ] || exit 1 - [ -f "/$TARGET_DIR/bin/$1-apple-$TARGET-ranlib" ] || exit 1 - [ -f "/$TARGET_DIR/bin/$1-apple-$TARGET-strip" ] || exit 1 + [ -f "$TARGET_DIR/bin/$1-apple-$TARGET-lipo" ] || exit 1 + [ -f "$TARGET_DIR/bin/$1-apple-$TARGET-ld" ] || exit 1 + [ -f "$TARGET_DIR/bin/$1-apple-$TARGET-nm" ] || exit 1 + [ -f "$TARGET_DIR/bin/$1-apple-$TARGET-ar" ] || exit 1 + [ -f "$TARGET_DIR/bin/$1-apple-$TARGET-ranlib" ] || exit 1 + [ -f "$TARGET_DIR/bin/$1-apple-$TARGET-strip" ] || exit 1 } check_cctools i386 @@ -274,7 +278,7 @@ extract $SDK 1 1 rm -rf $SDK_DIR/MacOSX$SDK_VERSION* 2>/dev/null -if [ "`ls -l SDKs/*$SDK_VERSION* 2>/dev/null | wc -l | tr -d ' '`" != "0" ]; then +if [ "$(ls -l SDKs/*$SDK_VERSION* 2>/dev/null | wc -l | tr -d ' ')" != "0" ]; then mv -f SDKs/*$SDK_VERSION* $SDK_DIR else mv -f *OSX*$SDK_VERSION*sdk* $SDK_DIR @@ -309,7 +313,7 @@ export OSXCROSS_LINKER_VERSION=$LINKER_VERSION if [ "$PLATFORM" != "Darwin" ]; then # libLTO.so set +e - eval `cat $BUILD_DIR/cctools*/cctools/config.log | grep LLVM_LIB_DIR | head -n1` + eval $(cat $BUILD_DIR/cctools*/cctools/config.log | grep LLVM_LIB_DIR | head -n1) set -e export OSXCROSS_LIBLTO_PATH=$LLVM_LIB_DIR fi @@ -318,11 +322,11 @@ $BASE_DIR/wrapper/build.sh 1>/dev/null echo "" -if [ `osxcross-cmp ${SDK_VERSION/u/} "<" $OSX_VERSION_MIN` -eq 1 ]; then +if [ $(osxcross-cmp ${SDK_VERSION/u/} "<" $OSX_VERSION_MIN) -eq 1 ]; then echo "OSX_VERSION_MIN must be <= SDK_VERSION" trap "" EXIT exit 1 -elif [ `osxcross-cmp $OSX_VERSION_MIN "<" 10.4` -eq 1 ]; then +elif [ $(osxcross-cmp $OSX_VERSION_MIN "<" 10.4) -eq 1 ]; then echo "OSX_VERSION_MIN must be >= 10.4" trap "" EXIT exit 1 @@ -336,7 +340,7 @@ test_compiler o64-clang $BASE_DIR/oclang/test.c test_compiler o32-clang++ $BASE_DIR/oclang/test.cpp test_compiler o64-clang++ $BASE_DIR/oclang/test.cpp -if [ `osxcross-cmp ${SDK_VERSION/u/} ">=" 10.7` -eq 1 ]; then +if [ $(osxcross-cmp ${SDK_VERSION/u/} ">=" 10.7) -eq 1 ]; then if [ ! -d "$SDK_DIR/MacOSX$SDK_VERSION.sdk/usr/include/c++/v1" ]; then echo "" echo -n "Given SDK does not contain libc++ headers " diff --git a/build_compiler_rt.sh b/build_compiler_rt.sh index 56ea5c4..f380ccc 100755 --- a/build_compiler_rt.sh +++ b/build_compiler_rt.sh @@ -31,17 +31,21 @@ set -e CLANG_VERSION=$(echo "__clang_major__ __clang_minor__ __clang_patchlevel__" | \ clang -xc -E - | tail -n1 | tr ' ' '.') -set +e -which llvm-config &>/dev/null && { CLANG_LIB_DIR=$(llvm-config --libdir); } -set -e +if [[ $PLATFORM == CYGWIN* ]] && [[ $(which clang) == "/usr/bin/clang" ]]; then + CLANG_LIB_DIR="/usr/lib/clang/$(uname -m)-pc-cygwin" +else + set +e + which llvm-config &>/dev/null && { CLANG_LIB_DIR=$(llvm-config --libdir); } + set -e -if [ -z "$CLANG_LIB_DIR" ]; then - require $READLINK - CLANG_LIB_DIR="$(dirname $($READLINK -f $(which clang)))/../lib" + if [ -z "$CLANG_LIB_DIR" ]; then + require $READLINK + CLANG_LIB_DIR="$(dirname $($READLINK -f $(which clang)))/../lib" + fi + + CLANG_LIB_DIR+="/clang" fi -CLANG_LIB_DIR+="/clang" - if [ ! -d "$CLANG_LIB_DIR" ]; then echo "$CLANG_LIB_DIR does not exist!" 1>&2 echo "Installing llvm-dev may help" 1>&2 @@ -84,10 +88,10 @@ git clean -fdx touch .clone_complete git pull -sed -i "s/Configs += ios//g" make/platform/clang_darwin.mk -sed -i "s/Configs += cc_kext_ios5//g" make/platform/clang_darwin.mk -sed -i "s/Configs += profile_ios//g" make/platform/clang_darwin.mk -sed -i "s/Configs += asan_iossim_dynamic//g" make/platform/clang_darwin.mk +$SED -i "s/Configs += ios//g" make/platform/clang_darwin.mk +$SED -i "s/Configs += cc_kext_ios5//g" make/platform/clang_darwin.mk +$SED -i "s/Configs += profile_ios//g" make/platform/clang_darwin.mk +$SED -i "s/Configs += asan_iossim_dynamic//g" make/platform/clang_darwin.mk # Unbreak the -Werror build. if [ -f lib/asan/asan_mac.h ]; then diff --git a/build_gcc.sh b/build_gcc.sh index be90267..73bcbfb 100755 --- a/build_gcc.sh +++ b/build_gcc.sh @@ -102,7 +102,7 @@ pushd $OSXCROSS_TARGET_DIR/x86_64-apple-$OSXCROSS_TARGET/include &>/dev/null pushd c++/${GCC_VERSION}* &>/dev/null cat $OSXCROSS_TARGET_DIR/../patches/libstdcxx.patch | \ - sed "s/darwin13/$OSXCROSS_TARGET/g" | \ + $SED "s/darwin13/$OSXCROSS_TARGET/g" | \ patch -p0 -l &>/dev/null || true popd &>/dev/null diff --git a/patches/cctools-ld64-epath.patch b/patches/cctools-ld64-epath.patch new file mode 100644 index 0000000..38a7189 --- /dev/null +++ b/patches/cctools-ld64-epath.patch @@ -0,0 +1,343 @@ +diff --git cctools/ld64/src/3rd/helper.c cctools/ld64/src/3rd/helper.c +index ef33219..6983e52 100644 +--- cctools/ld64/src/3rd/helper.c ++++ cctools/ld64/src/3rd/helper.c +@@ -17,11 +17,17 @@ const char ldVersionString[] = "134.9\n"; + #include + #include + #include +- +-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ++ ++#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) + #include + #endif + ++#ifdef __OpenBSD__ ++#include ++#include ++#include ++#endif ++ + #include "helper.h" + + void __assert_rtn(const char *func, const char *file, int line, const char *msg) +@@ -36,39 +42,75 @@ void __assert_rtn(const char *func, const char *file, int line, const char *msg) + } + + +-int _NSGetExecutablePath(char *path, unsigned int *size) ++int _NSGetExecutablePath(char *epath, unsigned int *size) + { +-#ifdef __FreeBSD__ ++#if defined(__FreeBSD__) || defined(__DragonFly__) + int mib[4]; +- mib[0] = CTL_KERN; ++ mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + size_t cb = *size; +- if (sysctl(mib, 4, path, &cb, NULL, 0) != 0) ++ if (sysctl(mib, 4, epath, &cb, NULL, 0) != 0) + return -1; + *size = cb; +- return 0; ++ return 0; + #elif defined(__OpenBSD__) + int mib[4]; +- const char *tmp[100]; +- size_t l = sizeof(tmp); ++ char **argv; ++ size_t len; ++ const char *comm; ++ int ok = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC_ARGS; + mib[2] = getpid(); + mib[3] = KERN_PROC_ARGV; +- if (sysctl(mib, 4, tmp, &l, NULL, 0) != 0) +- return -1; +- *size = strlcpy(path, tmp[0], *size); +- return 0; ++ if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) ++ abort(); ++ if (!(argv = malloc(len))) ++ abort(); ++ if (sysctl(mib, 4, argv, &len, NULL, 0) < 0) ++ abort(); ++ comm = argv[0]; ++ if (*comm == '/' || *comm == '.') { ++ char *rpath; ++ if ((rpath = realpath(comm, NULL))) { ++ snprintf(epath, *size, "%s", rpath); ++ free(rpath); ++ ok = 1; ++ } ++ } else { ++ char *sp; ++ char *xpath = strdup(getenv("PATH")); ++ char *path = strtok_r(xpath, ":", &sp); ++ struct stat st; ++ if (!xpath) ++ abort(); ++ while (path) { ++ snprintf(epath, *size, "%s/%s", path, comm); ++ if (!stat(epath, &st) && (st.st_mode & S_IXUSR)) { ++ ok = 1; ++ break; ++ } ++ path = strtok_r(NULL, ":", &sp); ++ } ++ free(xpath); ++ } ++ free(argv); ++ if (ok) { ++ *strrchr(epath, '/') = '\0'; ++ *size = strlen(epath); ++ return 0; ++ } ++ return -1; + #else + int bufsize = *size; + int ret_size; +- ret_size = readlink("/proc/self/exe", path, bufsize-1); ++ ret_size = readlink("/proc/self/exe", epath, bufsize-1); + if (ret_size != -1) + { + *size = ret_size; +- path[ret_size]=0; ++ epath[ret_size]=0; + return 0; + } + else +diff --git cctools/libstuff/emulated.c cctools/libstuff/emulated.c +index 1aa355c..b8c52e4 100644 +--- cctools/libstuff/emulated.c ++++ cctools/libstuff/emulated.c +@@ -14,46 +14,88 @@ + #include + #include + +-#if defined(__FreeBSD__) || defined(__OpenBSD__) ++#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) + #include + #endif + +-int _NSGetExecutablePath(char *path, unsigned int *size) ++#ifdef __OpenBSD__ ++#include ++#include ++#include ++#endif ++ ++int _NSGetExecutablePath(char *epath, unsigned int *size) + { +-#ifdef __FreeBSD__ +- int mib[4]; +- mib[0] = CTL_KERN; +- mib[1] = KERN_PROC; +- mib[2] = KERN_PROC_PATHNAME; +- mib[3] = -1; +- size_t cb = *size; +- if (sysctl(mib, 4, path, &cb, NULL, 0) != 0) ++#if defined(__FreeBSD__) || defined(__DragonFly__) ++ int mib[4]; ++ mib[0] = CTL_KERN; ++ mib[1] = KERN_PROC; ++ mib[2] = KERN_PROC_PATHNAME; ++ mib[3] = -1; ++ size_t cb = *size; ++ if (sysctl(mib, 4, epath, &cb, NULL, 0) != 0) + return -1; +- *size = cb; +- return 0; ++ *size = cb; ++ return 0; + #elif defined(__OpenBSD__) +- int mib[4]; +- const char *tmp[100]; +- size_t l = sizeof(tmp); +- mib[0] = CTL_KERN; +- mib[1] = KERN_PROC_ARGS; +- mib[2] = getpid(); +- mib[3] = KERN_PROC_ARGV; +- if (sysctl(mib, 4, tmp, &l, NULL, 0) != 0) +- return -1; +- *size = strlcpy(path, tmp[0], *size); +- return 0; ++ int mib[4]; ++ char **argv; ++ size_t len; ++ const char *comm; ++ int ok = 0; ++ mib[0] = CTL_KERN; ++ mib[1] = KERN_PROC_ARGS; ++ mib[2] = getpid(); ++ mib[3] = KERN_PROC_ARGV; ++ if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) ++ abort(); ++ if (!(argv = malloc(len))) ++ abort(); ++ if (sysctl(mib, 4, argv, &len, NULL, 0) < 0) ++ abort(); ++ comm = argv[0]; ++ if (*comm == '/' || *comm == '.') { ++ char *rpath; ++ if ((rpath = realpath(comm, NULL))) { ++ snprintf(epath, *size, "%s", rpath); ++ free(rpath); ++ ok = 1; ++ } ++ } else { ++ char *sp; ++ char *xpath = strdup(getenv("PATH")); ++ char *path = strtok_r(xpath, ":", &sp); ++ struct stat st; ++ if (!xpath) ++ abort(); ++ while (path) { ++ snprintf(epath, *size, "%s/%s", path, comm); ++ if (!stat(epath, &st) && (st.st_mode & S_IXUSR)) { ++ ok = 1; ++ break; ++ } ++ path = strtok_r(NULL, ":", &sp); ++ } ++ free(xpath); ++ } ++ free(argv); ++ if (ok) { ++ *strrchr(epath, '/') = '\0'; ++ *size = strlen(epath); ++ return 0; ++ } ++ return -1; + #else +- int bufsize = *size; +- int ret_size; +- ret_size = readlink("/proc/self/exe", path, bufsize-1); +- if (ret_size != -1) +- { ++ int bufsize = *size; ++ int ret_size; ++ ret_size = readlink("/proc/self/exe", epath, bufsize-1); ++ if (ret_size != -1) ++ { + *size = ret_size; +- path[ret_size]=0; ++ epath[ret_size]=0; + return 0; +- } +- else ++ } ++ else + return -1; + #endif + } +diff --git usage_examples/ios_toolchain/wrapper.c usage_examples/ios_toolchain/wrapper.c +index ed536b2..438032f 100644 +--- usage_examples/ios_toolchain/wrapper.c ++++ usage_examples/ios_toolchain/wrapper.c +@@ -19,30 +19,79 @@ + #include + #endif + +-#ifdef __FreeBSD__ ++#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) + #include + #endif + +-char *get_executable_path(char *buf, size_t len) ++#ifdef __OpenBSD__ ++#include ++#include ++#include ++#endif ++ ++char *get_executable_path(char *epath, size_t buflen) + { + char *p; + #ifdef __APPLE__ +- unsigned int l = len; +- if (_NSGetExecutablePath(buf, &l) != 0) return NULL; +-#elif defined(__FreeBSD__) ++ unsigned int l = buflen; ++ if (_NSGetExecutablePath(epath, &l) != 0) return NULL; ++#elif defined(__FreeBSD__) || defined(__DragonFly__) + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; +- size_t l = len; +- if (sysctl(mib, 4, buf, &l, NULL, 0) != 0) return NULL; +-#elif defined(_WIN32) +- size_t l = GetModuleFileName(NULL, buf, (DWORD)len); ++ size_t l = buflen; ++ if (sysctl(mib, 4, epath, &l, NULL, 0) != 0) return NULL; ++#elif defined(__OpenBSD__) ++ int mib[4]; ++ char **argv; ++ size_t len; ++ size_t l; ++ const char *comm; ++ int ok = 0; ++ mib[0] = CTL_KERN; ++ mib[1] = KERN_PROC_ARGS; ++ mib[2] = getpid(); ++ mib[3] = KERN_PROC_ARGV; ++ if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) ++ abort(); ++ if (!(argv = malloc(len))) ++ abort(); ++ if (sysctl(mib, 4, argv, &len, NULL, 0) < 0) ++ abort(); ++ comm = argv[0]; ++ if (*comm == '/' || *comm == '.') { ++ char *rpath; ++ if ((rpath = realpath(comm, NULL))) { ++ snprintf(epath, buflen, "%s", rpath); ++ free(rpath); ++ ok = 1; ++ } ++ } else { ++ char *sp; ++ char *xpath = strdup(getenv("PATH")); ++ char *path = strtok_r(xpath, ":", &sp); ++ struct stat st; ++ if (!xpath) ++ abort(); ++ while (path) { ++ snprintf(epath, buflen, "%s/%s", path, comm); ++ if (!stat(epath, &st) && (st.st_mode & S_IXUSR)) { ++ ok = 1; ++ break; ++ } ++ path = strtok_r(NULL, ":", &sp); ++ } ++ free(xpath); ++ } ++ free(argv); ++ if (!ok) return NULL; ++ l = strlen(epath); + #else +- ssize_t l = readlink("/proc/self/exe", buf, len); ++ ssize_t l = readlink("/proc/self/exe", epath, buflen); + #endif + if (l <= 0) return NULL; +- buf[len - 1] = '\0'; +- p = strrchr(buf, '/'); ++ epath[buflen - 1] = '\0'; ++ p = strrchr(epath, '/'); + if (p) *p = '\0'; +- return buf; ++ return epath; + } + + char *get_filename(char *str) +@@ -88,7 +137,7 @@ int main(int argc, char *argv[]) + target_info(argv, &target, &compiler); + if (!get_executable_path(execpath, sizeof(execpath))) abort(); + snprintf(sdkpath, sizeof(sdkpath), "%s/../SDK", execpath); +- ++ + snprintf(codesign_allocate, sizeof(codesign_allocate), + "%s-codesign_allocate", target); + diff --git a/tools/cpucount.c b/tools/cpucount.c index 9539b46..3c51de5 100644 --- a/tools/cpucount.c +++ b/tools/cpucount.c @@ -37,7 +37,8 @@ #endif /* __linux__ */ #if defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) || defined(__APPLE__) + defined(__OpenBSD__) || defined(__DragonFly__) || \ + defined(__APPLE__) #include #include #include @@ -70,7 +71,8 @@ int getcpucount() { return cpucount ? cpucount : 1; #else #if defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) || defined(__APPLE__) + defined(__OpenBSD__) || defined(__DragonFly__) || \ + defined(__APPLE__) int cpucount = 0; int mib[4]; size_t len = sizeof(cpucount); diff --git a/tools/osxcross-macports b/tools/osxcross-macports index d2e2d54..9750fb6 100755 --- a/tools/osxcross-macports +++ b/tools/osxcross-macports @@ -306,7 +306,8 @@ installPkg() echo "installing $pkgname ..." verboseMsg " extracting $pkgfile ..." - tar xf "$CACHE/$pkgfile" + + bzip2 -dc "$CACHE/$pkgfile" | tar xf - if [ -d opt/local ]; then verboseMsg " fixing permissions ..." diff --git a/tools/osxcross_conf.sh b/tools/osxcross_conf.sh index b8e7c1f..a0c9571 100755 --- a/tools/osxcross_conf.sh +++ b/tools/osxcross_conf.sh @@ -3,9 +3,10 @@ pushd "${0%/*}" &>/dev/null OSXCROSS_CONF="../target/bin/osxcross-conf" -test -f $OSXCROSS_CONF || { OSXCROSS_CONF=`which osxcross-conf 2>/dev/null` || exit 1; } +[ -f $OSXCROSS_CONF ] || { OSXCROSS_CONF=$(which osxcross-conf 2>/dev/null) || exit 1; } $OSXCROSS_CONF || exit 1 -`dirname $OSXCROSS_CONF`/osxcross-env + +$(dirname $OSXCROSS_CONF)/osxcross-env popd &>/dev/null diff --git a/tools/tools.sh b/tools/tools.sh index 451def4..a506e72 100755 --- a/tools/tools.sh +++ b/tools/tools.sh @@ -10,6 +10,10 @@ TARGET_DIR=$BASE_DIR/target PATCH_DIR=$BASE_DIR/patches SDK_DIR=$TARGET_DIR/SDK +PLATFORM=$(uname -s) +SCRIPT=$(basename $0) +ARCH=$(uname -m) + if [ -z "$USESYSTEMCOMPILER" ]; then # Default to gcc on some OSs rather than clang due to either # libstdc++ issues (clang uses an outdated version on those) @@ -53,18 +57,15 @@ fi # enable debug messages test -n "$OCDEBUG" && set -x -PLATFORM="`uname -s`" -SCRIPT="`basename $0`" - if [[ $SCRIPT != *wrapper/build.sh ]]; then # how many concurrent jobs should be used for compiling? - JOBS=${JOBS:=`tools/get_cpu_count.sh`} + JOBS=${JOBS:=$(tools/get_cpu_count.sh)} if [ $SCRIPT != "build.sh" -a $SCRIPT != "build_clang.sh" -a \ $SCRIPT != "mount_xcode_image.sh" -a \ $SCRIPT != "gen_sdk_package_darling_dmg.sh" -a \ $SCRIPT != "gen_sdk_package_p7zip.sh" ]; then - `tools/osxcross_conf.sh` + eval $(tools/osxcross_conf.sh) if [ $? -ne 0 ]; then echo -n "you need to complete ./build.sh first, before you can start " @@ -92,25 +93,31 @@ function require() set -e } -if [[ $PLATFORM == *BSD ]]; then +if [[ $PLATFORM == *BSD ]] || [ $PLATFORM == "DragonFly" ]; then MAKE=gmake else MAKE=make fi +if [[ $PLATFORM == OpenBSD ]]; then + SED=gsed +else + SED=sed +fi + if [[ $PLATFORM == *BSD ]] || [ $PLATFORM == "Darwin" ]; then READLINK=greadlink else READLINK=readlink fi - +require $SED require $MAKE function extract() { test $# -ge 2 -a $# -lt 4 && test $2 -eq 2 && echo "" - echo "extracting `basename $1` ..." + echo "extracting $(basename $1) ..." local tarflags @@ -119,6 +126,7 @@ function extract() case $1 in *.pkg) + require cpio which xar &>/dev/null || exit 1 xar -xf $1 cat Payload | gunzip -dc | cpio -i 2>/dev/null && rm Payload @@ -143,6 +151,17 @@ function extract() fi } +if [[ $PLATFORM == CYGWIN* ]]; then + +# Work around Cygwin brokenness. +function ln() { + [[ $1 == -* ]] && rm -f $3 + $(which ln) $@ +} +export -f ln + +fi + function verbose_cmd() { echo "$@" diff --git a/wrapper/Makefile b/wrapper/Makefile index 0c2da2c..018cf83 100644 --- a/wrapper/Makefile +++ b/wrapper/Makefile @@ -30,9 +30,18 @@ ifneq (,$(findstring FreeBSD, $(PLATFORM))) else ifneq (,$(findstring Darwin, $(PLATFORM))) override CXXFLAGS+=-Wno-deprecated override LDFLAGS+=-framework CoreServices -Wno-deprecated -else ifeq (,$(findstring Windows, $(PLATFORM))) +else ifneq (,$(findstring CYGWIN, $(PLATFORM))) + # -std=gnu++0x doesn't work, so work around... + override CXXFLAGS+=-U__STRICT_ANSI__ +else + +ifeq (,$(findstring Windows, $(PLATFORM))) +ifeq (,$(findstring OpenBSD, $(PLATFORM))) override LDFLAGS+=-lrt endif +endif + +endif BIN=wrapper diff --git a/wrapper/build.sh b/wrapper/build.sh index 7cac6b5..fbb8e1a 100755 --- a/wrapper/build.sh +++ b/wrapper/build.sh @@ -7,10 +7,10 @@ popd &>/dev/null set +e if [ -z "$OSXCROSS_VERSION" ]; then - `../target/bin/osxcross-conf 2>/dev/null` + eval $(../target/bin/osxcross-conf 2>/dev/null) if [ -n "$OSXCROSS_SDK_VERSION" ] && - [ `osxcross-cmp $OSXCROSS_SDK_VERSION ">=" 10.8` -eq 1 ]; then + [ $(osxcross-cmp $OSXCROSS_SDK_VERSION ">=" 10.8) -eq 1 ]; then X86_64H_SUPPORTED=1 fi fi @@ -97,7 +97,6 @@ if [ -n "$BWPLATFORM" ]; then [ -z "$BWCOMPILEONLY" ] && BWCOMPILEONLY=1 else - PLATFORM=$(uname -s) [ -z "$PORTABLE"] && FLAGS="-march=native $CXXFLAGS " fi diff --git a/wrapper/main.cpp b/wrapper/main.cpp index aa96824..77e45e9 100644 --- a/wrapper/main.cpp +++ b/wrapper/main.cpp @@ -777,7 +777,14 @@ int main(int argc, char **argv) { } } +#ifdef __DragonFly__ + // Escape DragonFlyBSD's weird PFS paths. + std::string escapedexecpath; + escapePath(target.execpath, escapedexecpath); + concatEnvVariable("COMPILER_PATH", escapedexecpath); +#else concatEnvVariable("COMPILER_PATH", target.execpath); +#endif if (target.targetarch.size() > 1 && (target.usegcclibs || target.isGCC())) generateMultiArchObjectFile(rc, argc, argv, target, debug); diff --git a/wrapper/programs/osxcross-env.cpp b/wrapper/programs/osxcross-env.cpp index db469aa..9474b26 100644 --- a/wrapper/programs/osxcross-env.cpp +++ b/wrapper/programs/osxcross-env.cpp @@ -37,43 +37,6 @@ int env(int argc, char **argv) { if (!getExecutablePath(epath, sizeof(epath))) exit(EXIT_FAILURE); - // TODO: escape? - - auto containsBadChars = [](const char * p, const char * desc)->bool { - if (!p) - return false; - - const char *pp = p; - - do { - auto badChar = [&](const char *p) { - err << desc << " should not contain '" << *p << "'" << warn.endl(); - - const char *start = p - std::min(p - pp, 30); - - size_t len = std::min(strlen(start), 60); - - std::cerr << std::endl; - std::cerr << std::string(start, len) << std::endl; - - while (start++ != p) - std::cerr << " "; - - std::cerr << "^" << std::endl; - }; - switch (*p) { - case '"': - case '\'': - case '$': - case ' ': - case ';': - badChar(p); - return true; - } - } while (*p && *++p); - return false; - }; - if (argc <= 1) { const std::string &pname = getParentProcessName(); @@ -86,58 +49,15 @@ int env(int argc, char **argv) { } } - auto hasPath = [](const char * ov, const char * v, const char * vs)->bool { - // ov = old value - // v = value - // vs = value suffix - - if (!ov || !v) - return false; - - bool hasPathSeparator = false; - - for (auto p = ov; *p; ++p) { - if (*p == ':') { - hasPathSeparator = true; - break; - } - } - - static std::string tmp; - - auto check = [&](int t)->bool { - tmp.clear(); - - if (t == 0) - tmp = ':'; - - tmp += v; - - if (vs) - tmp += vs; - - if (t == 1) - tmp += ':'; - - return strstr(ov, tmp.c_str()) != nullptr; - }; - - return ((hasPathSeparator && (check(0) || check(1))) || check(-1)); - }; - - if (containsBadChars(oldpath, "PATH")) - return 1; - - std::stringstream path; - std::stringstream librarypath; + std::vector path; std::map vars; - path << oldpath; + splitPath(oldpath, path); - if (!hasPath(oldpath, epath, nullptr)) - path << ":" << epath; + if (!hasPath(path, epath)) + path.push_back(epath); - vars["PATH"] = path.str(); + vars["PATH"] = joinPath(path); auto printVariable = [&](const std::string & var)->bool { auto it = vars.find(var); diff --git a/wrapper/target.cpp b/wrapper/target.cpp index b75c5b7..644b9fc 100644 --- a/wrapper/target.cpp +++ b/wrapper/target.cpp @@ -359,6 +359,14 @@ do { \ #define TRYDIR2(libdir) TRYDIR(clangbindir, libdir) #define TRYDIR3(libdir) TRYDIR(std::string(), libdir) +#ifdef __CYGWIN__ +#ifdef __x86_64__ + TRYDIR2("/../lib/clang/x86_64-pc-cygwin"); +#else + TRYDIR2("/../lib/clang/i686-pc-cygwin"); +#endif +#endif + TRYDIR2("/../lib/clang"); #ifdef __linux__ diff --git a/wrapper/tools.cpp b/wrapper/tools.cpp index 1f87308..6706667 100644 --- a/wrapper/tools.cpp +++ b/wrapper/tools.cpp @@ -52,10 +52,13 @@ #include #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #include #include #include +#endif + +#ifdef __FreeBSD__ #include #endif @@ -93,23 +96,60 @@ char *getExecutablePath(char *buf, size_t len) { unsigned int l = len; if (_NSGetExecutablePath(buf, &l) != 0) return nullptr; -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__DragonFly__) int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; size_t l = len; if (sysctl(mib, 4, buf, &l, nullptr, 0) != 0) return nullptr; +#elif defined(__OpenBSD__) + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV}; + char **argv; + size_t l; + const char *comm; + int ok = 0; + if (sysctl(mib, 4, NULL, &l, NULL, 0) < 0) + abort(); + argv = new char *[l]; + if (sysctl(mib, 4, argv, &l, NULL, 0) < 0) + abort(); + comm = argv[0]; + if (*comm == '/' || *comm == '.') { + if (realpath(comm, buf)) + ok = 1; + } else { + char *sp; + char *xpath = strdup(getenv("PATH")); + char *path = strtok_r(xpath, ":", &sp); + struct stat st; + if (!xpath) + abort(); + while (path) { + snprintf(buf, len, "%s/%s", path, comm); + if (!stat(buf, &st) && (st.st_mode & S_IXUSR)) { + ok = 1; + break; + } + path = strtok_r(NULL, ":", &sp); + } + free(xpath); + } + if (ok) + l = strlen(buf); + else + l = 0; + delete[] argv; #elif defined(_WIN32) size_t l = GetModuleFileName(nullptr, buf, (DWORD)len); #else ssize_t l = readlink("/proc/self/exe", buf, len); + assert(l > 0 && "/proc not mounted?"); #endif if (l <= 0) return nullptr; buf[len - 1] = '\0'; p = strrchr(buf, PATHDIV); - if (p) { + if (p) *p = '\0'; - } return buf; } @@ -234,6 +274,57 @@ void concatEnvVariable(const char *var, const std::string &val) { setenv(var, nval.c_str(), 1); } +std::string &escapePath(const std::string &path, std::string &escapedpath) { + for (const char *p = path.c_str(); *p; ++p) { + switch (*p) { + case '"': + case '\'': + case '\\': + case '$': + case '(': + case ')': + case ' ': + case ';': + case ':': + escapedpath += '\\'; + } + escapedpath += *p; + } + return escapedpath; +} + +void splitPath(const char *path, std::vector &result) { + char *sp; + char *xpath = strdup(path); + char *p = strtok_r(xpath, ":", &sp); + if (!xpath) + abort(); + while (p) { + result.push_back(p); + p = strtok_r(NULL, ":", &sp); + } + free(xpath); +} + +std::string joinPath(const std::vector &path) { + std::string tmp; + std::string escaped; + for (size_t i = 0; i < path.size(); ++i) { + escaped.clear(); + tmp += escapePath(path[i], escaped); + if (i != path.size() - 1) + tmp += ":"; + } + return tmp; +} + +bool hasPath(const std::vector &path, const char *find) { + for (const std::string &p : path) + if (p == find) + return true; + return false; +} + // // Files and Directories // diff --git a/wrapper/tools.h b/wrapper/tools.h index 845aadb..bff5f6b 100644 --- a/wrapper/tools.h +++ b/wrapper/tools.h @@ -127,6 +127,10 @@ std::string &fixPathDiv(std::string &path); // void concatEnvVariable(const char *var, const std::string &val); +std::string &escapePath(const std::string &path, std::string &escapedpath); +void splitPath(const char *path, std::vector &result); +std::string joinPath(const std::vector &path); +bool hasPath(const std::vector &path, const char *find); // // Files and directories