118 Commits

Author SHA1 Message Date
TheAssassin 56760df190 Fix patchelf unexpectedly overwriting symlinked libraries 2022-05-18 23:33:02 +02:00
TheAssassin 23dcaa5cda Log which boost version is used for build 2022-05-18 18:12:41 +02:00
TheAssassin 097212aa1e Merge pull request #200 from solemnwarning/exclude-library
Add --exclude-library option.
2022-05-03 19:09:03 +02:00
Daniel Collins 37b640fa86 Add --exclude-library option. 2022-05-01 21:49:22 +01:00
TheAssassin ed42a40a87 Rebuild at least once a month 2022-03-03 18:35:27 +01:00
TheAssassin 4c5b9c5daf Merge pull request #188 from smarttowel/fix_149
Possible fix for #149
2022-01-12 10:51:49 +01:00
TheAssassin 0f5361b457 Code style fixes 2022-01-11 19:24:08 +01:00
Pavel Mikhadzionak fc27076843 Codestyle update
Co-authored-by: TheAssassin <theassassin@assassinate-you.net>
2022-01-11 17:47:05 +03:00
smarttowel f59f8f9512 Add const modifier to rpath var 2022-01-11 17:33:27 +03:00
smarttowel ae8699854a Append $ORIGIN to rpath if missed 2022-01-11 17:18:15 +03:00
smarttowel fa3e51c7db Possible fix for #149 2022-01-11 16:24:37 +03:00
TheAssassin d2e9567029 Add FetchContent fallback for CImg 2021-12-03 18:28:41 +01:00
TheAssassin fb5cd4d32d Require static boost libs only if necessary
Some distros don't ship static libraries by default, therefore requiring
them by default breaks on those. Also, it makes no sense, really.

Fixes one build issue on openSUSE Leap.
2021-12-03 14:45:35 +01:00
TheAssassin 5fb5ca5a8b Remove duplicate inclusion of CTest 2021-12-03 14:44:18 +01:00
TheAssassin ae714d69ff Support system-provided CImg only from now on 2021-12-01 05:00:34 +01:00
TheAssassin 01331697d0 Support only system-provided boost from now on 2021-12-01 05:00:33 +01:00
TheAssassin d903364ffc Update linuxdeploy-desktopfile 2021-12-01 03:50:05 +01:00
TheAssassin d77cff2adc Update cmake-scripts 2021-12-01 03:49:32 +01:00
TheAssassin 5685bc575e Test invalid headers and missing files in ELF library
CC #185.
2021-11-30 00:08:52 +01:00
TheAssassin d621d3949d Refactor and simplify tests config in CMake 2021-11-30 00:05:15 +01:00
TheAssassin 0c49714228 Use cmake-scripts to manage gtest dependency 2021-11-30 00:01:54 +01:00
TheAssassin 9aa59f3e75 Improve detection of excluded test targets, mk. 2 2021-11-20 01:58:28 +01:00
TheAssassin bcd9d5337e Improve detection of excluded test targets 2021-11-20 01:56:42 +01:00
TheAssassin 39ab9909cf Fix test executable discovery 2021-11-20 01:35:16 +01:00
TheAssassin 03d8cb3234 Install missing dependencies for coverage builds 2021-10-16 03:52:18 +02:00
TheAssassin 2dfccf760b Fix coverage builds 2021-10-16 03:47:36 +02:00
TheAssassin 789222bae6 Test that deployment actually works 2021-10-16 03:40:43 +02:00
TheAssassin 7e3beb4336 Add new test to check minimum permissions 2021-10-16 03:37:22 +02:00
TheAssassin 63d2fa5437 Add minimum permissions to copied files
Fixes #181.
2021-10-16 03:22:02 +02:00
TheAssassin 49f4f23776 Remove accidentally committed debug code 2021-05-29 01:30:28 +02:00
TheAssassin 1d534d2b32 Do not set rpath in statically linked or debug symbols ELF files 2021-05-29 01:25:21 +02:00
TheAssassin 3c6096433d Detect dynamically linked and debug symbols only ELF files
TODO: extract ELF stuff into new small C++ wrapper library that can be used in various places (e.g., AppImageLauncher, the AppImage runtime, ...)
2021-05-29 01:19:42 +02:00
TheAssassin 86c99ccfb4 Fix header name collision 2021-05-29 01:09:48 +02:00
TheAssassin d5c4124a0b Make sure to compare canonical paths
Absolute paths do not have to be canonical. For instance, .../a/../AppDir may be equivalent to .../AppDir, however the current implementation would not match them.
2021-05-25 23:17:41 +02:00
TheAssassin a73dbf68f4 Fix linuxdeploy accidentally exiting on warning 2021-05-25 22:50:24 +02:00
TheAssassin a7a255f9f1 Fix escaping in auto-generated script, mk. 2 2021-05-25 17:38:09 +02:00
TheAssassin 679904ce7b Add $LINUXDEPLOY_PLUGIN_MODE
This enables a special mode used for plugins that intend to call linuxdeploy via $LINUXDEPLOY. It skips the finishing steps to make sure they are not run prematurely.

