From 0416c6dbec45f4268f682559735c7aa0620457df Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 19 Mar 2015 19:38:09 +0100 Subject: [PATCH] Robustify package detection on Linux --- README.md | 2 +- makepanda/makepanda.py | 2 +- makepanda/makepandacore.py | 92 +++++++++++++++++++++++++++----------- 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a216893938..93a20db562 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ If you are on Ubuntu, this command should cover the most frequently used third-party packages: ```bash -sudo apt-get install python-dev libpng-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev bison flex libfreetype6-dev libvorbis-dev libjpeg-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev nvidia-cg-toolkit +sudo apt-get install build-essential pkg-config python-dev libpng-dev libjpeg-dev libtiff-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev bison flex libfreetype6-dev libvorbis-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev nvidia-cg-toolkit libgtk2.0-dev ``` Once Panda3D has built, you can either install the .deb or .rpm package that diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 98576159df..b787a9b870 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -712,7 +712,7 @@ if (COMPILER=="GCC"): SmartPkgEnable("OPENAL", "openal", ("openal"), "AL/al.h", framework = "OpenAL") SmartPkgEnable("OPENCV", "opencv", ("cv", "highgui", "cvaux", "ml", "cxcore"), ("opencv", "opencv/cv.h")) SmartPkgEnable("SQUISH", "", ("squish"), "squish.h") - SmartPkgEnable("TIFF", "", ("tiff"), "tiff.h") + SmartPkgEnable("TIFF", "libtiff-4", ("tiff"), "tiff.h") SmartPkgEnable("VRPN", "", ("vrpn", "quat"), ("vrpn", "quat.h", "vrpn/vrpn_Types.h")) SmartPkgEnable("BULLET", "bullet", ("BulletSoftBody", "BulletDynamics", "BulletCollision", "LinearMath"), ("bullet", "bullet/btBulletDynamicsCommon.h")) SmartPkgEnable("VORBIS", "vorbisfile",("vorbisfile", "vorbis", "ogg"), ("ogg/ogg.h", "vorbis/vorbisfile.h")) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 3cea7ba1d8..5faff14a90 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -10,6 +10,7 @@ ######################################################################## import sys,os,time,stat,string,re,getopt,fnmatch,threading,signal,shutil,platform,glob,getpass,signal +import subprocess from distutils import sysconfig if sys.version_info >= (3, 0): @@ -39,6 +40,7 @@ HAS_TARGET_ARCH = False TOOLCHAIN_PREFIX = "" ANDROID_ABI = None SYS_LIB_DIRS = [] +SYS_INC_DIRS = [] DEBUG_DEPENDENCIES = False # Is the current Python a 32-bit or 64-bit build? There doesn't @@ -1551,7 +1553,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, LibName(target_pkg, "-l" + libname) else: # Try searching in the package's LibDirectories. - lpath = [dir for ppkg, dir in LIBDIRECTORIES if pkg == ppkg] + lpath = [dir for ppkg, dir in LIBDIRECTORIES if pkg == ppkg or ppkg == "ALWAYS"] if LibraryExists(libname, lpath): LibName(target_pkg, "-l" + libname) else: @@ -1559,27 +1561,26 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, if VERBOSE: print(GetColor("cyan") + "Couldn't find library lib" + libname + GetColor()) + # Determine which include directories to look in. + incdirs = list(SYS_INC_DIRS) + for ppkg, pdir in INCDIRECTORIES: + if pkg == ppkg or ppkg == "ALWAYS": + incdirs.append(pdir) + + # The incs list contains both subdirectories to explicitly add to + # the include path and header files to check the existence of. for i in incs: incdir = None - sysroot_usr = SDK.get("SYSROOT", "") + "/usr" - if (len(glob.glob(sysroot_usr + "/include/" + i)) > 0): - incdir = sorted(glob.glob(sysroot_usr + "/include/" + i))[-1] - elif (len(glob.glob(sysroot_usr + "/local/include/" + i)) > 0): - incdir = sorted(glob.glob(sysroot_usr + "/local/include/" + i))[-1] - elif (os.path.isdir(sysroot_usr + "/PCBSD") and len(glob.glob(sysroot_usr + "/PCBSD/local/include/" + i)) > 0): - incdir = sorted(glob.glob(sysroot_usr + "/PCBSD/local/include/" + i))[-1] - else: - # Try searching in the package's IncDirectories. - for ppkg, pdir in INCDIRECTORIES: - if pkg == ppkg and len(glob.glob(os.path.join(pdir, i))) > 0: - incdir = sorted(glob.glob(os.path.join(pdir, i)))[-1] - - if incdir is None and i.endswith(".h"): - have_pkg = False - if VERBOSE: - print(GetColor("cyan") + "Couldn't find header file " + i + GetColor()) + for dir in incdirs: + if len(glob.glob(os.path.join(dir, i))) > 0: + incdir = sorted(glob.glob(os.path.join(dir, i)))[-1] # Note: It's possible to specify a file instead of a dir, for the sake of checking if it exists. + if incdir is None and i.endswith(".h"): + have_pkg = False + if VERBOSE: + print(GetColor("cyan") + "Couldn't find header file " + i + GetColor()) + if incdir is not None and os.path.isdir(incdir): IncDirectory(target_pkg, incdir) @@ -2232,10 +2233,10 @@ def SetupBuildEnvironment(compiler): if compiler == "GCC": # Invoke gcc to determine the system library directories. - global SYS_LIB_DIRS + global SYS_LIB_DIRS, SYS_INC_DIRS if sys.platform == "darwin": - # We need to add this one explicitly. + # We need to add this one explicitly for some reason. SYS_LIB_DIRS.append(SDK["MACOSX"] + "/usr/lib") if not SDK.get("MACOSX"): @@ -2244,15 +2245,16 @@ def SetupBuildEnvironment(compiler): if os.path.isdir(local_lib): SYS_LIB_DIRS.append(local_lib) - cmd = GetCXX() + " -print-search-dirs" + sysroot_flag = "" if SDK.get("MACOSX"): # The default compiler in Leopard does not respect --sysroot correctly. - cmd += " -isysroot " + SDK["MACOSX"] + sysroot_flag = " -isysroot " + SDK["MACOSX"] if SDK.get("SYSROOT"): - cmd += ' --sysroot=%s -no-canonical-prefixes' % (SDK["SYSROOT"]) + sysroot_flag = ' --sysroot=%s -no-canonical-prefixes' % (SDK["SYSROOT"]) # Extract the dirs from the line that starts with 'libraries: ='. + cmd = GetCXX() + " -print-search-dirs" + sysroot_flag handle = os.popen(cmd) for line in handle: if not line.startswith('libraries: ='): @@ -2266,8 +2268,48 @@ def SetupBuildEnvironment(compiler): print("%sWARNING:%s %s failed" % (GetColor("red"), GetColor(), cmd)) SYS_LIB_DIRS += [SDK.get("SYSROOT", "") + "/usr/lib"] - elif GetVerbose(): - print("System library search path: %s" % ':'.join(SYS_LIB_DIRS)) + # Now extract the preprocessor's include directories. + cmd = GetCXX() + sysroot_flag + " -x c++ -v -E /dev/null" + null = open(os.devnull, 'w') + handle = subprocess.Popen(cmd, stdout=null, stderr=subprocess.PIPE, shell=True) + scanning = False + for line in handle.communicate()[1].splitlines(): + # Start looking at a line that says: #include "..." search starts here + if not scanning: + if line.startswith('#include'): + scanning = True + continue + + if not line.startswith(' /'): + continue + + line = line.strip() + if os.path.isdir(line): + SYS_INC_DIRS.append(line) + elif GetVerbose(): + print("Ignoring non-existent include directory %s" % (line)) + + if handle.returncode != 0 or not SYS_INC_DIRS: + print("%sWARNING:%s %s failed or did not produce the expected result" % (GetColor("red"), GetColor(), cmd)) + sysroot = SDK.get("SYSROOT", "") + # Add some sensible directories as a fallback. + SYS_INC_DIRS = [ + sysroot + "/usr/include", + sysroot + "/usr/local/include" + ] + pcbsd_inc = sysroot + "/usr/PCBSD/local/include" + if os.path.isdir(pcbsd_inc): + SYS_INC_DIRS.append(pcbsd_inc) + + # Print out the search paths + if GetVerbose(): + print("System library search path:") + for dir in SYS_LIB_DIRS: + print(" " + dir) + + print("System include search path:") + for dir in SYS_INC_DIRS: + print(" " + dir) # In the case of Android, we have to put the toolchain on the PATH in order to use it. if GetTarget() == 'android':