From 69a30f271d51138005876e05572d8b72df82e012 Mon Sep 17 00:00:00 2001 From: doe300 Date: Mon, 12 Sep 2022 17:09:43 +0200 Subject: [PATCH] Flatpak, use host system headers and run external programs outside of sandbox --- CMakeLists.txt | 6 +++++- jucipp.yaml | 4 ++-- lib/tiny-process-library | 2 +- src/compile_commands.cpp | 13 ++++++++++--- src/config.cpp | 6 +++++- src/ctags.cpp | 8 +++++++- src/filesystem.cpp | 12 ++++++++++-- src/source.cpp | 12 ++++++++++-- src/source_language_protocol.cpp | 7 ++++++- src/terminal.cpp | 22 ++++++++++++++++++---- 10 files changed, 74 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c297cdd..32e7c4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ option(BUILD_TESTING "Build tests") option(BUILD_FUZZING "Build tests") option(LIBCLANG_PATH "Use custom path for libclang") option(LIBLLDB_PATH "Use custom path for liblldb") -option(FLATPAK_SANDBOX "Runs from within a flatpak sandbox") # This is forwarded to the tiny-process-library submodule +option(FLATPAK_SANDBOX "Runs from within a flatpak sandbox") find_package(Boost 1.54 COMPONENTS REQUIRED filesystem serialization) find_package(ASPELL REQUIRED) @@ -129,6 +129,10 @@ else() message("liblldb not found. Building juCi++ without debugging support") endif() +if(FLATPAK_SANDBOX) + add_definitions(-DJUCI_FLATPAK_SANDBOX) +endif() + if(CMAKE_SYSTEM_NAME MATCHES .*BSD|DragonFly) add_definitions(-DJUCI_USE_UCTAGS) # See https://svnweb.freebsd.org/ports?view=revision&revision=452957 add_definitions(-DJUCI_USE_GREP_EXCLUDE) # --exclude-dir is not an argument in bsd grep diff --git a/jucipp.yaml b/jucipp.yaml index ced0cff..ee7846b 100644 --- a/jucipp.yaml +++ b/jucipp.yaml @@ -213,7 +213,7 @@ modules: prepend-ld-library-path: /usr/lib/sdk/llvm14/lib sources: - type: git - branch: gcc11_fix + branch: master url: https://gitlab.com/cppit/jucipp.git build-commands: - cp -r /usr/lib/sdk/llvm14/lib/* /app/lib/ @@ -225,7 +225,7 @@ modules: - /include - /lib/clang - /lib/cmake - - /lib/debug/lib + - /lib/debug - /lib/libear - /lib/libscanbuild - /lib/python3.9 diff --git a/lib/tiny-process-library b/lib/tiny-process-library index 839ff80..27bf021 160000 --- a/lib/tiny-process-library +++ b/lib/tiny-process-library @@ -1 +1 @@ -Subproject commit 839ff806dc447ff49af80f9a9eaa7949f770f8e5 +Subproject commit 27bf021d97d428b3c0cef4009cb9c03ad46c4376 diff --git a/src/compile_commands.cpp b/src/compile_commands.cpp index b13494d..f48dec7 100644 --- a/src/compile_commands.cpp +++ b/src/compile_commands.cpp @@ -167,10 +167,17 @@ std::vector CompileCommands::get_arguments(const boost::filesystem: else arguments.emplace_back(default_std_argument); +#ifdef JUCI_FLATPAK_SANDBOX + // The host file system is mounted here, need to add this as prefix to access host system headers + const std::string sysroot = "/var/run/host/"; +#else + const std::string sysroot = ""; +#endif + static FindSystemIncludePaths system_include_paths; if(system_include_paths) { for(auto &path : system_include_paths.include_paths) - arguments.emplace_back("-I" + path); + arguments.emplace_back("-I" + sysroot + path); for(auto &path : system_include_paths.framework_paths) arguments.emplace_back("-F" + path); #ifdef _WIN32 @@ -191,8 +198,8 @@ std::vector CompileCommands::get_arguments(const boost::filesystem: std::smatch sm; if(std::regex_match(clang_version_string, sm, clang_version_regex)) { auto clang_version = sm[1].str(); - arguments.emplace_back("-I/usr/lib/clang/" + clang_version + "/include"); - arguments.emplace_back("-I/usr/lib64/clang/" + clang_version + "/include"); // For Fedora + arguments.emplace_back("-I" + sysroot + "/usr/lib/clang/" + clang_version + "/include"); + arguments.emplace_back("-I" + sysroot + "/usr/lib64/clang/" + clang_version + "/include"); // For Fedora #if defined(__APPLE__) // Missing include and framework folders for MacOS: arguments.emplace_back("-I/usr/local/opt/llvm/include/c++/v1"); diff --git a/src/config.cpp b/src/config.cpp index 8c4a7af..43cdc08 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -206,12 +206,16 @@ std::string Config::default_config() { std::string cmake_version; unsigned thread_count = 0; std::stringstream ss; + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif TinyProcessLib::Process process( "cmake --version", "", [&ss](const char *buffer, size_t n) { ss.write(buffer, n); }, - [](const char *buffer, size_t n) {}); + [](const char *buffer, size_t n) {}, false, processConfig); if(process.get_exit_status() == 0) { std::string line; if(std::getline(ss, line)) { diff --git a/src/ctags.cpp b/src/ctags.cpp index 37e2cde..1541dbc 100644 --- a/src/ctags.cpp +++ b/src/ctags.cpp @@ -36,6 +36,11 @@ Ctags::Ctags(const boost::filesystem::path &path, bool enable_scope, bool enable command = Config::get().project.ctags_command + options + fields + " --c-kinds=+p --c++-kinds=+p " + filesystem::escape_argument(path.string()); } + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif + TinyProcessLib::Process process( command, project_path.string(), [this](const char *output, size_t length) { @@ -43,7 +48,8 @@ Ctags::Ctags(const boost::filesystem::path &path, bool enable_scope, bool enable }, [](const char *bytes, size_t n) { Terminal::get().async_print(std::string(bytes, n), true); - }); + }, + false, processConfig); int exit_status; size_t count = 0; diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 59a1b7b..d455fe8 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -132,12 +132,16 @@ const boost::filesystem::path &filesystem::get_home_path() noexcept { const boost::filesystem::path &filesystem::get_rust_sysroot_path() noexcept { auto get_path = [] { std::string path; + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif TinyProcessLib::Process process( "rustc --print sysroot", "", [&path](const char *buffer, size_t length) { path += std::string(buffer, length); }, - [](const char *buffer, size_t n) {}); + [](const char *buffer, size_t n) {}, false, processConfig); if(process.get_exit_status() == 0) { while(!path.empty() && (path.back() == '\n' || path.back() == '\r')) path.pop_back(); @@ -154,13 +158,17 @@ const boost::filesystem::path &filesystem::get_rust_sysroot_path() noexcept { boost::filesystem::path filesystem::get_rust_nightly_sysroot_path() noexcept { auto get_path = [] { std::string path; + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif TinyProcessLib::Process process( // Slightly complicated since "RUSTUP_TOOLCHAIN=nightly rustc --print sysroot" actually installs nightly toolchain if missing... "rustup toolchain list|grep nightly > /dev/null && RUSTUP_TOOLCHAIN=nightly rustc --print sysroot", "", [&path](const char *buffer, size_t length) { path += std::string(buffer, length); }, - [](const char *buffer, size_t n) {}); + [](const char *buffer, size_t n) {}, false, processConfig); if(process.get_exit_status() == 0) { while(!path.empty() && (path.back() == '\n' || path.back() == '\r')) path.pop_back(); diff --git a/src/source.cpp b/src/source.cpp index 2b57562..b2ae290 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -797,12 +797,16 @@ void Source::View::setup_format_style(bool is_generic_view) { static auto get_prettier_library = [] { std::string library; + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif TinyProcessLib::Process process( "npm root -g", "", [&library](const char *buffer, size_t length) { library += std::string(buffer, length); }, - [](const char *, size_t) {}); + [](const char *, size_t) {}, false, processConfig); if(process.get_exit_status() == 0) { while(!library.empty() && (library.back() == '\n' || library.back() == '\r')) library.pop_back(); @@ -859,6 +863,10 @@ void Source::View::setup_format_style(bool is_generic_view) { stdout_buffer = std::stringstream(); curly_count = 0; key_or_value = false; + TinyProcessLib::Config processConfig{1048576}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif prettier_background_process = std::make_unique( "node -e \"const repl = require('repl');repl.start({prompt: '', ignoreUndefined: true, preview: false});\"", "", @@ -930,7 +938,7 @@ void Source::View::setup_format_style(bool is_generic_view) { LockGuard lock(mutex); error = Error{std::move(message), line, line_index}; }, - true, TinyProcessLib::Config{1048576}); + true, processConfig); prettier_background_process->write("const prettier = require(\"" + escape(prettier_library, {'"'}) + "\");\n"); } diff --git a/src/source_language_protocol.cpp b/src/source_language_protocol.cpp index a8121e0..ad69eaf 100644 --- a/src/source_language_protocol.cpp +++ b/src/source_language_protocol.cpp @@ -112,6 +112,11 @@ LanguageProtocol::WorkspaceEdit::WorkspaceEdit(const JSON &workspace_edit, boost } LanguageProtocol::Client::Client(boost::filesystem::path root_path_, std::string language_id_, const std::string &language_server) : root_path(std::move(root_path_)), language_id(std::move(language_id_)) { + TinyProcessLib::Config processConfig{1048576}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif + process = std::make_unique( language_server, root_path.string(), [this](const char *bytes, size_t n) { @@ -121,7 +126,7 @@ LanguageProtocol::Client::Client(boost::filesystem::path root_path_, std::string [](const char *bytes, size_t n) { std::cerr.write(bytes, n); }, - true, TinyProcessLib::Config{1048576}); + true, processConfig); } std::shared_ptr LanguageProtocol::Client::get(const boost::filesystem::path &file_path, const std::string &language_id, const std::string &language_server) { diff --git a/src/terminal.cpp b/src/terminal.cpp index 42a1511..3e3390d 100644 --- a/src/terminal.cpp +++ b/src/terminal.cpp @@ -204,6 +204,10 @@ Terminal::Terminal() : Source::CommonView() { int Terminal::process(const std::string &command, const boost::filesystem::path &path, bool use_pipes) { std::unique_ptr process; + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif if(use_pipes) process = std::make_unique( command, path.string(), @@ -212,9 +216,10 @@ int Terminal::process(const std::string &command, const boost::filesystem::path }, [this](const char *bytes, size_t n) { async_print(std::string(bytes, n), true); - }); + }, + false, processConfig); else - process = std::make_unique(command, path.string()); + process = std::make_unique(command, path.string(), nullptr, nullptr, false, processConfig); if(process->get_id() <= 0) { async_print("\e[31mError\e[m: failed to run command: " + command + "\n", true); @@ -225,6 +230,10 @@ int Terminal::process(const std::string &command, const boost::filesystem::path } int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path, std::ostream *stderr_stream) { + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif TinyProcessLib::Process process( command, path.string(), [&stdout_stream](const char *bytes, size_t n) { @@ -243,7 +252,7 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c else async_print(std::string(bytes, n), true); }, - true); + true, processConfig); if(process.get_id() <= 0) { async_print("\e[31mError\e[m: failed to run command: " + command + "\n", true); @@ -288,6 +297,11 @@ std::shared_ptr Terminal::async_process(const std::stri cd_path_and_command = command; #endif + TinyProcessLib::Config processConfig{}; +#ifdef JUCI_FLATPAK_SANDBOX + processConfig.flatpak_spawn_host = true; +#endif + auto process = std::make_shared( #if defined(__APPLE__) "STDBUF1=L " + command, @@ -321,7 +335,7 @@ std::shared_ptr Terminal::async_process(const std::stri message_printed.get_future().get(); } }, - true); + true, processConfig); auto pid = process->get_id(); if(pid <= 0) {