Consider this a workaround to a bug in the AppDir root dir deployment.
2021-05-25 17:22:26 +02:00
TheAssassin 6b96159f88 Fix escaping in auto-generated script 2021-05-25 16:49:19 +02:00
TheAssassin ab49cecf09 Make sure custom AppRun files are executable 2021-05-25 16:49:00 +02:00
TheAssassin 49c3a57226 Embed GitHub run number 2021-05-25 10:51:05 +02:00
TheAssassin 39b03f630d Update linuxdeploy-desktopfile 2021-05-15 17:18:20 +02:00
TheAssassin 0a6a1c59b7 Fix test execution in CI build script 2021-05-14 08:38:45 +02:00
TheAssassin 7b1c858ff5 Fix macro like in linuxdeploy-desktopfile 2021-05-14 08:33:28 +02:00
TheAssassin 0c23a481fe Update linuxdeploy-desktopfile 2021-05-13 15:06:18 +02:00
TheAssassin b7c9785626 Fix source archive hash
For some reason, the SHA256 hash of the libjpeg source archive was
changed by the upstream. The archive seems to be okay, so changing the
hash should be fine.
2021-04-22 09:38:18 +02:00
TheAssassin 9fb2ac35d2 Use matrix to simplify workflow, mk. 3 2021-01-03 15:24:44 +01:00
TheAssassin f83a0e99eb Use matrix to simplify workflow, mk. 2 2021-01-03 15:23:32 +01:00
TheAssassin 8c848e6b26 Use matrix to simplify workflow 2021-01-03 15:21:44 +01:00
TheAssassin 58f8b6a6fd Fix FUSE issues on i386... in the right job 2020-12-11 12:09:43 +01:00
TheAssassin c1bd11028c Fix FUSE issues on i386 2020-12-11 11:54:46 +01:00
TheAssassin da1bae216a Install 32-bit dependencies, mk. 2 2020-12-11 11:17:59 +01:00
TheAssassin b42420e731 Install 32-bit dependencies 2020-12-11 11:13:42 +01:00
TheAssassin 8f86082322 Fix bug in actions workflow 2020-12-11 09:53:36 +01:00
TheAssassin fb80d6a4f4 Update ignore patterns 2020-12-10 22:32:37 +01:00
TheAssassin 575dde281d Switch to GitHub actions 2020-12-10 22:24:35 +01:00
TheAssassin 3e05627373 Merge pull request #156 from patrickelectric/fix_include_std_runtime_error
subprocess: Add missing include for std::runtime_error
2020-11-18 18:19:48 +01:00
Patrick José Pereira 73f3126a59 subprocess: Add missing include for std::runtime_error
Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
2020-11-18 11:58:15 -03:00
TheAssassin b6a1ba290e Close file descriptors when process has exited 2020-10-07 04:37:50 +02:00
TheAssassin 3c21d86574 Improve file descriptor connection
Instead of passing the fd array for no real reason, the actual fd is passed from now on. The lambda now also logs error message received via errno.
2020-10-07 04:25:14 +02:00
TheAssassin 2554b35403 Check return code of ::close
It appears to be pretty common not to check the return code, but it's a serious programming flaw.
2020-10-07 03:37:00 +02:00
TheAssassin bfcde878e2 Log error when pipe creation fails 2020-10-05 22:35:15 +02:00
TheAssassin 04d5321a5f Merge pull request #148 from JokerQyou/master
Read ldd error message from both stdout and stderr
2020-09-25 14:18:42 +02:00
Joker_ 76f1d8fee5 Read ldd error message from both stdout and stderr 2020-09-23 11:49:24 +08:00
TheAssassin e4fff0a5b7 Merge pull request #146 from linuxdeploy/fix-145
Read subprocesses' pipes until they're empty
2020-09-22 13:46:31 +02:00
TheAssassin 407ecc408d Read subprocesses' pipes until they're empty 2020-09-22 13:04:23 +02:00
TheAssassin 8ee0e43c23 Switch to new subprocess lib in type 0 plugins, mk. 3
This commit fixes the remaining buffer issues by introducing a little more complexity. It shall be refactored in the future to decrease complexity again, but for now, it works well and function is more important than form at this point.

CC #143
2020-09-04 18:02:40 +02:00
TheAssassin e9bbbc80f4 Switch to new subprocess lib in type 0 plugins, mk. 2
Apparently fixes all buffer-related crashes, but there's a few minor bugs left.

