diff --git a/.github/workflows/build-native.yml b/.github/workflows/build-native.yml index dd6033f..6fa5f70 100644 --- a/.github/workflows/build-native.yml +++ b/.github/workflows/build-native.yml @@ -7,6 +7,12 @@ name: Build native # They are committed rather than built during a normal build so that a plain # `dotnet build src --configuration Release` produces a shippable package on any machine, and # contributors never need a C++ toolchain. Run this whenever native/ changes. +# +# The work is PlatformHeads' build-native workflow, which DiffEngine's viewer is built by too: the +# Linux library built in a manylinux_2_28 container and checked for the glibc it needs and the +# libraries it records as needed, the universal dylib, and the pull request with the binaries. +# Each of those was once a copy here, and a fix made to the other copy did not reach this one. +# The tag is the one native/CMakeLists.txt fetches and Directory.Packages.props names. on: push: paths: @@ -27,206 +33,22 @@ concurrency: cancel-in-progress: true jobs: - build: - name: ${{ matrix.rid }} - runs-on: ${{ matrix.os }} - timeout-minutes: 45 - strategy: - fail-fast: false - matrix: - include: - # No Windows entries. That head renders with WinForms and loads no native library. - - rid: linux-x64 - os: ubuntu-24.04 - - rid: linux-arm64 - os: ubuntu-24.04-arm - # One universal binary covers both macOS RIDs; it is copied into each below. - - rid: osx - os: macos-14 - steps: - - name: Checkout - uses: actions/checkout@v7 - - # In a manylinux_2_28 container rather than on the runner, for its glibc 2.28, which is - # RHEL 8's. A library records the glibc symbol versions of the headers it was compiled - # against, and the loader refuses it anywhere older. Built on the runner's own Ubuntu 24.04 - # it needed GLIBC_2.38, so the Linux head could not load it on Ubuntu 22.04, Debian 12, or - # RHEL 8 or 9, and BuildMonitor exited there without opening a window. - - name: Build - if: runner.os == 'Linux' - run: docker run --rm -v "$PWD:/src" -w /src "quay.io/pypa/manylinux_2_28_$(uname -m)" bash native/build-linux.sh - - # The floor the container is there to hold, checked rather than trusted, since nothing else - # would notice until a user on an older distribution did. - - name: Check glibc floor - if: runner.os == 'Linux' - env: - GLIBC_FLOOR: GLIBC_2.28 - run: | - highest=$(objdump -T build/libbuildmonitor_ui.so | grep -o 'GLIBC_[0-9][0-9.]*' | sort -uV | tail -n 1) - echo "Highest glibc symbol version required: $highest" - if [ "$(printf '%s\n' "$GLIBC_FLOOR" "$highest" | sort -V | tail -n 1)" != "$GLIBC_FLOOR" ]; then - echo "::error::libbuildmonitor_ui.so requires $highest, above the $GLIBC_FLOOR floor" - exit 1 - fi - # libGL.so.1 is on every machine with a GL driver; libOpenGL.so.0 is not - if objdump -p build/libbuildmonitor_ui.so | grep -q 'NEEDED.*libOpenGL'; then - echo "::error::libbuildmonitor_ui.so links libOpenGL.so.0 rather than libGL.so.1" - exit 1 - fi - - # Everything recorded as needed has to be on a machine for the library to load at all, so - # the list is held to what any machine that runs .NET and has a display already has. The - # container's linker records every library it is handed, used or not, and raylib hands on - # libSM and libICE, which a stock Ubuntu lacks. native/CMakeLists.txt links with --as-needed - # so that neither is recorded, and this is what notices the list growing by any other route. - - name: Check needed libraries - if: runner.os == 'Linux' - env: - ALLOWED: >- - libc.so.6 libm.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libstdc++.so.6 libgcc_s.so.1 - libX11.so.6 libGL.so.1 ld-linux-x86-64.so.2 ld-linux-aarch64.so.1 - run: | - needed=$(objdump -p build/libbuildmonitor_ui.so | awk '$1 == "NEEDED" { print $2 }') - echo "Needed:" $needed - failed=0 - for library in $needed; do - case " $ALLOWED " in - *" $library "*) ;; - *) - echo "::error::libbuildmonitor_ui.so needs $library, which is not in the list of libraries it may need" - failed=1 - ;; - esac - done - exit $failed - - # macOS draws with AppKit and Core Text rather than raylib and ImGui, so it is a Swift - # package rather than a CMake project. Both --arch flags in one invocation produce a - # universal binary, so there is no separate lipo step. - - name: Build - if: matrix.rid == 'osx' - run: swift build -c release --arch arm64 --arch x86_64 --package-path native/swift - - # The folder panel, and turning AppKit's frames into the ABI's placements, are what this head - # decides by itself rather than drawing from a screen the managed side built, so they are - # what has tests here. A scratch path of its - # own, because a test build is debug and for this machine's architecture alone: left in .build - # its dylib would be among the candidates the collect step below merges. - - name: Test - if: matrix.rid == 'osx' - run: swift test --package-path native/swift --scratch-path native/swift/.build-tests - - - name: Collect - shell: bash - run: | - # Laid out as src/{head}/runtimes/{rid}/native, so the propose job below can merge every - # artifact straight into src and the binaries land in the head that loads them. - collect() { - mkdir -p "artifacts/$1/runtimes/$2/native" - cp "$3" "artifacts/$1/runtimes/$2/native/" - } - case "${{ matrix.rid }}" in - linux-*) - # Already stripped, inside the container that owns the build directory - collect BuildMonitor.Native "${{ matrix.rid }}" build/libbuildmonitor_ui.so - ;; - osx) - # swift build leaves a per architecture dylib in more than one place. Every candidate - # is checked, and if none is already universal they are merged, so the only thing - # that can be collected is a fat binary. The dSYM holds a DWARF file of the same - # name which is also universal, so it is excluded by path. - candidates=$(find native/swift/.build -name libbuildmonitor_ui.dylib -not -path '*.dSYM/*') - if [ -z "$candidates" ]; then - echo "::error::swift build produced no libbuildmonitor_ui.dylib" - exit 1 - fi - - dylib="" - for candidate in $candidates; do - archs=$(lipo -archs "$candidate" 2>/dev/null || echo "") - if [[ "$archs" == *x86_64* && "$archs" == *arm64* ]]; then - dylib="$candidate" - break - fi - done - - if [ -z "$dylib" ]; then - dylib=universal/libbuildmonitor_ui.dylib - mkdir -p universal - # shellcheck disable=SC2086 - lipo -create $candidates -output "$dylib" - fi - - archs=$(lipo -archs "$dylib") - echo "collecting $dylib: $archs" - for arch in x86_64 arm64; do - case " $archs " in - *" $arch "*) ;; - *) echo "::error::$dylib is missing the $arch slice"; exit 1 ;; - esac - done - - strip -x "$dylib" - # The dylib is universal, so both macOS RIDs get the same file. - collect BuildMonitor.Native osx-x64 "$dylib" - collect BuildMonitor.Native osx-arm64 "$dylib" - ;; - esac - ls -lhR artifacts - - - name: Upload - uses: actions/upload-artifact@v7 - with: - name: native-${{ matrix.rid }} - path: artifacts/ - retention-days: 7 - - propose: - name: propose update - needs: build - # Also on push, not just manual dispatch. workflow_dispatch does not appear in the Actions UI - # until the workflow is on the default branch, so on a feature branch a push is the only way - # to trigger this. - # - # Branches only. Never on pull_request, which would mean opening a PR from a PR, and never on - # a tag: a tag checkout is a detached HEAD with no base branch to target. - if: >- - github.event_name != 'pull_request' && - startsWith(github.ref, 'refs/heads/') && - (github.event_name != 'workflow_dispatch' || inputs.commit) - runs-on: ubuntu-latest + native: + uses: SimonCropp/PlatformHeads/.github/workflows/build-native.yml@0.1.0 permissions: contents: write pull-requests: write - steps: - - name: Checkout - uses: actions/checkout@v7 - - - name: Download - uses: actions/download-artifact@v8 - with: - pattern: native-* - merge-multiple: true - path: src - - - name: Show what changed - run: | - ls -lhR src/BuildMonitor.Native/runtimes - git status --short - - # A PR rather than a direct push: these are binaries, so the diff is not reviewable and the - # change deserves an explicit approval. - - name: Open pull request - uses: peter-evans/create-pull-request@v8 - with: - branch: native-binaries-${{ github.ref_name }} - title: 'Rebuild native UI binaries' - commit-message: 'Rebuild native UI binaries' - body: | - Rebuilt `buildmonitor_ui` from `native/` for the four RIDs that load one. - Windows is not among them: that head renders with WinForms. - - Produced by the `build-native` workflow from ${{ github.sha }}. - add-paths: | - src/BuildMonitor.Native/runtimes + with: + library: buildmonitor_ui + linux-runtimes: src/BuildMonitor.Native/runtimes + swift-package: native/swift + mac-runtimes: src/BuildMonitor.Native/runtimes + # The folder panel, and turning AppKit's frames into the ABI's placements, are what the + # macOS head decides by itself rather than drawing from a screen the managed side built, so + # they are what has tests there. + swift-test: true + # Also on push, not just manual dispatch. workflow_dispatch does not appear in the Actions + # UI until the workflow is on the default branch, so on a feature branch a push is the only + # way to trigger this. + propose: ${{ github.event_name != 'workflow_dispatch' || inputs.commit }} + pull-request-title: Rebuild native UI binaries diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 26dbec6..cf77038 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,7 +70,7 @@ jobs: if-no-files-found: ignore retention-days: 14 - # BM0001 warns when a RID has no native renderer. Shipping a package that cannot run on a + # PH0001 warns when a RID has no native renderer. Shipping a package that cannot run on a # platform it claims to support is worse than failing the release. - name: Verify every RID has a native renderer if: startsWith(github.ref, 'refs/tags/') diff --git a/claude.md b/claude.md index 589d9cd..ae49cfb 100644 --- a/claude.md +++ b/claude.md @@ -61,7 +61,8 @@ BuildMonitor is a tray app that polls CI services and shows one row per pipeline - `Auth/` — OAuth browser flow (PKCE + loopback listener), device flow, and per-OS secret stores. Secrets never go in settings.json. - `Protocol/` — the loopback socket the tray binds (single-instance gate) and the line protocol the launcher and the MCP server use to talk to it. - `src/BuildMonitor.Windows/` — WinForms head (`BuildMonitor.Tray.exe`): `NotifyIcon` tray, owner-drawn rows, real controls for form pages. -- `src/BuildMonitor.Native/` — macOS and Linux head (`BuildMonitor.Tray`) over the C ABI in `native/include/bm.h`; Swift/AppKit on macOS (`native/swift`), raylib + Dear ImGui on Linux (`native/`). Binaries are committed under `runtimes/{rid}/native` and regenerated by the `build-native` workflow, which opens a PR. The Linux library is built in a `manylinux_2_28` container (`native/build-linux.sh`), so it needs no glibc newer than 2.28: built on the runner's own Ubuntu 24.04 it needed 2.38, and would not load on Ubuntu 22.04 or Debian 12. It is linked with `--as-needed`, since that container's linker otherwise records libSM and libICE, which a stock Ubuntu lacks, and `build-native` fails a build above the floor or one whose `NEEDED` entries are outside a short list. The Linux tray is StatusNotifierItem over D-Bus in managed code. +- `src/BuildMonitor.Native/` — macOS and Linux head (`BuildMonitor.Tray`) over the C ABI in `native/include/bm.h`; Swift/AppKit on macOS (`native/swift`), raylib + Dear ImGui on Linux (`native/`). Binaries are committed under `runtimes/{rid}/native` and regenerated by the `build-native` workflow, which opens a PR. The Linux library is built in a `manylinux_2_28` container, so it needs no glibc newer than 2.28: built on the runner's own Ubuntu 24.04 it needed 2.38, and would not load on Ubuntu 22.04 or Debian 12. It is linked with `--as-needed`, since that container's linker otherwise records libSM and libICE, which a stock Ubuntu lacks, and `build-native` fails a build above the floor or one whose `NEEDED` entries are outside a short list. The Linux tray is StatusNotifierItem over D-Bus in managed code. +- The build and packaging of the heads is PlatformHeads' (`D:\Code\PlatformHeads`, github.com/SimonCropp/PlatformHeads), which DiffEngine's viewer is to share: it was a copy here, and fixes made to DiffEngine's copy did not reach this one. Three pins name one tag of it and move together: the `uses:` of `.github/workflows/build-native.yml`, the `GIT_TAG` in `native/CMakeLists.txt`, and `PlatformHeads` in `Directory.Packages.props`. The workflow is its reusable `build-native`; the CMake module pins raylib and Dear ImGui and carries the raylib 6.0 option workarounds; the package's targets publish and bundle the `PlatformHead` items of `BuildMonitor.csproj` (`PH0001` for a native head with no library, `PH0002` for an apphost that was not staged). A fix to any of that goes there, not here. To build the Linux library by hand, from the repository root: `docker run --rm -v "$PWD:/src" -v "D:/Code/PlatformHeads/native:/ph:ro" -w /src -e LIBRARY=buildmonitor_ui "quay.io/pypa/manylinux_2_28_$(uname -m)" bash /ph/build-linux.sh`. - `src/BuildMonitor/` — the one package (`dotnet tool install -g BuildMonitor`). A launcher that starts the head for the current RID from `heads/{rid}/`, plus the `mcp` (stdio MCP server) and `status` verbs. It is `WinExe` so the tool shim is GUI subsystem and can sit in the Run-at-login key. Set `BuildMonitor_Head` to a head executable to run a local build through it. - Heads are bundled, never packaged on their own. diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 80bd485..176e2d0 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -1,137 +1,28 @@ cmake_minimum_required(VERSION 3.24) project(buildmonitor_ui LANGUAGES C CXX) -set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_C_VISIBILITY_PRESET hidden) -set(CMAKE_CXX_VISIBILITY_PRESET hidden) -set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) - -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE) -endif() - # -# Sources are fetched rather than vendored as submodules. +# Everything about this build that is not BuildMonitor's own is PlatformHeads', fetched at a tag: +# the raylib and Dear ImGui it pins, the raylib 6.0 options it switches off, and how the library +# is compiled and linked. It was a copy of DiffEngine's here, and three fixes made to that copy +# were found again in this one, each by a user's machine: a library that needed glibc 2.38, a +# window that stayed blank, and libraries recorded as needed that a stock Ubuntu lacks. # -# Nothing in a normal `dotnet build` touches this directory: the built binaries are committed to -# the runtimes folder of the native head, so only this file's own build needs raylib and imgui. -# The versions are pinned by tag here, in the same file as the build configuration. +# The tag is the one .github/workflows/build-native.yml calls and Directory.Packages.props names. # include(FetchContent) - -# raylib, static so the shipped artifact is a single file per RID. -set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) -set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) -set(BUILD_GAMES OFF CACHE BOOL "" FORCE) -set(CUSTOMIZE_BUILD ON CACHE BOOL "" FORCE) -# raylib 6.0 reads every SUPPORT_ flag in its config.h into an option that defaults to ON, the ones -# config.h defines as 0 included (raysan5/raylib#5844, fixed after 6.0), and CUSTOMIZE_BUILD skips -# config.h's own values. So each of those is on unless it is switched off here. -# SUPPORT_CUSTOM_FRAME_CONTROL was: EndDrawing then neither puts the frame on the screen, reads -# input nor waits for the next frame, and bm_present leaves all three to it for every frame it -# draws. So the Linux window stayed black, and from the first input bm_present drew one frame -# after another with no wait between them and read nothing more. A capture draws into a texture -# and never gets that far, which is why the pixel snapshots passed throughout; -# PixelTests.PresentWaitsForTheNextFrame is what notices. The busy wait loop was on the same way, -# and WaitTime is how bm_present waits out a frame it does not draw, so a tray with its window -# hidden spun through every one of them: a seventh of a core, for as long as it ran. The rest are -# formats and features nothing here uses. -foreach(flag IN ITEMS - SUPPORT_CUSTOM_FRAME_CONTROL - SUPPORT_BUSY_WAIT_LOOP - SUPPORT_GPU_SKINNING - SUPPORT_FILEFORMAT_TGA - SUPPORT_FILEFORMAT_JPG - SUPPORT_FILEFORMAT_PSD - SUPPORT_FILEFORMAT_HDR - SUPPORT_FILEFORMAT_PIC - SUPPORT_FILEFORMAT_PNM - SUPPORT_FILEFORMAT_KTX - SUPPORT_FILEFORMAT_ASTC - SUPPORT_FILEFORMAT_PKM - SUPPORT_FILEFORMAT_PVR - SUPPORT_FILEFORMAT_BDF - SUPPORT_FILEFORMAT_FLAC) - set(${flag} OFF CACHE BOOL "" FORCE) -endforeach() -# raylib spins for the last part of every wait by default, for timing precision nothing here -# needs: most of a millisecond of a core per frame, for as long as the tray runs. -set(SUPPORT_PARTIALBUSY_WAIT_LOOP OFF CACHE BOOL "" FORCE) -# F12 saves a screenshot into the working directory, which is wherever the tray was started from. -# raylib looks for the key at the end of a frame it has drawn, so that is F12 pressed while frames -# are being drawn, as they are for as long as the pointer is crossing the window. -set(SUPPORT_SCREEN_CAPTURE OFF CACHE BOOL "" FORCE) -set(SUPPORT_MODULE_RAUDIO OFF CACHE BOOL "" FORCE) -set(SUPPORT_MODULE_RMODELS OFF CACHE BOOL "" FORCE) -# PNG is the one picture format anything here reads or writes: a row's icons arrive as PNG, and a -# capture is saved as one. The other four that config.h has on, nothing here loads or saves. -foreach(flag IN ITEMS - SUPPORT_FILEFORMAT_BMP - SUPPORT_FILEFORMAT_GIF - SUPPORT_FILEFORMAT_QOI - SUPPORT_FILEFORMAT_DDS) - set(${flag} OFF CACHE BOOL "" FORCE) -endforeach() -set(SUPPORT_FILEFORMAT_PNG ON CACHE BOOL "" FORCE) - FetchContent_Declare( - raylib - GIT_REPOSITORY https://github.com/raysan5/raylib.git - GIT_TAG 6.0 + platformheads + GIT_REPOSITORY https://github.com/SimonCropp/PlatformHeads.git + GIT_TAG 0.1.0 GIT_SHALLOW ON) +FetchContent_MakeAvailable(platformheads) +include(${platformheads_SOURCE_DIR}/cmake/PlatformHeads.cmake) -# imgui has no CMake build of its own, so it is fetched as plain sources and compiled below. -FetchContent_Declare( - imgui - GIT_REPOSITORY https://github.com/ocornut/imgui.git - GIT_TAG v1.92.9b - GIT_SHALLOW ON) +platformheads_defaults() -FetchContent_MakeAvailable(raylib) -FetchContent_MakeAvailable(imgui) - -add_library(buildmonitor_ui SHARED - src/bm.cpp - ${imgui_SOURCE_DIR}/imgui.cpp - ${imgui_SOURCE_DIR}/imgui_draw.cpp - ${imgui_SOURCE_DIR}/imgui_tables.cpp - ${imgui_SOURCE_DIR}/imgui_widgets.cpp) - -target_include_directories(buildmonitor_ui PRIVATE include ${imgui_SOURCE_DIR}) -# ImWchar is sixteen bits unless this is defined, and the robot a Dependabot row carries is -# U+1F916. Without it the codepoint does not survive ImGui's own UTF-8 decoding, whatever font is -# loaded. Set on the target, so imgui's own sources are compiled with it too: it changes a type -# they share with this one. -target_compile_definitions(buildmonitor_ui PRIVATE IMGUI_USE_WCHAR32) -target_link_libraries(buildmonitor_ui PRIVATE raylib) - -# Only the libraries something is actually called in are recorded as needed. raylib hands on -# everything CMake's FindX11 found, which includes libSM and libICE wherever their headers are -# installed, and nothing here or in raylib calls either. A library recorded as needed has to be -# on the machine for this one to load at all, and a stock Ubuntu has neither of those two. -# Ubuntu's own compiler passes this by default, so a library built on the runner never recorded -# them. The manylinux container build-native builds in does not pass it. -if(UNIX AND NOT APPLE) - target_link_options(buildmonitor_ui PRIVATE LINKER:--as-needed) -endif() - -# The managed side probes for a bare name; keep it identical on every platform apart from the -# platform's own prefix and extension. -set_target_properties(buildmonitor_ui PROPERTIES - OUTPUT_NAME "buildmonitor_ui" - C_VISIBILITY_PRESET hidden - CXX_VISIBILITY_PRESET hidden) - -if(MSVC) - target_compile_options(buildmonitor_ui PRIVATE /W3 /permissive-) - target_compile_definitions(buildmonitor_ui PRIVATE _CRT_SECURE_NO_WARNINGS) -else() - target_compile_options(buildmonitor_ui PRIVATE -Wall -Wextra -Wno-unused-parameter) -endif() +# PNG is the one picture format anything here reads or writes: a row's icons arrive as PNG, and a +# capture is saved as one. +platformheads_fetch(FORMATS PNG) -if(APPLE) - set_target_properties(buildmonitor_ui PROPERTIES SUFFIX ".dylib") -endif() +platformheads_add_library(buildmonitor_ui SOURCES src/bm.cpp) diff --git a/native/build-linux.sh b/native/build-linux.sh deleted file mode 100644 index df9e2f2..0000000 --- a/native/build-linux.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash -# Builds build/libbuildmonitor_ui.so inside a manylinux_2_28 container, whose glibc 2.28 is the -# floor the library then needs - see the Linux build step in .github/workflows/build-native.yml. -# Runs from the repository root: -# -# docker run --rm -v "$PWD:/src" -w /src "quay.io/pypa/manylinux_2_28_$(uname -m)" bash native/build-linux.sh -set -euo pipefail - -# What raylib's bundled GLFW builds against, for both its X11 and Wayland backends: what the -# runner used to install for it, under this distribution's names. -dnf install -y \ - git pkgconfig \ - libX11-devel libXext-devel libXrandr-devel libXi-devel libXcursor-devel libXinerama-devel \ - mesa-libGL-devel wayland-devel libxkbcommon-devel - -# native/CMakeLists.txt needs CMake 3.24, newer than the distribution's own. The image carries -# current releases through pipx, so these are only installed where it does not. -export PATH="$HOME/.local/bin:$PATH" -for tool in cmake ninja; do - if ! command -v "$tool" > /dev/null 2>&1; then - pipx install "$tool" - fi -done - -# LEGACY links libGL.so.1, which every GL driver ships. This distribution's CMake otherwise -# prefers the GLVND split and links libOpenGL.so.0, which a machine with only libgl1 lacks. -cmake -S native -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DOpenGL_GL_PREFERENCE=LEGACY -cmake --build build --config Release - -# Here rather than in the workflow's collect step: the build directory belongs to this -# container's root, and the runner cannot rewrite what is in it. -strip build/libbuildmonitor_ui.so diff --git a/src/BuildMonitor.Native/BuildMonitor.Native.csproj b/src/BuildMonitor.Native/BuildMonitor.Native.csproj index 7d1f6fe..8ba4d72 100644 --- a/src/BuildMonitor.Native/BuildMonitor.Native.csproj +++ b/src/BuildMonitor.Native/BuildMonitor.Native.csproj @@ -10,6 +10,14 @@ true false LatestMajor + + true @@ -21,23 +29,6 @@ - - - - - - - - - + diff --git a/src/BuildMonitor/BuildMonitor.csproj b/src/BuildMonitor/BuildMonitor.csproj index 386a1af..6f4a2c9 100644 --- a/src/BuildMonitor/BuildMonitor.csproj +++ b/src/BuildMonitor/BuildMonitor.csproj @@ -43,7 +43,7 @@ @@ -58,78 +58,37 @@ - - $(MSBuildProjectDirectory)\obj\heads\ - true - AddHeadsToPackage;$(GenerateNuspecDependsOn) - + + + + + + + + + - + - - - - - - - - - - + tools\$(TargetFramework)\any\heads - - - <_RidWithoutApphost Include="@(HeadRid)" - Condition="!Exists('$(HeadStageDir)%(HeadRid.Identity)\%(HeadRid.Apphost)')" /> - - - - - - - - <_HeadFile Include="$(HeadStageDir)**\*" /> - - - - - - - - <_PackageFiles Include="$(HeadStageDir)**\*" - BuildAction="None" - PackagePath="tools\$(TargetFramework)\any\heads" /> - - + heads + diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index e0625bf..f56b8b5 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -14,6 +14,7 @@ +