mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Fix building LOOT as a native Linux application.
Not all Windows-specific code has equivalent Linux code, file path to URL conversion is hacky, and only that LOOT launches correctly with no game detected has been tested.
This commit is contained in:
+37
-18
@@ -143,7 +143,7 @@ set (LOOT_HEADERS "${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_grammar.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/error.h")
|
||||
|
||||
set (LOOT_GUI_SRC ${LOOT_SRC}
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/main_win.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/main.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/handler.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_handler.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_app.cpp"
|
||||
@@ -213,7 +213,7 @@ include_directories ("${CMAKE_SOURCE_DIR}/src"
|
||||
${CEF_ROOT}
|
||||
"${LIBESPM_ROOT}/include"
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${YAML_CPP_INCLUDE_DIR}
|
||||
${YAML_CPP_INCLUDE_DIR}
|
||||
${GTEST_INCLUDE_DIRS}
|
||||
"${PSEUDOSEM_ROOT}/include")
|
||||
|
||||
@@ -255,6 +255,17 @@ IF (CMAKE_COMPILER_IS_GNUCXX)
|
||||
ssl
|
||||
curl
|
||||
loadorder${PROJECT_ARCH})
|
||||
set (LOOT_GUI_LIBS ${LOOT_LIBS}
|
||||
cef
|
||||
cef_dll_wrapper
|
||||
z
|
||||
crypto
|
||||
X11)
|
||||
|
||||
IF (NOT MINGW)
|
||||
link_directories("${CEF_ROOT}/Release")
|
||||
add_definitions(-DNDEBUG)
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
# MinGW settings.
|
||||
@@ -267,10 +278,8 @@ IF (MINGW)
|
||||
version
|
||||
ws2_32
|
||||
shlwapi)
|
||||
set (LOOT_GUI_LIBS ${LOOT_LIBS}
|
||||
set (LOOT_GUI_LIBS ${LOOT_GUI_LIBS}
|
||||
cef_sandbox
|
||||
libcef
|
||||
libcef_dll_wrapper
|
||||
rpcrt4
|
||||
comctl32)
|
||||
ELSEIF (MSVC)
|
||||
@@ -355,20 +364,30 @@ ENDIF ()
|
||||
# Post-Build Steps
|
||||
##############################
|
||||
|
||||
add_custom_command(
|
||||
TARGET LOOT
|
||||
POST_BUILD
|
||||
COMMAND "mt.exe" -manifest \"${CMAKE_SOURCE_DIR}/src/gui/LOOT.exe.manifest\" -inputresource:"$(TargetDir)$(TargetFileName)"\;\#1 -outputresource:"$(TargetDir)$(TargetFileName)"\;\#1
|
||||
COMMENT "Adding manifest..."
|
||||
)
|
||||
IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
add_custom_command(
|
||||
TARGET LOOT
|
||||
POST_BUILD
|
||||
COMMAND "mt.exe" -manifest \"${CMAKE_SOURCE_DIR}/src/gui/LOOT.exe.manifest\" -inputresource:"$(TargetDir)$(TargetFileName)"\;\#1 -outputresource:"$(TargetDir)$(TargetFileName)"\;\#1
|
||||
COMMENT "Adding manifest..."
|
||||
)
|
||||
|
||||
# Copy CEF binaries.
|
||||
FOREACH(cef_dll libcef.dll natives_blob.bin snapshot_blob.bin d3dcompiler_47.dll libEGL.dll libGLESv2.dll wow_helper.exe)
|
||||
add_custom_command(TARGET LOOT POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_SOURCE_DIR}/${CEF_ROOT}/$<CONFIGURATION>/${cef_dll}"
|
||||
$<TARGET_FILE_DIR:LOOT>/${cef_dll})
|
||||
ENDFOREACH()
|
||||
# Copy CEF binaries.
|
||||
FOREACH(cef_dll libcef.dll natives_blob.bin snapshot_blob.bin d3dcompiler_47.dll libEGL.dll libGLESv2.dll wow_helper.exe)
|
||||
add_custom_command(TARGET LOOT POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_SOURCE_DIR}/${CEF_ROOT}/$<CONFIGURATION>/${cef_dll}"
|
||||
$<TARGET_FILE_DIR:LOOT>/${cef_dll})
|
||||
ENDFOREACH()
|
||||
ELSE ()
|
||||
# Copy CEF binaries.
|
||||
FOREACH(cef_dll libcef.so natives_blob.bin snapshot_blob.bin chrome-sandbox)
|
||||
add_custom_command(TARGET LOOT POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_SOURCE_DIR}/${CEF_ROOT}/Release/${cef_dll}"
|
||||
$<TARGET_FILE_DIR:LOOT>/${cef_dll})
|
||||
ENDFOREACH()
|
||||
ENDIF ()
|
||||
|
||||
# Copy CEF resources.
|
||||
FOREACH(cef_resource icudtl.dat cef.pak cef_100_percent.pak cef_200_percent.pak devtools_resources.pak)
|
||||
|
||||
@@ -46,13 +46,26 @@ In addition, LOOT's UI relies on the web libraries below, which can be fetched b
|
||||
|
||||
### Building
|
||||
|
||||
Aside from Libespm and Pseudosem, the C/C++ libraries must be built separately. Instructions for building them and LOOT itself using Microsoft Visual Studio are given in [docs/BUILD.MSVC.md](docs/BUILD.MSVC.md).
|
||||
Instructions for building Windows binaries using Microsoft Visual Studio are given in [docs/BUILD.MSVC.md](docs/BUILD.MSVC.md), and instructions for building Linux binaries using GCC are given in [docs/BUILD.LINUX.md](docs/BUILD.LINUX.md).
|
||||
|
||||
The HTML UI is automatically built when building the LOOT executable, but it can also be built by running `node scripts/vulcanize.js` from the repository root.
|
||||
|
||||
### Cross-Platform Support
|
||||
#### CMake Variables
|
||||
|
||||
Although LOOT uses a cross-platform build system and cross-platform libraries, it does rely on some Windows API functionality. Anyone wishing to port LOOT to other platforms will need to ensure equivalent functionality is implemented for their target platform. The Windows API code is wrapped in `#ifdef _WIN32` blocks so that it can be easily identified.
|
||||
LOOT uses the following CMake variables to set build parameters:
|
||||
|
||||
Parameter | Values | Default |Description
|
||||
----------|--------|---------|-----------
|
||||
`BUILD_SHARED_LIBS` | `ON`, `OFF` | `OFF` | Whether or not to build a shared libloot.
|
||||
`PROJECT_STATIC_RUNTIME` | `ON`, `OFF` | `ON` | Whether to link the C++ runtime statically or not. This also affects the whether static or shared Boost libraries are used.
|
||||
`PROJECT_ARCH` | `32`, `64` | `32` | Whether to build 32 or 64 bit LOOT binaries.
|
||||
`CEF_ROOT` | path | `../../cef` | Path to the root of the Chromium Embedded Framework folder.
|
||||
`LIBESPM_ROOT` | path | `../../libespm` | Path to the root of the libespm repository folder.
|
||||
`LIBGIT2_ROOT` | path | `../../libgit2` | Path to the root of the libgit2 repository folder.
|
||||
`LIBLOADORDER_ROOT` | path | `../../libloadorder` | Path to the root of the libloadorder repository folder.
|
||||
`PSEUDOSEM_ROOT` | Path | `../../pseudosem` | Path to the root of the Pseudosem repository folder.
|
||||
|
||||
The default paths given in the table above are relative to LOOT's `CMakeLists.txt`.
|
||||
|
||||
## Packaging Releases
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# Build Instructions using GCC
|
||||
|
||||
Linux binaries can be built for LOOT, and these instructions are for doing so on
|
||||
Ubuntu Desktop 14.04, though they may also apply to other versions and
|
||||
distributions.
|
||||
|
||||
Most of the procedure for building the API, tests and metadata validator can be
|
||||
found in the `.travis.yml` file, which is the configuration file for LOOT's
|
||||
Travis CI instance. However, Travis instances have a few more libraries and
|
||||
utilities by default than Ubuntu Desktop 14.04 does, and the procedure does not
|
||||
cover building the GUI application, so these differences will be covered here.
|
||||
|
||||
Linux builds of the GUI application should be considered officially
|
||||
**unsupported and unmaintained**, though contributions are welcome.
|
||||
|
||||
## Installing Missing Dependencies
|
||||
|
||||
To install Node.js (for building the HTML UI) and the libcurl and X11
|
||||
development libraries (for libgit2 and the UI respectively), run the following:
|
||||
|
||||
```
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 68576280
|
||||
sudo apt-add-repository 'deb https://deb.nodesource.com/node_4.x precise main'
|
||||
sudo apt-get update
|
||||
sudo apt-get install nodejs npm libcurl4-openssl-dev libx11-dev
|
||||
sudo ln -s /usr/bin/nodejs /usr/bin/node
|
||||
sudo npm install -g bower vulcanize@0.7.11
|
||||
```
|
||||
|
||||
If you wish to build the GUI application, you must also manually download the
|
||||
Chromium Embedded Framework binary archive, then extract it and run
|
||||
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
from the extracted folder.
|
||||
|
||||
## Runtime Differences
|
||||
|
||||
Not all LOOT's features have been implemented for Linux builds. Issues labelled
|
||||
`linux` on LOOT's issue tracker cover such missing features where they can be
|
||||
implemented. Unavoidable platform differences are documented here:
|
||||
|
||||
* On Windows, LOOT can detect game installs using their Registry entries. On
|
||||
Linux this is obviously not possible, so either game paths will have to be
|
||||
entered manually in LOOT's settings dialog when it is run, or LOOT will need
|
||||
to be installed beside a game's Data folder for that game to be detected.
|
||||
@@ -69,21 +69,6 @@ Example CMake keys: `-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=build -DCMAKE_ARCHIVE_OUTP
|
||||
|
||||
LOOT uses a third-party CMake module to generate its build revision data, so first download the `GetGitRevisionDescription.cmake` and `GetGitRevisionDescription.cmake.in` files found in [this repository](https://github.com/rpavlik/cmake-modules) to the `build` subdirectory of the LOOT folder.
|
||||
|
||||
LOOT uses the following CMake variables to set build parameters:
|
||||
|
||||
Parameter | Values | Default |Description
|
||||
----------|--------|---------|-----------
|
||||
`BUILD_SHARED_LIBS` | `ON`, `OFF` | `OFF` | Whether or not to build a shared libloot.
|
||||
`PROJECT_STATIC_RUNTIME` | `ON`, `OFF` | `ON` | Whether to link the C++ runtime statically or not. This also affects the Boost libraries used.
|
||||
`PROJECT_ARCH` | `32`, `64` | `32` | Whether to build 32 or 64 bit LOOT binaries.
|
||||
`CEF_ROOT` | path | `../../cef` | Path to the root of the Chromium Embedded Framework folder.
|
||||
`LIBESPM_ROOT` | path | `../../libespm` | Path to the root of the libespm repository folder.
|
||||
`LIBGIT2_ROOT` | path | `../../libgit2` | Path to the root of the libgit2 repository folder.
|
||||
`LIBLOADORDER_ROOT` | path | `../../libloadorder` | Path to the root of the libloadorder repository folder.
|
||||
`PSEUDOSEM_ROOT` | Path | `../../pseudosem` | Path to the root of the Pseudosem repository folder.
|
||||
|
||||
The default paths given in the table above are relative to LOOT's `CMakeLists.txt`.
|
||||
|
||||
1. Set CMake up so that it builds the binaries in the `build` subdirectory of the LOOT folder.
|
||||
2. Define any necessary parameters.
|
||||
3. Configure CMake, then generate a build system for Visual Studio 12.
|
||||
|
||||
+59
-50
@@ -6,12 +6,9 @@
|
||||
var child_process = require('child_process');
|
||||
var path = require('path');
|
||||
var fs = require('fs-extra');
|
||||
var os = require('os');
|
||||
var helpers = require('./helpers');
|
||||
|
||||
function isApi64Bit(root_path) {
|
||||
return helpers.fileExists(path.join(root_path, 'build', 'Release', 'loot64.dll'));
|
||||
}
|
||||
|
||||
function vulcanize() {
|
||||
return child_process.execFileSync('node', [
|
||||
'scripts/vulcanize.js',
|
||||
@@ -28,7 +25,12 @@ function getGitDescription() {
|
||||
}
|
||||
|
||||
function compress(source_path, dest_path) {
|
||||
var sevenzip_path = path.join('C:\\', 'Program Files', '7-Zip', '7z.exe');
|
||||
var sevenzip_path = '';
|
||||
if (os.platform() == 'win32') {
|
||||
sevenzip_path = path.join('C:\\', 'Program Files', '7-Zip', '7z.exe');
|
||||
} else {
|
||||
sevenzip_path = '/usr/bin/7z';
|
||||
}
|
||||
|
||||
// First remove any existing archive.
|
||||
fs.removeSync(dest_path);
|
||||
@@ -43,32 +45,43 @@ function compress(source_path, dest_path) {
|
||||
]);
|
||||
}
|
||||
|
||||
function createAppArchive(dest_path) {
|
||||
function createAppArchive(release_path, dest_path) {
|
||||
// Ensure that the output directory is empty.
|
||||
fs.emptyDirSync(temp_path);
|
||||
|
||||
if (helpers.isMultiArch(root_path)) {
|
||||
var release_path = path.join(root_path, 'build', '32', 'Release');
|
||||
} else {
|
||||
var release_path = path.join(root_path, 'build', 'Release');
|
||||
}
|
||||
|
||||
// Copy LOOT exectuable and CEF files.
|
||||
[
|
||||
'LOOT.exe',
|
||||
'd3dcompiler_47.dll',
|
||||
'libEGL.dll',
|
||||
'libGLESv2.dll',
|
||||
'libcef.dll',
|
||||
'wow_helper.exe',
|
||||
'natives_blob.bin',
|
||||
'snapshot_blob.bin',
|
||||
'cef.pak',
|
||||
'cef_100_percent.pak',
|
||||
'cef_200_percent.pak',
|
||||
'devtools_resources.pak',
|
||||
'icudtl.dat'
|
||||
].forEach(function(file){
|
||||
var binaries = [];
|
||||
if (os.platform() == 'win32') {
|
||||
binaries = [
|
||||
'LOOT.exe',
|
||||
'd3dcompiler_47.dll',
|
||||
'libEGL.dll',
|
||||
'libGLESv2.dll',
|
||||
'libcef.dll',
|
||||
'wow_helper.exe',
|
||||
'natives_blob.bin',
|
||||
'snapshot_blob.bin',
|
||||
'cef.pak',
|
||||
'cef_100_percent.pak',
|
||||
'cef_200_percent.pak',
|
||||
'devtools_resources.pak',
|
||||
'icudtl.dat'
|
||||
];
|
||||
} else {
|
||||
binaries = [
|
||||
'LOOT',
|
||||
'chrome-sandbox',
|
||||
'libcef.so',
|
||||
'natives_blob.bin',
|
||||
'snapshot_blob.bin',
|
||||
'cef.pak',
|
||||
'cef_100_percent.pak',
|
||||
'cef_200_percent.pak',
|
||||
'devtools_resources.pak',
|
||||
'icudtl.dat'
|
||||
];
|
||||
}
|
||||
binaries.forEach(function(file){
|
||||
fs.copySync(
|
||||
path.join(release_path, file),
|
||||
path.join(temp_path, file)
|
||||
@@ -130,31 +143,15 @@ function createAppArchive(dest_path) {
|
||||
fs.removeSync(temp_path);
|
||||
}
|
||||
|
||||
function createApiArchive(dest_path) {
|
||||
function createApiArchive(binary_path, dest_path) {
|
||||
// Ensure that the output directory is empty.
|
||||
fs.emptyDirSync(temp_path);
|
||||
|
||||
// API binary/binaries.
|
||||
if (helpers.isMultiArch(root_path)) {
|
||||
fs.copySync(
|
||||
path.join(root_path, 'build', '32', 'Release', 'loot32.dll'),
|
||||
path.join(temp_path, 'loot32.dll')
|
||||
);
|
||||
fs.copySync(
|
||||
path.join(root_path, 'build', '64', 'Release', 'loot64.dll'),
|
||||
path.join(temp_path, 'loot64.dll')
|
||||
);
|
||||
} else if (isApi64Bit(root_path)) {
|
||||
fs.copySync(
|
||||
path.join(root_path, 'build', 'Release', 'loot64.dll'),
|
||||
path.join(temp_path, 'loot64.dll')
|
||||
);
|
||||
} else {
|
||||
fs.copySync(
|
||||
path.join(root_path, 'build', 'Release', 'loot32.dll'),
|
||||
path.join(temp_path, 'loot32.dll')
|
||||
);
|
||||
}
|
||||
fs.copySync(
|
||||
binary_path,
|
||||
path.join(temp_path, path.basename(binary_path))
|
||||
);
|
||||
|
||||
// API header file.
|
||||
fs.mkdirsSync(path.join(temp_path, 'include', 'loot'));
|
||||
@@ -191,5 +188,17 @@ var temp_path = path.join(root_path, 'build', 'archive.tmp');
|
||||
|
||||
var git_desc = getGitDescription();
|
||||
vulcanize();
|
||||
createAppArchive(path.join(root_path, 'build', 'LOOT ' + git_desc + '.7z'));
|
||||
createApiArchive(path.join(root_path, 'build', 'LOOT API ' + git_desc + '.7z'));
|
||||
|
||||
var release_paths = helpers.getAppReleasePaths(root_path);
|
||||
for (var i = 0; i < release_paths.length; ++i) {
|
||||
if (release_paths[i].label) {
|
||||
createAppArchive(release_paths[i].path, path.join(root_path, 'build', 'LOOT ' + git_desc + ' (' + release_paths[i].label + ').7z'));
|
||||
} else {
|
||||
createAppArchive(release_paths[i].path, path.join(root_path, 'build', 'LOOT ' + git_desc + '.7z'));
|
||||
}
|
||||
}
|
||||
|
||||
var binary_paths = helpers.getApiBinaryPaths(root_path);
|
||||
for (var i = 0; i < binary_paths.length; ++i) {
|
||||
createApiArchive(binary_paths[i].path, path.join(root_path, 'build', 'LOOT API ' + git_desc + ' (' + binary_paths[i].label + ').7z'));
|
||||
}
|
||||
|
||||
+94
-3
@@ -1,6 +1,7 @@
|
||||
// Helper functions shared across scripts.
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
|
||||
function fileExists(file_path) {
|
||||
try {
|
||||
@@ -16,9 +17,99 @@ function fileExists(file_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isMultiArch(root_path) {
|
||||
return fileExists(path.join(root_path, 'build', '64', 'Release', 'loot64.dll'));
|
||||
function getAppReleasePaths(root_path) {
|
||||
var paths = [];
|
||||
var file = 'LOOT';
|
||||
var paths_to_try = [
|
||||
{
|
||||
path: path.join(root_path, 'build'),
|
||||
label: null
|
||||
},
|
||||
{
|
||||
path: path.join(root_path, 'build', '32'),
|
||||
label: '32 bit'
|
||||
},
|
||||
{
|
||||
path: path.join(root_path, 'build', '64'),
|
||||
label: '64 bit'
|
||||
}
|
||||
];
|
||||
|
||||
if (os.platform() == 'win32') {
|
||||
file += '.exe';
|
||||
}
|
||||
|
||||
for (var i = 0; i < paths_to_try.length; ++i) {
|
||||
if (os.platform() == 'win32') {
|
||||
paths_to_try[i].path = path.join(paths_to_try[i].path, 'Release');
|
||||
}
|
||||
|
||||
if (fileExists(path.join(paths_to_try[i].path, file))) {
|
||||
paths.push(paths_to_try[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
function getApiBinaryPaths(root_path) {
|
||||
var paths = [];
|
||||
var files = [];
|
||||
var paths_to_try = [
|
||||
{
|
||||
path: path.join(root_path, 'build'),
|
||||
label: null
|
||||
},
|
||||
{
|
||||
path: path.join(root_path, 'build', '32'),
|
||||
label: '32 bit'
|
||||
},
|
||||
{
|
||||
path: path.join(root_path, 'build', '64'),
|
||||
label: '64 bit'
|
||||
}
|
||||
];
|
||||
|
||||
for (var i = 0; i < paths_to_try.length; ++i) {
|
||||
if (os.platform() == 'win32') {
|
||||
paths_to_try[i].path = path.join(paths_to_try[i].path, 'Release');
|
||||
|
||||
files = [
|
||||
{
|
||||
name: 'loot32.dll',
|
||||
label: '32 bit'
|
||||
},
|
||||
{
|
||||
name: 'loot64.dll',
|
||||
label: '64 bit'
|
||||
}
|
||||
];
|
||||
} else {
|
||||
files = [
|
||||
{
|
||||
name: 'libloot32.so',
|
||||
label: '32 bit'
|
||||
},
|
||||
{
|
||||
name: 'libloot64.so',
|
||||
label: '64 bit'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
for (var j = 0; j < files.length; ++j) {
|
||||
if (fileExists(path.join(paths_to_try[i].path, files[j].name))) {
|
||||
paths_to_try[i].path = path.join(paths_to_try[i].path, files[j].name);
|
||||
paths_to_try[i].label = files[j].label;
|
||||
paths.push(paths_to_try[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
module.exports.fileExists = fileExists;
|
||||
module.exports.isMultiArch = isMultiArch;
|
||||
module.exports.getAppReleasePaths = getAppReleasePaths;
|
||||
module.exports.getApiBinaryPaths = getApiBinaryPaths;
|
||||
|
||||
+27
-21
@@ -4,6 +4,7 @@
|
||||
var child_process = require('child_process');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
var helpers = require('./helpers');
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
@@ -12,27 +13,32 @@ if (process.argv.length < 3) {
|
||||
var root_path = process.argv[2];
|
||||
}
|
||||
|
||||
if (helpers.isMultiArch(root_path)) {
|
||||
var output_path = path.join(root_path, 'build', '32', 'Release', 'resources', 'ui');
|
||||
} else {
|
||||
var output_path = path.join(root_path, 'build', 'Release', 'resources', 'ui');
|
||||
}
|
||||
var release_paths = helpers.getAppReleasePaths(root_path);
|
||||
|
||||
// Makes sure output directory exists first.
|
||||
try {
|
||||
fs.mkdirSync(output_path);
|
||||
} catch (e) {
|
||||
if (e.code != 'EEXIST') {
|
||||
console.log(e);
|
||||
for (var i = 0; i < release_paths.length; ++i) {
|
||||
var output_path = path.join(release_paths[i].path, 'resources', 'ui');
|
||||
|
||||
// Makes sure output directory exists first.
|
||||
try {
|
||||
fs.mkdirSync(output_path);
|
||||
} catch (e) {
|
||||
if (e.code != 'EEXIST') {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
child_process.execFileSync('vulcanize.cmd', [
|
||||
'--inline',
|
||||
'--strip',
|
||||
'--config',
|
||||
path.join(root_path, 'scripts', 'vulcanize.config.json'),
|
||||
'-o',
|
||||
path.join(output_path, 'index.html'),
|
||||
path.join(root_path, 'src', 'gui', 'html', 'index.html')
|
||||
]);
|
||||
var vulcanize = 'vulcanize';
|
||||
if (os.platform() == 'win32') {
|
||||
vulcanize += '.cmd';
|
||||
}
|
||||
|
||||
child_process.execFileSync('vulcanize.cmd', [
|
||||
'--inline',
|
||||
'--strip',
|
||||
'--config',
|
||||
path.join(root_path, 'scripts', 'vulcanize.config.json'),
|
||||
'-o',
|
||||
path.join(output_path, 'index.html'),
|
||||
path.join(root_path, 'src', 'gui', 'html', 'index.html')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,37 @@ namespace loot {
|
||||
return out;
|
||||
}
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const fs::path& file) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Converting file path " << file << " to a URL.";
|
||||
string url;
|
||||
|
||||
#ifdef _WIN32
|
||||
wstring wstr(MAX_PATH, 0);
|
||||
DWORD len = MAX_PATH;
|
||||
UrlCreateFromPath(ToWinWide(file.string()).c_str(), &wstr[0], &len, NULL);
|
||||
url = FromWinWide(wstr.c_str()); // Passing c_str() cuts off any unused buffer.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Converted to: " << url;
|
||||
#else
|
||||
// Let's be naive about this.
|
||||
url = "file://" + file.string();
|
||||
#endif
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
//Opens the file in its registered default application.
|
||||
void OpenInDefaultApplication(const boost::filesystem::path& file) {
|
||||
#ifdef _WIN32
|
||||
HINSTANCE ret = ShellExecute(0, NULL, ToWinWide(file.string()).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
if ((int)ret <= 32)
|
||||
throw error(error::windows_error, lc::translate("Failed to open file in its default application."));
|
||||
#else
|
||||
if (system(("/usr/bin/xdg-open" + file.string()).c_str()) != 0)
|
||||
throw error(error::windows_error, lc::translate("Failed to open file in its default application."));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
//Get registry subkey value string.
|
||||
string RegKeyStringValue(const std::string& keyStr, const std::string& subkey, const std::string& value) {
|
||||
@@ -150,19 +181,6 @@ namespace loot {
|
||||
return fs::path("");
|
||||
}
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const fs::path& file) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Converting file path " << file << " to a URL.";
|
||||
|
||||
wstring wstr(MAX_PATH, 0);
|
||||
DWORD len = MAX_PATH;
|
||||
UrlCreateFromPath(ToWinWide(file.string()).c_str(), &wstr[0], &len, NULL);
|
||||
string str = FromWinWide(wstr.c_str()); // Passing c_str() cuts off any unused buffer.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Converted to: " << str;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//Helper to turn UTF8 strings into strings that can be used by WinAPI.
|
||||
std::wstring ToWinWide(const std::string& str) {
|
||||
size_t len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), 0, 0);
|
||||
|
||||
@@ -36,6 +36,12 @@ namespace loot {
|
||||
//Converts an unsigned 32-bit integer to a hex string using BOOST's Spirit.Karma. Faster than a stringstream conversion.
|
||||
std::string IntToHexString(const uint32_t n);
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const boost::filesystem::path& file);
|
||||
|
||||
//Opens the file in its registered default application.
|
||||
void OpenInDefaultApplication(const boost::filesystem::path& file);
|
||||
|
||||
#ifdef _WIN32
|
||||
//Get registry subkey value string.
|
||||
std::string RegKeyStringValue(const std::string& keyStr, const std::string& subkey, const std::string& value);
|
||||
@@ -43,9 +49,6 @@ namespace loot {
|
||||
//Get the local application data path, within which LOOT's data folder should be stored.
|
||||
boost::filesystem::path GetLocalAppDataPath();
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const boost::filesystem::path& file);
|
||||
|
||||
//Helper to turn UTF8 strings into strings that can be used by WinAPI.
|
||||
std::wstring ToWinWide(const std::string& str);
|
||||
|
||||
|
||||
+6
-7
@@ -180,7 +180,10 @@ namespace loot {
|
||||
// May be a request with arguments.
|
||||
YAML::Node req;
|
||||
try {
|
||||
req = JSON::parse(request.ToString());
|
||||
// Can't pass this as a reference directly as GCC
|
||||
// complains about it.
|
||||
std::string requestString = request.ToString();
|
||||
req = JSON::parse(requestString);
|
||||
}
|
||||
catch (exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to parse CEF query request \"" << request.ToString() << "\": " << e.what();
|
||||
@@ -568,17 +571,13 @@ namespace loot {
|
||||
void Handler::OpenReadme() {
|
||||
BOOST_LOG_TRIVIAL(info) << "Opening LOOT readme.";
|
||||
// Open readme in default application.
|
||||
HINSTANCE ret = ShellExecute(0, NULL, ToWinWide(ToFileURL(g_path_readme)).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
if ((int)ret <= 32)
|
||||
throw error(error::windows_error, loc::translate("Shell execute failed."));
|
||||
OpenInDefaultApplication(g_path_readme);
|
||||
}
|
||||
|
||||
void Handler::OpenLogLocation() {
|
||||
BOOST_LOG_TRIVIAL(info) << "Opening LOOT local appdata folder.";
|
||||
//Open debug log folder.
|
||||
HINSTANCE ret = ShellExecute(NULL, L"open", ToWinWide(g_path_log.parent_path().string()).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
if ((int)ret <= 32)
|
||||
throw error(error::windows_error, loc::translate("Shell execute failed."));
|
||||
OpenInDefaultApplication(g_path_log.parent_path());
|
||||
}
|
||||
|
||||
std::string Handler::GetVersion() {
|
||||
|
||||
@@ -248,10 +248,7 @@ namespace loot {
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Opening link in Windows' default handler.";
|
||||
// Open readme in default application.
|
||||
HINSTANCE ret = ShellExecute(0, NULL, request->GetURL().ToWString().c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
if ((int)ret <= 32)
|
||||
throw error(error::windows_error, "Shell execute failed.");
|
||||
OpenInDefaultApplication(fs::path(request->GetURL().ToString()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,8 @@ namespace loot {
|
||||
_initErrors.push_back((format(translate("Error: Games' settings parsing failed. %1%")) % e.what()).str());
|
||||
// Now redo, but with no games settings, so only the hardcoded defaults get loaded. It means the user can
|
||||
// at least still then edit them.
|
||||
_games = ToGames(GetGameSettings(YAML::Node()));
|
||||
YAML::Node node;
|
||||
_games = ToGames(GetGameSettings(node));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -369,7 +370,7 @@ namespace loot {
|
||||
// Conversion from 0.6 key.
|
||||
_settings["games"] = _settings["Games"];
|
||||
|
||||
for (auto &node : _settings["games"]) {
|
||||
for (auto node : _settings["games"]) {
|
||||
if (node["url"]) {
|
||||
node["repo"] = node["url"];
|
||||
node["branch"] = "v0.8";
|
||||
@@ -385,7 +386,7 @@ namespace loot {
|
||||
else {
|
||||
// Update existing default branches to new version default, if the
|
||||
// default repositories are used.
|
||||
for (auto &node : _settings["games"]) {
|
||||
for (auto node : _settings["games"]) {
|
||||
GameSettings settings(node.as<GameSettings>());
|
||||
|
||||
set<string> oldDefaultBranches({
|
||||
|
||||
@@ -26,8 +26,13 @@
|
||||
#include "loot_state.h"
|
||||
#include "../backend/globals.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <include/cef_sandbox_win.h>
|
||||
#else
|
||||
#include <X11/Xlib.h>
|
||||
#include "include/base/cef_logging.h"
|
||||
#endif
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
@@ -60,23 +65,49 @@ CefSettings GetCefSettings() {
|
||||
return cef_settings;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
namespace {
|
||||
int XErrorHandlerImpl(Display *display, XErrorEvent *event) {
|
||||
LOG(WARNING)
|
||||
<< "X error received: "
|
||||
<< "type " << event->type << ", "
|
||||
<< "serial " << event->serial << ", "
|
||||
<< "error_code " << static_cast<int>(event->error_code) << ", "
|
||||
<< "request_code " << static_cast<int>(event->request_code) << ", "
|
||||
<< "minor_code " << static_cast<int>(event->minor_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XIOErrorHandlerImpl(Display *display) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
|
||||
#else
|
||||
int main(int argc, char* argv[]) {
|
||||
#endif
|
||||
|
||||
// Do all the standard CEF setup stuff.
|
||||
//-------------------------------------
|
||||
|
||||
void * sandbox_info = nullptr;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Enable High-DPI support on Windows 7 or newer.
|
||||
CefEnableHighDPISupport();
|
||||
|
||||
// Set up CEF sandbox.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
void * sandbox_info = scoped_sandbox.sandbox_info();
|
||||
sandbox_info = scoped_sandbox.sandbox_info();
|
||||
|
||||
// Read command line arguments.
|
||||
#ifdef _WIN32
|
||||
CefMainArgs main_args(hInstance);
|
||||
#else
|
||||
// Read command line arguments.
|
||||
CefMainArgs main_args(argc, argv);
|
||||
#endif
|
||||
|
||||
// Create the process reference.
|
||||
@@ -89,6 +120,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmd
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Check if LOOT is already running
|
||||
//---------------------------------
|
||||
|
||||
@@ -103,6 +135,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmd
|
||||
//Create the mutex so that future instances will not run.
|
||||
hMutex = ::CreateMutex(NULL, FALSE, L"LOOT.Shell.Instance");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Handle command line args (not CEF args)
|
||||
//----------------------------------------
|
||||
@@ -125,25 +158,28 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmd
|
||||
|
||||
// Initialise CEF settings.
|
||||
CefSettings cef_settings = GetCefSettings();
|
||||
|
||||
#ifndef _WIN32
|
||||
// Install xlib error handlers so that the application won't be terminated
|
||||
// on non-fatal errors.
|
||||
XSetErrorHandler(XErrorHandlerImpl);
|
||||
XSetIOErrorHandler(XIOErrorHandlerImpl);
|
||||
#endif
|
||||
|
||||
// Initialize CEF.
|
||||
CefInitialize(main_args, cef_settings, app.get(), sandbox_info);
|
||||
|
||||
// Do application init
|
||||
//--------------------
|
||||
|
||||
// Run the CEF message loop. This will block until CefQuitMessageLoop() is called.
|
||||
CefRunMessageLoop();
|
||||
|
||||
// Shut down CEF.
|
||||
CefShutdown();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Release the program instance mutex.
|
||||
if (hMutex != NULL)
|
||||
ReleaseMutex(hMutex);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
}
|
||||
#endif
|
||||
@@ -25,8 +25,10 @@ along with LOOT. If not, see
|
||||
#ifndef __LOOT_GUI_RESOURCE__
|
||||
#define __LOOT_GUI_RESOURCE__
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
#define MAINICON 101
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user