From 5a217484ecc709b41bddb7c36382a50cf4dbe1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20P=C3=B6chtrager?= Date: Wed, 24 Dec 2014 10:52:24 +0100 Subject: [PATCH] add osxcross-macports - a minimalistic macports packet manager for 16.000+ binary packages --- AUTHORS | 15 +- CHANGELOG | 1 + README.MACPORTS.md | 158 +++++++++ README.md | 5 + build.sh | 7 + tools/osxcross-macports | 577 ++++++++++++++++++++++++++++++++ wrapper/programs/pkg-config.cpp | 64 +++- wrapper/progs.h | 2 +- wrapper/target.cpp | 73 ++++ wrapper/target.h | 7 + wrapper/tools.cpp | 9 +- wrapper/tools.h | 3 +- 12 files changed, 903 insertions(+), 18 deletions(-) create mode 100644 README.MACPORTS.md create mode 100755 tools/osxcross-macports diff --git a/AUTHORS b/AUTHORS index 9fadb15..1fb9da2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,14 @@ -Thomas Poechtrager (t.poechtrager@gmail.com) -Don Bright (hugh.m.bright@gmail.com) +N: Thomas Poechtrager +E: t.poechtrager@gmail.com +D: OSXCross, cctools/ld64 port +N: Cjacker +W: https://code.google.com/p/ios-toolchain-based-on-clang-for-linux +D: cctools/ld64 port + +N: Don Bright +E: hugh.m.bright@gmail.com +D: tools/get_dependencies.sh + +N: Marcel Wysocki +D: Initial MacPorts script (https://github.com/maci0/pmmacports) diff --git a/CHANGELOG b/CHANGELOG index dcc7c43..e2e8465 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ changed: added: * OSXCROSS_GCC_NO_STATIC_RUNTIME option (env) + * osxcross-macports: a minimalistic macports packet manager /******************************* v0.8 *******************************/ diff --git a/README.MACPORTS.md b/README.MACPORTS.md new file mode 100644 index 0000000..3217f69 --- /dev/null +++ b/README.MACPORTS.md @@ -0,0 +1,158 @@ +## OSXCROSS-MACPORTS ## + +`osxcross-macports` is a small "packet manager" for 16.000+ binary MacPorts packages. + +Packages are installed to `target/macports/pkgs`. + +## Dependencies: ## + +`bash`, `wget` and `openssl` + +Also ensure that you are using the 10.6 SDK (or later). + +## Installation: ## + +Run OSXCross's `./build.sh`, then you should have `osxcross-macports` in PATH. + +**Setting up osxcross-macports:** + +MacPorts doesn't support 10.5 anymore, so we need to change OSXCross's +default target to 10.6 (better 10.7, or later). + +\-- + +It may be worth to mention that you should stay below 10.10, there aren't +a lot packages for 10.10 yet. + +You can of course use (for example) 10.6 libraries on 10.10. + +\-- + +To achive this, add the following to your bashrc (or similar): + + export MACOSX_DEPLOYMENT_TARGET=10.7 + +Then run `osxcross-macports `. + +## Things you should know: ## + +**shortcuts:** + +`osxcross-mp`, `omp` + +\-- + +**pkg-config:** + +OSXCross's `pkg-config` (`-apple-darwinXX-pkg-config`) +is automatically aware of MacPorts packages. + +If you want `pkg-config` to be unaware of MacPorts packages +(for whatever reason), do the following: + +`export OSXCROSS_PKG_CONFIG_NO_MP_INC=1` + +\-- + +**automatic compiler includes:** + +You can set up automatic compiler includes (`-I / -L / -F`) by doing the +following: + +`export OSXCROSS_MP_INC=1` + +\-- + +**verbose messages:** + +Can be enabled by adding '-v' or '--verbose'. + +\-- + +**upgrading packages:** + +Run `osxcross-macports upgrade`. + +This will simply re-install the latest version of all your installed packages. + +**listing all available packages:** + +`osxcross-macports search $` + +## Commands: ## + +osxcross-macports [...] + + * install <pkg1> [<pkg2> [...]] + * Install and its deps. + + * search <pkg> + * Prints a list of matching package names. + + * update-cache + * Updates the search index cache. + + * clear-cache + * Clears the download and search cache. + + * remove-dylibs + * Removes all \*.dylib (useful for static linking). + + * upgrade + * Reinstalls the latest version of every package. + +Useful flags: + + * '-v', '--verbose': + * Print verbose messages. + + * '-v=2', '--verbose=2': + * Print more verbose messages. + + * '-s', '--static': + * Install static libraries only. + + * '-c', '--cflags' <lib>: + * Shows cflags for <lib> (same as pkg-config). + + * '-l', '--ldflags' <lib>: + * Shows ldflags for <lib> (same as pkg-config). + +Uninstalling is not supported (and probably never will be). + +However, you can remove packages by hand. A simpler (and cleaner) way would +be to remove the whole macports directory (target/macports) and to reinstall +all other packages again. + +## Example: ## + +LIB INSTALLATION EXAMPLE: + + $ osxcross-macports install libsdl2 + searching package libsdl2 ... + downloading libsdl2-2.0.3_0.darwin_11.x86_64.tbz2 ... + installing libsdl2 ... + installed libsdl2 + +LIBFLAGS (osxcross-macports): + + $ osxcross-macports --cflags sdl2 + -D_THREAD_SAFE -I/data/development/osxcross/target/bin/../macports/pkgs/opt/local/include/SDL2 + + $ osxcross-macports --ldflags sdl2 + -L/data/development/osxcross/target/bin/../macports/pkgs/opt/local/lib -lSDL2 + +LIBFLAGS (pkg-config): + + $ x86_64-apple-darwinXX-pkg-config --cflags sdl2 + -D_THREAD_SAFE -I/data/development/osxcross/target/bin/../macports/pkgs/opt/local/include/SDL2 + + $ x86_64-apple-darwinXX-pkg-config --libs sdl2 + -L/data/development/osxcross/target/bin/../macports/pkgs/opt/local/lib -lSDL2 + +AUTOMATIC INCLUDES: + + OSXCROSS_MP_INC=1 o64-clang file.c -lSDL2 + + OSXCROSS_MP_INC=1 make [...] + diff --git a/README.md b/README.md index e18e17a..64484ea 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,11 @@ If you want, then you can build an up-to-date vanilla GCC as well. Basically everything you can build on OS X with clang/gcc should build with this cross toolchain as well. +### PACKET MANAGERS ### + +OSXCross comes with a minimalistic MacPorts Packet Manager. +Please see [README.MACPORTS](https://github.com/tpoechtrager/osxcross/blob/master/README.MACPORTS.md) for more. + ### INSTALLATION: ### Move your packaged SDK to the tarballs/ directory. diff --git a/build.sh b/build.sh index 0f8ee57..402dfef 100755 --- a/build.sh +++ b/build.sh @@ -202,6 +202,13 @@ popd &>/dev/null fi # CCTOOLS END +# MacPorts symlinks +pushd $TARGET_DIR/bin &>/dev/null # The BSD ln command doesn't support '-r' +ln -sf ../../tools/osxcross-macports osxcross-macports +ln -sf ../../tools/osxcross-macports osxcross-mp +ln -sf ../../tools/osxcross-macports omp +popd &>/dev/null + SDK=`ls $TARBALL_DIR/MacOSX$SDK_VERSION*` # XAR diff --git a/tools/osxcross-macports b/tools/osxcross-macports new file mode 100755 index 0000000..feb9e5b --- /dev/null +++ b/tools/osxcross-macports @@ -0,0 +1,577 @@ +#!/usr/bin/env bash + +## +## A minimalistic MacPorts Packet Manager for OSXCross, +## based on: https://github.com/maci0/pmmacports. +## Please see README.MACPORTS for more. +## License: GPLv2. +## + +set -e +export LC_ALL=C +pushd "${0%/*}" &>/dev/null + +MIRROR="$OSXCROSS_MACPORTS_MIRROR" + +if [ -z "$MIRROR" ]; then + MIRROR="http://packages.macports.org" +fi + +PUBKEYURL="https://svn.macports.org/repository/" +PUBKEYURL+="macports/trunk/base/macports-pubkey.pem" + +# Darwin's antique OpenSSL does not support the SHA-2 family +PUBKEYRMD160="d3a22f5be7184d6575afcc1be6fdb82fd25562e8" +PUBKEYSHA1="214baa965af76ff71187e6c1ac91c559547f48ab" + +if [ -n "$OSXCROSS_MACPORTS_ENABLE_HTTPS" ]; then + MIRROR=$(echo $MIRROR | sed 's/http:/https:/g') +fi + +if [ -z "$BASHPID" ]; then + BASHPID=$(sh -c 'echo $PPID') +fi + +errorMsg() +{ + echo "$@" 1>&2 +} + +verboseMsg() +{ + if [ -n "$VERBOSE" ]; then + errorMsg "$@" + fi +} + +verbosePlaceHolder() +{ + if [ -n "$VERBOSE" ]; then + errorMsg "" + fi +} + +require() +{ + set +e + which $1 &>/dev/null + if [ $? -ne 0 ]; then + errorMsg "$1 is required" + exit 1 + fi + set -e +} + +PLATFORM=$(uname -s) + +if [ -z "$MACOSX_DEPLOYMENT_TARGET" ]; then + errorMsg "You must set MACOSX_DEPLOYMENT_TARGET first." + errorMsg "Please see README.MACPORTS." + exit 1 +fi + +unsupportedDepTarget() +{ + errorMsg "unsupported deployment target" + exit 1 +} + +require "wget" +require "openssl" + +case $MACOSX_DEPLOYMENT_TARGET in + 10.6* ) OSXVERSION="darwin_10" ;; + 10.7* ) OSXVERSION="darwin_11" ;; + 10.8* ) OSXVERSION="darwin_12" ;; + 10.9* ) OSXVERSION="darwin_13" ;; + 10.10* ) OSXVERSION="darwin_14" ;; + * ) unsupportedDepTarget ;; +esac + +require "osxcross-conf" +eval $(osxcross-conf) + +if [ -z "$OSXCROSS_TARGET_DIR" ]; then + errorMsg "OSXCROSS_TARGET_DIR should be set" + exit 1 +fi + +ROOT="$OSXCROSS_TARGET_DIR/macports" + +if [ ! -d "$ROOT" ]; then + echo "creating macports directory: $ROOT" + mkdir -p $ROOT +fi + +PUBKEY="$ROOT/mp-pubkey.pem" +INSTALLDB="$ROOT/INSTALLED" +CACHE="$ROOT/cache" +INSTALL="$ROOT/pkgs" +TMP="$ROOT/tmp" +LASTPKGNAME="" + +LOCKDIR="/tmp/osxcross-macports-lock" +LOCKPID="$LOCKDIR/pid" + +checkLock() +{ + if mkdir $LOCKDIR 2>/dev/null; then + echo $BASHPID > $LOCKPID + else + pid=$(cat $LOCKPID 2>/dev/null) || { errorMsg "remove $LOCKDIR"; exit 1; } + if [ $? -eq 0 -a "$(ps -p $pid -o comm=)" == "bash" ]; then + errorMsg "locked by pid $pid" + else + errorMsg "dead lockdir detected! please remove '$LOCKDIR' by hand." + fi + exit 1 + fi +} + +createDir() +{ + if [ ! -d $2 ]; then + echo "creating $1 directory: $2" + mkdir -p $2 + fi +} + +checkLock + +createDir "cache" $CACHE +createDir "install" $INSTALL +createDir "tmp" $TMP + +getFileStdout() +{ + verbosePlaceHolder + local xargs="" + [ -z "$VERBOSE" ] && xargs+="--quiet" + wget "$1" -O- $xargs + #verbosePlaceHolder +} + +getFile() +{ + verbosePlaceHolder + local xargs="" + if [ $# -ge 2 ]; then + xargs+="-O $2 " + else + xargs+="-P $CACHE " + fi + [ -z "$VERBOSE" ] && xargs+="--quiet" + wget -c "$1" $xargs + #verbosePlaceHolder +} + +verifyFileIntegrity() +{ + local file="$1" + + if [ ! -e "$PUBKEY" ]; then + echo "getting macports public key ..." + getFile $PUBKEYURL "$PUBKEY" + fi + + local rmd160=$(openssl rmd160 "$PUBKEY" | awk '{print $2}') + local sha1=$(openssl sha1 "$PUBKEY" | awk '{print $2}') + + if [ "$rmd160" != "$PUBKEYRMD160" -o "$sha1" != "$PUBKEYSHA1" ]; then + errorMsg "invalid macports public key (hash check failed)" + exit 1 + fi + + verboseMsg "verifying file integrity ..." + + set +e + + openssl dgst -ripemd160 -verify "$PUBKEY" -signature \ + "$CACHE/$file.rmd160" "$CACHE/$file" 1>/dev/null + + if [ $? -ne 0 ]; then + errorMsg "file integrity check failed ($CACHE/$file)" + exit 2 + fi + + set -e +} + +getPkgUrl() +{ + local pkgname="$1" + local pkgs + local pkg + + set +e + + pkgs=$(getFileStdout "$MIRROR/$pkgname/?C=M;O=A" | \ + grep -o -E 'href="([^"#]+)"' | \ + cut -d'"' -f2 | grep '.tbz2$') + + local ec=$? + + set -e + + if [ $ec -ne 0 ]; then + errorMsg "no package found" + return + fi + + verboseMsg " candidates for $pkgname:" + + for p in $pkgs; do + verboseMsg " $p" + done + + local pkg=$(echo "$pkgs" | grep $OSXVERSION | uniq | tail -n1) + + verboseMsg " selected: $pkg" + + if [ -z "$pkg" ]; then + verboseMsg -n " " + errorMsg "no suitable version found for $OSXVERSION" + return + fi + + echo "$MIRROR/$pkgname/$pkg" +} + +pkgInstalled() +{ + local pkgname="$1" + + if [ ! -e "$INSTALLDB" ]; then + echo 0 + return + fi + + set +e + grep -x "$pkgname" "$INSTALLDB" &>/dev/null + local status=$? + set -e + + if [ $status -eq 0 ]; then + echo 1 + else + echo 0 + fi +} + +installPkg() +{ + local pkgname="$1" + + LASTPKGNAME=$pkgname + + if [ $(pkgInstalled $pkgname) -eq 1 ]; then + continue + fi + + echo "searching package $pkgname ..." + + local pkgurl=$(getPkgUrl "$pkgname") + local pkgfile=$(echo "$pkgurl" | awk -F'/' '{print $NF}') + + if [ -z "$pkgurl" ]; then + local oldpkgname=$pkgname + pkgname=$(echo "$pkgname" | cut -f1 -d'-') + + if [ "$pkgname" != "$oldpkgname" ]; then + echo "trying $pkgname instead ..." + else + [ -n "$UPGRADE" ] && return + exit 3 + fi + + installPkg $pkgname + return + fi + + echo "getting $pkgfile ..." + getFile "$pkgurl" + + verboseMsg "getting $pkgname.rmd160 ..." + getFile "$pkgurl.rmd160" + + verifyFileIntegrity "$pkgfile" + + pushd $TMP &>/dev/null + + echo "installing $pkgname ..." + verboseMsg " extracting $pkgfile ..." + tar xf "$CACHE/$pkgfile" + + if [ -d opt/local ]; then + verboseMsg " fixing permissions ..." + find opt/local -type d -exec chmod 770 {} \; + find opt/local -type f -exec chmod 660 {} \; + if [ -d opt/local/lib ]; then + if [ -n "$STATIC" ]; then + verboseMsg " " + echo "removing dylibs ..." + find opt/local/lib -name "*.dylib" -exec rm {} \; + else + find opt/local/lib -type f -name "*.dylib" -exec chmod +x {} \; + fi + fi + set +e + cp -r opt $INSTALL + local status=$? + set -e + if [ $status -eq 1 ]; then + errorMsg "removing broken symlinks ..." + find -L . -type l -exec rm {} \; + cp -r opt $INSTALL + fi + fi + + local pkgdeps=$(grep '@pkgdep' \+CONTENTS | cut -d\ -f2 | \ + rev | cut -f2-100 -d\- | rev) + + popd &>/dev/null # TMP + rm -rf $TMP/* + + for pkgdep in $pkgdeps; do + installPkg $pkgdep + done + + echo "$pkgname" >> "$INSTALLDB" +} + +installPkgs() +{ + local packages="$1" + + for pkgname in $packages; do + if [ $(pkgInstalled $pkgname) == "1" ]; then + errorMsg "$pkgname is already installed" + continue + fi + installPkg $pkgname + echo "installed $pkgname" + rm -f $INSTALL/+* + done +} + +updateSearchCache() +{ + pushd $CACHE &>/dev/null + + echo "generating index cache (this may take several minutes ...)" + getFile $MIRROR $CACHE/packages + + cat packages | grep -o -E 'href="([^"#]+)"' | cut -d'"' -f2 | \ + sed 's/.\{1\}$//' | uniq | sort > INDEXCACHE + + rm -f packages + echo "generated index cache for $(cat INDEXCACHE | wc -l) packages" + + popd &>/dev/null +} + +searchPkg() +{ + local pkg="$1" + + pushd $CACHE &>/dev/null + + if [ ! -e INDEXCACHE ]; then + updateSearchCache + fi + + local packages=$(grep -i "$pkg" INDEXCACHE) + + if [ -z "$packages" ]; then + echo "no matching packages found for $1" + return + fi + + for pkg in $packages; do + echo $pkg + done + + popd &>/dev/null +} + +_exit() +{ + local ec=$? + if [ $ec -ne 0 ]; then + if [ -n "$LASTPKGNAME" ]; then + errorMsg "failed to install $LASTPKGNAME, try with '-v'" + fi + if [ $ec -eq 3 ]; then + errorMsg -n "use '$(basename $0) fake-install ' to " + errorMsg "fake install non-existing packages" + fi + fi + + rm -rf $LOCKDIR +} + +showFlags() +{ + if [ -n "$OSXCROSS_TARGET" ]; then + PKG_CONFIG="x86_64-apple-${OSXCROSS_TARGET}-pkg-config" + else + PKG_CONFIG="pkg-config" + fi + + $PKG_CONFIG $1 $2 +} + +showCFLAGS() +{ + showFlags "--cflags" $1 +} + +showLDFLAGS() +{ + showFlags "--libs" $1 +} + +upgrade() +{ + if [ ! -e $INSTALLDB ]; then + if [ -e $INSTALLDB.old ]; then + echo "restoring old installation database" + mv $INSTALLDB.old $INSTALLDB + else + errorMsg "no install database" + exit 1 + fi + fi + + local PKGS=$(cat $INSTALLDB) + mv $INSTALLDB $INSTALLDB.old + + UPGRADE=1 + rm -rf $INSTALL + + for pkg in $PKGS; do + installPkg $pkg + done +} + +clearCache() +{ + rm -rf $CACHE +} + +removeDylibs() +{ + find $INSTALL -name "*.dylib" -exec rm {} \; +} + +showHelpText() +{ + errorMsg "Please see README.MACPORTS" +} + +main() +{ + local args + local cmd + + for opt in $@; do + if [[ $opt == -* ]]; then + if [ $opt == "-v" -o $opt == "--verbose" ]; then + VERBOSE=1 + elif [ $opt == "-v=2" -o $opt == "--verbose=2" ]; then + set -x + VERBOSE=1 + elif [ $opt == "-s" -o $opt == "--static" ]; then + STATIC=1 + elif [ $opt == "-c" -o $opt == "--cflags" ]; then + showCFLAGS $2 + exit + elif [ $opt == "-l" -o $opt == "--ldflags" ]; then + showLDFLAGS $2 + exit + elif [ $opt == "-h" -o $opt == "--help" ]; then + showHelpText + exit + else + errorMsg "unknown option: $opt" + exit 1 + fi + else + if [ -z "$cmd" ]; then + cmd="$opt" + else + args+="$opt " + fi + fi + done + + if [ -z "$cmd" ]; then + errorMsg "no command given" + showHelpText + exit 1 + fi + + case "$cmd" in + update*cache ) + updateSearchCache + exit + ;; + + upgrade ) + upgrade + exit + ;; + + clear*cache ) + clearCache + echo "done" + exit + ;; + + remove*dylibs ) + removeDylibs + echo "done" + exit + ;; + esac + + local packages="$args" + + if [ -z "$packages" ]; then + errorMsg "no package name given" + exit 1 + fi + + case "$cmd" in + install ) + installPkgs "$packages" + ;; + + fake*install ) + for pkgname in $args; do + if [ $(pkgInstalled $pkgname) -eq 0 ]; then + echo $pkgname >> $INSTALLDB + fi + done + + echo "done" + ;; + + search ) + for pkgname in $args; do + searchPkg $pkgname + done + ;; + + * ) + showHelpText + ;; + esac +} + +trap '' TERM +trap '' INT + +trap _exit EXIT + +main "$@" diff --git a/wrapper/programs/pkg-config.cpp b/wrapper/programs/pkg-config.cpp index dd1bd9b..6b0c9b7 100644 --- a/wrapper/programs/pkg-config.cpp +++ b/wrapper/programs/pkg-config.cpp @@ -26,6 +26,7 @@ #endif extern char **environ; +using namespace tools; namespace program { namespace osxcross { @@ -33,30 +34,67 @@ namespace osxcross { struct envvar { std::string name; std::string value; + envvar() {} envvar(std::string name, std::string value) : name(name), value(value) {} }; -int pkg_config(int argc, char **argv) { +static envvar &var(const char *p, envvar &evar, const bool skipval = false) { + const char *value = strchr(p, '=') + 1; // find value offset + evar.name.assign(p, value - p - 1); + if (!skipval) + evar.value = value; + return evar; +} + +int pkg_config(int argc, char **argv, Target &target) { (void)argc; std::vector envvars; + std::vector unset; + envvar evar; - // Map OSXCROSS_PKG_* to PKG_* - for (char **env = environ; *env; ++env) { - char *p = *env; + if (!getenv("OSXCROSS_PKG_CONFIG_NO_MP_INC")) { + std::string MacPortsSysRoot; - if (!strncmp(p, "OSXCROSS_PKG", 12)) { - p += 9; // skip OSXCROSS_ - const char *val = strchr(p, '=') + 1; // find value offset - envvars.push_back(envvar(std::string(p, val - p - 1), val)); - } + if (target.getMacPortsSysRootDir(MacPortsSysRoot)) { + concatEnvVariable("OSXCROSS_PKG_CONFIG_SYSROOT_DIR", MacPortsSysRoot); + std::string MacPortsPkgConfigPath; + + if (target.getMacPortsPkgConfigDir(MacPortsPkgConfigPath)) + concatEnvVariable("OSXCROSS_PKG_CONFIG_PATH", MacPortsPkgConfigPath); + } + } else { + unsetenv("OSXCROSS_PKG_CONFIG_NO_MP_INC"); } - for (const envvar &evar : envvars) - setenv(evar.name.c_str(), evar.value.c_str(), 1); + // Map OSXCROSS_PKG_* to PKG_*. + for (char **env = environ; *env; ++env) { + char *p = *env; - if (!envvars.empty() && execvp("pkg-config", argv)) - std::cerr << "cannot find or execute pkg-config" << std::endl; + if (!strncmp(p, "OSXCROSS_PKG_CONFIG", 19)) { + p += 9; // skip OSXCROSS_ + envvars.push_back(var(p, evar)); + } else if (!strncmp(p, "PKG_CONFIG", 10)) { + // Unset native pkg-config vars. + unset.push_back(var(p, evar, true)); + } + } + + if (!envvars.empty()) { + for (const envvar &evar : unset) + unsetenv(evar.name.c_str()); + + for (const envvar &evar : envvars) + setenv(evar.name.c_str(), evar.value.c_str(), 1); + + // Prevent pkg-config from looking for *.pc files + // in pre-defined search paths, such as /usr. + if (!getenv("PKG_CONFIG_LIBDIR")) + setenv("PKG_CONFIG_LIBDIR", "", 1); + + if (execvp("pkg-config", argv)) + std::cerr << "cannot find or execute pkg-config" << std::endl; + } return 1; } diff --git a/wrapper/progs.h b/wrapper/progs.h index 9e4e098..2e3063b 100644 --- a/wrapper/progs.h +++ b/wrapper/progs.h @@ -81,7 +81,7 @@ int version(); int env(int argc, char **argv); int conf(Target &target); int cmp(int argc, char **argv); -int pkg_config(int argc, char **argv); +int pkg_config(int argc, char **argv, Target &target); } // namespace osxcross static int dummy() { return 0; } diff --git a/wrapper/target.cpp b/wrapper/target.cpp index 1d15e87..f6e84c8 100644 --- a/wrapper/target.cpp +++ b/wrapper/target.cpp @@ -59,6 +59,52 @@ bool Target::getSDKPath(std::string &path) const { return dirExists(path); } +bool Target::getMacPortsDir(std::string &path) const { + path = execpath; + path += "/../macports"; + return dirExists(path); +} + +bool Target::getMacPortsSysRootDir(std::string &path) const { + if (!getMacPortsDir(path)) + return false; + + path += "/pkgs"; + return dirExists(path); +} + +bool Target::getMacPortsPkgConfigDir(std::string &path) const { + if (!getMacPortsDir(path)) + return false; + + path += "/pkgs/opt/local/lib/pkgconfig"; + return dirExists(path); +} + +bool Target::getMacPortsIncludeDir(std::string &path) const { + if (!getMacPortsDir(path)) + return false; + + path += "/pkgs/opt/local/include"; + return dirExists(path); +} + +bool Target::getMacPortsLibDir(std::string &path) const { + if (!getMacPortsDir(path)) + return false; + + path += "/pkgs/opt/local/lib"; + return dirExists(path); +} + +bool Target::getMacPortsFrameworksDir(std::string &path) const { + if (!getMacPortsDir(path)) + return false; + + path += "/pkgs/opt/local/Library/Frameworks"; + return dirExists(path); +} + void Target::addArch(const Arch arch) { auto &v = targetarch; for (size_t i = 0; i < v.size(); ++i) { @@ -622,6 +668,33 @@ bool Target::setup() { for (auto &path : AdditionalCXXHeaderPaths) addCXXHeaderPath(path); + if (getenv("OSXCROSS_MP_INC")) { + std::string MacPortsIncludeDir; + std::string MacPortsLibraryDir; + std::string MacPortsFrameworksDir; + + // Add them to args (instead of fargs), + // so the user's -I / -L / -F is prefered. + + if (getMacPortsIncludeDir(MacPortsIncludeDir)) { + args.push_back("-isystem"); + args.push_back(MacPortsIncludeDir); + + if (getMacPortsLibDir(MacPortsLibraryDir)) { + if (isClang()) + args.push_back("-Qunused-arguments"); + + args.push_back("-L"); + args.push_back(MacPortsLibraryDir); + } + + if (getMacPortsFrameworksDir(MacPortsFrameworksDir)) { + args.push_back("-iframework"); + args.push_back(MacPortsFrameworksDir); + } + } + } + if (langGiven() && !usegcclibs) { // usegcclibs: delay it to later fargs.push_back("-x"); diff --git a/wrapper/target.h b/wrapper/target.h index 1fbc7ef..4a2762d 100644 --- a/wrapper/target.h +++ b/wrapper/target.h @@ -84,6 +84,13 @@ struct Target { OSVersion getSDKOSNum() const; bool getSDKPath(std::string &path) const; + bool getMacPortsDir(std::string &path) const; + bool getMacPortsSysRootDir(std::string &path) const; + bool getMacPortsPkgConfigDir(std::string &path) const; + bool getMacPortsIncludeDir(std::string &path) const; + bool getMacPortsLibDir(std::string &path) const; + bool getMacPortsFrameworksDir(std::string &path) const; + void addArch(const Arch arch); bool haveArch(const Arch arch); diff --git a/wrapper/tools.cpp b/wrapper/tools.cpp index 04f8aed..017bfa5 100644 --- a/wrapper/tools.cpp +++ b/wrapper/tools.cpp @@ -202,7 +202,7 @@ std::string &fixPathDiv(std::string &path) { // Environment // -void concatEnvVariable(const char *var, const std::string val) { +void concatEnvVariable(const char *var, const std::string &val) { std::string nval = val; if (char *oldval = getenv(var)) { nval += ":"; @@ -451,6 +451,13 @@ int setenv(const char *name, const char *value, int overwrite) { } int unsetenv(const char *name) { return setenv(name, "", 1); } + +int execvp(const char *file, char *const argv[]) { + (void)file; + (void)argv; + + return 1; +} #endif } // namespace tools diff --git a/wrapper/tools.h b/wrapper/tools.h index bc74355..f741010 100644 --- a/wrapper/tools.h +++ b/wrapper/tools.h @@ -45,7 +45,7 @@ std::string &fixPathDiv(std::string &path); // Environment // -void concatEnvVariable(const char *var, const std::string val); +void concatEnvVariable(const char *var, const std::string &val); // // Files and directories @@ -201,6 +201,7 @@ typedef OSVersion ClangVersion; #ifdef _WIN32 int setenv(const char *name, const char *value, int overwrite); int unsetenv(const char *name); +int execvp(const char *file, char *const argv[]); constexpr char PATHDIV = '\\'; #else constexpr char PATHDIV = '/';