From 92327f87384c357264454a98c83aae733a6b6495 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 19 Nov 2020 03:08:27 +0300 Subject: initial commit --- .gitattributes | 1 + .github/workflows/test.yml | 48 ++++++++++++++++ LICENSE.txt | 21 +++++++ README.md | 49 +++++++++++++++++ action.yml | 133 +++++++++++++++++++++++++++++++++++++++++++++ foo.cpp | 39 +++++++++++++ 6 files changed, 291 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/workflows/test.yml create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 action.yml create mode 100644 foo.cpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b0957f9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,48 @@ +name: Test + +on: + push: + pull_request: + schedule: + # Weekly, at 5:45 AM on Friday (somewhat randomly chosen). + - cron: '45 6 * * 5' + workflow_dispatch: + +jobs: + test: + strategy: + fail-fast: false + matrix: + os: [ubuntu-18.04, windows-2019, windows-2016] + platform: [x86, x64] + + include: + # Prettier run names. + - {os: ubuntu-18.04, name: Ubuntu} + - {os: windows-2019, name: Windows Server 2019} + - {os: windows-2016, name: Windows Server 2016} + + runs-on: '${{ matrix.os }}' + + name: '${{ matrix.name }} / ${{ matrix.platform }}' + + defaults: + run: + shell: pwsh + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up MinGW + id: setup + uses: ./ + with: + platform: '${{ matrix.platform }}' + + - name: Build foo.exe + run: | + & '${{ steps.setup.outputs.gxx }}' -std=c++11 -o foo foo.cpp + if ('${{ runner.os }}' -eq 'Windows') { + .\foo.exe + } diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..ab8c3ff --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Egor Tensin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..796d540 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +Set up MinGW-w64 +================ + +This is a GitHub action that sets up MinGW-w64 in your workflow run. + +1. Installs MinGW-w64 on either Ubuntu or Windows. +2. Fixes the infamous libwinpthread-1.dll [static linking issue]. + +[static linking issue]: https://stackoverflow.com/q/13768515/514684 + +Use it in your workflow like this: + + - name: Set up MinGW + uses: egor-tensin/setup-mingw@v1 + with: + platform: x64 + +`x64` is the default value for the `platform` parameter and can be omitted. +Use `x86` if you want to build 32-bit binaries. + +Set the `cygwin` parameter to `1` to set up MinGW inside an existing Cygwin +installation (installing Cygwin itself is as simple as `choco install cygwin`). + +API +--- + +| Input | Value | Default | Description +| -------- | ------- | ------- | ----------- +| platform | x64 | Yes | Install the x86_64 toolchain. +| | *Other* | No | Install the i686 toolchain. +| cygwin | 1 | No | Install Cygwin packages. +| | *Other* | Yes | Install native binaries. +| static | 1 | Yes | Enable the static-linking workaround. +| | *Other* | No | Disable the static-linking workaround. + +| Output | Example | Description +| ------- | ------------------------ | ----------- +| prefix | x86_64-w64-mingw32 | Cross-compilation toolchain prefix +| gcc | x86_64-w64-mingw32-gcc | gcc binary name +| gxx | i686-w64-mingw32-g++ | g++ binary name +| windres | i686-w64-mingw32-windres | windres binary name + +License +------- + +Distributed under the MIT License. +See [LICENSE.txt] for details. + +[LICENSE.txt]: LICENSE.txt diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..77afb1b --- /dev/null +++ b/action.yml @@ -0,0 +1,133 @@ +name: Install MinGW +description: Install MinGW-w64 + +inputs: + platform: + description: Target platform + required: false + default: x64 + cygwin: + description: Install inside Cygwin + required: false + default: 0 + static: + description: Enable static linking workaround + required: False + default: 1 + +outputs: + prefix: + description: Cross-compilation toolchain prefix + value: '${{ steps.setup.outputs.prefix }}' + gcc: + description: gcc binary name + value: '${{ steps.setup.outputs.gcc }}' + gxx: + description: g++ binary name + value: '${{ steps.setup.outputs.gxx }}' + windres: + description: windres binary name + value: '${{ steps.setup.outputs.windres }}' + +runs: + using: composite + steps: + - id: setup + run: | + $x64 = '${{ inputs.platform }}' -eq 'x64' + $cygwin = '${{ inputs.cygwin }}' -eq '1' + $static_workaround = '${{ inputs.static }}' -eq '1' + + $prefix32 = 'i686-w64-mingw32' + $prefix64 = 'x86_64-w64-mingw32' + $prefix = if ($x64) { $prefix64 } else { $prefix32 } + + if ('${{ runner.os }}' -eq 'Linux') { + # ------------------------------------------------------------- + # Ubuntu + # ------------------------------------------------------------- + sudo apt install mingw-w64 + + # Make the compilers use the POSIX threading model, whatever that + # is. Without it, the stuff from //etc. doesn't + # compile. Of course, it makes the binaries depend on + # libwinpthread-1.dll, but what you gonna do? + + sudo update-alternatives --set "$prefix32-gcc" "/usr/bin/$prefix32-gcc-posix" + sudo update-alternatives --set "$prefix32-g++" "/usr/bin/$prefix32-g++-posix" + sudo update-alternatives --set "$prefix64-gcc" "/usr/bin/$prefix64-gcc-posix" + sudo update-alternatives --set "$prefix64-g++" "/usr/bin/$prefix64-g++-posix" + + if ($static_workaround) { + sudo rm ` + "/usr/$prefix32/lib/libpthread.dll.a" ` + "/usr/$prefix32/lib/libwinpthread.dll.a" ` + "/usr/$prefix64/lib/libpthread.dll.a" ` + "/usr/$prefix64/lib/libwinpthread.dll.a" + } + } elseif ('${{ runner.os }}' -eq 'Windows') { + if ($cygwin) { + # ------------------------------------------------------------- + # Cygwin + # ------------------------------------------------------------- + $cygwin_pkg = if ($x64) { 'mingw64-x86_64-gcc-g++' } else { 'mingw64-i686-gcc-g++' } + choco.exe install -y --no-progress --source=cygwin $cygwin_pkg + + if ($static_workaround) { + $cygwin_lib = Join-Path C: tools cygwin usr $prefix sys-root mingw lib + Remove-Item (Join-Path $cygwin_lib 'libpthread.dll.a') + Remove-Item (Join-Path $cygwin_lib 'libwinpthread.dll.a') + } + } else { + # ------------------------------------------------------------- + # Windows + # ------------------------------------------------------------- + $mingw32 = 'mingw32' + $mingw64 = 'mingw64' + $mingw = if ($x64) { $mingw64 } else { $mingw32 } + + $mingw_install = Join-Path C: ProgramData chocolatey lib mingw tools install + + $mingw32_root = Join-Path $mingw_install $mingw32 + $mingw64_root = Join-Path $mingw_install $mingw64 + $mingw_root = Join-Path $mingw_install $mingw + + $mingw32_bin = Join-Path $mingw32_root bin + $mingw64_bin = Join-Path $mingw64_root bin + $mingw_bin = Join-Path $mingw_root bin + + $mingw_lib = Join-Path $mingw_root $prefix lib + + if ($x64) { + # Assuming the 64-bit version is installed. If 32-bit + # version is installed, we won't detect that. But it's not + # _that_ important, and we save a lot of time. + choco.exe install -y --no-progress mingw + echo $mingw64_bin >> $env:GITHUB_PATH + } else { + # Assuming the 64-bit version is installed. + choco.exe uninstall -y --no-progress mingw + choco.exe install -y --no-progress --x86 mingw + echo $mingw32_bin >> $env:GITHUB_PATH + } + + if ($static_workaround) { + Remove-Item (Join-Path $mingw_lib 'libpthread.dll.a') + Remove-Item (Join-Path $mingw_lib 'libwinpthread.dll.a') + } + } + } + + $gcc = $prefix + '-gcc' + $gxx = $prefix + '-g++' + $windres = $prefix = '-windres' + + echo "::set-output name=prefix::$prefix" + echo "::set-output name=gcc::$gcc" + echo "::set-output name=gxx::$gxx" + echo "::set-output name=windres::$windres" + shell: pwsh + +branding: + icon: star + color: green diff --git a/foo.cpp b/foo.cpp new file mode 100644 index 0000000..a7891bb --- /dev/null +++ b/foo.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace { + +struct Counter { + std::mutex mtx; + std::size_t impl = 0; +}; + +void do_something(Counter& counter) { + std::lock_guard lck{counter.mtx}; + ++counter.impl; + std::cout << "Doing something #" << counter.impl << '\n'; +} + +} + +int main() { + try { + Counter counter; + std::array workers; + for (auto& worker : workers) { + worker = std::thread{&do_something, std::ref(counter)}; + } + for (auto& worker : workers) { + worker.join(); + } + } catch (const std::exception& e) { + std::cerr << e.what() << '\n'; + return 1; + } + return 0; +} -- cgit v1.2.3