CC #143
2020-08-31 08:39:43 +02:00
TheAssassin 68f4655fc4 Add method to write from buffers to ldLog streams 2020-08-31 06:30:06 +02:00
TheAssassin 1072c6d9f0 Improve check_output performance 2020-08-31 05:08:24 +02:00
TheAssassin f33dc8dd34 Switch to new subprocess lib in type 0 plugins, mk. 1 2020-08-31 04:41:01 +02:00
TheAssassin 6621f1edf7 Forgot to add pipe reader to CMake 2020-08-31 04:20:40 +02:00
TheAssassin ee73ac6c8e Use new pipe_reader in subprocess's check_output
The class will read until the process quits (or until memory's up).

TODO: reduce load on CPU with some sleep (right now, it's pretty much some busy waiting)
2020-08-31 04:20:03 +02:00
TheAssassin 66691ee882 Add new helper class pipe reader
Implements synchronous, non-block reading from pipes.
2020-08-28 17:36:56 +02:00
TheAssassin e91b459fce Use std::distance instead of pointer arithmetics 2020-08-08 11:54:58 +02:00
TheAssassin 3f86f178a5 Use classic C string handling
That way, we don't have to allocate memory, and it's also shorter.
2020-08-08 11:49:17 +02:00
TheAssassin a8975e0e50 Clean up memory in case exec* fails
Prevents memory leaks.
2020-08-08 11:44:21 +02:00
TheAssassin 6c47939fdc Fix initialization bug 2020-08-08 11:34:02 +02:00
TheAssassin 8663e5bf26 Update license information in help text 2020-08-08 01:06:51 +02:00
TheAssassin 89493e399b Build fully static strip binary 2020-08-08 00:47:54 +02:00
TheAssassin 4d999ef5c6 Build somewhat static strip ourselves 2020-08-08 00:30:28 +02:00
TheAssassin b39dfa6591 Fix static binaries handling 2020-08-08 00:30:28 +02:00
TheAssassin 484ff3f004 Fix C string processing bug
Well, makes sense now that I look at it... but caused a couple of hours worrying why my child processes were crashing until I noticed it'd only happen if I specified custom environment variables...
2020-08-08 00:30:28 +02:00
TheAssassin 8b604871cc Refactor duplicate code into static method 2020-08-08 00:30:28 +02:00
TheAssassin 88dd09f2d1 Set all variables to defaults in header 2020-08-08 00:30:28 +02:00
TheAssassin d43e8a42bf Fix whitespace 2020-08-08 00:30:28 +02:00
TheAssassin 5feef7880e Try to fix waitpid issues 2020-08-08 00:30:28 +02:00
TheAssassin 2b2c6a913f Set default value 2020-08-07 21:22:58 +02:00
TheAssassin aeb0bfa98b Use consistent error message for all plugins 2020-08-07 21:22:58 +02:00
TheAssassin 37aa37f5fe Fix behavior of close()
The implementation was obviously wrong/incomplete.
2020-08-07 21:22:58 +02:00
TheAssassin 59a8ec41ba Replace cpp-subprocess with own linuxdeploy-subprocess 2020-08-07 21:22:58 +02:00
TheAssassin 4a0cfe323d Require newer CMake version only for static builds 2020-08-07 21:22:58 +02:00
TheAssassin c895a1dc59 Add kill and poll features for processes 2020-08-07 21:22:58 +02:00
TheAssassin 80a5667ca7 Check waitpid() for errors 2020-08-07 21:22:58 +02:00
TheAssassin 2425ccc832 Extract process handling into separate class
Needed for plugins' subprocess handling.
2020-08-07 21:22:58 +02:00
TheAssassin 55b2d00f23 Add reusable assert template 2020-08-07 21:22:58 +02:00
TheAssassin e1f6da17b4 Add basic subprocess micro library
cpp-subprocess does not work when linked statically for some weird reason. Therefore, we're going to ship our own.
2020-08-07 21:22:58 +02:00
TheAssassin 326b002ed5 Fetch up-to-date CMake for AppImage builds 2020-08-07 21:22:58 +02:00
TheAssassin 86d4404a16 Try to use target_link_options again 2020-08-07 21:22:58 +02:00
TheAssassin cbfbb1ee2d Debug CI build issues mk. 1 2020-08-07 21:22:58 +02:00
TheAssassin 5fde708954 Improve CMake check 2020-08-06 14:44:00 +02:00
TheAssassin dc07fbd401 Build static binaries for releases on Travis 2020-08-06 14:10:57 +02:00
TheAssassin 5b713b3bee Add support for fully static builds 2020-08-06 02:07:31 +02:00
TheAssassin 5644d5ca06 Add license notices to binary for dependencies
Was long overdue.
2020-08-06 01:19:29 +02:00
TheAssassin 557bad2241 Add --deploy-deps-only 2020-07-15 03:17:37 +02:00
TheAssassin 590a746882 Replace std::cerr messages with ldLog
Was long overdue now. Makes for a consistent logging, and helps communicate that the messages are errors to the user.
2020-07-15 03:10:12 +02:00
TheAssassin a609adb4f5 Merge pull request #135 from komputerwiz/master
Fix update information used by Travis builds
2020-07-05 20:41:00 +02:00
Matthew Barry 591e21a766 fix update information used by Travis builds
Seems like this was overlooked by commit 2af5430 when fixing #126
2020-07-05 12:50:47 -05:00
TheAssassin 0f3a118687 Add param to automatically rename deployed icons
Useful e.g., when passing multiple icons with different resolutions via -i, if they have the resolution in the filename.

Also removes all traces of that appName concept that has been abandoned.
2020-06-11 21:04:33 +02:00
TheAssassin 1c0ce6a0a5 Merge pull request #132 from X0rg/patch-1
Update README.md with CPU-X project
2020-05-24 01:50:12 +02:00
Xorg 2f00292756 Update README.md with CPU-X project 2020-05-24 01:00:32 +02:00
TheAssassin f24c167722 Add $LINUXDEPLOY for input plugins
The input plugins can use this environment variable to call linuxdeploy themselves. This can be very handy to have it deploy additional dependencies on libraries they copy themselves.

An alternative approach is to simply use liblinuxdeploy inside the plugin, like the Qt plugin does.
2020-05-03 18:32:55 +02:00
TheAssassin 2af54304e2 Fix update information
Closes #126.
2020-04-08 23:41:58 +02:00
TheAssassin 4391ad24d9 Merge pull request #125 from d1vanov/master
Fix links in README.md
2020-04-04 16:19:13 +02:00
Dmitry Ivanov f3ae65bc57 Fix links in README.md 2020-04-04 17:17:41 +03:00
TheAssassin d086da38c4 Allow users to use custom patchelf
Fixes #120.
2020-02-06 02:34:37 +01:00
TheAssassin 652ef5a215 Use the right method to resolve symlinks
Just checked with absolute, it doesn't always resolve symlinks. canonical is supposed to do that according to https://www.boost.org/doc/libs/1_48_0/libs/filesystem/v3/doc/reference.html#Canonical-path.
2019-12-13 17:53:28 +01:00
TheAssassin 2b13c52452 Workaround for ldd bug
Closes #110.

See https://sourceware.org/bugzilla/show_bug.cgi?id=25263 for more information.
2019-12-13 17:49:22 +01:00
TheAssassin c45cd46319 Move which to utils module
Also uses the native split functionality provided by the utils module
instead of some external dependency's.

Preparation for using this method in plugins such as the Qt plugin.
2019-11-19 11:28:24 +01:00
87 changed files with 2163 additions and 1156 deletions
+75
View File
@@ -0,0 +1,75 @@
name: CI
on:
push:
pull_request:
workflow_dispatch:
schedule:
# build at least once a month
- cron: '0 0 1 * *'
jobs:
build-and-test:
strategy:
matrix:
ARCH: [x86_64, i386]
BUILD_TYPE: [appimage, coverage]
fail-fast: false
name: ${{ matrix.BUILD_TYPE }} ${{ matrix.ARCH }}
runs-on: ubuntu-latest
env:
ARCH: ${{ matrix.ARCH }}
BUILD_TYPE: ${{ matrix.BUILD_TYPE }}
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Install dependencies (x86_64)
if: matrix.ARCH == 'x86_64'
run: |
sudo apt-get update
sudo apt-get install -y gcovr libmagic-dev libjpeg-dev libpng-dev libboost-filesystem-dev libboost-regex-dev cimg-dev
- name: Install dependencies (i386)
if: matrix.ARCH == 'i386'
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y gcovr libmagic-dev:i386 libjpeg-dev:i386 libpng-dev:i386 libboost-filesystem-dev:i386 libboost-regex-dev:i386 cimg-dev gcc-multilib g++-multilib libfuse2:i386
- name: Test coverage
run: bash -ex ci/test-coverage.sh
if: matrix.BUILD_TYPE == 'coverage'
- name: Build, test and build AppImage
run: bash -ex ci/build.sh
if: matrix.BUILD_TYPE != 'coverage'
- name: Archive artifacts
uses: actions/upload-artifact@v2
if: matrix.BUILD_TYPE != 'coverage'
with:
name: AppImage
path: linuxdeploy*.AppImage*
upload:
name: Create release and upload artifacts
needs:
- build-and-test
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v2
- name: Inspect directory after downloading artifacts
run: ls -alFR
- name: Create release and upload artifacts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
wget -q https://github.com/TheAssassin/pyuploadtool/releases/download/continuous/pyuploadtool-x86_64.AppImage
chmod +x pyuploadtool-x86_64.AppImage
./pyuploadtool-x86_64.AppImage **/linuxdeploy*.AppImage*
+1
View File
@@ -3,3 +3,4 @@ cmake-build-*/
.idea/
squashfs-root/
*.AppImage
*.swp
+3 -75
View File
@@ -1,84 +1,12 @@
[submodule "lib/cpp-subprocess"]
path = lib/cpp-subprocess
url = https://github.com/arun11299/cpp-subprocess.git
[submodule "lib/args"]
path = lib/args
url = https://github.com/Taywee/args.git
[submodule "lib/boost-filesystem"]
path = lib/boost-filesystem
url = https://github.com/boostorg/filesystem.git
[submodule "lib/boost-regex"]
path = lib/boost-regex
url = https://github.com/boostorg/regex.git
[submodule "lib/boost-system"]
path = lib/boost-system
url = https://github.com/boostorg/system.git
[submodule "lib/boost-config"]
path = lib/boost-config
url = https://github.com/boostorg/config.git
[submodule "lib/boost-utility"]
path = lib/boost-utility
url = https://github.com/boostorg/utility.git
[submodule "lib/boost-predef"]
path = lib/boost-predef
url = https://github.com/boostorg/predef.git
[submodule "lib/boost-assert"]
path = lib/boost-assert
url = https://github.com/boostorg/assert.git
[submodule "lib/boost-core"]
path = lib/boost-core
url = https://github.com/boostorg/core.git
[submodule "lib/boost-type_traits"]
path = lib/boost-type_traits
url = https://github.com/boostorg/type_traits.git
[submodule "lib/boost-iterator"]
path = lib/boost-iterator
url = https://github.com/boostorg/iterator.git
[submodule "lib/boost-mpl"]
path = lib/boost-mpl
url = https://github.com/boostorg/mpl.git
[submodule "lib/boost-preprocessor"]
path = lib/boost-preprocessor
url = https://github.com/boostorg/preprocessor.git
[submodule "lib/boost-static_assert"]
path = lib/boost-static_assert
url = https://github.com/boostorg/static_assert.git
[submodule "lib/boost-detail"]
path = lib/boost-detail
url = https://github.com/boostorg/detail.git
[submodule "lib/boost-smart_ptr"]
path = lib/boost-smart_ptr
url = https://github.com/boostorg/smart_ptr.git
[submodule "lib/boost-exception"]
path = lib/boost-exception
url = https://github.com/boostorg/exception.git
[submodule "lib/boost-throw_exception"]
path = lib/boost-throw_exception
url = https://github.com/boostorg/throw_exception.git
[submodule "lib/boost-io"]
path = lib/boost-io
url = https://github.com/boostorg/io.git
[submodule "lib/boost-functional"]
path = lib/boost-functional
url = https://github.com/boostorg/functional.git
[submodule "lib/boost-container_hash"]
path = lib/boost-container_hash
url = https://github.com/boostorg/container_hash.git
[submodule "lib/boost-range"]
path = lib/boost-range
url = https://github.com/boostorg/range.git
[submodule "lib/boost-integer"]
path = lib/boost-integer
url = https://github.com/boostorg/integer.git
[submodule "lib/CImg"]
path = lib/CImg
url = https://github.com/dtschump/CImg.git
[submodule "lib/googletest"]
path = lib/googletest
url = https://github.com/google/googletest
[submodule "lib/boost-container"]
path = lib/boost-container
url = https://github.com/boostorg/container
[submodule "lib/linuxdeploy-desktopfile"]
path = lib/linuxdeploy-desktopfile
url = https://github.com/linuxdeploy/linuxdeploy-desktopfile
[submodule "lib/cmake-scripts"]
path = lib/cmake-scripts
url = https://github.com/linuxdeploy/cmake-scripts.git
-98
View File
@@ -1,98 +0,0 @@
language: cpp
sudo: required
matrix:
include:
- name: CentOS 6 x86_64 build
env: ARCH=x86_64 BUILD_TYPE=centos6
install: true
services:
- docker
script: travis/build-centos6-docker.sh
after_success:
- if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ] && [ "$TRAVIS_BRANCH" != "master" ]; then export TRAVIS_EVENT_TYPE=pull_request; fi
- wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
- bash upload.sh linuxdeploy-"$ARCH".AppImage*
- name: CentOS 6 i386 build
env: ARCH=i386 BUILD_TYPE=centos6
install: true
services:
- docker
script: travis/build-centos6-docker.sh
after_success:
- if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ] && [ "$TRAVIS_BRANCH" != "master" ]; then export TRAVIS_EVENT_TYPE=pull_request; fi
- wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
- bash upload.sh linuxdeploy-"$ARCH".AppImage*
- name: Ubuntu bionic arm64 build
env: ARCH=arm64 BUILD_TYPE=arm64-native
dist: bionic
arch: arm64
addons:
apt:
update: true
packages:
- libmagic-dev
- libjpeg-dev
- libpng-dev
- cimg-dev
- patchelf
before_script:
- git clone https://github.com/NixOS/patchelf.git && \
- pushd patchelf && \
- # cannot use -b since it's not supported in really old versions of git
- git checkout 0.8 && \
- ./bootstrap.sh && \
- ./configure --prefix=/usr && \
- make -j $(nproc) && \
- make install && \
- popd && \
- rm -r patchelf/
script: travis/build.sh
after_success:
- if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ] && [ "$TRAVIS_BRANCH" != "master" ]; then export TRAVIS_EVENT_TYPE=pull_request; fi
- wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
- bash upload.sh linuxdeploy-"$ARCH".AppImage*
- name: Ubuntu xenial x86_64 coverage build (no binaries uploaded)
env: ARCH=x86_64 BUILD_TYPE=coverage
dist: xenial
addons:
apt:
update: true
packages:
- libmagic-dev
- libjpeg-dev
- libpng-dev
- cimg-dev
before_script:
- sudo pip install gcovr
script: travis/test-coverage.sh
after_success: true # also, we don't intend to upload release binaries
- name: Ubuntu xenial i386 coverage build (no binaries uploaded)
env: ARCH=i386 BUILD_TYPE=coverage
dist: xenial
addons:
apt:
update: true
packages:
- libmagic-dev:i386
- libjpeg-dev:i386
- libpng-dev:i386
- gcc-multilib
- g++-multilib
- libfuse2:i386
- libcairo2:i386
before_script:
- sudo pip install gcovr
script: travis/test-coverage.sh
after_success: true # also, we don't intend to upload release binaries
branches:
except:
- # Do not build tags that we create when we upload to GitHub Releases
- /^(?i:continuous)$/
+8 -9
View File
@@ -7,14 +7,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/Modules/")
set(USE_SYSTEM_BOOST OFF CACHE BOOL "Set to ON to use system boost libraries instead of building up to date boost libraries from source")
set(USE_SYSTEM_CIMG ON CACHE BOOL "Set to OFF to use CImg library bundled in lib directory")
if (EXISTS "${PROJECT_SOURCE_DIR}/lib/cpp-subprocess/subprocess.hpp")
else()
message (FATAL_ERROR "Missing submodule(s), please 'git submodule update --init --recursive'...")
endif()
# support for ccache
# call CMake with -DUSE_CCACHE=ON to make use of it
set(USE_CCACHE ON CACHE BOOL "")
@@ -48,11 +40,18 @@ if(ENABLE_COVERAGE)
setup_target_for_coverage_gcovr_text(NAME coverage_text EXECUTABLE "${command}")
endif()
include(CTest)
if(BUILD_TESTING)
# including this before including lib/ makes sure that the top level project's gtest is used everywhere
include(${PROJECT_SOURCE_DIR}/lib/cmake-scripts/include-or-build-gtest.cmake)
endif()
add_subdirectory(lib)
add_subdirectory(src)
include(CTest)
if(BUILD_TESTING)
enable_testing()
add_subdirectory(tests)
endif()
+2 -1
View File
@@ -16,7 +16,7 @@ linuxdeploy was greatly influenced by [linuxdeployqt](https://github.com/probono
## User guides and examples
Please see the [linuxdeploy user guide](https://docs.appimage.org/packaging-guide/linuxdeploy-user-guide.html) and the [native binaries packaging guide](https://docs.appimage.org/packaging-guide/native-binaries.html) in the [AppImage documentation](https://docs.appimage.org). There's also an [examples section](https://docs.appimage.org/packaging-guide/native-binaries.html#examples).
Please see the [linuxdeploy user guide](https://docs.appimage.org/packaging-guide/from-source/linuxdeploy-user-guide.html) and the [native binaries packaging guide](https://docs.appimage.org/packaging-guide/from-source/native-binaries.html) in the [AppImage documentation](https://docs.appimage.org). There's also an [examples section](https://docs.appimage.org/packaging-guide/from-source/native-binaries.html#examples).
## Projects using linuxdeploy
@@ -29,6 +29,7 @@ This is an incomplete list of projects using linuxdeploy. You might want to read
- [AppImageUpdate](https://github.com/AppImage/AppImageUpdate)
- [appimaged](https://github.com/AppImage/appimaged)
- [MediaElch](https://github.com/Komet/MediaElch/)
- [CPU-X](https://github.com/X0rg/CPU-X) (details available [here](https://github.com/AppImage/AppImageKit/wiki/Bundling-GTK3-apps#fully-automated-deployment-from-sources-with-github-actions-cpu-x))
## Plugins
+59
View File
@@ -0,0 +1,59 @@
#! /bin/bash
set -e
set -x
INSTALL_DESTDIR="$1"
if [[ "$INSTALL_DESTDIR" == "" ]]; then
echo "Error: build dir $BUILD_DIR does not exist" 1>&2
exit 1
fi
# support cross-compilation for 32-bit ISAs
case "$ARCH" in
"x86_64"|"amd64")
;;
"i386"|"i586"|"i686")
export CFLAGS="-m32"
export CXXFLAGS="-m32"
;;
*)
echo "Error: unsupported architecture: $ARCH"
exit 1
;;
esac
# use RAM disk if possible
if [ "$CI" == "" ] && [ -d /dev/shm ]; then
TEMP_BASE=/dev/shm
else
TEMP_BASE=/tmp
fi
cleanup () {
if [ -d "$BUILD_DIR" ]; then
rm -rf "$BUILD_DIR"
fi
}
trap cleanup EXIT
BUILD_DIR=$(mktemp -d -p "$TEMP_BASE" linuxdeploy-build-XXXXXX)
pushd "$BUILD_DIR"
# fetch source code
wget https://ftp.gnu.org/gnu/binutils/binutils-2.35.tar.xz -O- | tar xJ --strip-components=1
# configure static build
# inspired by https://github.com/andrew-d/static-binaries/blob/master/binutils/build.sh
./configure --prefix=/usr --disable-nls --enable-static-link --disable-shared-plugins --disable-dynamicplugin --disable-tls --disable-pie
# citing the script linked above: "This strange dance is required to get things to be statically linked."
make -j "$(nproc)"
make clean
make -j "$(nproc)" LDFLAGS="-all-static"
# install into user-specified destdir
make install DESTDIR="$(readlink -f "$INSTALL_DESTDIR")"
+62
View File
@@ -0,0 +1,62 @@
#! /bin/bash
set -e
set -x
INSTALL_DESTDIR="$1"
if [[ "$INSTALL_DESTDIR" == "" ]]; then
echo "Error: build dir $BUILD_DIR does not exist" 1>&2
exit 1
fi
# support cross-compilation for 32-bit ISAs
case "$ARCH" in
"x86_64"|"amd64")
;;
"i386"|"i586"|"i686")
export CFLAGS="-m32"
export CXXFLAGS="-m32"
;;
*)
echo "Error: unsupported architecture: $ARCH"
exit 1
;;
esac
# use RAM disk if possible
if [ "$CI" == "" ] && [ -d /dev/shm ]; then
TEMP_BASE=/dev/shm
else
TEMP_BASE=/tmp
fi
cleanup () {
if [ -d "$BUILD_DIR" ]; then
rm -rf "$BUILD_DIR"
fi
}
trap cleanup EXIT
BUILD_DIR=$(mktemp -d -p "$TEMP_BASE" linuxdeploy-build-XXXXXX)
pushd "$BUILD_DIR"
# fetch source code
git clone https://github.com/NixOS/patchelf.git .
# cannot use -b since it's not supported in really old versions of git
git checkout 0.8
# prepare configure script
./bootstrap.sh
# configure static build
env LDFLAGS="-static -static-libgcc -static-libstdc++" ./configure --prefix=/usr
# build binary
make -j "$(nproc)"
# install into user-specified destdir
make install DESTDIR="$INSTALL_DESTDIR"
+21 -21
View File
@@ -30,38 +30,38 @@ if [ "$ARCH" == "x86_64" ]; then
EXTRA_CMAKE_ARGS=()
elif [ "$ARCH" == "i386" ]; then
EXTRA_CMAKE_ARGS=("-DCMAKE_TOOLCHAIN_FILE=$REPO_ROOT/cmake/toolchains/i386-linux-gnu.cmake" "-DUSE_SYSTEM_CIMG=OFF")
elif [ "$ARCH" == "arm64" ] && [ "$BUILD_TYPE" == "arm64-native" ]; then
EXTRA_CMAKE_ARGS=()
else
echo "Architecture not supported: $ARCH" 1>&2
exit 1
fi
cmake "$REPO_ROOT" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo "${EXTRA_CMAKE_ARGS[@]}"
# fetch up-to-date CMake
mkdir cmake-prefix
wget -O- https://github.com/Kitware/CMake/releases/download/v3.18.1/cmake-3.18.1-Linux-x86_64.tar.gz | tar -xz -C cmake-prefix --strip-components=1
export PATH="$(readlink -f cmake-prefix/bin):$PATH"
cmake --version
make -j$(nproc)
# configure build for AppImage release
cmake "$REPO_ROOT" -DSTATIC_BUILD=On -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo "${EXTRA_CMAKE_ARGS[@]}"
make -j"$(nproc)"
## Run Unit Tests
ctest -V
strip_path=$(which strip)
# build patchelf
"$REPO_ROOT"/ci/build-static-patchelf.sh "$(readlink -f out/)"
patchelf_path="$(readlink -f out/usr/bin/patchelf)"
if [ "$ARCH" == "i386" ]; then
# download i386 strip for i386 AppImage
# https://github.com/linuxdeploy/linuxdeploy/issues/59
wget http://security.ubuntu.com/ubuntu/pool/main/b/binutils/binutils-multiarch_2.24-5ubuntu14.2_i386.deb
echo "0106f170cebf5800e863a558cad039e4f16a76d3424ae943209c3f6b0cacd511 binutils-multiarch_2.24-5ubuntu14.2_i386.deb" | sha256sum -c
wget http://security.ubuntu.com/ubuntu/pool/main/b/binutils/binutils-multiarch-dev_2.24-5ubuntu14.2_i386.deb
echo "ed9ca4fbbf492233228f79fae6b349a2ed2ee3e0927bdc795425fccf5fae648e binutils-multiarch-dev_2.24-5ubuntu14.2_i386.deb" | sha256sum -c
dpkg -x binutils-multiarch_2.24-5ubuntu14.2_i386.deb out/
dpkg -x binutils-multiarch-dev_2.24-5ubuntu14.2_i386.deb out/
rm binutils-multiarch*.deb
strip_path=$(readlink -f out/usr/bin/strip)
export LD_LIBRARY_PATH=$(readlink -f out/usr/lib)
fi
# build custom strip
"$REPO_ROOT"/ci/build-static-binutils.sh "$(readlink -f out/)"
strip_path="$(readlink -f out/usr/bin/strip)"
# use tools we just built for linuxdeploy run
export PATH="$(readlink -f out/usr/bin):$PATH"
# args are used more than once
LINUXDEPLOY_ARGS=("--appdir" "AppDir" "-e" "bin/linuxdeploy" "-i" "$REPO_ROOT/resources/linuxdeploy.png" "-d" "$REPO_ROOT/resources/linuxdeploy.desktop" "-e" "/usr/bin/patchelf" "-e" "$strip_path")
LINUXDEPLOY_ARGS=("--appdir" "AppDir" "-e" "bin/linuxdeploy" "-i" "$REPO_ROOT/resources/linuxdeploy.png" "-d" "$REPO_ROOT/resources/linuxdeploy.desktop" "-e" "$patchelf_path" "-e" "$strip_path")
# deploy patchelf which is a dependency of linuxdeploy
bin/linuxdeploy "${LINUXDEPLOY_ARGS[@]}"
@@ -76,8 +76,8 @@ mv squashfs-root/ AppDir/plugins/linuxdeploy-plugin-appimage
ln -s ../../plugins/linuxdeploy-plugin-appimage/AppRun AppDir/usr/bin/linuxdeploy-plugin-appimage
export UPD_INFO="gh-releases-zsync|linuxdeploy|linuxdeploy|continuous|linuxdeploy-$ARCH.AppImage"
export OUTPUT="linuxdeploy-devbuild-$ARCH.AppImage"
export UPD_INFO="gh-releases-zsync|linuxdeploy|linuxdeploy|continuous|linuxdeploy-$ARCH.AppImage.zsync"
export OUTPUT="linuxdeploy-$ARCH.AppImage"
# build AppImage using plugin
AppDir/usr/bin/linuxdeploy-plugin-appimage --appdir AppDir/
+88 -19
View File
@@ -1,28 +1,97 @@
# required for PNG imported target
cmake_minimum_required(VERSION 3.5)
#[=======================================================================[.rst:
FindCImg
-------
find_package(PNG REQUIRED)
find_package(JPEG REQUIRED)
Finds the CImg library.
if(NOT USE_SYSTEM_CIMG)
message(STATUS "Using bundled CImg library")
Imported Targets
^^^^^^^^^^^^^^^^
set(CIMG_H_DIR "${PROJECT_SOURCE_DIR}/lib/CImg/")
This module provides the following imported targets, if found:
``CImg``
The CImg library
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables:
``CImg_FOUND``
True if the system has the CImg library.
``CImg_VERSION``
The version of the CImg library which was found.
``CImg_INCLUDE_DIRS``
Include directories needed to use CImg.
``CImg_LIBRARIES``
Libraries needed to link to CImg.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``CImg_INCLUDE_DIR``
The directory containing ``CImg.h``.
#]=======================================================================]
# 3.6 required for PNG imported target
# 3.9 required for CMAKE_MATCH_<n>
cmake_minimum_required(VERSION 3.9)
find_path(CIMG_H_DIR
NAMES CImg.h
HINTS ${CMAKE_INSTALL_PREFIX} ${CIMG_DIR}
PATH_SUFFIXES include include/linux
)
if(NOT CIMG_H_DIR)
set(CImg_FOUND FALSE)
else()
message(STATUS "Searching for CImg")
set(CImg_FOUND TRUE)
find_path(CIMG_H_DIR
NAMES CImg.h
HINTS ${CMAKE_INSTALL_PREFIX}
PATH_SUFFIXES include include/linux
)
find_package(PkgConfig)
if(NOT CIMG_H_DIR)
message(FATAL_ERROR "CImg.h not found")
pkg_check_modules(libpng REQUIRED libpng)
pkg_check_modules(libjpeg REQUIRED libjpeg)
set(PNG_INCLUDE_DIR ${libpng_INCLUDE_DIRS})
set(JPEG_INCLUDE_DIR ${libjpeg_INCLUDE_DIRS})
if(STATIC_BUILD)
set(PNG_LIBRARY ${libpng_STATIC_LIBRARIES})
set(JPEG_LIBRARIES ${libjpeg_STATIC_LIBRARIES})
else()
set(PNG_LIBRARY ${libpng_LIBRARIES})
set(JPEG_LIBRARIES ${libjpeg_LIBRARIES})
endif()
set(CImg_INCLUDE_DIR ${CIMG_H_DIR} CACHE STRING "")
set(CImg_INCLUDE_DIRS ${CImg_INCLUDE_DIR})
set(CImg_LIBRARIES "${PNG_LIBRARY};${JPEG_LIBRARIES}")
set(CImg_DEFINITIONS "cimg_display=0;cimg_use_png=1;cimg_use_jpeg=1")
file(READ "${CIMG_H_DIR}/CImg.h" header)
string(REGEX MATCH "#define cimg_version ([0-9a-zA-Z\.]+)" _ "${header}")
set(CImg_VERSION "${CMAKE_MATCH_1}")
# CImg_VERSION
if(NOT TARGET CImg)
add_library(CImg INTERFACE)
set_property(TARGET CImg PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CIMG_H_DIR};${PNG_INCLUDE_DIR};${JPEG_INCLUDE_DIR}")
set_property(TARGET CImg PROPERTY INTERFACE_LINK_LIBRARIES "${CImg_LIBRARIES}")
set_property(TARGET CImg PROPERTY INTERFACE_COMPILE_DEFINITIONS "${CImg_DEFINITIONS}")
endif()
endif()
add_library(CImg INTERFACE)
set_property(TARGET CImg PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CIMG_H_DIR};${JPEG_INCLUDE_DIR}")
set_property(TARGET CImg PROPERTY INTERFACE_LINK_LIBRARIES "PNG::PNG;${JPEG_LIBRARIES}")
set_property(TARGET CImg PROPERTY INTERFACE_COMPILE_DEFINITIONS "cimg_display=0;cimg_use_png=1;cimg_use_jpeg=1")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CImg
FOUND_VAR CImg_FOUND
REQUIRED_VARS
CImg_INCLUDE_DIRS
CImg_LIBRARIES
CImg_DEFINITIONS
VERSION_VAR CImg_VERSION
)
+11
View File
@@ -38,6 +38,9 @@ namespace linuxdeploy {
// shortcut for using a normal string instead of a path
explicit AppDir(const std::string& path);
// Set additional shared library name patterns to be excluded from deployment.
void setExcludeLibraryPatterns(const std::vector<std::string> &excludeLibraryPatterns);
// creates basic directory structure of an AppDir in "FHS" mode
bool createBasicStructure() const;
@@ -57,12 +60,20 @@ namespace linuxdeploy {
// deploy executable
bool deployExecutable(const boost::filesystem::path& path, const boost::filesystem::path& destination = "");
// deploy dependencies for ELF file in AppDir, without copying it into the library dir
//
// the dependencies end up in the regular location
bool deployDependenciesOnlyForElfFile(const boost::filesystem::path& elfFilePath, bool failSilentForNonElfFile = false);
// deploy desktop file
bool deployDesktopFile(const desktopfile::DesktopFile& desktopFile);
// deploy icon
bool deployIcon(const boost::filesystem::path& path);
// deploy icon, changing its name to <target filename>.<ext>
bool deployIcon(const boost::filesystem::path& path, const std::string& targetFilename);
// deploy arbitrary file
boost::filesystem::path deployFile(const boost::filesystem::path& from, const boost::filesystem::path& to);
@@ -11,7 +11,7 @@
namespace linuxdeploy {
namespace core {
namespace elf {
namespace elf_file {
// thrown by constructor if file is not an ELF file
class ElfFileParseError : public std::runtime_error {
public:
@@ -64,6 +64,12 @@ namespace linuxdeploy {
// return OS ABI
uint8_t getElfABI();
// check if this file is a debug symbols file
bool isDebugSymbolsFile();
// check whether the file contains a dynsym section
bool isDynamicallyLinked();
};
}
}
+2
View File
@@ -65,6 +65,8 @@ namespace linuxdeploy {
ldLog operator<<(stdEndlType strm);
ldLog operator<<(const LD_LOGLEVEL logLevel);
ldLog operator<<(const LD_STREAM_CONTROL streamControl);
void write(const char* s, const size_t n);
};
}
}
+20 -136
View File
@@ -2,15 +2,19 @@
#include <set>
#include <string>
#include <vector>
#include <fcntl.h>
#include <poll.h>
// library headers
#include <boost/filesystem.hpp>
#include <fnmatch.h>
#include <subprocess.hpp>
#include <thread>
// local headers
#include "linuxdeploy/core/log.h"
#include "linuxdeploy/util/util.h"
#include "linuxdeploy/subprocess/process.h"
#include "linuxdeploy/plugin/plugin_process_handler.h"
#pragma once
@@ -45,13 +49,20 @@ namespace linuxdeploy {
private:
int getApiLevelFromExecutable() {
auto output = subprocess::check_output({pluginPath.c_str(), "--plugin-api-version"});
std::string stdoutOutput = output.buf.data();
const auto arg = "--plugin-api-version";
const subprocess::subprocess proc({pluginPath.string(), arg});
const auto stdoutOutput = proc.check_output();
if (stdoutOutput.empty()) {
ldLog() << LD_WARNING << "received empty response from plugin" << pluginPath << "while trying to fetch data for" << "--plugin-api-version" << std::endl;
return -1;
}
try {
auto apiLevel = std::stoi(stdoutOutput);
return apiLevel;
} catch (const std::invalid_argument&) {
} catch (const std::exception&) {
return -1;
}
}
@@ -62,9 +73,8 @@ namespace linuxdeploy {
// check whether plugin implements --plugin-type
try {
auto output = subprocess::check_output({pluginPath.c_str(), "--plugin-type"});
std::string stdoutOutput = output.buf.data();
const subprocess::subprocess proc({pluginPath.c_str(), "--plugin-type"});
const auto stdoutOutput = proc.check_output();
// the specification requires a single line, but we'll silently accept more than that, too
if (std::count(stdoutOutput.begin(), stdoutOutput.end(), '\n') >= 1) {
@@ -75,7 +85,7 @@ namespace linuxdeploy {
else if (firstLine == "output")
type = OUTPUT_TYPE;
}
} catch (const subprocess::CalledProcessError&) {}
} catch (const std::logic_error&) {}
return type;
}
@@ -126,134 +136,8 @@ namespace linuxdeploy {
template<int API_LEVEL>
int PluginBase<API_LEVEL>::run(const boost::filesystem::path& appDirPath) {
auto pluginPath = path();
auto args = {pluginPath.c_str(), "--appdir", appDirPath.string().c_str()};
auto log = ldLog();
log << "Running process:";
for (const auto& arg : args) {
log << "" << arg;
}
log << std::endl;
auto process = subprocess::Popen(args, subprocess::output{subprocess::PIPE}, subprocess::error{subprocess::PIPE});
std::vector<pollfd> pfds(2);
auto* opfd = &pfds[0];
auto* epfd = &pfds[1];
opfd->fd = fileno(process.output());
opfd->events = POLLIN;
epfd->fd = fileno(process.error());
epfd->events = POLLIN;
for (const auto& fd : {process.output(), process.error()}) {
auto flags = fcntl(fileno(fd), F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fileno(fd), F_SETFL, flags);
}
auto printOutput = [&pfds, opfd, epfd, this, &process]() {
poll(pfds.data(), pfds.size(), -1);
auto printUntilLastLine = [this](std::vector<char>& buf, size_t& bufSize, const std::string& streamType) {
std::ostringstream oss;
while (true) {
const auto firstLineFeed = std::find(buf.begin(), buf.end(), '\n');
const auto firstCarriageReturn = std::find(buf.begin(), buf.end(), '\r');
if (firstLineFeed == buf.end() && firstCarriageReturn == buf.end())
break;
const auto endOfLine = std::min(firstLineFeed, firstCarriageReturn);
std::string line(buf.begin(), endOfLine+1);
oss << "[" << d->name << "/" << streamType << "] " << line;
bufSize -= std::distance(buf.begin(), endOfLine+1);
buf.erase(buf.begin(), endOfLine+1);
}
auto messages = oss.str();
if (!messages.empty())
ldLog() << messages;
};
std::vector<char> stdoutBuf(16 * 1024);
std::vector<char> stderrBuf(16 * 1024);
size_t stdoutBufSize = 0;
size_t stderrBufSize = 0;
if (opfd->revents & POLLIN) {
if (stdoutBufSize >= stdoutBuf.size())
throw std::runtime_error("Buffer overflow");
while (true) {
auto bytesRead = fread(
reinterpret_cast<void*>(stdoutBuf.data() + stdoutBufSize),
sizeof(char),
static_cast<size_t>(stdoutBuf.size() - stdoutBufSize),
process.output()
);
if (bytesRead == 0)
break;
stdoutBufSize += bytesRead;
printUntilLastLine(stdoutBuf, stdoutBufSize, "stdout");
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (epfd->revents & POLLIN) {
if (stderrBufSize >= stderrBuf.size())
throw std::runtime_error("Buffer overflow");
while (true) {
auto bytesRead = fread(
reinterpret_cast<void*>(stderrBuf.data() + stderrBufSize),
sizeof(char),
static_cast<size_t>(stderrBuf.size() - stderrBufSize),
process.error()
);
if (bytesRead == 0)
break;
stderrBufSize += bytesRead;
printUntilLastLine(stderrBuf, stderrBufSize, "stderr");
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
return true;
};
int retcode;
do {
if (!printOutput()) {
ldLog() << LD_ERROR << "Failed to communicate with process" << std::endl;
process.kill();
return -1;
}
} while ((retcode = process.poll()) < 0);
if (!printOutput()) {
ldLog() << LD_ERROR << "Failed to communicate with process" << std::endl;
process.kill();
return -1;
}
return retcode;
plugin_process_handler handler(d->name, path());
return handler.run(appDirPath);
}
}
}
@@ -0,0 +1,19 @@
#pragma once
// library headers
#include <boost/filesystem/path.hpp>
namespace linuxdeploy {
namespace plugin {
class plugin_process_handler {
private:
std::string name_;
boost::filesystem::path path_;
public:
plugin_process_handler(std::string name, boost::filesystem::path path);
int run(const boost::filesystem::path& appDir) const;
};
}
}
@@ -0,0 +1,36 @@
#pragma once
#include <string>
#include <set>
#include <vector>
#include <poll.h>
/**
* Reads from a pipe when data is available, and hands data to registered callbacks.
*/
class pipe_reader {
private:
const int pipe_fd_;
public:
/**
* Construct new instance from pipe file descriptor.
* @param pipe_fd file descriptor for pipe we will read from (e.g., a subprocess's stdout, stderr pipes)
*/
explicit pipe_reader(int pipe_fd);
/**
* Read from pipe file descriptor and store data in buffer.
* This method is non-blocking, i.e., if there is no data to read, it returns immediately.
* Otherwise, it will read until either of the following conditions is met:
*
* - no more data left in the pipe to be read
* - buffer is completely filled
*
* On errors, a subprocess_error is thrown.
*
* @param buffer buffer to store read data into
* @returns amount of characters read from the pipe
*/
size_t read(std::vector<std::string::value_type>& buffer) const;
};
+88
View File
@@ -0,0 +1,88 @@
// system headers
#include <unordered_map>
#include <vector>
#include <signal.h>
// local headers
#include "linuxdeploy/subprocess/subprocess.h"
namespace linuxdeploy {
namespace subprocess {
class process {
private:
// child process ID
int child_pid_ = -1;
// pipes to child process's stdout/stderr
int stdout_fd_ = -1;
int stderr_fd_ = -1;
// process exited
bool exited_ = false;
// exit code -- will be initialized by close()
int exit_code_ = -1;
// these constants help make the pipe code more readable
static constexpr int READ_END_ = 0, WRITE_END_ = 1;
static std::vector<char*> make_args_vector_(const std::vector<std::string>& args);
static std::vector<char*> make_env_vector_(const subprocess_env_map_t& env);
static int check_waitpid_status_(int status);
static void close_pipe_fd_(int fd);
public:
/**
* Create a child process.
* @param args parameters for process
* @param env additional environment variables (current environment will be copied)
*/
process(std::initializer_list<std::string> args, const subprocess_env_map_t& env);
/**
* Create a child process.
* @param args parameters for process
* @param env additional environment variables (current environment will be copied)
*/
process(const std::vector<std::string>& args, const subprocess_env_map_t& env);
~process();
/**
* @return child process's ID
*/
int pid() const;
/**
* @return child process's stdout file descriptor ID
*/
int stdout_fd() const;
/**
* @return child process's stderr file descriptor ID
*/
int stderr_fd() const;
/**
* Close all pipes and wait for process to exit.
* If process is not running any more, just returns exit code.
* @return child process's exit code
*/
int close();
/**
* Kill underlying process with given signal. By default, SIGTERM is used to end the process.
*/
void kill(int signal = SIGTERM) const;
/**
* Check whether process is still alive. Use close() to fetch exit code.
* @return true while process is alive, false otherwise
*/
bool is_running();
};
}
}
@@ -0,0 +1,32 @@
#pragma once
// system headers
#include <cstdio>
#include <unordered_map>
#include <string>
#include <utility>
#include <vector>
// local headers
#include "subprocess_result.h"
namespace linuxdeploy {
namespace subprocess {
typedef std::unordered_map<std::string, std::string> subprocess_env_map_t;
class subprocess {
private:
std::vector<std::string> args_{};
std::unordered_map<std::string, std::string> env_{};
public:
subprocess(std::initializer_list<std::string> args, subprocess_env_map_t env = {});
explicit subprocess(std::vector<std::string> args, subprocess_env_map_t env = {});
subprocess_result run() const;
std::string check_output() const;
};
}
}

Some files were not shown because too many files have changed in this diff Show More