mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
deploy-ng: support logging via log_filename (and log_append) setting
This commit is contained in:
parent
f5932bf070
commit
742c143a01
@ -1642,7 +1642,8 @@ class Freezer:
|
||||
|
||||
return target
|
||||
|
||||
def generateRuntimeFromStub(self, target, stub_file, use_console, fields={}):
|
||||
def generateRuntimeFromStub(self, target, stub_file, use_console, fields={},
|
||||
log_append=False):
|
||||
# We must have a __main__ module to make an exe file.
|
||||
if not self.__writingModule('__main__'):
|
||||
message = "Can't generate an executable without a __main__ module."
|
||||
@ -1735,7 +1736,7 @@ class Freezer:
|
||||
|
||||
# Determine the format of the header and module list entries depending
|
||||
# on the platform.
|
||||
num_pointers = 11
|
||||
num_pointers = 12
|
||||
stub_data = bytearray(stub_file.read())
|
||||
bitnesses = self._get_executable_bitnesses(stub_data)
|
||||
|
||||
@ -1808,6 +1809,10 @@ class Freezer:
|
||||
# A null entry marks the end of the module table.
|
||||
blob += struct.pack(entry_layout, 0, 0, 0)
|
||||
|
||||
flags = 0
|
||||
if log_append:
|
||||
flags |= 1
|
||||
|
||||
# Compose the header we will be writing to the stub, to tell it
|
||||
# where to find the module data blob, as well as other variables.
|
||||
header = struct.pack(header_layout,
|
||||
@ -1816,7 +1821,7 @@ class Freezer:
|
||||
1, # Version number
|
||||
num_pointers, # Number of pointers that follow
|
||||
0, # Codepage, not yet used
|
||||
0, # Flags, not yet used
|
||||
flags,
|
||||
table_offset, # Module table pointer.
|
||||
# The following variables need to be set before static init
|
||||
# time. See configPageManager.cxx, where they are read.
|
||||
@ -1830,6 +1835,7 @@ class Freezer:
|
||||
field_offsets.get('prc_executable_patterns', 0),
|
||||
field_offsets.get('prc_executable_args_envvar', 0),
|
||||
field_offsets.get('main_dir', 0),
|
||||
field_offsets.get('log_filename', 0),
|
||||
0)
|
||||
|
||||
# Now, find the location of the 'blobinfo' symbol in the binary,
|
||||
|
@ -11,6 +11,7 @@ import shutil
|
||||
import struct
|
||||
import io
|
||||
import imp
|
||||
import string
|
||||
|
||||
import distutils.core
|
||||
import distutils.log
|
||||
@ -86,6 +87,8 @@ class build_apps(distutils.core.Command):
|
||||
self.extra_prc_files = []
|
||||
self.extra_prc_data = ''
|
||||
self.default_prc_dir = None
|
||||
self.log_filename = None
|
||||
self.log_append = False
|
||||
self.requirements_path = './requirements.txt'
|
||||
self.pypi_extra_indexes = []
|
||||
self.file_handlers= {
|
||||
@ -382,7 +385,9 @@ class build_apps(distutils.core.Command):
|
||||
'prc_encryption_key': None,
|
||||
'prc_executable_patterns': None,
|
||||
'prc_executable_args_envvar': None,
|
||||
})
|
||||
'main_dir': None,
|
||||
'log_filename': self.expand_path(self.log_filename, platform),
|
||||
}, self.log_append)
|
||||
stub_file.close()
|
||||
|
||||
# Copy the dependencies.
|
||||
@ -818,6 +823,20 @@ class build_apps(distutils.core.Command):
|
||||
|
||||
return deps
|
||||
|
||||
def expand_path(self, path, platform):
|
||||
"Substitutes variables in the given path string."
|
||||
|
||||
if path is None:
|
||||
return None
|
||||
|
||||
t = string.Template(path)
|
||||
if platform.startswith('win'):
|
||||
return t.substitute(HOME='~', USER_APPDATA='~/AppData/Local')
|
||||
elif platform.startswith('macosx'):
|
||||
return t.substitute(HOME='~', USER_APPDATA='~/Documents')
|
||||
else:
|
||||
return t.substitute(HOME='~', USER_APPDATA='~/.local/share')
|
||||
|
||||
|
||||
class bdist_apps(distutils.core.Command):
|
||||
DEFAULT_INSTALLERS = {
|
||||
|
@ -115,6 +115,7 @@ reload_implicit_pages() {
|
||||
const char *prc_executable_patterns;
|
||||
const char *prc_executable_args_envvar;
|
||||
const char *main_dir;
|
||||
const char *log_filename;
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
const BlobInfo *blobinfo = (const BlobInfo *)GetProcAddress(GetModuleHandle(NULL), "blobinfo");
|
||||
|
@ -6712,12 +6712,12 @@ if PkgSkip("PYTHON") == 0:
|
||||
TargetAdd('deploy-stub.exe', input='deploy-stub.obj')
|
||||
if GetTarget() == 'windows':
|
||||
TargetAdd('deploy-stub.exe', input='frozen_dllmain.obj')
|
||||
TargetAdd('deploy-stub.exe', opts=['PYTHON', 'DEPLOYSTUB', 'NOICON'])
|
||||
TargetAdd('deploy-stub.exe', opts=['WINSHELL', 'PYTHON', 'DEPLOYSTUB', 'NOICON'])
|
||||
|
||||
if GetTarget() == 'windows':
|
||||
TargetAdd('deploy-stubw.exe', input='deploy-stub.obj')
|
||||
TargetAdd('deploy-stubw.exe', input='frozen_dllmain.obj')
|
||||
TargetAdd('deploy-stubw.exe', opts=['SUBSYSTEM:WINDOWS', 'PYTHON', 'DEPLOYSTUB', 'NOICON'])
|
||||
TargetAdd('deploy-stubw.exe', opts=['SUBSYSTEM:WINDOWS', 'WINSHELL', 'PYTHON', 'DEPLOYSTUB', 'NOICON'])
|
||||
elif GetTarget() == 'darwin':
|
||||
DefSymbol('MACOS_APP_BUNDLE', 'MACOS_APP_BUNDLE')
|
||||
OPTS = OPTS + ['MACOS_APP_BUNDLE']
|
||||
|
@ -3,8 +3,10 @@
|
||||
#include "Python.h"
|
||||
#ifdef _WIN32
|
||||
# include "malloc.h"
|
||||
# include <Shlobj.h>
|
||||
#else
|
||||
# include <sys/mman.h>
|
||||
# include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
@ -18,6 +20,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
# include <locale.h>
|
||||
@ -31,6 +34,11 @@
|
||||
other pointers that are being read by configPageManager.cxx. */
|
||||
#define MAX_NUM_POINTERS 24
|
||||
|
||||
/* Stored in the flags field of the blobinfo structure below. */
|
||||
enum Flags {
|
||||
F_log_append = 1,
|
||||
};
|
||||
|
||||
/* Define an exposed symbol where we store the offset to the module data. */
|
||||
#ifdef _MSC_VER
|
||||
__declspec(dllexport)
|
||||
@ -113,6 +121,206 @@ static void set_main_dir(char *main_dir) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the parent directories of the given path. Returns 1 on success.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
static int mkdir_parent(const wchar_t *path) {
|
||||
// Copy the path to a temporary buffer.
|
||||
wchar_t buffer[4096];
|
||||
size_t buflen = wcslen(path);
|
||||
if (buflen + 1 >= _countof(buffer)) {
|
||||
return 0;
|
||||
}
|
||||
wcscpy_s(buffer, _countof(buffer), path);
|
||||
|
||||
// Seek back to find the last path separator.
|
||||
while (buflen-- > 0) {
|
||||
if (buffer[buflen] == '/' || buffer[buflen] == '\\') {
|
||||
buffer[buflen] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buflen == 0) {
|
||||
// There was no path separator.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CreateDirectoryW(buffer, NULL) != 0) {
|
||||
// Success!
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Failed.
|
||||
DWORD last_error = GetLastError();
|
||||
if (last_error == ERROR_ALREADY_EXISTS) {
|
||||
// Not really an error: the directory is already there.
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (last_error == ERROR_PATH_NOT_FOUND) {
|
||||
// We need to make the parent directory first.
|
||||
if (mkdir_parent(buffer)) {
|
||||
// Parent successfully created. Try again to make the child.
|
||||
if (CreateDirectoryW(buffer, NULL) != 0) {
|
||||
// Got it!
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int mkdir_parent(const char *path) {
|
||||
// Copy the path to a temporary buffer.
|
||||
char buffer[4096];
|
||||
size_t buflen = strlen(path);
|
||||
if (buflen + 1 >= sizeof(buffer)) {
|
||||
return 0;
|
||||
}
|
||||
strcpy(buffer, path);
|
||||
|
||||
// Seek back to find the last path separator.
|
||||
while (buflen-- > 0) {
|
||||
if (buffer[buflen] == '/') {
|
||||
buffer[buflen] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buflen == 0) {
|
||||
// There was no path separator.
|
||||
return 0;
|
||||
}
|
||||
if (mkdir(buffer, 0755) == 0) {
|
||||
// Success!
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Failed.
|
||||
if (errno == EEXIST) {
|
||||
// Not really an error: the directory is already there.
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (errno == ENOENT || errno == EACCES) {
|
||||
// We need to make the parent directory first.
|
||||
if (mkdir_parent(buffer)) {
|
||||
// Parent successfully created. Try again to make the child.
|
||||
if (mkdir(buffer, 0755) == 0) {
|
||||
// Got it!
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Redirects the output streams to point to the log file with the given path.
|
||||
*
|
||||
* @param path specifies the location of log file, may start with ~
|
||||
* @param append should be nonzero if it should not truncate the log file.
|
||||
*/
|
||||
static int setup_logging(const char *path, int append) {
|
||||
#ifdef _WIN32
|
||||
// Does it start with a tilde? Perform tilde expansion if so.
|
||||
wchar_t pathw[MAX_PATH * 2];
|
||||
size_t offset = 0;
|
||||
if (path[0] == '~' && (path[1] == 0 || path[1] == '/' || path[1] == '\\')) {
|
||||
// Strip off the tilde.
|
||||
++path;
|
||||
|
||||
// Get the home directory path for the current user.
|
||||
if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, pathw))) {
|
||||
return 0;
|
||||
}
|
||||
offset = wcslen(pathw);
|
||||
}
|
||||
|
||||
// We need to convert the rest of the path from UTF-8 to UTF-16.
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, path, -1, pathw + offset,
|
||||
(int)(_countof(pathw) - offset)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD access = append ? FILE_APPEND_DATA : (GENERIC_READ | GENERIC_WRITE);
|
||||
int creation = append ? OPEN_ALWAYS : CREATE_ALWAYS;
|
||||
HANDLE handle = CreateFileW(pathw, access, FILE_SHARE_DELETE | FILE_SHARE_READ,
|
||||
NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
// Make the parent directories first.
|
||||
mkdir_parent(pathw);
|
||||
handle = CreateFileW(pathw, access, FILE_SHARE_DELETE | FILE_SHARE_READ,
|
||||
NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (append) {
|
||||
SetFilePointer(handle, 0, NULL, FILE_END);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
int fd = _open_osfhandle((intptr_t)handle, _O_WRONLY | _O_TEXT | (append ? _O_APPEND : 0));
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, handle);
|
||||
_dup2(fd, 1);
|
||||
|
||||
SetStdHandle(STD_ERROR_HANDLE, handle);
|
||||
_dup2(fd, 2);
|
||||
|
||||
_close(fd);
|
||||
return 1;
|
||||
#else
|
||||
// Does it start with a tilde? Perform tilde expansion if so.
|
||||
char buffer[PATH_MAX * 2];
|
||||
size_t offset = 0;
|
||||
if (path[0] == '~' && (path[1] == 0 || path[1] == '/')) {
|
||||
// Strip off the tilde.
|
||||
++path;
|
||||
|
||||
// Get the home directory path for the current user.
|
||||
const char *home_dir = getenv("HOME");
|
||||
if (home_dir == NULL) {
|
||||
home_dir = getpwuid(getuid())->pw_dir;
|
||||
}
|
||||
offset = strlen(home_dir);
|
||||
assert(offset < sizeof(buffer));
|
||||
strncpy(buffer, home_dir, sizeof(buffer));
|
||||
}
|
||||
|
||||
// Copy over the rest of the path.
|
||||
strcpy(buffer + offset, path);
|
||||
|
||||
mode_t mode = O_CREAT | O_WRONLY | (append ? O_APPEND : O_TRUNC);
|
||||
int fd = open(buffer, mode, 0644);
|
||||
if (fd == -1) {
|
||||
// Make the parent directories first.
|
||||
mkdir_parent(buffer);
|
||||
fd = open(buffer, mode, 0644);
|
||||
}
|
||||
|
||||
if (fd == -1) {
|
||||
perror(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2);
|
||||
|
||||
close(fd);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Main program */
|
||||
|
||||
#ifdef WIN_UNICODE
|
||||
@ -389,7 +597,9 @@ int main(int argc, char *argv[]) {
|
||||
#endif
|
||||
int retval;
|
||||
struct _frozen *moddef;
|
||||
const char *log_filename;
|
||||
void *blob = NULL;
|
||||
log_filename = NULL;
|
||||
|
||||
/*
|
||||
printf("blob_offset: %d\n", (int)blobinfo.blob_offset);
|
||||
@ -418,6 +628,9 @@ int main(int argc, char *argv[]) {
|
||||
blobinfo.pointers[i] = (void *)((uintptr_t)blobinfo.pointers[i] + (uintptr_t)blob);
|
||||
}
|
||||
}
|
||||
if (blobinfo.num_pointers >= 12) {
|
||||
log_filename = blobinfo.pointers[11];
|
||||
}
|
||||
} else {
|
||||
blobinfo.pointers[0] = blob;
|
||||
}
|
||||
@ -434,6 +647,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (log_filename != NULL) {
|
||||
setup_logging(log_filename, (blobinfo.flags & F_log_append) != 0);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (blobinfo.codepage != 0) {
|
||||
SetConsoleCP(blobinfo.codepage);
|
||||
|
@ -12,6 +12,8 @@ setup(
|
||||
'gui_apps': {
|
||||
'asteroids': 'main.py',
|
||||
},
|
||||
'log_filename': '$USER_APPDATA/Asteroids/output.log',
|
||||
'log_append': False,
|
||||
'plugins': [
|
||||
'pandagl',
|
||||
'p3openal_audio',
|
||||
|
Loading…
x
Reference in New Issue
Block a user