diff options
Diffstat (limited to '')
-rw-r--r-- | .gitattributes | 1 | ||||
-rw-r--r-- | .github/workflows/test.yml | 78 | ||||
-rw-r--r-- | LICENSE.txt | 21 | ||||
-rw-r--r-- | action.yml | 92 | ||||
-rw-r--r-- | foo.cpp | 39 |
5 files changed, 231 insertions, 0 deletions
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..dc8e74f --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,78 @@ +name: Test + +on: + push: + pull_request: + schedule: + # Weekly, at 5:45 AM on Friday (somewhat randomly chosen). + - cron: '45 5 * * 5' + workflow_dispatch: + +jobs: + test: + strategy: + fail-fast: false + matrix: + platform: [x86, x64] + cygwin: [0, 1] + os: [ubuntu-18.04, windows-2019, windows-2016] + + include: + # Prettier run names. + - {os: ubuntu-18.04, name: Ubuntu} + - {os: windows-2019, name: Windows Server 2019} + - {os: windows-2016, name: Windows Server 2016} + - {cygwin: 1, name: Cygwin} + exclude: + # No Cygwin on Ubuntu. + - {os: ubuntu-18.04, cygwin: 1} + # Cygwin is the same on Windows Server 2016 & 2019. + - {os: windows-2016, cygwin: 1} + + runs-on: '${{ matrix.os }}' + + name: '${{ matrix.name }} / ${{ matrix.platform }}' + + defaults: + run: + shell: pwsh + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Clean up PATH + uses: egor-tensin/cleanup-path@v1 + if: runner.os == 'Windows' + + - name: Install Cygwin + uses: egor-tensin/setup-cygwin@master + with: + platform: '${{ matrix.platform }}' + if: matrix.cygwin + + - name: Set up Clang + id: setup + uses: ./ + with: + platform: '${{ matrix.platform }}' + cygwin: '${{ matrix.cygwin }}' + + - name: Build foo.exe + run: | + $flags = @() + if ('${{ matrix.platform }}' -eq 'x86') { + $flags += '-m32' + } + $flags += @( + '-x', 'c++', + '-std=c++14', + '-o', 'foo', + 'foo.cpp', + '-lstdc++' + ) + if ('${{ runner.os }}' -eq 'Linux') { + $flags += '-lpthread' + } + & '${{ steps.setup.outputs.clangxx }}' $flags + & (Join-Path . foo) 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 <Egor.Tensin@gmail.com> + +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/action.yml b/action.yml new file mode 100644 index 0000000..72e0e80 --- /dev/null +++ b/action.yml @@ -0,0 +1,92 @@ +name: Install Clang +description: Install Clang & LLVM + +inputs: + platform: + description: Target platform + required: false + default: x64 + cygwin: + description: Install inside Cygwin + required: false + default: 0 + +outputs: + clang: + description: clang executable name or path + value: '${{ steps.setup.outputs.clang }}' + clangxx: + description: clang++ executable name or path + value: '${{ steps.setup.outputs.clangxx }}' + +runs: + using: composite + steps: + - id: setup + run: | + New-Variable os -Value '${{ runner.os }}' -Option Constant + + New-Variable linux_host -Value ($os -eq 'Linux') -Option Constant + New-Variable cygwin_host -Value ('${{ inputs.cygwin }}' -eq '1') -Option Constant + New-Variable windows_host -Value ($os -eq 'Windows' -and !$cygwin) -Option Constant + + New-Variable x64 -Value ('${{ inputs.platform }}' -eq 'x64') -Option Constant + + function Locate-Choco { + $path = Get-Command 'choco' -ErrorAction SilentlyContinue + if ($path) { + $path.Path + } else { + Join-Path ${env:ProgramData} 'chocolatey' 'bin' 'choco' + } + } + + if ($linux_host) { + sudo apt update + if ($x64) { + sudo apt install -y clang g++ + } else { + sudo apt install -y clang g++-multilib + } + + echo "::set-output name=clang::clang" + echo "::set-output name=clangxx::clang++" + } elseif ($cygwin_host) { + if (!$x64) { + echo @' + ::warning :: + 32-bit-targeting Clang is unavailable on 64-bit Cygwin. + Please use 32-bit Cygwin instead. + If you _are_ using 32-bit Cygwin, please ignore this message. + '@ + } + $choco = Locate-Choco + + # IDK why, but without libiconv-devel, even a "Hello, world!" + # C++ app cannot be compiled as of December 2020. + # Also, libstdc++ is required, and for simplicity's sake, gcc-g++ + # is installed. + & $choco install -y --no-progress --source=cygwin clang libiconv-devel gcc-g++ + + # clang/clang++ are symlinks on Cygwin, pointing to clang-VERSION.exe. + $clang = cygpath.exe -wa (readlink.exe --canonicalize-existing /usr/bin/clang) + $clangxx = cygpath.exe -wa (readlink.exe --canonicalize-existing /usr/bin/clang++) + + echo "::set-output name=clang::$clang" + echo "::set-output name=clangxx::$clangxx" + } elseif ($windows_host) { + $choco = Locate-Choco + + & $choco install -y --no-progress llvm + echo (Join-Path $env:ProgramFiles LLVM bin) >> $env:GITHUB_PATH + + echo "::set-output name=clang::clang" + echo "::set-output name=clangxx::clang++" + } else { + throw "Sorry, installing Clang is unsupported on $os" + } + shell: pwsh + +branding: + icon: star + color: green @@ -0,0 +1,39 @@ +#include <array> +#include <cstddef> +#include <exception> +#include <functional> +#include <iostream> +#include <mutex> +#include <thread> + +namespace { + +struct Counter { + std::mutex mtx; + std::size_t impl = 0; +}; + +void do_something(Counter& counter) { + std::lock_guard<std::mutex> lck{counter.mtx}; + ++counter.impl; + std::cout << "Doing something #" << counter.impl << '\n'; +} + +} + +int main() { + try { + Counter counter; + std::array<std::thread, 3> 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; +} |