diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ba3fb6..fe64a85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,12 @@ if (WIN32) link_directories("${PANDA_LIBRARY_DIRS}") else() + if(EXISTS "${LOCAL_PANDA_BUILD}") + set(PANDA_LIBRARY_DIRS "${LOCAL_PANDA_BUILD}/lib") + set(PANDA_INCLUDE_DIR "${LOCAL_PANDA_BUILD}/include") + set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};${PANDA_LIBRARY_DIRS}") + endif() + set(PYTHONVERDOT CACHE STRING "2.7") set(Python_ADDITIONAL_VERSIONS ${PYTHONVERDOT}) find_package(PythonLibs REQUIRED) @@ -210,7 +216,6 @@ else() if (NOT EXISTS ${PANDA_INCLUDE_DIR}) # Okay, the standard package handling failed. Try finding a local panda3d installation - # Find panda path execute_process( COMMAND "${PYTHON_EXECUTABLE}" "-B" "scripts/common.py" "--print-sdk-path" diff --git a/build.py b/build.py index fdadbbe..7ffa13a 100755 --- a/build.py +++ b/build.py @@ -8,6 +8,48 @@ import argparse from os.path import join, realpath, dirname +# Configure Logging Module +import logging + +# Custom logging formatter +VERBOSE = logging.INFO - 1 # INFO== for verbose logging + +class CustomLogFormatter(logging.Formatter): + err_fmt = "ERROR: %(message)s" + dbg_fmt = "DEBUG: %(module)s: %(lineno)d: %(message)s" + info_fmt = "%(message)s" + + def __init__(self, fmt="%(msg)s"): + logging.Formatter.__init__(self, fmt) + + def format(self, record): + format_orig = self._fmt + if record.levelno == logging.DEBUG: + self._fmt = CustomLogFormatter.dbg_fmt +# elif record.levelno in (logging.INFO, VERBOSE): +# self._fmt = CustomLogFormatter.info_fmt + elif record.levelno == logging.ERROR: + self._fmt = CustomLogFormatter.err_fmt + result = super().format(record) + self._fmt = format_orig + return result + +logging.addLevelName(VERBOSE, 'VERBOSE') +# -logger - add custom loglevel +def verbose(self, message, *args, **kwargs): + # Yes, logger takes its '*args' as 'args'. + if self.isEnabledFor(VERBOSE): + self._log(VERBOSE, message, args, **kwargs) +#add method for verbose logging +logging.Logger.verbose = verbose +custom_log_format = CustomLogFormatter() +handler_hook = logging.StreamHandler() +handler_hook.setFormatter(custom_log_format) +logging.basicConfig(level=logging.DEBUG, + format='%(message)s', + handlers=[handler_hook]) +logger = logging.getLogger(__name__) + # Change into the current directory os.chdir(dirname(realpath(__file__))) @@ -15,7 +57,6 @@ from scripts.setup import make_output_dir, run_cmake, run_cmake_build if __name__ == "__main__": - # Arguments parser = argparse.ArgumentParser(description="P3DModuleBuilder") parser.add_argument( @@ -23,8 +64,15 @@ help="Optimize level, should match the one used for the Panda3D build",) parser.add_argument( "--clean", action="store_true", help="Forces a clean rebuild") + parser.add_argument('--debug', action='store_true') + parser.add_argument('--verbose', action='store_true') args = parser.parse_args() + if args.debug: + logger.setLevel(logging.DEBUG) + elif args.verbose: + logger.setLevel(VERBOSE) + # Python 2 compatibility if sys.version_info.major > 2: raw_input = input @@ -40,7 +88,7 @@ # Check for outdated parameters for outdated_param in ["vc_version", "use_lib_eigen", "use_lib_bullet", "use_lib_freetype"]: if outdated_param in config: - print("WARNING: Removing obsolete parameter '" + outdated_param + "', is now auto-detected.") + logger.warn("Removing obsolete parameter '" + outdated_param + "', is now auto-detected.") del config[outdated_param] # Write back config @@ -51,5 +99,4 @@ run_cmake(config, args) run_cmake_build(config, args) - print("Success!") - sys.exit(0) + logger.info("Success!") diff --git a/scripts/common.py b/scripts/common.py index 0302f68..cbf2a6f 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -6,16 +6,29 @@ from __future__ import print_function +import logging +logger = logging.getLogger(__name__) + import locale import sys import subprocess import platform from os.path import dirname, realpath, join, isdir, isfile -from os import makedirs +from os import makedirs, environ from sys import argv, stdout, stderr, exit from panda3d.core import PandaSystem, Filename, ExecutionEnvironment +build_path_envvar = 'LOCAL_PANDA_BUILD' + +class FatalError(Exception): + """FatalError + Exception to raise fatal errors instead of calling exit + """ + msgs = None + def __init__(self, *msgs): + super().__init__(msgs[0]) + self.msgs = msgs class MSVCVersion(object): def __init__(self, msc_ver, cmake_str, suffix): @@ -86,6 +99,8 @@ def is_installed_via_pip(): def get_panda_sdk_path(): """ Returns the path of the panda3d sdk, under windows """ + if build_path_envvar in environ: + return environ[build_path_envvar] # Import the base panda3d module import panda3d @@ -102,6 +117,10 @@ def get_panda_sdk_path(): def get_panda_core_lib_path(): """ Returns of the path of the core panda3d module, either core.pyd on windows or core.so on linux. This is an absolute path """ + # NOTE: this may be completely different than the local build + # but even if it is the local build core and the import core + # **should** be identical. If they aren't then the developer + # should get a warning so s/he knows about it. import panda3d.core return panda3d.core.__file__ @@ -112,6 +131,8 @@ def find_in_sdk(folder, filename, on_error=""): def get_panda_bin_path(): """ Returns the path to the panda3d binaries """ + if build_path_envvar in environ: + return join(environ[build_path_envvar], 'bin') if is_windows(): return find_in_sdk("bin", "interrogate.exe", on_error="Failed to find binary path") elif is_linux() or is_freebsd(): @@ -129,6 +150,8 @@ def get_panda_bin_path(): def get_panda_lib_path(): """ Returns the path to the panda3d libraries """ + if build_path_envvar in environ: + return join(environ[build_path_envvar], 'lib') if is_windows(): return find_in_sdk("lib", "libpanda.lib") elif is_linux() or is_macos() or is_freebsd(): @@ -138,6 +161,8 @@ def get_panda_lib_path(): def get_panda_include_path(): """ Returns the path to the panda3d includes """ + if build_path_envvar in environ: + return join(environ[build_path_envvar], 'include') if is_windows() or is_macos(): return find_in_sdk("include", "dtoolbase.h") elif is_linux() or is_freebsd(): @@ -209,18 +234,18 @@ def decode_str(s): def fatal_error(*args): """ Prints an error to stderr and then exits with a nonzero status code """ - print("\n\n[!] FATAL ERROR:", *[decode_str(i) for i in args], file=stderr) - exit(1) + logger.error(' '.join('FATAL: ', *[decode_str(i) for i in args])) + raise FatalError(args) def debug_out(*args): """ Prints a debug output string """ - print(*[decode_str(i) for i in args]) + logger.debug(''.join([decode_str(i) for i in args])) def print_error(*args): """ Prints a debug output string """ - print(*[decode_str(i) for i in args], file=sys.stderr) + logger.error(' '.join([decode_str(i) for i in args])) def try_makedir(dirname): @@ -288,13 +313,12 @@ def get_panda_msvc_version(): if msvc_version.compiler_search_string in compiler: return msvc_version - print("FATAL ERROR: Unable to detect visual studio version of your Panda3D Build!", file=sys.stderr) - print("Unkown compiler string was: '" + compiler + "'", file=sys.stderr) - print("", file=sys.stderr) - print("Known visual studio versions are:", file=sys.stderr) + logger.error("FATAL ERROR: Unable to detect visual studio version of your Panda3D Build!") + logger.error("Unkown compiler string was: '" + compiler + "'") + logger.error("Known visual studio versions are:") for msvc_version in MSVC_VERSIONS: - print("-", msvc_version.cmake_str, "(" + msvc_version.compiler_search_string + ")", file=sys.stderr) - print("", file=sys.stderr) + logger.error("-", msvc_version.cmake_str, "(" + msvc_version.compiler_search_string + ")") + logger.error("") fatal_error("Unable to determine compiler") def get_panda_short_version(): diff --git a/scripts/interrogate.py b/scripts/interrogate.py index 0fbd824..29a9a4e 100644 --- a/scripts/interrogate.py +++ b/scripts/interrogate.py @@ -8,6 +8,8 @@ import sys from os import listdir, chdir from os.path import join, isfile, isdir +import logging +logger = logging.getLogger(__name__) from panda3d.core import PandaSystem from common import debug_out, get_panda_bin_path, get_panda_include_path @@ -19,8 +21,9 @@ # Parameters -MODULE_NAME = sys.argv[1] -VERBOSE_LVL = int(sys.argv[2]) # Assume the user did specify something valid +#set with __main__ or caller, don't default +MODULE_NAME = None +VERBOSE_LVL = None def check_ignore(source): @@ -128,8 +131,20 @@ def interrogate_module(): if __name__ == "__main__": + # Parameters + # TODO: add reall param processing + loglevel = logging.INFO + param_offset = 0 + if sys.argv[1] == '-d' or sys.argv[1] == '--debug': + loglevel = logging.DEBUG + param_offset+=1 + logging.basicConfig(level=loglevel) + + MODULE_NAME = sys.argv[1+param_offset] + VERBOSE_LVL = int(sys.argv[2+param_offset]) + # Change into the source directory - source_dir = join(get_script_dir(), "../source/") + source_dir = join(get_script_dir(), '..', 'source') chdir(source_dir) interrogate() diff --git a/scripts/setup.py b/scripts/setup.py index 4126b87..3e831ca 100644 --- a/scripts/setup.py +++ b/scripts/setup.py @@ -2,15 +2,18 @@ import shutil import sys import multiprocessing -from os import chdir, _exit +from os import chdir, _exit, environ from os.path import isdir, isfile +import logging +logger = logging.getLogger(__name__) + from panda3d.core import PandaSystem from .common import get_output_dir, try_makedir, fatal_error, is_windows from .common import is_linux, join_abs, get_panda_lib_path, is_64_bit from .common import try_execute, get_script_dir, get_panda_msvc_version from .common import have_eigen, have_bullet, have_freetype, print_error -from .common import is_macos, is_freebsd, is_installed_via_pip +from .common import is_macos, is_freebsd, build_path_envvar, is_installed_via_pip from .common import get_win_thirdparty_dir @@ -21,7 +24,7 @@ def make_output_dir(clean=False): # Cleanup output directory in case clean is specified if isdir(output_dir) and clean: - print("Cleaning up output directory ..") + logger.info("Cleaning up output directory ..") shutil.rmtree(output_dir) try_makedir(output_dir) @@ -92,6 +95,10 @@ def run_cmake(config, args): # Panda is 64-bit only on macOS. cmake_args += ["-DCMAKE_CL_64:STRING=1"] + if build_path_envvar in environ: + cmake_args.append("-D{}:STRING={}".format(build_path_envvar, + environ[build_path_envvar])) + # Specify python version, once as integer, once seperated by a dot pyver = "{}{}".format(sys.version_info.major, sys.version_info.minor) pyver_dot = "{}.{}".format(sys.version_info.major, sys.version_info.minor) @@ -121,12 +128,12 @@ def is_required(lib): """ # Eigen is always included in 1.9.1 and up cmake_args += ["-DHAVE_LIB_EIGEN=TRUE"] - + if is_required("bullet"): if not have_bullet(): fatal_error("Your Panda3D build was not compiled with bullet support, but it is required!") cmake_args += ["-DHAVE_LIB_BULLET=TRUE"] - + if is_required("freetype"): if not have_freetype(): fatal_error("Your Panda3D build was not compiled with freetype support, but it is required!")