diff --git a/cpp/server/CMakeLists.txt b/cpp/server/CMakeLists.txt index 76aa80f3..ea1e78b4 100644 --- a/cpp/server/CMakeLists.txt +++ b/cpp/server/CMakeLists.txt @@ -211,14 +211,6 @@ endif() if(ENABLE_TESTS) add_subdirectory(tests) - - if(IS_MULTI_CONFIG) - set(CONFIG_JSON ${CMAKE_CURRENT_BINARY_DIR}/$/config.json) - else() - set(CONFIG_JSON ${CMAKE_CURRENT_BINARY_DIR}/config.json) - endif() - - file(GENERATE OUTPUT ${CONFIG_JSON} CONTENT "{\"webRoot\":\"${WEBUI_OUTPUT_DIR}\"}") endif() print_toolchain_flags() diff --git a/cpp/server/settings.cpp b/cpp/server/settings.cpp index 29adb35e..a102d52d 100644 --- a/cpp/server/settings.cpp +++ b/cpp/server/settings.cpp @@ -127,6 +127,8 @@ bool SettingsData::isAllowedPath(const Path& path) const void SettingsData::initialize(const Path& resourceDir, const Path& profileDir) { + logDebug("init settings: resourceDir = %s, profileDir = %s", resourceDir.c_str(), profileDir.c_str()); + assert(!resourceDir.empty()); assert(!profileDir.empty()); diff --git a/js/api_tests/src/install_plugin.js b/js/api_tests/src/install_plugin.js new file mode 100755 index 00000000..7347c5ce --- /dev/null +++ b/js/api_tests/src/install_plugin.js @@ -0,0 +1,150 @@ +#!/usr/bin/env node + +import mkdirp from 'mkdirp'; +import fs from 'fs/promises'; +import path from 'path'; +import { buildTypes, getBuildConfig, getBuildType } from '../../build_config.mjs' +import { callBySystem, tryStat, rimraf } from './utils.js'; + +function getSymlinks(buildConfig) +{ + const webRoot = 'beefweb.root'; + + return callBySystem({ + windows() + { + const installDir = path.join( + process.env.APPDATA, + 'foobar2000-v2', + 'user-components-x64', + 'foo_beefweb'); + + const pluginFile = 'foo_beefweb.dll'; + + return [ + { + from: path.join(installDir, pluginFile), + to: path.join(buildConfig.pluginBuildDir.foobar2000, pluginFile), + }, + { + from: path.join(installDir, webRoot), + to: buildConfig.webBuildDir, + } + ]; + }, + + mac() + { + const fooPluginFile = 'foo_beefweb.component'; + const ddbPluginFile = 'beefweb.dylib'; + + const fooInstallDir = path.join( + process.env.HOME, + 'Library', + 'foobar2000-v2', + 'user-components', + 'foo_beefweb'); + + const ddbInstallDir = path.join( + process.env.HOME, + 'Library', + 'Application Support', + 'Deadbeef', + 'Plugins'); + + return [ + { + from: path.join(fooInstallDir, fooPluginFile), + to: path.join(buildConfig.pluginBuildDir.foobar2000, fooPluginFile), + }, + { + from: path.join(buildConfig.pluginBuildDir.foobar2000, fooPluginFile, 'Contents', 'Resources', webRoot), + to: buildConfig.webBuildDir, + }, + { + from: path.join(ddbInstallDir, ddbPluginFile), + to: path.join(buildConfig.pluginBuildDir.deadbeef, ddbPluginFile), + }, + { + from: path.join(buildConfig.pluginBuildDir.deadbeef, webRoot), + to: buildConfig.webBuildDir, + } + ]; + }, + + posix() + { + const pluginFile = 'beefweb.so'; + + const installDir = path.join( + process.env.HOME, + '.local', + 'lib', + 'deadbeef'); + + return [ + { + from: path.join(installDir, pluginFile), + to: path.join(buildConfig.pluginBuildDir.deadbeef, pluginFile), + }, + { + from: path.join(installDir, webRoot), + to: buildConfig.webBuildDir, + } + ]; + } + }); +} + +async function run(buildTypeRaw) +{ + const buildType = getBuildType(buildTypeRaw); + if (!buildType) + throw new Error(`Invalid build type: ${buildTypeRaw}`); + + const buildConfig = getBuildConfig(buildType); + + for (let link of getSymlinks(buildConfig)) + { + const { from, to } = link; + + if (await tryStat(from)) + { + console.error(`removing ${from}`); + await rimraf(from); + } + + console.error(`adding link ${from} -> ${to}`); + await mkdirp(path.dirname(from)); + await fs.symlink(to, from); + } +} + +async function main() +{ + if (process.argv.length !== 3) + { + console.error('Usage:'); + console.error(' install_app.js install locally built plugin (via symlinks)'); + console.error(); + console.error('Build types:'); + console.error(' ' + Object.values(buildTypes).join(' ')); + console.error(); + console.error('Warning:'); + console.error(' Existing installed plugin will be removed without backup'); + return process.argv.length > 3 ? 1 : 0; + } + + try + { + await run(process.argv[2]); + return 0; + } + catch (e) + { + console.error(e); + return 1; + } +} + +main().then(exitCode => process.exit(exitCode)); diff --git a/js/api_tests/src/test_context.js b/js/api_tests/src/test_context.js index 876d4dc4..b93e4c10 100644 --- a/js/api_tests/src/test_context.js +++ b/js/api_tests/src/test_context.js @@ -1,6 +1,6 @@ import path from 'path' import fsObj from 'fs'; -import { getBuildConfig } from '../../config.mjs'; +import { getBuildConfig, getPluginBuildDir } from '../../build_config.mjs'; import RequestHandler from './request_handler.js'; import TestPlayerClient from './test_player_client.js'; import { testsRootDir } from './utils.js'; @@ -151,13 +151,7 @@ export class TestContextFactory { const buildType = process.env.BEEFWEB_TEST_BUILD_TYPE || 'Debug'; const port = parseInt(process.env.BEEFWEB_TEST_PORT) || 8879; - const { buildDir, isMultiConfig } = getBuildConfig(buildType); - const pluginBuildDir = path.join( - buildDir, - 'cpp', - 'server', - this.playerId, - isMultiConfig ? buildType : ''); + const pluginBuildDir = getBuildConfig(buildType).pluginBuildDir[this.playerId]; const serverUrl = `http://127.0.0.1:${port}`; const webRootDir = path.join(testsRootDir, 'webroot'); diff --git a/js/config.mjs b/js/build_config.mjs similarity index 55% rename from js/config.mjs rename to js/build_config.mjs index 337e8ff1..1fe03c93 100644 --- a/js/config.mjs +++ b/js/build_config.mjs @@ -6,6 +6,13 @@ import os from 'os'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +export const buildTypes = Object.freeze({ + debug: 'Debug', + release: 'Release', + minsizerel: 'MinSizeRel', + relwithdebinfo: 'RelWithDebInfo' +}); + function toAbsolutePath(p) { return path.isAbsolute(p) ? p : path.join(path.dirname(__dirname), p); @@ -36,10 +43,42 @@ function readBuildConfig(buildDir) } } +function getWebBuildDir(buildConfig) +{ + return path.join( + buildConfig.buildDir, + 'js', + 'webui', + buildConfig.isMultiConfig ? buildConfig.buildType : 'output') +} + +function getPluginBuildDir(buildConfig, player) +{ + return path.join( + buildConfig.buildDir, + 'cpp', + 'server', + player, + buildConfig.isMultiConfig ? buildConfig.buildType : ''); +} + +export function getBuildType(value) +{ + return buildTypes[value.toLowerCase()]; +} + export function getBuildConfig(buildType) { const buildDir = getBuildDir(buildType); const buildConfig = readBuildConfig(buildDir); + + buildConfig.buildType = buildType; buildConfig.buildDir = buildDir; + buildConfig.webBuildDir = getWebBuildDir(buildConfig); + buildConfig.pluginBuildDir = {}; + + for (let player of ['deadbeef', 'foobar2000']) + buildConfig.pluginBuildDir[player] = getPluginBuildDir(buildConfig, player); + return buildConfig; } diff --git a/js/webui/webpack.config.js b/js/webui/webpack.config.js index e1cc2b23..1c6471d5 100644 --- a/js/webui/webpack.config.js +++ b/js/webui/webpack.config.js @@ -5,18 +5,11 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin' import CssMinimizerPlugin from 'css-minimizer-webpack-plugin' import TerserPlugin from 'terser-webpack-plugin' import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer' -import { getBuildConfig } from '../config.mjs'; +import { buildTypes, getBuildConfig, getBuildType as resolveBuildType } from '../build_config.mjs'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const buildTypes = { - debug: 'Debug', - release: 'Release', - minsizerel: 'MinSizeRel', - relwithdebinfo: 'RelWithDebInfo' -}; - function configCommon(config, params) { // Common configuration @@ -124,12 +117,6 @@ function configRelease(config) }); } -function getDefaultOutputDir(buildType) -{ - const { buildDir, isMultiConfig } = getBuildConfig(buildType); - return path.join(buildDir, 'js', 'webui', isMultiConfig ? buildType : 'output'); -} - function getBuildType(env) { const matchedTypes = []; @@ -138,7 +125,7 @@ function getBuildType(env) { // --env {type} - const buildType = buildTypes[key.toLowerCase()]; + const buildType = resolveBuildType(key); if (buildType) matchedTypes.push(buildType); } @@ -147,7 +134,7 @@ function getBuildType(env) { // --env buildType={type} - const buildType = buildTypes[env.buildType.toLowerCase()]; + const buildType = resolveBuildType(env.buildType); if (buildType) matchedTypes.push(buildType) else @@ -169,7 +156,7 @@ function makeBuildParams(env) const buildType = getBuildType(env); if (!outputDir) - outputDir = getDefaultOutputDir(buildType); + outputDir = getBuildConfig(buildType).webBuildDir; const sourceDir = path.join(__dirname, 'src'); diff --git a/scripts/dev_install.cmd b/scripts/dev_install.cmd deleted file mode 100644 index 0e503b2d..00000000 --- a/scripts/dev_install.cmd +++ /dev/null @@ -1,37 +0,0 @@ -@setlocal - -@if [%1] == [] goto :usage -@if [%1] == [-?] goto :usage -@if [%1] == [--help] goto :usage - -set BUILD_TYPE=%1 -set PROFILE_DIR=%APPDATA%\foobar2000-v2 -set COMPONENT_DIR=%PROFILE_DIR%\user-components-x64\foo_beefweb -set CONFIG_DIR=%PROFILE_DIR%\beefweb - -mkdir "%COMPONENT_DIR%" -mkdir "%CONFIG_DIR%" - -cd "%~dp0..\build\%BUILD_TYPE%\cpp\server" - -@if errorlevel 1 ( - @echo Build directory does not exist, aborting - @goto :end -) - -copy /Y foobar2000\%BUILD_TYPE%\*.* "%COMPONENT_DIR%" -copy /Y %BUILD_TYPE%\config.json "%CONFIG_DIR%" - -@goto :end - -:usage -@echo Copy binaries and config file from current build directory to foobar2000 profile -@echo. -@echo Usage: -@echo %~nx0 ^ -@echo. -@echo Build types: -@echo Debug, Release, MinSizeRel, RelWithDebInfo -@echo. - -:end diff --git a/scripts/dev_install.sh b/scripts/dev_install.sh deleted file mode 100755 index f43ef08a..00000000 --- a/scripts/dev_install.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -set -e - -cd "$(dirname $0)/.." - -plugin_file=beefweb.so -webui_root=beefweb.root - -function relink -{ - if [ -L "$1" ]; then - echo "removing existing link '$1'" - rm "$1" - elif [ -e "$1" ]; then - echo "target '$1' exists and is not a symbolic link, aborting" - exit 1 - fi - - echo "setting up link '$1' -> '$2'" - ln -s "$2" "$1" -} - -function install -{ - plugin_dir="$HOME/.local/lib/deadbeef" - server_build_dir="$(pwd)/build/$1/cpp/server/deadbeef" - webui_build_dir="$(pwd)/build/$1/js/webui/output" - - if [ ! -e "$plugin_dir" ]; then - mkdir -p "$plugin_dir" - fi - - relink "$plugin_dir/$plugin_file" "$server_build_dir/$plugin_file" - relink "$plugin_dir/$webui_root" "$webui_build_dir" -} - -usage="Add symlinks from ~/.local/lib/deadbeef to binaries in current build directory - -Usage: - $(basename $0) - -Build types: - Debug, Release, MinSizeRel, RelWithDebInfo -" - -case "$1" in - Debug|Release|MinSizeRel|RelWithDebInfo) - install "$1" - ;; - - - ""|-?|--help) - echo "$usage" - ;; - - *) - echo "invalid build type: $1, try --help" - exit 1 - ;; -esac