diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..50361afbf6
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+docs/changelog.txt merge=union
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..e68a754c63
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1 @@
+If this PR makes an externally-visible change in behavior or API, please add an appropriate line to `docs/changelog.txt`.
diff --git a/.github/release_template.md b/.github/release_template.md
new file mode 100644
index 0000000000..2bfc7a3c04
--- /dev/null
+++ b/.github/release_template.md
@@ -0,0 +1,64 @@
+#### Q: How do I download DFHack?
+**A:** Either add to your Steam library from our [Steam page](https://store.steampowered.com/app/2346660/DFHack) or scroll to the latest release on our [GitHub releases page](https://github.com/DFHack/dfhack/releases), expand the "Assets" list, and download the file for your platform (e.g. `dfhack-XX.XX-rX-Windows-64bit.zip`. If you are on Windows and are manually installing from the zip file, please remember to right click on the file after downloading, open the file properties, and select the "Unblock" checkbox. This will prevent issues with Windows antivirus programs.
+
+-------------
+
+This release is compatible with all distributions of Dwarf Fortress: [Steam](https://store.steampowered.com/app/975370/Dwarf_Fortress/), [Itch](https://kitfoxgames.itch.io/dwarf-fortress), and [Classic](https://www.bay12games.com/dwarves/).
+
+- [Install DFHack from Steam](https://store.steampowered.com/app/2346660/DFHack)
+- [Manual install](https://docs.dfhack.org/en/stable/docs/Installing.html#installing)
+- [Quickstart guide (for players)](https://docs.dfhack.org/en/stable/docs/Quickstart.html#quickstart)
+- [Modding guide (for modders)](https://docs.dfhack.org/en/stable/docs/guides/modding-guide.html)
+
+Please report any issues (or feature requests) on the DFHack [GitHub issue tracker](https://github.com/DFHack/dfhack/issues). When reporting issues, please upload a zip file of your savegame and a zip file of your `mods` directory to the cloud and add links to the GitHub issue. Make sure your files are downloadable by "everyone with the link". We need your savegame to reproduce the problem and test the fix, and we need your active mods so we can load your savegame. Issues with savegames and mods attached get fixed first!
+
+Highlights
+----------------------------------
+
+
+Highlight 1, Highlight 2
+
+### Highlight 1
+
+Demo screenshot/vidcap
+
+Text
+
+### Highlight 2
+
+Demo screenshot/vidcap
+
+Text
+
+
+
+Announcements
+----------------------------------
+
+
+Annc 1, PSAs
+
+### Annc 1
+
+Text
+
+### PSAs
+
+As always, remember that, just like the vanilla DF game, DFHack tools can also have bugs. It is a good idea to **save often and keep backups** of the forts that you care about.
+
+Some DFHack tools that worked in previous (pre-Steam) versions of DF have not been updated yet and are marked with the "unavailable" tag in their docs. If you try to run them, they will show a warning and exit immediately. You can run the command again to override the warning (though of course the tools may not work). We make no guarantees of reliability for the tools that are marked as "unavailable".
+
+The in-game interface for running DFHack commands (`gui/launcher`) will not show "unavailable" tools by default. You can still run them if you know their names, or you can turn on dev mode by hitting Ctrl-D while in `gui/launcher` and they will be added to the autocomplete list. Some tools listed as "unavailable" in the docs do not compile yet and are not accessible at all, even when in dev mode.
+
+If you see a tool complaining about the lack of a cursor, know that it's referring to the **keyboard** cursor (which used to be the only real option in Dwarf Fortress). You can enable the keyboard cursor by entering mining mode or selecting the dump/forbid tool and hitting Alt-K (the DFHack keybinding for `toggle-kbd-cursor`). We're working on making DFHack tools more mouse-aware and accessible so this step isn't necessary in the future.
+
+
+
+Changelog
+====================
+
+
+New tools, fixes, and improvements
+
+%RELEASE_NOTES%
+
diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml
new file mode 100644
index 0000000000..c2d946e300
--- /dev/null
+++ b/.github/workflows/build-linux.yml
@@ -0,0 +1,205 @@
+name: Build linux64
+
+on:
+ workflow_call:
+ inputs:
+ dfhack_repo:
+ type: string
+ default: DFHack/dfhack
+ dfhack_ref:
+ type: string
+ scripts_repo:
+ type: string
+ default: DFHack/scripts
+ scripts_ref:
+ type: string
+ structures_repo:
+ type: string
+ default: DFHack/df-structures
+ structures_ref:
+ type: string
+ stonesense_repo:
+ type: string
+ default: DFHack/stonesense
+ stonesense_ref:
+ type: string
+ artifact-name:
+ type: string
+ append-date-and-hash:
+ type: boolean
+ default: false
+ cache-id:
+ type: string
+ default: ''
+ cache-readonly:
+ type: boolean
+ default: false
+ platform-files:
+ type: boolean
+ default: true
+ plugins:
+ type: boolean
+ default: true
+ common-files:
+ type: boolean
+ default: true
+ docs:
+ type: boolean
+ default: false
+ html:
+ type: boolean
+ default: true
+ stonesense:
+ type: boolean
+ default: false
+ launchdf:
+ type: boolean
+ default: false
+ extras:
+ type: boolean
+ default: false
+ tests:
+ type: boolean
+ default: false
+ xml-dump-type-sizes:
+ type: boolean
+ default: false
+ gcc-ver:
+ type: string
+ default: "11"
+
+jobs:
+ build-linux64:
+ name: Build linux64
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Install basic build dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install ninja-build
+ - name: Install binary build dependencies
+ if: inputs.platform-files || inputs.xml-dump-type-sizes
+ run: |
+ sudo apt-get install \
+ ccache \
+ gcc-${{ inputs.gcc-ver }} \
+ g++-${{ inputs.gcc-ver }} \
+ libxml-libxslt-perl
+ - name: Install stonesense dependencies
+ if: inputs.stonesense
+ run: sudo apt-get install libgl-dev
+ - name: Install doc dependencies
+ if: inputs.docs
+ run: pip install 'sphinx'
+ - name: Clone DFHack
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.dfhack_repo }}
+ ref: ${{ inputs.dfhack_ref }}
+ submodules: true
+ fetch-depth: ${{ !inputs.platform-files && 1 || 0 }}
+ - name: Clone scripts
+ if: inputs.scripts_ref
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.scripts_repo }}
+ ref: ${{ inputs.scripts_ref }}
+ path: scripts
+ - name: Clone structures
+ if: inputs.structures_ref
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.structures_repo }}
+ ref: ${{ inputs.structures_ref }}
+ path: library/xml
+ - name: Clone stonesense
+ if: inputs.stonesense_ref
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.stonesense_repo }}
+ ref: ${{ inputs.stonesense_ref }}
+ path: plugins/stonesense
+ - name: Get 3rd party SDKs
+ if: inputs.launchdf
+ uses: actions/checkout@v4
+ with:
+ repository: DFHack/3rdparty
+ ref: main
+ ssh-key: ${{ secrets.DFHACK_3RDPARTY_TOKEN }}
+ path: depends/steam
+ - name: Fetch ccache
+ if: inputs.platform-files
+ uses: actions/cache/restore@v4
+ with:
+ path: ~/.cache/ccache
+ key: linux-gcc-${{ inputs.gcc-ver }}-${{ inputs.cache-id }}-${{ github.sha }}
+ restore-keys: |
+ linux-gcc-${{ inputs.gcc-ver }}-${{ inputs.cache-id }}
+ linux-gcc-${{ inputs.gcc-ver }}
+ - name: Configure DFHack
+ env:
+ CC: gcc-${{ inputs.gcc-ver }}
+ CXX: g++-${{ inputs.gcc-ver }}
+ run: |
+ cmake \
+ -S . \
+ -B build \
+ -G Ninja \
+ -DCMAKE_INSTALL_PREFIX=build/image \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DDFHACK_RUN_URL='https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' \
+ ${{ inputs.platform-files && '-DCMAKE_C_COMPILER_LAUNCHER=ccache' || '' }} \
+ ${{ inputs.platform-files && '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache' || '' }} \
+ -DBUILD_LIBRARY:BOOL=${{ inputs.platform-files }} \
+ -DBUILD_PLUGINS:BOOL=${{ inputs.platform-files && inputs.plugins }} \
+ -DBUILD_STONESENSE:BOOL=${{ inputs.stonesense }} \
+ -DBUILD_DFLAUNCH:BOOL=${{ inputs.launchdf }} \
+ -DBUILD_DEV_PLUGINS:BOOL=${{ inputs.extras }} \
+ -DBUILD_SIZECHECK:BOOL=${{ inputs.extras }} \
+ -DBUILD_SKELETON:BOOL=${{ inputs.extras }} \
+ -DBUILD_DOCS:BOOL=${{ inputs.docs }} \
+ -DBUILD_DOCS_NO_HTML:BOOL=${{ !inputs.html }} \
+ -DBUILD_TESTS:BOOL=${{ inputs.tests }} \
+ -DBUILD_XMLDUMP:BOOL=${{ inputs.xml-dump-type-sizes }} \
+ ${{ inputs.xml-dump-type-sizes && '-DINSTALL_XMLDUMP:BOOL=1' || ''}} \
+ -DINSTALL_DATA_FILES:BOOL=${{ inputs.common-files }} \
+ -DINSTALL_SCRIPTS:BOOL=${{ inputs.common-files }}
+ - name: Build DFHack
+ run: ninja -C build install
+ - name: Run cpp tests
+ if: inputs.platform-files
+ run: ninja -C build test
+ - name: Finalize ccache
+ if: inputs.platform-files
+ run: |
+ ccache --show-stats --verbose
+ ccache --max-size 40M
+ ccache --cleanup
+ ccache --max-size 500M
+ ccache --zero-stats
+ - name: Save ccache
+ if: inputs.platform-files && !inputs.cache-readonly
+ uses: actions/cache/save@v4
+ with:
+ path: ~/.cache/ccache
+ key: linux-gcc-${{ inputs.gcc-ver }}-${{ inputs.cache-id }}-${{ github.sha }}
+ - name: Format artifact name
+ if: inputs.artifact-name
+ id: artifactname
+ run: |
+ if test "false" = "${{ inputs.append-date-and-hash }}"; then
+ echo name=${{ inputs.artifact-name }} >> $GITHUB_OUTPUT
+ else
+ echo name=${{ inputs.artifact-name }}-$(date +%Y%m%d)-$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT
+ fi
+ - name: Prep artifact
+ if: inputs.artifact-name
+ run: |
+ cd build/image
+ tar cjf ../../${{ steps.artifactname.outputs.name }}.tar.bz2 .
+ - name: Upload artifact
+ if: inputs.artifact-name
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ steps.artifactname.outputs.name }}
+ path: ${{ steps.artifactname.outputs.name }}.tar.bz2
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
new file mode 100644
index 0000000000..1dec211117
--- /dev/null
+++ b/.github/workflows/build-windows.yml
@@ -0,0 +1,206 @@
+name: Build win64
+
+on:
+ workflow_call:
+ inputs:
+ dfhack_repo:
+ type: string
+ default: DFHack/dfhack
+ dfhack_ref:
+ type: string
+ scripts_repo:
+ type: string
+ default: DFHack/scripts
+ scripts_ref:
+ type: string
+ structures_repo:
+ type: string
+ default: DFHack/df-structures
+ structures_ref:
+ type: string
+ stonesense_repo:
+ type: string
+ default: DFHack/stonesense
+ stonesense_ref:
+ type: string
+ artifact-name:
+ type: string
+ append-date-and-hash:
+ type: boolean
+ default: false
+ cache-id:
+ type: string
+ default: ''
+ cache-readonly:
+ type: boolean
+ default: false
+ platform-files:
+ type: boolean
+ default: true
+ plugins:
+ type: boolean
+ default: true
+ common-files:
+ type: boolean
+ default: true
+ docs:
+ type: boolean
+ default: false
+ html:
+ type: boolean
+ default: true
+ stonesense:
+ type: boolean
+ default: false
+ tests:
+ type: boolean
+ default: false
+ xml-dump-type-sizes:
+ type: boolean
+ default: false
+ launchdf:
+ type: boolean
+ default: false
+
+
+jobs:
+ build-win64:
+ name: Build win64
+ runs-on: windows-2022
+ steps:
+ - name: Set up Python
+ uses: actions/setup-python@v6
+ with:
+ python-version: '3.x'
+ - name: Install build dependencies
+ run: |
+ choco install sccache
+ pip install Jinja2
+ - name: Install doc dependencies
+ if: inputs.docs
+ run: |
+ pip install sphinx
+ - name: Clone DFHack
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.dfhack_repo }}
+ ref: ${{ inputs.dfhack_ref }}
+ submodules: true
+ fetch-depth: 0
+ - name: Clone scripts
+ if: inputs.scripts_ref
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.scripts_repo }}
+ ref: ${{ inputs.scripts_ref }}
+ path: scripts
+ - name: Clone structures
+ if: inputs.structures_ref
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.structures_repo }}
+ ref: ${{ inputs.structures_ref }}
+ path: library/xml
+ - name: Clone stonesense
+ if: inputs.stonesense_ref
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.stonesense_repo }}
+ ref: ${{ inputs.stonesense_ref }}
+ path: plugins/stonesense
+ - name: Get 3rd party SDKs
+ if: inputs.launchdf
+ uses: actions/checkout@v4
+ with:
+ repository: DFHack/3rdparty
+ ref: main
+ ssh-key: ${{ secrets.DFHACK_3RDPARTY_TOKEN }}
+ path: depends/steam
+ - name: Prepare output directories
+ run: |
+ mkdir output
+ mkdir pdb
+ - name: Get sccache path
+ run: echo ("SCCACHE_DIR=" + $env:LOCALAPPDATA + "\Mozilla\sccache\cache") >> $env:GITHUB_ENV
+ - name: Fetch ccache
+ if: inputs.platform-files
+ uses: actions/cache/restore@v4
+ with:
+ path: ${{ env.SCCACHE_DIR }}
+ key: win-msvc-${{ inputs.cache-id }}-${{ github.sha }}
+ restore-keys: |
+ win-msvc-${{ inputs.cache-id }}
+ win-msvc
+ - uses: ilammy/msvc-dev-cmd@v1
+ - name: Configure DFHack
+ run: |
+ cmake `
+ -S . `
+ -B build `
+ -GNinja `
+ -DDFHACK_BUILD_ARCH=64 `
+ -DCMAKE_BUILD_TYPE=Release `
+ -DCMAKE_INSTALL_PREFIX=output `
+ -DCMAKE_C_COMPILER_LAUNCHER=sccache `
+ -DCMAKE_CXX_COMPILER_LAUNCHER=sccache `
+ -DBUILD_PDBS:BOOL=${{ inputs.cache-id == 'release' }} `
+ -DDFHACK_RUN_URL='https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' `
+ -DBUILD_LIBRARY=${{ inputs.platform-files }} `
+ -DBUILD_PLUGINS:BOOL=${{ inputs.platform-files && inputs.plugins }} `
+ -DBUILD_STONESENSE:BOOL=${{ inputs.stonesense }} `
+ -DBUILD_DOCS:BOOL=${{ inputs.docs }} `
+ -DBUILD_DOCS_NO_HTML:BOOL=${{ !inputs.html }} `
+ -DINSTALL_DATA_FILES:BOOL=${{ inputs.common-files }} `
+ -DBUILD_DFLAUNCH:BOOL=${{ inputs.launchdf }} `
+ -DBUILD_TESTS:BOOL=${{ inputs.tests }} `
+ -DBUILD_XMLDUMP:BOOL=${{ inputs.xml-dump-type-sizes }} `
+ ${{ inputs.xml-dump-type-sizes && '-DINSTALL_XMLDUMP:BOOL=1' || '' }}
+ - name: Build DFHack
+ env:
+ SCCACHE_CACHE_SIZE: 500M
+ run: |
+ ninja install -C build
+ - name: Finalize cache
+ run: |
+ cd build
+ sccache --show-stats
+ sccache --zero-stats
+ - name: Save ccache
+ if: inputs.platform-files && !inputs.cache-readonly
+ uses: actions/cache/save@v4
+ with:
+ path: ${{ env.SCCACHE_DIR }}
+ key: win-msvc-${{ inputs.cache-id }}-${{ github.sha }}
+ - name: Format artifact name
+ if: inputs.artifact-name
+ id: artifactname
+ run: |
+ if ("${{ inputs.append-date-and-hash }}" -eq "false") {
+ "name=${{ inputs.artifact-name }}" | Out-File -Append $env:GITHUB_OUTPUT
+ } else {
+ $date = Get-Date -Format "yyyMMdd"
+ $hash = git rev-parse --short HEAD
+ "name=${{ inputs.artifact-name}}-$date-$hash" | Out-File -Append $env:GITHUB_OUTPUT
+ }
+ - name: Prep pdbs
+ if: inputs.artifact-name && inputs.cache-id == 'release'
+ run: |
+ Get-ChildItem -Recurse -File -Path "build" -Filter *.pdb |
+ Copy-Item -Destination "pdb"
+ - name: Prep artifact
+ run: |
+ cd output
+ 7z a -ttar -so -an . |
+ 7z a -si -tbzip2 ../${{ steps.artifactname.outputs.name }}.tar.bz2
+ - name: Upload artifact
+ if: inputs.artifact-name
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ steps.artifactname.outputs.name }}
+ path: ${{ steps.artifactname.outputs.name }}.tar.bz2
+ - name: Upload PDBs
+ if: inputs.artifact-name && inputs.cache-id == 'release'
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ steps.artifactname.outputs.name }}_pdb
+ path: pdb
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 139bff74f9..3767b42ba5 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -3,170 +3,36 @@ name: Build
on: [push, pull_request]
jobs:
- build:
- runs-on: ${{ matrix.os }}
- name: build (Linux, GCC ${{ matrix.gcc }}, ${{ matrix.plugins }} plugins)
- strategy:
- fail-fast: false
- matrix:
- os:
- - ubuntu-18.04
- gcc:
- - 4.8
- - 7
- plugins:
- - default
- include:
- - os: ubuntu-20.04
- gcc: 10
- plugins: all
- steps:
- - name: Set up Python 3
- uses: actions/setup-python@v2
- with:
- python-version: 3
- - name: Install dependencies
- run: |
- sudo apt-get update
- sudo apt-get install \
- libgtk2.0-0 \
- libncursesw5 \
- libsdl-image1.2-dev \
- libsdl-ttf2.0-dev \
- libsdl1.2-dev \
- libxml-libxml-perl \
- libxml-libxslt-perl \
- lua5.3 \
- ninja-build \
- zlib1g-dev
- pip install sphinx
- - name: Install GCC
- run: |
- sudo apt-get install gcc-${{ matrix.gcc }} g++-${{ matrix.gcc }}
- - name: Clone DFHack
- uses: actions/checkout@v1
- with:
- fetch-depth: 0 # unlimited - we need past tags
- submodules: true
- - name: Set up environment
- id: env_setup
- run: |
- DF_VERSION="$(sh ci/get-df-version.sh)"
- echo "::set-output name=df_version::${DF_VERSION}"
- echo "DF_VERSION=${DF_VERSION}" >> $GITHUB_ENV
- echo "DF_FOLDER=${HOME}/DF/${DF_VERSION}/df_linux" >> $GITHUB_ENV
- - name: Fetch DF cache
- uses: actions/cache@v2
- with:
- path: ~/DF
- key: ${{ steps.env_setup.outputs.df_version }}
- - name: Download DF
- run: |
- sh ci/download-df.sh
- - name: Build DFHack
- env:
- CC: gcc-${{ matrix.gcc }}
- CXX: g++-${{ matrix.gcc }}
- run: |
- cmake \
- -S . \
- -B build-ci \
- -G Ninja \
- -DDFHACK_BUILD_ARCH=64 \
- -DBUILD_TESTS:BOOL=ON \
- -DBUILD_DEV_PLUGINS:BOOL=${{ matrix.plugins == 'all' }} \
- -DBUILD_SIZECHECK:BOOL=${{ matrix.plugins == 'all' }} \
- -DBUILD_STONESENSE:BOOL=${{ matrix.plugins == 'all' }} \
- -DBUILD_SUPPORTED:BOOL=1 \
- -DCMAKE_INSTALL_PREFIX="$DF_FOLDER"
- ninja -C build-ci install
- - name: Run tests
- id: run_tests
- run: |
- export TERM=dumb
- status=0
- mv "$DF_FOLDER"/dfhack.init-example "$DF_FOLDER"/dfhack.init
- script -qe -c "python ci/run-tests.py --headless --keep-status \"$DF_FOLDER\"" || status=$((status + 1))
- python ci/check-rpc.py "$DF_FOLDER/dfhack-rpc.txt" || status=$((status + 2))
- mkdir -p artifacts
- cp "$DF_FOLDER"/test*.json "$DF_FOLDER"/*.log artifacts || status=$((status + 4))
- exit $status
- - name: Upload test artifacts
- uses: actions/upload-artifact@v1
- if: (success() || failure()) && steps.run_tests.outcome != 'skipped'
- continue-on-error: true
- with:
- name: test-artifacts-${{ matrix.gcc }}
- path: artifacts
- - name: Clean up DF folder
- # prevent DFHack-generated files from ending up in the cache
- # (download-df.sh also removes them, this is just to save cache space)
- if: success() || failure()
- run: |
- rm -rf "$DF_FOLDER"
+ test:
+ uses: ./.github/workflows/test.yml
+ with:
+ dfhack_repo: ${{ github.repository }}
+ dfhack_ref: ${{ github.ref }}
+ secrets: inherit
+
+ package:
+ uses: ./.github/workflows/package.yml
+ with:
+ dfhack_repo: ${{ github.repository }}
+ dfhack_ref: ${{ github.ref }}
+ secrets: inherit
docs:
- runs-on: ubuntu-18.04
- steps:
- - name: Set up Python 3
- uses: actions/setup-python@v2
- with:
- python-version: 3
- - name: Install dependencies
- run: |
- pip install sphinx
- - name: Clone DFHack
- uses: actions/checkout@v1
- with:
- submodules: true
- - name: Build docs
- run: |
- sphinx-build -W --keep-going -j3 . docs/html
- - name: Upload docs
- uses: actions/upload-artifact@v1
- with:
- name: docs
- path: docs/html
+ uses: ./.github/workflows/build-linux.yml
+ with:
+ dfhack_repo: ${{ github.repository }}
+ dfhack_ref: ${{ github.ref }}
+ platform-files: false
+ common-files: false
+ docs: true
+ secrets: inherit
lint:
- runs-on: ubuntu-18.04
- steps:
- - name: Set up Python 3
- uses: actions/setup-python@v2
- with:
- python-version: 3
- - name: Set up Ruby 2.7
- uses: actions/setup-ruby@v1
- with:
- ruby-version: 2.7
- - name: Install Lua
- run: |
- sudo apt-get update
- sudo apt-get install lua5.3
- - name: Clone DFHack
- uses: actions/checkout@v1
- with:
- submodules: true
- # don't need tags here
- - name: Check whitespace
- run: |
- python ci/lint.py --git-only --github-actions
- - name: Check Authors.rst
- if: success() || failure()
- run: |
- python ci/authors-rst.py
- - name: Check for missing documentation
- if: success() || failure()
- run: |
- python ci/script-docs.py
- - name: Check Lua syntax
- if: success() || failure()
- run: |
- python ci/script-syntax.py --ext=lua --cmd="luac5.3 -p" --github-actions
- - name: Check Ruby syntax
- if: success() || failure()
- run: |
- python ci/script-syntax.py --ext=rb --cmd="ruby -c" --github-actions
+ uses: ./.github/workflows/lint.yml
+ with:
+ dfhack_repo: ${{ github.repository }}
+ dfhack_ref: ${{ github.ref }}
+ secrets: inherit
check-pr:
runs-on: ubuntu-latest
diff --git a/.github/workflows/clean-cache.yml b/.github/workflows/clean-cache.yml
new file mode 100644
index 0000000000..91d5675ad8
--- /dev/null
+++ b/.github/workflows/clean-cache.yml
@@ -0,0 +1,32 @@
+name: Clean up PR caches
+
+on:
+ workflow_call:
+ pull_request_target:
+ types:
+ - closed
+
+jobs:
+ cleanup:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v4
+ - name: Cleanup
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh extension install actions/gh-actions-cache
+
+ REPO=${{ github.repository }}
+ BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
+
+ echo "Fetching list of cache keys"
+ cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1)
+
+ set +e
+ echo "Deleting caches..."
+ for cacheKey in $cacheKeysForPR; do
+ gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
+ done
+ echo "Done"
diff --git a/.github/workflows/generate-symbols.yml b/.github/workflows/generate-symbols.yml
new file mode 100644
index 0000000000..f78da19e74
--- /dev/null
+++ b/.github/workflows/generate-symbols.yml
@@ -0,0 +1,421 @@
+name: Generate symbols
+
+on:
+ workflow_dispatch:
+ inputs:
+ structures_ref:
+ description: Structures branch to build from and update
+ required: true
+ default: master
+ version:
+ description: DF version (can be "auto" if channel is steam)
+ required: true
+ platform:
+ description: Target OS platform
+ type: choice
+ required: true
+ default: all
+ options:
+ - all
+ - windows
+ - linux
+ channel:
+ description: DF distribution channel
+ type: choice
+ required: true
+ default: all
+ options:
+ - all
+ - steam
+ - itch
+ - classic
+ df_steam_branch:
+ description: DF Steam branch to read from (if processing Steam distribution channel)
+ required: true
+ type: choice
+ default: default
+ options:
+ - default
+ - experimental
+ - testing
+ - adventure_test
+ - beta
+ steam_branch:
+ description: DFHack Steam branch to deploy to (leave blank to skip deploy)
+ type: string
+
+jobs:
+ package-linux:
+ uses: ./.github/workflows/build-linux.yml
+ if: inputs.platform == 'all' || inputs.platform == 'linux'
+ with:
+ dfhack_ref: ${{ github.ref }}
+ structures_ref: ${{ inputs.structures_ref }}
+ artifact-name: dfhack-symbols-linux64-build
+ append-date-and-hash: false
+ cache-id: test
+ cache-readonly: true
+ plugins: false
+ secrets: inherit
+
+ package-win64:
+ uses: ./.github/workflows/build-windows.yml
+ if: (inputs.platform == 'all' || inputs.platform == 'windows') && inputs.version == 'auto'
+ with:
+ dfhack_ref: ${{ github.ref }}
+ structures_ref: ${{ inputs.structures_ref }}
+ artifact-name: dfhack-symbols-windows64-build
+ append-date-and-hash: false
+ cache-id: test
+ cache-readonly: true
+ plugins: false
+ secrets: inherit
+
+ generate-linux:
+ name: Generate linux64 symbols
+ runs-on: ubuntu-latest
+ if: inputs.platform == 'all' || inputs.platform == 'linux'
+ needs:
+ - package-linux
+ steps:
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install \
+ ansifilter \
+ libsdl2-2.0-0 \
+ libsdl2-image-2.0-0
+ - name: Clone structures
+ uses: actions/checkout@v4
+ with:
+ repository: DFHack/df-structures
+ ref: ${{ inputs.structures_ref }}
+ token: ${{ secrets.DFHACK_GITHUB_TOKEN }}
+ path: xml
+ - name: Download DFHack
+ uses: actions/download-artifact@v4
+ with:
+ name: dfhack-symbols-linux64-build
+ - name: Start X server
+ run: Xvfb :0 -screen 0 1600x1200x24 &
+
+ # Steam
+ - name: Setup steamcmd
+ if: inputs.channel == 'all' || inputs.channel == 'steam'
+ id: steamcmd
+ uses: CyberAndrii/setup-steamcmd@v1
+ - name: Generate Steam symbols
+ if: inputs.channel == 'all' || inputs.channel == 'steam'
+ env:
+ DISPLAY: :0
+ STEAM_USERNAME: ${{ secrets.STEAM_USERNAME }}
+ STEAM_CONFIG_VDF: ${{ secrets.STEAM_CONFIG_VDF }}
+ STEAM_DF_TESTING: ${{ secrets.STEAM_DF_TESTING }}
+ STEAM_DF_ADVENTURE_TEST: ${{ secrets.STEAM_DF_ADVENTURE_TEST }}
+ run: |
+ mkdir DF_steam
+ mkdir -p $HOME/Steam/config
+ echo "$STEAM_CONFIG_VDF" | base64 -d >$HOME/Steam/config/config.vdf
+ echo "DF steam branch: ${{ inputs.df_steam_branch }}"
+ if [ "${{ inputs.df_steam_branch }}" = "default" ]; then
+ BETA_PARAMS=""
+ elif [ "${{ inputs.df_steam_branch }}" = "testing" ]; then
+ BETA_PARAMS="-beta testing -betapassword $STEAM_DF_TESTING"
+ elif [ "${{ inputs.df_steam_branch }}" = "adventure_test" ]; then
+ BETA_PARAMS="-beta adventure_test -betapassword $STEAM_DF_ADVENTURE_TEST"
+ else
+ BETA_PARAMS="-beta ${{ inputs.df_steam_branch }}"
+ fi
+ ${{ steps.steamcmd.outputs.executable }} \
+ +@ShutdownOnFailedCommand 1 \
+ +force_install_dir $PWD/DF_steam \
+ +login $STEAM_USERNAME \
+ "+app_update 975370 $BETA_PARAMS validate" \
+ +quit
+ tar xjf dfhack-symbols-linux64-build.tar.bz2 -C DF_steam
+ xml/symbols_gen_linux.sh ${{ inputs.version == 'auto' && '50.0' || inputs.version }} STEAM DF_steam
+ if [ "${{ inputs.version }}" == "auto" ]; then
+ while pgrep dwarfort; do
+ echo "waiting for DF to exit"
+ sleep 0.5
+ done
+ cp xml/symbols.xml DF_steam/hack
+ cd DF_steam
+ DFHACK_DISABLE_CONSOLE=1 ./dfhack &
+ while ! ./dfhack-run lua 'print(scr)' | fgrep 'viewscreen_titlest' 2>/dev/null; do
+ echo "waiting for DF to start"
+ sleep 0.5
+ done
+ df_ver=`./dfhack-run lua 'print(dfhack.gui.getDFViewscreen(true).str_version)' | ansifilter`
+ echo "Found version string: '$df_ver'"
+ echo "DETECTED_DF_VER=$df_ver" >>$GITHUB_ENV
+ sed -i "s/v0.50.0 linux64 STEAM/v0.$df_ver linux64 STEAM/" ../xml/symbols.xml
+ ./dfhack-run die || true
+ fi
+
+ # Itch
+ - name: Generate Itch symbols
+ if: (inputs.channel == 'all' || inputs.channel == 'itch') && inputs.version != 'auto'
+ env:
+ DISPLAY: :0
+ ITCH_API_KEY: ${{ secrets.ITCH_API_KEY }}
+ run: |
+ mkdir DF_itch
+ pip install itch-dl
+ minor=$(echo "${{ inputs.version }}" | cut -d. -f1)
+ patch=$(echo "${{ inputs.version }}" | cut -d. -f2)
+ fname="dwarf_fortress_${minor}_${patch}_linux.tar.bz2"
+ itch-dl https://kitfoxgames.itch.io/dwarf-fortress --download-to . --api-key $ITCH_API_KEY --filter-files-glob "${fname}"
+ tar xjf "kitfoxgames/dwarf-fortress/files/${fname}" -C DF_itch
+ tar xjf dfhack-symbols-linux64-build.tar.bz2 -C DF_itch
+ xml/symbols_gen_linux.sh ${{ inputs.version }} ITCH DF_itch
+
+ # Classic
+ - name: Generate Classic symbols
+ if: (inputs.channel == 'all' || inputs.channel == 'classic') && inputs.version != 'auto'
+ env:
+ DISPLAY: :0
+ run: |
+ mkdir DF_classic
+ minor=$(echo "${{ inputs.version }}" | cut -d. -f1)
+ patch=$(echo "${{ inputs.version }}" | cut -d. -f2)
+ fname="df_${minor}_${patch}_linux.tar.bz2"
+ wget "https://www.bay12games.com/dwarves/${fname}"
+ tar xjf "${fname}" -C DF_classic
+ tar xjf dfhack-symbols-linux64-build.tar.bz2 -C DF_classic
+ xml/symbols_gen_linux.sh ${{ inputs.version }} CLASSIC DF_classic
+
+ # Finalize
+ - name: Merge updates
+ run: |
+ cd xml
+ if ! git diff --exit-code; then
+ git stash
+ git pull
+ git stash pop
+ fi
+ - name: Commit symbol updates
+ uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: Auto-update symbols for Linux DF version ${{ env.DETECTED_DF_VER || inputs.version }}
+ repository: xml
+ commit_user_name: DFHack-Urist via GitHub Actions
+ commit_user_email: 63161697+DFHack-Urist@users.noreply.github.com
+
+ generate-windows:
+ name: Generate win64 symbols
+ runs-on: ubuntu-latest
+ if: inputs.platform == 'all' || inputs.platform == 'windows'
+ steps:
+ - name: Install dependencies
+ run: pip install pefile
+ - name: Clone structures
+ uses: actions/checkout@v4
+ with:
+ repository: DFHack/df-structures
+ ref: ${{ inputs.structures_ref }}
+ token: ${{ secrets.DFHACK_GITHUB_TOKEN }}
+ path: xml
+ - name: Clone df_misc
+ uses: actions/checkout@v4
+ with:
+ repository: DFHack/df_misc
+ path: df_misc
+ - name: Clone metasm
+ uses: actions/checkout@v4
+ with:
+ repository: jjyg/metasm
+ path: metasm
+
+ # Steam
+ - name: Setup steamcmd
+ if: inputs.channel == 'all' || inputs.channel == 'steam'
+ id: steamcmd
+ uses: CyberAndrii/setup-steamcmd@v1
+ - name: Generate Steam symbols
+ if: inputs.channel == 'all' || inputs.channel == 'steam'
+ env:
+ STEAM_USERNAME: ${{ secrets.STEAM_USERNAME }}
+ STEAM_CONFIG_VDF: ${{ secrets.STEAM_CONFIG_VDF }}
+ STEAM_DF_TESTING: ${{ secrets.STEAM_DF_TESTING }}
+ STEAM_DF_ADVENTURE_TEST: ${{ secrets.STEAM_DF_ADVENTURE_TEST }}
+ run: |
+ mkdir DF_steam
+ mkdir -p $HOME/Steam/config
+ echo "$STEAM_CONFIG_VDF" | base64 -d >$HOME/Steam/config/config.vdf
+ echo "DF steam branch: ${{ inputs.df_steam_branch }}"
+ if [ "${{ inputs.df_steam_branch }}" = "default" ]; then
+ BETA_PARAMS=""
+ elif [ "${{ inputs.df_steam_branch }}" = "testing" ]; then
+ BETA_PARAMS="-beta testing -betapassword $STEAM_DF_TESTING"
+ elif [ "${{ inputs.df_steam_branch }}" = "adventure_test" ]; then
+ BETA_PARAMS="-beta adventure_test -betapassword $STEAM_DF_ADVENTURE_TEST"
+ else
+ BETA_PARAMS="-beta ${{ inputs.df_steam_branch }}"
+ fi
+ ${{ steps.steamcmd.outputs.executable }} \
+ +@ShutdownOnFailedCommand 1 \
+ +@sSteamCmdForcePlatformType windows \
+ +force_install_dir $PWD/DF_steam \
+ +login $STEAM_USERNAME \
+ "+app_update 975370 $BETA_PARAMS validate" \
+ +quit
+ xml/symbols_gen_windows.sh ${{ inputs.version == 'auto' && '50.0' || inputs.version }} STEAM DF_steam
+
+ # Itch
+ - name: Generate Itch symbols
+ if: (inputs.channel == 'all' || inputs.channel == 'itch') && inputs.version != 'auto'
+ env:
+ ITCH_API_KEY: ${{ secrets.ITCH_API_KEY }}
+ run: |
+ mkdir DF_itch
+ pip install itch-dl
+ minor=$(echo "${{ inputs.version }}" | cut -d. -f1)
+ patch=$(echo "${{ inputs.version }}" | cut -d. -f2)
+ fname="dwarf_fortress_${minor}_${patch}_windows.zip"
+ itch-dl https://kitfoxgames.itch.io/dwarf-fortress --download-to . --api-key $ITCH_API_KEY --filter-files-glob "${fname}"
+ unzip -d DF_itch "kitfoxgames/dwarf-fortress/files/${fname}"
+ xml/symbols_gen_windows.sh ${{ inputs.version }} ITCH DF_itch
+
+ # Classic
+ - name: Generate Classic symbols
+ if: (inputs.channel == 'all' || inputs.channel == 'classic') && inputs.version != 'auto'
+ run: |
+ mkdir DF_classic
+ minor=$(echo "${{ inputs.version }}" | cut -d. -f1)
+ patch=$(echo "${{ inputs.version }}" | cut -d. -f2)
+ fname="df_${minor}_${patch}_win.zip"
+ wget "https://www.bay12games.com/dwarves/${fname}"
+ unzip -d DF_classic "${fname}"
+ xml/symbols_gen_windows.sh ${{ inputs.version }} CLASSIC DF_classic
+
+ # Finalize
+ - name: Merge updates
+ run: |
+ cd xml
+ if ! git diff --exit-code; then
+ git stash
+ git pull
+ git stash pop
+ fi
+ - name: Commit symbol updates
+ uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: Auto-update symbols for Windows DF version ${{ inputs.version }}
+ repository: xml
+ commit_user_name: DFHack-Urist via GitHub Actions
+ commit_user_email: 63161697+DFHack-Urist@users.noreply.github.com
+
+ auto-ver-windows:
+ name: Autodetect DF version string (Windows)
+ if: (inputs.platform == 'all' || inputs.platform == 'windows') && (inputs.channel == 'all' || inputs.channel == 'steam') && inputs.version == 'auto'
+ needs:
+ - package-win64
+ - generate-windows
+ runs-on: windows-latest
+ steps:
+ - name: Clone structures
+ uses: actions/checkout@v4
+ with:
+ repository: DFHack/df-structures
+ ref: ${{ inputs.structures_ref }}
+ token: ${{ secrets.DFHACK_GITHUB_TOKEN }}
+ path: xml
+ - name: Download DFHack
+ uses: actions/download-artifact@v4
+ with:
+ name: dfhack-symbols-windows64-build
+ - name: Setup steamcmd
+ id: steamcmd
+ uses: CyberAndrii/setup-steamcmd@v1
+ - name: Update DF version string
+ env:
+ STEAM_USERNAME: ${{ secrets.STEAM_USERNAME }}
+ STEAM_CONFIG_VDF: ${{ secrets.STEAM_CONFIG_VDF }}
+ STEAM_DF_TESTING: ${{ secrets.STEAM_DF_TESTING }}
+ STEAM_DF_ADVENTURE_TEST: ${{ secrets.STEAM_DF_ADVENTURE_TEST }}
+ shell: bash
+ run: |
+ mkdir DF_steam
+ echo "$STEAM_CONFIG_VDF" | base64 -d >${{ steps.steamcmd.outputs.directory }}/config/config.vdf
+ echo "DF steam branch: ${{ inputs.df_steam_branch }}"
+ if [ "${{ inputs.df_steam_branch }}" = "default" ]; then
+ BETA_PARAMS=""
+ elif [ "${{ inputs.df_steam_branch }}" = "testing" ]; then
+ BETA_PARAMS="-beta testing -betapassword $STEAM_DF_TESTING"
+ elif [ "${{ inputs.df_steam_branch }}" = "adventure_test" ]; then
+ BETA_PARAMS="-beta adventure_test -betapassword $STEAM_DF_ADVENTURE_TEST"
+ else
+ BETA_PARAMS="-beta ${{ inputs.df_steam_branch }}"
+ fi
+ ${{ steps.steamcmd.outputs.executable }} \
+ +@ShutdownOnFailedCommand 1 \
+ +@sSteamCmdForcePlatformType windows \
+ +force_install_dir $PWD/DF_steam \
+ +login $STEAM_USERNAME \
+ "+app_update 975370 $BETA_PARAMS validate" \
+ +quit
+ tar xjf dfhack-symbols-windows64-build.tar.bz2 -C DF_steam
+ cp xml/symbols.xml DF_steam/hack
+ cd DF_steam
+ "./Dwarf Fortress.exe" &
+ while ! ./dfhack-run.exe lua 'print(scr)' | fgrep 'viewscreen_titlest' 2>/dev/null; do
+ echo "waiting for DF to start"
+ sleep 0.5
+ done
+ df_ver=`./dfhack-run.exe lua 'print(dfhack.gui.getDFViewscreen(true).str_version)'`
+ echo "Found version string: '$df_ver'"
+ echo "DETECTED_DF_VER=$df_ver" >>$GITHUB_ENV
+ sed -i "s/v0.50.0 win64 STEAM/v0.$df_ver win64 STEAM/" ../xml/symbols.xml
+ ./dfhack-run.exe die || true
+ - name: Merge updates
+ shell: bash
+ run: |
+ cd xml
+ if ! git diff --exit-code; then
+ git stash
+ git pull
+ git stash pop
+ fi
+ - name: Commit symbol updates
+ uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: Auto-update Windows DF version to ${{ env.DETECTED_DF_VER }} in symbols
+ repository: xml
+ commit_user_name: DFHack-Urist via GitHub Actions
+ commit_user_email: 63161697+DFHack-Urist@users.noreply.github.com
+
+ update-ref:
+ name: Update structures ref
+ runs-on: ubuntu-latest
+ needs:
+ - generate-linux
+ - auto-ver-windows
+ if: ${{ ! failure() }}
+ steps:
+ - name: Clone DFHack
+ uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.DFHACK_GITHUB_TOKEN }}
+ - name: Update ref
+ shell: bash
+ run: |
+ git submodule update --init --no-single-branch library/xml
+ cd library/xml
+ git checkout ${{ inputs.structures_ref }}
+ git pull
+ df_ver=`grep -E 'symbol-table.*STEAM' symbols.xml | head -n1 | sed -r "s/.*name='v0.([^ ]+) .*/\1/"`
+ echo "using DF version: $df_ver"
+ echo "DETECTED_DF_VER=$df_ver" >>$GITHUB_ENV
+ - name: Commit ref update
+ uses: stefanzweifel/git-auto-commit-action@v5
+ with:
+ commit_message: Auto-update structures ref for ${{ env.DETECTED_DF_VER }}
+ commit_user_name: DFHack-Urist via GitHub Actions
+ commit_user_email: 63161697+DFHack-Urist@users.noreply.github.com
+ - name: Launch steam-deploy
+ if: inputs.steam_branch
+ shell: bash
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: gh workflow run steam-deploy.yml -R DFHack/dfhack -r ${{ github.ref }} -f version=${{ env.DETECTED_DF_VER }} -f steam_branch=${{ inputs.steam_branch }}
diff --git a/.github/workflows/github-release.yml b/.github/workflows/github-release.yml
new file mode 100644
index 0000000000..16a4602141
--- /dev/null
+++ b/.github/workflows/github-release.yml
@@ -0,0 +1,81 @@
+name: Deploy to GitHub
+
+on:
+ push:
+ tags:
+ - '*-r*'
+
+ workflow_dispatch:
+ inputs:
+ ref:
+ description: Tag
+ required: true
+
+jobs:
+ package:
+ uses: ./.github/workflows/package.yml
+ with:
+ dfhack_ref: ${{ github.event.inputs && github.event.inputs.ref || github.event.ref }}
+ append-date-and-hash: false
+ cache-readonly: true
+ launchdf: true
+ secrets: inherit
+
+ create-update-release:
+ name: Draft GitHub release
+ needs: package
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Install doc dependencies
+ run: pip install 'sphinx'
+ - name: Clone DFHack
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs && github.event.inputs.ref || github.event.ref }}
+ submodules: true
+ - name: Get tag
+ id: gettag
+ run: |
+ TAG=$(git describe --tags --abbrev=0 --exact-match)
+ echo name="$TAG" >> $GITHUB_OUTPUT
+ echo type=$(echo "$TAG" | egrep 'r[0-9]+$' && echo "release" || echo "prerelease") >> $GITHUB_OUTPUT
+ - name: Generate release text
+ run: |
+ python docs/gen_changelog.py -a
+ CHANGELOG_FILE=docs/changelogs/${{ steps.gettag.outputs.name }}-github.txt
+ if ! test -f $CHANGELOG_FILE; then CHANGELOG_FILE=docs/changelogs/future-github.txt; fi
+ TOKEN_LINE=$(grep -Fhne '%RELEASE_NOTES%' .github/release_template.md | sed 's/:.*//')
+ head -n $((TOKEN_LINE - 1)) .github/release_template.md > release_body.md
+ CHANGELOG_LINES=$(wc -l <$CHANGELOG_FILE)
+ tail -n $((CHANGELOG_LINES - 3)) $CHANGELOG_FILE >> release_body.md
+ tail -n 1 .github/release_template.md >> release_body.md
+ cat release_body.md
+ - name: Stage release
+ uses: actions/download-artifact@v4
+ - name: Prep artifacts
+ run: |
+ mkdir artifacts
+ cd dfhack-windows64-build
+ tar xjf dfhack-windows64-build.tar.bz2
+ rm dfhack-windows64-build.tar.bz2
+ zip -qr ../artifacts/dfhack-${{ steps.gettag.outputs.name }}-Windows-64bit.zip .
+ cd ../dfhack-linux64-build
+ mv dfhack-linux64-build.tar.bz2 ../artifacts/dfhack-${{ steps.gettag.outputs.name }}-Linux-64bit.tar.bz2
+ - name: Create or update GitHub release
+ uses: ncipollo/release-action@v1
+ with:
+ artifacts: "artifacts/dfhack-*"
+ bodyFile: "release_body.md"
+ allowUpdates: true
+ artifactErrorsFailBuild: true
+ draft: true
+ name: "DFHack ${{ steps.gettag.outputs.name }}"
+ omitBodyDuringUpdate: true
+ omitDraftDuringUpdate: true
+ omitNameDuringUpdate: true
+ omitPrereleaseDuringUpdate: true
+ prerelease: ${{ steps.gettag.outputs.type == 'prerelease' }}
+ replacesArtifacts: true
+ tag: ${{ steps.gettag.outputs.name }}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 0000000000..0b44747c01
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,50 @@
+name: Lint
+
+on:
+ workflow_call:
+ inputs:
+ dfhack_repo:
+ type: string
+ default: DFHack/dfhack
+ dfhack_ref:
+ type: string
+ scripts_repo:
+ type: string
+ default: DFHack/scripts
+ scripts_ref:
+ type: string
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install Lua
+ run: |
+ sudo apt-get update
+ sudo apt-get install lua5.3
+ - name: Clone DFHack
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.dfhack_repo }}
+ ref: ${{ inputs.dfhack_ref }}
+ - name: Get scripts submodule ref
+ if: '!inputs.scripts_ref'
+ id: scriptssubmoduleref
+ run: echo ref=$(git submodule | fgrep scripts | cut -c2-41) >> $GITHUB_OUTPUT
+ - name: Clone scripts
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.scripts_repo }}
+ ref: ${{ inputs.scripts_ref || steps.scriptssubmoduleref.outputs.ref }}
+ path: scripts
+ - name: Check whitespace
+ run: python ci/lint.py --git-only --github-actions
+ - name: Check Authors.rst
+ if: always()
+ run: python ci/authors-rst.py
+ - name: Check for missing documentation
+ if: always()
+ run: python ci/script-docs.py
+ - name: Check Lua syntax
+ if: always()
+ run: python ci/script-syntax.py --ext=lua --cmd="luac5.3 -p" --github-actions
diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml
new file mode 100644
index 0000000000..41e72ea636
--- /dev/null
+++ b/.github/workflows/package.yml
@@ -0,0 +1,76 @@
+name: Package
+
+on:
+ workflow_call:
+ inputs:
+ dfhack_repo:
+ type: string
+ dfhack_ref:
+ type: string
+ scripts_repo:
+ type: string
+ scripts_ref:
+ type: string
+ structures_repo:
+ type: string
+ structures_ref:
+ type: string
+ append-date-and-hash:
+ type: boolean
+ default: true
+ cache-readonly:
+ type: boolean
+ default: false
+ launchdf:
+ type: boolean
+ default: false
+ include_windows:
+ type: boolean
+ default: true
+ include_linux:
+ type: boolean
+ default: true
+
+
+jobs:
+ package-win64:
+ name: Windows
+ uses: ./.github/workflows/build-windows.yml
+ if: inputs.include_windows
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ scripts_repo: ${{ inputs.scripts_repo }}
+ scripts_ref: ${{ inputs.scripts_ref }}
+ structures_repo: ${{ inputs.structures_repo }}
+ structures_ref: ${{ inputs.structures_ref }}
+ artifact-name: dfhack-windows64-build
+ append-date-and-hash: ${{ inputs.append-date-and-hash }}
+ cache-id: release
+ cache-readonly: ${{ inputs.cache-readonly }}
+ stonesense: true
+ docs: true
+ html: false
+ launchdf: ${{ inputs.launchdf }}
+ secrets: inherit
+
+ package-linux:
+ name: Linux
+ uses: ./.github/workflows/build-linux.yml
+ if: inputs.include_linux
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ scripts_repo: ${{ inputs.scripts_repo }}
+ scripts_ref: ${{ inputs.scripts_ref }}
+ structures_repo: ${{ inputs.structures_repo }}
+ structures_ref: ${{ inputs.structures_ref }}
+ artifact-name: dfhack-linux64-build
+ append-date-and-hash: ${{ inputs.append-date-and-hash }}
+ cache-id: release
+ cache-readonly: ${{ inputs.cache-readonly }}
+ stonesense: true
+ docs: true
+ html: false
+ launchdf: ${{ inputs.launchdf }}
+ secrets: inherit
diff --git a/.github/workflows/steam-deploy.yml b/.github/workflows/steam-deploy.yml
new file mode 100644
index 0000000000..2fbe6849e1
--- /dev/null
+++ b/.github/workflows/steam-deploy.yml
@@ -0,0 +1,96 @@
+name: Deploy to Steam
+
+on:
+ push:
+ tags:
+ - '*-r*'
+ workflow_dispatch:
+ inputs:
+ version:
+ description: Version or build description
+ type: string
+ required: true
+ steam_branch:
+ description: Steam release branch
+ type: string
+ required: true
+ default: staging
+
+jobs:
+ depot-common:
+ name: Common depot files
+ uses: ./.github/workflows/build-linux.yml
+ with:
+ artifact-name: common-depot
+ dfhack_ref: ${{ github.ref }}
+ platform-files: false
+ docs: true
+ html: false
+ stonesense: true
+ secrets: inherit
+
+ depot-win64:
+ name: Windows depot files
+ uses: ./.github/workflows/build-windows.yml
+ with:
+ artifact-name: win64-depot
+ dfhack_ref: ${{ github.ref }}
+ cache-id: release
+ cache-readonly: true
+ common-files: false
+ stonesense: true
+ launchdf: true
+ secrets: inherit
+
+ depot-linux64:
+ name: Linux depot files
+ uses: ./.github/workflows/build-linux.yml
+ with:
+ artifact-name: linux64-depot
+ dfhack_ref: ${{ github.ref }}
+ cache-id: release
+ cache-readonly: true
+ common-files: false
+ stonesense: true
+ launchdf: true
+ secrets: inherit
+
+ deploy-to-steam:
+ name: Deploy to Steam
+ needs:
+ - depot-common
+ - depot-win64
+ - depot-linux64
+ runs-on: ubuntu-latest
+ concurrency: steamdeploy
+ steps:
+ - name: Download depot files
+ uses: actions/download-artifact@v4
+ - name: Stage depot files
+ run: |
+ for name in common win64 linux64; do
+ cd ${name}-depot
+ tar xjf ${name}-depot.tar.bz2
+ rm ${name}-depot.tar.bz2
+ cd ..
+ done
+ - name: Get short SHA of commit
+ run: echo "SHORT_SHA=`echo ${{ github.sha }} | cut -c1-8`" >>$GITHUB_ENV
+ - name: steamcmd cache
+ uses: actions/cache@v4
+ with:
+ path: /home/runner/work/_temp/_github_home
+ key: steamcmd-${{ github.sha }}
+ restore-keys: steamcmd
+ - name: Steam deploy
+ uses: game-ci/steam-deploy@v3
+ with:
+ username: ${{ secrets.STEAM_USERNAME }}
+ configVdf: ${{ secrets.STEAM_CONFIG_VDF}}
+ appId: 2346660
+ buildDescription: ${{ github.event.inputs && github.event.inputs.version || github.ref_name }} (${{ env.SHORT_SHA }})
+ rootPath: .
+ depot1Path: common-depot
+ depot2Path: win64-depot
+ depot3Path: linux64-depot
+ releaseBranch: ${{ github.event.inputs && github.event.inputs.steam_branch || 'staging' }}
diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml
new file mode 100644
index 0000000000..3fbf683b63
--- /dev/null
+++ b/.github/workflows/test-suite.yml
@@ -0,0 +1,93 @@
+name: Test suite
+
+on:
+ workflow_call:
+ inputs:
+ dfhack_repo:
+ type: string
+ dfhack_ref:
+ type: string
+ os:
+ type: string
+ compiler:
+ type: string
+ plugins:
+ type: string
+ config:
+ type: string
+
+jobs:
+ run-tests:
+ name: Test (${{ inputs.os }}, ${{ inputs.compiler }}, ${{ inputs.plugins }} plugins, ${{ inputs.config }} config)
+ runs-on: ${{ inputs.os }}-latest
+ steps:
+ - name: Set env
+ shell: bash
+ run: echo "DF_FOLDER=DF" >>$GITHUB_ENV
+ - name: Install dependencies
+ if: inputs.os == 'ubuntu'
+ run: |
+ sudo apt-get update
+ sudo apt-get install \
+ libsdl2-2.0-0 \
+ libsdl2-image-2.0-0
+ - name: Clone DFHack
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ inputs.dfhack_repo }}
+ ref: ${{ inputs.dfhack_ref }}
+ - name: Detect DF version
+ shell: bash
+ run: echo DF_VERSION="$(sh ci/get-df-version.sh)" >>$GITHUB_ENV
+ - name: Fetch DF cache
+ id: restore-df
+ uses: actions/cache/restore@v4
+ with:
+ path: ${{ env.DF_FOLDER }}
+ key: df-${{ inputs.os }}-${{ env.DF_VERSION }}-${{ hashFiles('ci/download-df.sh') }}
+ - name: Download DF
+ if: steps.restore-df.outputs.cache-hit != 'true'
+ run: sh ci/download-df.sh ${{ env.DF_FOLDER }} ${{ inputs.os }} ${{ env.DF_VERSION }}
+ - name: Save DF cache
+ if: steps.restore-df.outputs.cache-hit != 'true'
+ uses: actions/cache/save@v4
+ with:
+ path: ${{ env.DF_FOLDER }}
+ key: df-${{ inputs.os }}-${{ env.DF_VERSION }}-${{ hashFiles('ci/download-df.sh') }}
+ - name: Install blank DFHack init scripts
+ if: inputs.config == 'empty'
+ shell: bash
+ run: |
+ mkdir -p ${{ env.DF_FOLDER }}/dfhack-config/init
+ cd data/dfhack-config/init
+ for fname in *.init; do touch ../../../${{ env.DF_FOLDER }}/dfhack-config/init/$fname; done
+ - name: Download DFHack
+ uses: actions/download-artifact@v4
+ with:
+ name: test-${{ inputs.compiler }}
+ - name: Install DFHack
+ shell: bash
+ run: tar xjf test-${{ inputs.compiler }}.tar.bz2 -C ${{ env.DF_FOLDER }}
+ - name: Start X server
+ if: inputs.os == 'ubuntu'
+ run: Xvfb :0 -screen 0 1600x1200x24 &
+ - name: Run lua tests
+ uses: nick-fields/retry@v3
+ env:
+ DISPLAY: :0
+ TERM: xterm-256color
+ with:
+ timeout_minutes: 1
+ command: python ci/run-tests.py --keep-status "${{ env.DF_FOLDER }}"
+ - name: Check RPC interface
+ run: python ci/check-rpc.py "${{ env.DF_FOLDER }}/dfhack-rpc.txt"
+ - name: Upload test artifacts
+ uses: actions/upload-artifact@v4
+ if: always()
+ continue-on-error: true
+ with:
+ name: test-output-${{ inputs.compiler }}-${{ inputs.plugins }}_plugins-${{ inputs.config }}_config
+ path: |
+ ${{ env.DF_FOLDER }}/dfhack-rpc.txt
+ ${{ env.DF_FOLDER }}/test*.json
+ ${{ env.DF_FOLDER }}/*.log
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000000..175a1adf48
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,113 @@
+name: Test
+
+on:
+ workflow_call:
+ inputs:
+ dfhack_repo:
+ type: string
+ default: DFHack/dfhack
+ dfhack_ref:
+ type: string
+ scripts_repo:
+ type: string
+ default: DFHack/scripts
+ scripts_ref:
+ type: string
+ structures_repo:
+ type: string
+ default: DFHack/df-structures
+ structures_ref:
+ type: string
+
+jobs:
+ build-windows:
+ name: Windows MSVC
+ uses: ./.github/workflows/build-windows.yml
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ scripts_repo: ${{ inputs.scripts_repo }}
+ scripts_ref: ${{ inputs.scripts_ref }}
+ structures_repo: ${{ inputs.structures_repo }}
+ structures_ref: ${{ inputs.structures_ref }}
+ artifact-name: test-msvc
+ cache-id: test
+ docs: true
+ html: false
+ tests: true
+
+ build-linux:
+ name: Linux gcc-${{ matrix.gcc }}
+ uses: ./.github/workflows/build-linux.yml
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ scripts_repo: ${{ inputs.scripts_repo }}
+ scripts_ref: ${{ inputs.scripts_ref }}
+ structures_repo: ${{ inputs.structures_repo }}
+ structures_ref: ${{ inputs.structures_ref }}
+ artifact-name: test-gcc-${{ matrix.gcc }}
+ cache-id: test
+ stonesense: ${{ matrix.plugins == 'all' }}
+ extras: ${{ matrix.plugins == 'all' }}
+ docs: true
+ html: false
+ tests: true
+ gcc-ver: ${{ matrix.gcc }}
+ secrets: inherit
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - gcc: 11 # baseline compatibility with ubuntu LTS 22.04
+ plugins: "default"
+ - gcc: 12 # highest available in ubuntu 22.04
+ plugins: "all"
+
+ test-windows:
+ name: Run Windows test suite
+ needs: build-windows
+ uses: ./.github/workflows/test-suite.yml
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ os: windows
+ compiler: msvc
+ plugins: default
+ config: default
+
+ test-windows-empty:
+ name: Run Windows test suite (empty config)
+ needs: build-windows
+ uses: ./.github/workflows/test-suite.yml
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ os: windows
+ compiler: msvc
+ plugins: default
+ config: empty
+
+ test-linux:
+ name: Run Linux test suite
+ needs: build-linux
+ uses: ./.github/workflows/test-suite.yml
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ os: ubuntu
+ compiler: gcc-11
+ plugins: default
+ config: default
+
+ test-linux-gcc-12-all-plugins:
+ name: Run Linux test suite (gcc-12, all plugins)
+ needs: build-linux
+ uses: ./.github/workflows/test-suite.yml
+ with:
+ dfhack_repo: ${{ inputs.dfhack_repo }}
+ dfhack_ref: ${{ inputs.dfhack_ref }}
+ os: ubuntu
+ compiler: gcc-12
+ plugins: all
+ config: default
diff --git a/.github/workflows/update-submodules.yml b/.github/workflows/update-submodules.yml
index 45eaceb020..c634e94d0a 100644
--- a/.github/workflows/update-submodules.yml
+++ b/.github/workflows/update-submodules.yml
@@ -4,11 +4,6 @@ on:
schedule:
- cron: '0 7 * * *'
workflow_dispatch:
- inputs:
- branch:
- description: DFHack branch to update
- required: false
- default: develop
jobs:
run:
@@ -16,10 +11,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone DFHack
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- ref: ${{ github.event.inputs.branch }}
+ ref: ${{ github.ref }}
submodules: true
token: ${{ secrets.DFHACK_GITHUB_TOKEN }}
- name: Update submodules
diff --git a/.github/workflows/watch-df-release.yml b/.github/workflows/watch-df-release.yml
new file mode 100644
index 0000000000..50950140d1
--- /dev/null
+++ b/.github/workflows/watch-df-release.yml
@@ -0,0 +1,159 @@
+name: Watch DF Releases
+
+on:
+ schedule:
+ - cron: '8/10 * * * *'
+ workflow_dispatch:
+
+jobs:
+ check-steam:
+ if: github.repository == 'DFHack/dfhack'
+ name: Check Steam (${{ matrix.df_steam_branch }}) for new DF releases
+ runs-on: ubuntu-latest
+ concurrency: watch-release-steam-${{ matrix.df_steam_branch }}
+ strategy:
+ fail-fast: false
+ matrix:
+ # df_steam_branch: which DF Steam branch to watch
+ # platform: for symbols generation; leave blank to default to all
+ # structures_ref: leave blank to default to master
+ # dfhack_ref: leave blank if no structures update is desired
+ # steam_branch: leave blank if no DFHack steam push is desired
+ include:
+ - df_steam_branch: public
+# - df_steam_branch: beta
+# - df_steam_branch: experimental
+# structures_ref: experimental
+# dfhack_ref: experimental
+# steam_branch: experimental
+ steps:
+ - name: Fetch state
+ uses: actions/cache/restore@v4
+ with:
+ path: state
+ key: watch-release-steam-${{ matrix.df_steam_branch }}
+ - name: Compare branch metadata
+ uses: nick-fields/retry@v3
+ with:
+ timeout_minutes: 5
+ retry_wait_seconds: 60
+ command: |
+ blob=$(wget 'https://api.steamcmd.net/v1/info/975370?pretty=1' -O- | \
+ awk '/^ *"branches"/,0' | \
+ awk '/^ *"${{ matrix.df_steam_branch }}"/,0')
+ buildid=$(echo "$blob" | \
+ fgrep buildid | \
+ head -n1 | \
+ cut -d'"' -f4)
+ timestamp=$(echo "$blob" | \
+ fgrep timeupdated | \
+ head -n1 | \
+ cut -d'"' -f4)
+ test -z "$buildid" && echo "no buildid result" && exit 1
+ test -z "$timestamp" && echo "no timestamp result" && exit 1
+ test "$buildid" -gt 0 || exit 1
+ test "$timestamp" -gt 0 || exit 1
+ echo "buildid and timestamp of last branch update: $buildid, $timestamp"
+ mkdir -p state
+ touch state/buildid state/timestamp
+ last_buildid=$(cat state/buildid)
+ last_timestamp=$(cat state/timestamp)
+ if [ -z "$last_timestamp" ]; then
+ echo "no stored timestamp"
+ last_buildid=0
+ last_timestamp=0
+ else
+ echo "stored buildid and timestamp of last branch update: $last_buildid, $last_timestamp"
+ fi
+ if [ "$buildid" -ne "$last_buildid" -a "$timestamp" -gt "$last_timestamp" ]; then
+ echo "branch updated"
+ echo "$buildid" >state/buildid
+ echo "$timestamp" >state/timestamp
+ echo BUILDID=$buildid >> $GITHUB_ENV
+ fi
+ - name: Discord Webhook Action
+ uses: tsickert/discord-webhook@v5.3.0
+ if: env.BUILDID
+ with:
+ webhook-url: ${{ secrets.DISCORD_TEAM_PRIVATE_WEBHOOK_URL }}
+ content: "<@&${{ secrets.DISCORD_TEAM_ROLE_ID }}> Steam ${{ matrix.df_steam_branch }} branch updated (build id: ${{ env.BUILDID }})"
+ - name: Launch symbol generation workflow
+ if: env.BUILDID && matrix.dfhack_ref
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh workflow run generate-symbols.yml \
+ -R DFHack/dfhack \
+ -r ${{ matrix.dfhack_ref }} \
+ -f structures_ref=${{ matrix.structures_ref }} \
+ -f version=auto \
+ -f platform=${{ matrix.platform }} \
+ -f channel=steam \
+ -f df_steam_branch=${{ matrix.df_steam_branch }} \
+ -f steam_branch=${{ matrix.steam_branch }}
+ - name: Save state
+ uses: actions/cache/save@v4
+ if: env.BUILDID
+ with:
+ path: state
+ key: watch-release-steam-${{ matrix.df_steam_branch }}-${{ env.BUILDID }}
+
+ check-non-steam:
+ if: github.repository == 'DFHack/dfhack'
+ name: Check ${{ matrix.channel }} for new DF releases
+ runs-on: ubuntu-latest
+ concurrency: watch-release-${{ matrix.channel }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - channel: itch
+ url: 'https://kitfoxgames.itch.io/dwarf-fortress'
+ prefix: 'dwarf_fortress'
+ - channel: classic
+ url: 'https://www.bay12games.com/dwarves/'
+ prefix: 'df'
+ steps:
+ - name: Fetch state
+ uses: actions/cache/restore@v4
+ with:
+ path: state
+ key: watch-release-${{ matrix.channel }}
+ - name: Compare versions
+ uses: nick-fields/retry@v3
+ with:
+ timeout_minutes: 5
+ retry_wait_seconds: 60
+ command: |
+ version=$(wget "${{ matrix.url }}" -qO- | tr '"' '\n' | fgrep 'tar.bz2' | head -n1 | sed -r 's/${{ matrix.prefix }}_([0-9]{2})_([0-9]{2})_linux.tar.bz2/\1.\2/')
+ echo "latest ${{ matrix.channel }} version: $version"
+ if ! grep -qE '^[0-9]+\.[0-9]+$' <<<"$version"; then
+ echo "invalid version"
+ exit 1
+ fi
+ mkdir -p state
+ touch state/last_version
+ last_version=$(cat state/last_version)
+ if [ -z "$last_version" ]; then
+ echo "no stored version"
+ last_version=0
+ else
+ echo "stored ${{ matrix.channel }} version: $last_version"
+ fi
+ if [ "$(tr -d '.' <<<"$version")" -gt "$(tr -d '.' <<<"$last_version")" ]; then
+ echo "${{ matrix.channel }} has been updated"
+ echo "$version" >state/last_version
+ echo NEW_VERSION=$version >> $GITHUB_ENV
+ fi
+ - name: Discord Webhook Action
+ uses: tsickert/discord-webhook@v5.3.0
+ if: env.NEW_VERSION
+ with:
+ webhook-url: ${{ secrets.DISCORD_TEAM_PRIVATE_WEBHOOK_URL }}
+ content: "<@&${{ secrets.DISCORD_TEAM_ROLE_ID }}> ${{ matrix.channel }} updated to ${{ env.NEW_VERSION }}"
+ - name: Save state
+ uses: actions/cache/save@v4
+ if: env.NEW_VERSION
+ with:
+ path: state
+ key: watch-release-${{ matrix.channel }}-${{ env.NEW_VERSION }}
diff --git a/.gitignore b/.gitignore
index 4b533ab20f..eda2b226d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
# linux backup files
*~
-#Kdevelop project files
+# Kdevelop project files
*.kdev4
.kdev4
@@ -9,27 +9,35 @@
build*/
nix
buntu
-build/VC2010
#except for the real one
!build/
# Sphinx generated documentation
-docs/_*
+docs/changelogs/
docs/html/
docs/pdf/
+docs/pseudoxml/
+docs/tags/
+docs/text/
+docs/tools/
+docs/xml/
# in-place build
build/Makefile
build/CMakeCache.txt
build/cmake_install.cmake
build/CMakeFiles
+build/CTestTestfile.cmake
+build/DartConfiguration.tcl
build/data
-build/doc
+build/docs
build/lua
build/bin
+build/lib
build/depends
build/library
+build/package
build/plugins
build/scripts
build/install_manifest.txt
@@ -40,6 +48,8 @@ build/*ninja*
build/compile_commands.json
build/dfhack_setarch.txt
build/ImportExecutables.cmake
+build/Testing
+build/_deps
# Python binding binaries
*.pyc
@@ -55,6 +65,7 @@ build/CPack*Config.cmake
# VSCode files
.vscode
+*.code-workspace
# ctags file
tags
@@ -62,7 +73,7 @@ tags
# Mac OS X .DS_Store files
.DS_Store
-#VS is annoying about this one.
+# VS is annoying about this one.
/build/win64/DF_PATH.txt
/build/win32/DF_PATH.txt
/.vs
@@ -70,5 +81,9 @@ tags
# CLion
.idea
-# custom plugins
+# external plugins
/plugins/CMakeLists.custom.txt
+
+# 3rd party downloads
+depends/steam
+depends/SDL2
diff --git a/.gitmodules b/.gitmodules
index 9c5ac2d511..596bafc98f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,9 +1,6 @@
[submodule "plugins/stonesense"]
path = plugins/stonesense
url = ../../DFHack/stonesense.git
-[submodule "plugins/isoworld"]
- path = plugins/isoworld
- url = ../../DFHack/isoworld.git
[submodule "library/xml"]
path = library/xml
url = ../../DFHack/df-structures.git
@@ -28,3 +25,9 @@
[submodule "depends/luacov"]
path = depends/luacov
url = ../../DFHack/luacov.git
+[submodule "depends/googletest"]
+ path = depends/googletest
+ url = ../../google/googletest.git
+[submodule "depends/dfhooks"]
+ path = depends/dfhooks
+ url = ../../DFHack/dfhooks
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000000..47251d8ed3
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,44 @@
+ci:
+ autofix_prs: false
+ autoupdate_schedule: monthly
+repos:
+# shared across repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v6.0.0
+ hooks:
+ - id: check-added-large-files
+ - id: check-case-conflict
+ - id: check-executables-have-shebangs
+ - id: check-merge-conflict
+ - id: check-shebang-scripts-are-executable
+ - id: check-symlinks
+ - id: check-xml
+ - id: check-yaml
+ - id: destroyed-symlinks
+ - id: end-of-file-fixer
+ - id: mixed-line-ending
+ args: ['--fix=lf']
+ - id: trailing-whitespace
+- repo: https://github.com/python-jsonschema/check-jsonschema
+ rev: 0.37.4
+ hooks:
+ - id: check-github-workflows
+- repo: https://github.com/Lucas-C/pre-commit-hooks
+ rev: v1.5.6
+ hooks:
+ - id: forbid-tabs
+ exclude_types:
+ - json
+ - id: remove-tabs
+ exclude_types:
+ - json
+# specific to dfhack:
+- repo: local
+ hooks:
+ - id: authors-rst
+ name: Check Authors.rst
+ language: python
+ entry: python3 ci/authors-rst.py
+ files: docs/about/Authors\.rst
+ pass_filenames: false
+exclude: '^(depends/|data/.*\.json$|.*\.diff$|.*\.dfstock$)'
diff --git a/plugins/tweak/tweaks/cursor-cross.h b/.readthedocs.requirements.txt
similarity index 100%
rename from plugins/tweak/tweaks/cursor-cross.h
rename to .readthedocs.requirements.txt
diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644
index 0000000000..bf71c46b78
--- /dev/null
+++ b/.readthedocs.yml
@@ -0,0 +1,22 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+version: 2
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3"
+
+submodules:
+ include: all
+
+sphinx:
+ configuration: conf.py
+
+formats: all
+
+python:
+ install:
+ - requirements: .readthedocs.requirements.txt
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
index e98f7a2a63..31a336b2b6 100644
--- a/.ycm_extra_conf.py
+++ b/.ycm_extra_conf.py
@@ -19,7 +19,6 @@ def DirectoryOfThisScript():
'-I','depends/md5',
'-I','depends/jsoncpp/include',
'-I','depends/tinyxml',
- '-I','depends/tthread',
'-I','depends/clsocket/src',
'-x','c++',
'-D','PROTOBUF_USE_DLLS',
diff --git a/CMake/DownloadFile.cmake b/CMake/DownloadFile.cmake
index aabcaeb3a6..d0165b11a3 100644
--- a/CMake/DownloadFile.cmake
+++ b/CMake/DownloadFile.cmake
@@ -11,7 +11,7 @@ endfunction()
function(search_downloads FILE_MD5 VAR)
set(${VAR} "" PARENT_SCOPE)
- file(GLOB FILES ${CMAKE_SOURCE_DIR}/CMake/downloads/*)
+ file(GLOB FILES ${dfhack_SOURCE_DIR}/CMake/downloads/*)
foreach(FILE ${FILES})
file(MD5 "${FILE}" CUR_MD5)
if("${CUR_MD5}" STREQUAL "${FILE_MD5}")
@@ -53,7 +53,7 @@ function(download_file_unzip URL ZIP_TYPE ZIP_DEST ZIP_MD5 UNZIP_DEST UNZIP_MD5)
message("* Decompressing ${FILENAME}")
if("${ZIP_TYPE}" STREQUAL "gz")
execute_process(COMMAND
- "${PERL_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/depends/gunzip.pl"
+ "${PERL_EXECUTABLE}" "${dfhack_SOURCE_DIR}/depends/gunzip.pl"
"${ZIP_DEST}" --force)
else()
message(SEND_ERROR "Unknown ZIP_TYPE: ${ZIP_TYPE}")
diff --git a/CMake/Modules/FindSphinx.cmake b/CMake/Modules/FindSphinx.cmake
index 54fc5ea8dc..6b78a555ff 100644
--- a/CMake/Modules/FindSphinx.cmake
+++ b/CMake/Modules/FindSphinx.cmake
@@ -13,4 +13,3 @@ find_package_handle_standard_args(Sphinx DEFAULT_MSG
)
mark_as_advanced(SPHINX_EXECUTABLE)
-
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f07cdf5af8..1495bea2b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,22 +1,31 @@
# main project file. use it from a build sub-folder, see COMPILE for details
## some generic CMake magic
-cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
cmake_policy(SET CMP0048 NEW)
-project(dfhack)
+cmake_policy(SET CMP0074 NEW)
+set(CMAKE_INSTALL_MESSAGE "LAZY")
-if("${CMAKE_GENERATOR}" STREQUAL Ninja)
- if("${CMAKE_VERSION}" VERSION_LESS 3.9)
- message(WARNING "You are using an old version of CMake (${CMAKE_VERSION}) with Ninja. This may result in ninja errors - see docs/Compile.rst for more details. Upgrading your CMake version is recommended.")
- endif()
-endif()
+# set up versioning.
+set(DF_VERSION "53.16")
+set(DFHACK_RELEASE "r1.1")
+set(DFHACK_PRERELEASE FALSE)
-if(NOT("${CMAKE_VERSION}" VERSION_LESS 3.12))
- # make ZLIB_ROOT work in CMake >= 3.12
- # https://cmake.org/cmake/help/git-stage/policy/CMP0074.html
- cmake_policy(SET CMP0074 NEW)
+set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
+set(DFHACK_ABI_VERSION 2)
+set(DFHACK_BUILD_ID "" CACHE STRING "Build ID (should be specified on command line)")
+
+# set up ccache
+find_program(CCACHE_EXECUTABLE "ccache" HINTS /usr/local/bin /opt/local/bin)
+if(CCACHE_EXECUTABLE)
+ message(STATUS "using ccache")
+ set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
+ set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
endif()
+# project must be declared *after* ccache setup
+project(dfhack)
+
# Set up build types
if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo" CACHE STRING "List of supported configuration types" FORCE)
@@ -32,18 +41,20 @@ else(CMAKE_CONFIGURATION_TYPES)
endif(CMAKE_CONFIGURATION_TYPES)
option(BUILD_DOCS "Choose whether to build the documentation (requires python and Sphinx)." OFF)
+option(BUILD_DOCS_NO_HTML "Don't build the HTML docs, only the in-game docs." OFF)
option(REMOVE_SYMBOLS_FROM_DF_STUBS "Remove debug symbols from DF stubs. (Reduces libdfhack size to about half but removes a few useful symbols)" ON)
macro(CHECK_GCC compiler_path)
execute_process(COMMAND ${compiler_path} -dumpversion OUTPUT_VARIABLE GCC_VERSION_OUT)
string(STRIP "${GCC_VERSION_OUT}" GCC_VERSION_OUT)
- if(${GCC_VERSION_OUT} VERSION_LESS "4.8")
- message(SEND_ERROR "${compiler_path} version ${GCC_VERSION_OUT} cannot be used - use GCC 4.8 or later")
- elseif(${GCC_VERSION_OUT} VERSION_GREATER "4.9.9")
- # GCC 5 changes ABI name mangling to enable C++11 changes.
- # This must be disabled to enable linking against DF.
- # http://developerblog.redhat.com/2015/02/05/gcc5-and-the-c11-abi/
- add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+ if(${GCC_VERSION_OUT} VERSION_LESS "11")
+ message(SEND_ERROR "${compiler_path} version ${GCC_VERSION_OUT} cannot be used - use GCC 11 or later")
+ endif()
+ # GCC 16 currently has a defect that prevents it from compiling DFHack
+ # -Warray-bounds is broken in GCC 16 and we'd rather disable the compiler than remove this warning
+ # will reconsider when this defect is fixed in a future GCC release
+ if(${GCC_VERSION_OUT} VERSION_GREATER_EQUAL "16")
+ message(SEND_ERROR "${compiler_path} version ${GCC_VERSION_OUT} cannot be used - use GCC 15 or earlier")
endif()
endmacro()
@@ -61,21 +72,29 @@ if(UNIX)
endif()
if(WIN32)
- if((NOT MSVC) OR (MSVC_VERSION LESS 1900) OR (MSVC_VERSION GREATER 1919))
- message(SEND_ERROR "MSVC 2015 or 2017 is required")
+ set(MSVC_MIN_VER 1930)
+ set(MSVC_MAX_VER 1944)
+ if(NOT MSVC)
+ message(SEND_ERROR "No MSVC found! MSVC 2022 version ${MSVC_MIN_VER} to ${MSVC_MAX_VER} is required.")
+ elseif((MSVC_VERSION LESS MSVC_MIN_VER) OR (MSVC_VERSION GREATER MSVC_MAX_VER))
+ message(SEND_ERROR "MSVC 2022 version ${MSVC_MIN_VER} to ${MSVC_MAX_VER} is required, Version Found: ${MSVC_VERSION}")
endif()
endif()
-# Ask for C++11 standard from compilers
-set(CMAKE_CXX_STANDARD 11)
+# Ask for C++-20 standard from compilers
+set(CMAKE_CXX_STANDARD 20)
# Require the standard support from compilers.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Use only standard c++ to keep code portable
set(CMAKE_CXX_EXTENSIONS OFF)
if(MSVC)
+ # increase warning level and treat warnings as errors
+ add_compile_options("/WX")
+ add_compile_options("/W3")
+
# disable C4819 code-page warning
- add_definitions("/wd4819")
+ add_compile_options("/wd4819")
# disable use of POSIX name warnings
add_definitions("/D_CRT_NONSTDC_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS")
@@ -84,24 +103,46 @@ if(MSVC)
# weird and mysterious linking errors, you can disable this, but you'll have to
# deal with a LOT of compiler noise over it
# see https://msdn.microsoft.com/en-us/library/074af4b6.aspx
- add_definitions("/wd4503")
+ add_compile_options("/wd4503")
+
+ # suppress C4267 - VC++ considers a narrowing conversion from size_t to a smaller
+ # integer type a warning. this is technically correct but there are so many instances
+ # of this that we don't want to fix, so....
+ add_compile_options("/wd4267")
- # suppress C4267 - VC++ complains whenever we implicitly convert an integer to
- # a smaller type, and most of the time this is just conversion from 64 to 32 bits
- # for things like vector sizes, which are never that big anyway.
- add_definitions("/wd4267")
+ # suppress C4251 - VC++ will warn when exporting an entire class which contains members
+ # referencing unexported compound types as this is potentially unsafe. because we don't
+ # guarantee a stable ABI for exports, we don't really care about this, and so we choose to
+ # be lazy and continue to export entire classes instead of exporting on a method-by-method basis
+ add_compile_options("/wd4251")
+
+ # suppress C4068 - VC++ will warn for unknown pragmas by default. this is equivalent to gcc
+ # -Wno-unknown-pragmas (which is enabled for gcc below).
+ # we could work around this with sufficiently complex macros
+ add_compile_options("/wd4068")
+
+ # suppress C4244 - VC++ warns by default (with /W3) about narrowing conversions that may lose data
+ # (such as double -> int or int32_t -> int16_t). dfhack has many of these, mostly related to Lua
+ # this is equivalent to gcc -Wno_conversions which is the default as gcc -Wall doesn't enable -Wconversions
+ add_compile_options("/wd4244")
+
+ # Enable C5038 - This is equivalent to gcc's -Werror=reorder, which is enabled by default by gcc -Wall
+ add_compile_options("/w15038")
+
+ # Enable C4062 - Warns about missing enum case in switch statement, equivalent to gcc -Wswitch
+ add_compile_options("/w14062")
# MSVC panics if an object file contains more than 65,279 sections. this
# happens quite frequently with code that uses templates, such as vectors.
- add_definitions("/bigobj")
+ add_compile_options("/bigobj")
endif()
# Automatically detect architecture based on Visual Studio generator
if(MSVC AND NOT DEFINED DFHACK_BUILD_ARCH)
- if(${CMAKE_GENERATOR} MATCHES "Win64")
- set(DFHACK_BUILD_ARCH "64")
+ if ((${CMAKE_GENERATOR} MATCHES "Win32") OR (${CMAKE_GENERATOR} MATCHES "x86"))
+ message(SEND_ERROR "DF v50 does not support 32-bit")
else()
- set(DFHACK_BUILD_ARCH "32")
+ set(DFHACK_BUILD_ARCH "64")
endif()
else()
set(DFHACK_BUILD_ARCH "64" CACHE STRING "Architecture to build ('32' or '64')")
@@ -117,7 +158,7 @@ elseif("${DFHACK_BUILD_ARCH}" STREQUAL "64")
set(DFHACK_SETARCH "x86_64")
add_definitions(-DDFHACK64)
else()
- message(SEND_ERROR "Invalid build architecture (should be 32/64): ${DFHACK_BUILD_ARCH}")
+ message(SEND_ERROR "Invalid build architecture (should be 32 or 64): ${DFHACK_BUILD_ARCH}")
endif()
if(CMAKE_CROSSCOMPILING)
@@ -128,14 +169,8 @@ endif()
find_package(Perl REQUIRED)
# set up folder structures for IDE solutions
-# MSVC Express won't load solutions that use this. It also doesn't include MFC supported
-# Check for MFC!
-find_package(MFC QUIET)
-if(MFC_FOUND OR (NOT MSVC))
- option(CMAKE_USE_FOLDERS "Enable folder grouping of projects in IDEs." ON)
-else()
- option(CMAKE_USE_FOLDERS "Enable folder grouping of projects in IDEs." OFF)
-endif()
+# checking for msvc express is meaningless now, all available editions of msvc support folder groupings
+option(CMAKE_USE_FOLDERS "Enable folder grouping of projects in IDEs." ON)
if(CMAKE_USE_FOLDERS)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@@ -174,78 +209,58 @@ if(HAVE_CUCHAR2)
endif()
# mixing the build system with the source code is ugly and stupid. enforce the opposite :)
-if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
+if("${dfhack_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "In-source builds are not allowed.")
endif()
# make sure all the necessary submodules have been set up
if(NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl
OR NOT EXISTS ${dfhack_SOURCE_DIR}/scripts/CMakeLists.txt
+ OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/dfhooks/CMakeLists.txt
OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/clsocket/CMakeLists.txt
+ OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/jsoncpp-sub/CMakeLists.txt
OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/libexpat/expat/CMakeLists.txt
OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/libzip/CMakeLists.txt
OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/xlsxio/CMakeLists.txt
+ OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/googletest/CMakeLists.txt
OR NOT EXISTS ${dfhack_SOURCE_DIR}/depends/luacov/src
)
- message(SEND_ERROR "One or more required submodules could not be found! Run 'git submodule update --init' from the root DFHack directory. (See the section 'Getting the Code' in docs/Compile.rst)")
+ message(SEND_ERROR "One or more required submodules could not be found! Run 'git submodule update --init' from the root DFHack directory. (See the section 'Getting the Code' in docs/dev/compile/Compile.rst)")
endif()
-# set up versioning.
-set(DF_VERSION "0.47.05")
-set(DFHACK_RELEASE "r3")
-set(DFHACK_PRERELEASE FALSE)
-
-set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
-
-set(DFHACK_ABI_VERSION 1)
-
-set(DFHACK_BUILD_ID "" CACHE STRING "Build ID (should be specified on command line)")
+# dfhack data goes here:
+set(DFHACK_DATA_DESTINATION hack)
## where to install things (after the build is done, classic 'make install' or package structure)
# the dfhack libraries will be installed here:
-if(UNIX)
- # put the lib into DF/hack
- set(DFHACK_LIBRARY_DESTINATION hack)
- set(DFHACK_EGGY_DESTINATION libs)
-else()
- # windows is crap, therefore we can't do nice things with it. leave the libs on a nasty pile...
- set(DFHACK_LIBRARY_DESTINATION .)
- set(DFHACK_EGGY_DESTINATION .)
-endif()
+
+# put the lib into DF/hack
+# windows will find it because dfhooks will `AddDllDirectory` the hack folder at runtime
+set(DFHACK_LIBRARY_DESTINATION ${DFHACK_DATA_DESTINATION})
# external tools will be installed here:
set(DFHACK_BINARY_DESTINATION .)
-# dfhack data goes here:
-set(DFHACK_DATA_DESTINATION hack)
# plugin libs go here:
-set(DFHACK_PLUGIN_DESTINATION hack/plugins)
-# dfhack header files go here:
-set(DFHACK_INCLUDES_DESTINATION hack/include)
+set(DFHACK_PLUGIN_DESTINATION ${DFHACK_DATA_DESTINATION}/plugins)
# dfhack lua files go here:
-set(DFHACK_LUA_DESTINATION hack/lua)
-# the windows .lib file goes here:
-set(DFHACK_DEVLIB_DESTINATION hack)
+set(DFHACK_LUA_DESTINATION ${DFHACK_DATA_DESTINATION}/lua)
# user documentation goes here:
-set(DFHACK_USERDOC_DESTINATION hack)
-# developer documentation goes here:
-set(DFHACK_DEVDOC_DESTINATION hack)
+set(DFHACK_USERDOC_DESTINATION ${DFHACK_DATA_DESTINATION})
# some options for the user/developer to play with
-option(BUILD_LIBRARY "Build the library that goes into DF." ON)
-option(BUILD_PLUGINS "Build the plugins." ON)
+option(BUILD_LIBRARY "Build the DFHack library." ON)
+option(BUILD_PLUGINS "Build the DFHack plugins." ON)
+option(INSTALL_SCRIPTS "Install DFHack scripts." ON)
+option(INSTALL_DATA_FILES "Install DFHack platform independent files." ON)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
if(UNIX)
## flags for GCC
# default to hidden symbols
- # build 32bit
# ensure compatibility with older CPUs
- # enable C++11 features
add_definitions(-DLINUX_BUILD)
- add_definitions(-D_GLIBCXX_USE_C99)
- set(GCC_COMMON_FLAGS "-fvisibility=hidden -mtune=generic -Wall -Werror")
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g")
+ set(GCC_COMMON_FLAGS "-fvisibility=hidden -mtune=generic -Wall -Werror -Wl,--disable-new-dtags -Wno-unknown-pragmas")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COMMON_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COMMON_FLAGS}")
if(DFHACK_BUILD_64)
@@ -256,12 +271,20 @@ if(UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -march=i686")
endif()
string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+ set(CMAKE_INSTALL_RPATH "$ORIGIN")
elseif(MSVC)
# for msvc, tell it to always use 8-byte pointers to member functions to avoid confusion
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /vmg /vmm /MP")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od")
string(REPLACE "/O2" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+
+ option(BUILD_PDBS "Build PDB debug symbol files." OFF)
+ if(BUILD_PDBS)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Z7")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /DEBUG")
+ endif()
endif()
# use shared libraries for protobuf
@@ -277,48 +300,72 @@ elseif(WIN32)
add_definitions(-DWIN32)
endif()
-#### download depends ####
+#### dependencies ####
+
+# fix for pyenv: default to `python3` before `python3.x`
+set(Python_FIND_UNVERSIONED_NAMES FIRST)
include(CMake/DownloadFile.cmake)
if(WIN32)
- # Download zlib on Windows
- set(ZLIB_DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/depends/zlib/lib/win${DFHACK_BUILD_ARCH})
- if(${DFHACK_BUILD_ARCH} STREQUAL "64")
- download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win64-zlib.lib"
- ${ZLIB_DOWNLOAD_DIR}/zlib.lib
- "a3b2fc6b68efafa89b0882e354fc8418")
- else()
- download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win32-zlib.lib"
- ${ZLIB_DOWNLOAD_DIR}/zlib.lib
- "f4ebaa21d9de28566e88b1edfcdff901")
+ set(ZLIB_FILE zlib.lib)
+ set(ZLIB_PATH ${dfhack_SOURCE_DIR}/depends/zlib/)
+ set(ZLIB_MD5 a3b2fc6b68efafa89b0882e354fc8418)
+ download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win64-${ZLIB_FILE}"
+ ${ZLIB_PATH}lib/${ZLIB_FILE}
+ ${ZLIB_MD5})
+ set(ZLIB_ROOT ${ZLIB_PATH})
+else()
+ # Rescan for pthread and zlib if the build arch changed
+ if(NOT "${DFHACK_BUILD_ARCH}" STREQUAL "${DFHACK_BUILD_ARCH_PREV}")
+ unset(ZLIB_LIBRARY CACHE)
+ unset(CMAKE_HAVE_PTHREAD_H CACHE)
+ endif()
+
+ if(NOT APPLE AND DFHACK_BUILD_32)
+ set(ZLIB_ROOT /usr/lib/i386-linux-gnu)
endif()
+endif()
+find_package(ZLIB REQUIRED)
- # Move zlib to the build folder so possible 32 and 64-bit builds
- # in the same source tree don't conflict
- file(COPY ${CMAKE_SOURCE_DIR}/depends/zlib
- DESTINATION ${CMAKE_BINARY_DIR}/depends/)
- file(COPY ${ZLIB_DOWNLOAD_DIR}/zlib.lib
- DESTINATION ${CMAKE_BINARY_DIR}/depends/zlib/lib/)
+set(USE_SYSTEM_SDL2 OFF CACHE BOOL "Set to ON to use the system SDL2 headers.")
- # Do the same for SDLreal.dll
- # (DFHack doesn't require this at build time, so no need to move it to the build folder)
- set(SDLREAL_DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/package/windows/win${DFHACK_BUILD_ARCH})
- if(${DFHACK_BUILD_ARCH} STREQUAL "64")
- download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win64-SDL.dll"
- ${SDLREAL_DOWNLOAD_DIR}/SDLreal.dll
- "1ae242c4b94cb03756a1288122a66faf")
+if(BUILD_LIBRARY)
+ if(USE_SYSTEM_SDL2)
+ find_package(SDL2 REQUIRED CONFIG REQUIRED COMPONENTS SDL2)
else()
- download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win32-SDL.dll"
- ${SDLREAL_DOWNLOAD_DIR}/SDLreal.dll
- "5a09604daca6b2b5ce049d79af935d6a")
+ # Download SDL release and extract into depends in the build dir
+ # all we need are the header files (including generated headers), so the same release package
+ # will work for all platforms
+ # (the above statement is untested for OSX)
+ set(SDL_VERSION 2.26.2)
+ set(SDL_ZIP_MD5 574daf26d48de753d0b1e19823c9d8bb)
+ set(SDL_ZIP_FILE SDL2-devel-${SDL_VERSION}-VC.zip)
+ set(SDL_ZIP_PATH ${dfhack_SOURCE_DIR}/depends/SDL2/)
+ download_file("https://github.com/libsdl-org/SDL/releases/download/release-${SDL_VERSION}/${SDL_ZIP_FILE}"
+ ${SDL_ZIP_PATH}${SDL_ZIP_FILE}
+ ${SDL_ZIP_MD5})
+ file(ARCHIVE_EXTRACT INPUT ${SDL_ZIP_PATH}${SDL_ZIP_FILE}
+ DESTINATION ${SDL_ZIP_PATH})
+ set(SDL2_INCLUDE_DIRS ${SDL_ZIP_PATH}/SDL2-${SDL_VERSION}/include)
endif()
endif()
+# this can be made conditional once we get to better platform support for std::format
+INCLUDE(FetchContent)
+FetchContent_Declare(
+ fmt
+ GIT_REPOSITORY https://github.com/fmtlib/fmt.git
+ GIT_TAG 790b9389ae99c4ddebdd2736a8602eca1fec684e # 12.1.0 + bugfix for MSVC warning + build time improvements
+)
+FetchContent_MakeAvailable(fmt)
+set(FMTLIB fmt)
+add_definitions("-DUSE_FMTLIB")
+
if(APPLE)
# libstdc++ (GCC 4.8.5 for OS X 10.6)
# fixes crash-on-unwind bug in DF's libstdc++
- set(LIBSTDCXX_DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/package/darwin/osx${DFHACK_BUILD_ARCH})
+ set(LIBSTDCXX_DOWNLOAD_DIR ${dfhack_SOURCE_DIR}/package/darwin/osx${DFHACK_BUILD_ARCH})
if(${GCC_VERSION_OUT} VERSION_LESS "4.9")
set(LIBSTDCXX_GCC_VER "48")
@@ -373,30 +420,6 @@ endif()
#### expose depends ####
-if(UNIX)
- # Rescan for pthread and zlib if the build arch changed
- if(NOT "${DFHACK_BUILD_ARCH}" STREQUAL "${DFHACK_BUILD_ARCH_PREV}")
- unset(ZLIB_LIBRARY CACHE)
- unset(CMAKE_HAVE_PTHREAD_H CACHE)
- endif()
-endif()
-
-# find and make available libz
-if(NOT UNIX) # Windows
- # zlib is in here so 32-bit and 64-bit builds in the same source tree are possible
- set(ZLIB_ROOT ${CMAKE_BINARY_DIR}/depends/zlib/)
-else()
- if(NOT APPLE AND DFHACK_BUILD_32)
- # 32-bit Linux
- set(ZLIB_ROOT /usr/lib/i386-linux-gnu)
- endif()
-endif()
-
-find_package(ZLIB REQUIRED)
-include_directories(depends/protobuf)
-include_directories(depends/lua/include)
-include_directories(depends/md5)
-
# Support linking against external tinyxml
# If we find an external tinyxml, set the DFHACK_TINYXML variable to "tinyxml"
# Otherwise, set it to "dfhack-tinyxml"
@@ -408,16 +431,23 @@ if(EXTERNAL_TINYXML)
endif()
set(DFHACK_TINYXML "tinyxml")
else()
- include_directories(depends/tinyxml)
set(DFHACK_TINYXML "dfhack-tinyxml")
endif()
-include_directories(depends/lodepng)
-include_directories(depends/tthread)
-include_directories(${ZLIB_INCLUDE_DIRS})
-include_directories(depends/clsocket/src)
-include_directories(depends/xlsxio/include)
-add_subdirectory(depends)
+if(BUILD_LIBRARY)
+ add_subdirectory(depends)
+endif()
+
+# Testing with CTest
+macro(dfhack_test name files)
+if(BUILD_LIBRARY AND UNIX AND NOT APPLE) # remove this once our MSVC build env has been updated
+ add_executable(${name} ${files})
+ target_include_directories(${name} PUBLIC depends/googletest/googletest/include)
+ target_link_libraries(${name} dfhack ${FMTLIB} gtest)
+ add_test(NAME ${name} COMMAND ${name})
+endif()
+endmacro()
+include(CTest)
find_package(Git REQUIRED)
if(NOT GIT_FOUND)
@@ -425,62 +455,95 @@ if(NOT GIT_FOUND)
endif()
# build the lib itself
+add_subdirectory(library)
if(BUILD_LIBRARY)
- add_subdirectory(library)
- install(FILES LICENSE.rst DESTINATION ${DFHACK_USERDOC_DESTINATION})
- install(FILES docs/changelog-placeholder.txt DESTINATION ${DFHACK_USERDOC_DESTINATION} RENAME changelog.txt)
+ file(WRITE ${CMAKE_BINARY_DIR}/dfhack_setarch.txt ${DFHACK_SETARCH})
+ install(FILES ${CMAKE_BINARY_DIR}/dfhack_setarch.txt DESTINATION ${DFHACK_DATA_DESTINATION})
endif()
-file(WRITE "${CMAKE_BINARY_DIR}/dfhack_setarch.txt" ${DFHACK_SETARCH})
-install(FILES "${CMAKE_BINARY_DIR}/dfhack_setarch.txt" DESTINATION "${DFHACK_DATA_DESTINATION}")
-
-install(DIRECTORY dfhack-config/ DESTINATION dfhack-config/default)
-
# build the plugins
-if(BUILD_PLUGINS)
- add_subdirectory(plugins)
+add_subdirectory(plugins)
+
+if(INSTALL_DATA_FILES)
+ add_subdirectory(data)
+ install(FILES LICENSE.rst DESTINATION ${DFHACK_USERDOC_DESTINATION})
+ install(FILES docs/changelog-placeholder.txt DESTINATION ${DFHACK_USERDOC_DESTINATION} RENAME changelog.txt)
+ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/depends/luacov/src/luacov/ DESTINATION ${DFHACK_DATA_DESTINATION}/lua/luacov)
endif()
-add_subdirectory(data)
-add_subdirectory(scripts)
+if(INSTALL_SCRIPTS)
+ add_subdirectory(scripts)
+endif()
-find_package(Sphinx QUIET)
if(BUILD_DOCS)
+ find_package(Python3)
+ find_package(Sphinx)
+
if(NOT SPHINX_FOUND)
message(SEND_ERROR "Sphinx not found but BUILD_DOCS enabled")
endif()
- file(GLOB SPHINX_DEPS
- "${CMAKE_CURRENT_SOURCE_DIR}/docs/*.rst"
- "${CMAKE_CURRENT_SOURCE_DIR}/docs/guides/*.rst"
- "${CMAKE_CURRENT_SOURCE_DIR}/docs/changelog.txt"
- "${CMAKE_CURRENT_SOURCE_DIR}/docs/gen_changelog.py"
+ file(GLOB SPHINX_GLOB_DEPS
+ LIST_DIRECTORIES false
"${CMAKE_CURRENT_SOURCE_DIR}/docs/images/*.png"
"${CMAKE_CURRENT_SOURCE_DIR}/docs/styles/*"
- "${CMAKE_CURRENT_SOURCE_DIR}/conf.py"
- "${CMAKE_CURRENT_SOURCE_DIR}/scripts/about.txt"
- "${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/about.txt"
+ "${CMAKE_CURRENT_SOURCE_DIR}/data/init/*init"
+ )
+ file(GLOB_RECURSE SPHINX_GLOB_RECURSE_DEPS
+ "${CMAKE_CURRENT_SOURCE_DIR}/*.rst"
+ "${CMAKE_CURRENT_SOURCE_DIR}/changelog.txt"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/*py"
)
- file(GLOB_RECURSE SPHINX_SCRIPT_DEPS
- "${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.lua"
- "${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.rb"
+ list(FILTER SPHINX_GLOB_RECURSE_DEPS
+ EXCLUDE REGEX "docs/changelogs"
)
- set(SPHINX_DEPS ${SPHINX_DEPS} ${SPHINX_SCRIPT_DEPS}
- "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.rst"
+ list(FILTER SPHINX_GLOB_RECURSE_DEPS
+ EXCLUDE REGEX "docs/html"
+ )
+ list(FILTER SPHINX_GLOB_RECURSE_DEPS
+ EXCLUDE REGEX "docs/tags"
+ )
+ list(FILTER SPHINX_GLOB_RECURSE_DEPS
+ EXCLUDE REGEX "docs/text"
+ )
+ list(FILTER SPHINX_GLOB_RECURSE_DEPS
+ EXCLUDE REGEX "docs/tools"
+ )
+ set(SPHINX_DEPS ${SPHINX_GLOB_DEPS} ${SPHINX_GLOB_RECURSE_DEPS} ${SPHINX_SCRIPT_DEPS}
"${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt"
+ "${CMAKE_CURRENT_SOURCE_DIR}/conf.py"
+ )
+
+ if(BUILD_DOCS_NO_HTML)
+ set(SPHINX_OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/docs/text/index.txt")
+ set(SPHINX_BUILD_TARGETS text)
+ else()
+ set(SPHINX_OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/docs/html/.buildinfo")
+ set(SPHINX_BUILD_TARGETS html text)
+ endif()
+
+ set_property(
+ DIRECTORY PROPERTY ADDITIONAL_CLEAN_FILES TRUE
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/changelogs"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/html"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/pdf"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/pseudoxml"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/tags"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/text"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/tools"
+ "${CMAKE_CURRENT_SOURCE_DIR}/docs/xml"
+ "${CMAKE_BINARY_DIR}/docs/html"
+ "${CMAKE_BINARY_DIR}/docs/pdf"
+ "${CMAKE_BINARY_DIR}/docs/pseudoxml"
+ "${CMAKE_BINARY_DIR}/docs/text"
+ "${CMAKE_BINARY_DIR}/docs/xml"
)
- set(SPHINX_OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/docs/html/.buildinfo")
- set_source_files_properties(${SPHINX_OUTPUT} PROPERTIES GENERATED TRUE)
add_custom_command(OUTPUT ${SPHINX_OUTPUT}
- COMMAND ${SPHINX_EXECUTABLE}
- -a -E -q -b html
- "${CMAKE_CURRENT_SOURCE_DIR}"
- "${CMAKE_CURRENT_SOURCE_DIR}/docs/html"
- -w "${CMAKE_CURRENT_SOURCE_DIR}/docs/_sphinx-warnings.txt"
- -j 2
+ COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/docs/build.py"
+ ${SPHINX_BUILD_TARGETS} --sphinx="${SPHINX_EXECUTABLE}" --quiet -- -W
DEPENDS ${SPHINX_DEPS}
- COMMENT "Building HTML documentation with Sphinx"
+ COMMENT "Building documentation with Sphinx"
)
add_custom_target(dfhack_docs ALL
@@ -491,9 +554,15 @@ if(BUILD_DOCS)
add_custom_command(TARGET dfhack_docs POST_BUILD
COMMAND ${CMAKE_COMMAND} -E touch ${SPHINX_OUTPUT})
- install(DIRECTORY ${dfhack_SOURCE_DIR}/docs/html/
+ if(NOT BUILD_DOCS_NO_HTML)
+ install(DIRECTORY ${dfhack_SOURCE_DIR}/docs/html/
+ DESTINATION ${DFHACK_USERDOC_DESTINATION}/docs
+ FILES_MATCHING PATTERN "*"
+ PATTERN html/_sources EXCLUDE)
+ endif()
+ install(DIRECTORY ${dfhack_SOURCE_DIR}/docs/text/
DESTINATION ${DFHACK_USERDOC_DESTINATION}/docs)
- install(FILES docs/_auto/news.rst docs/_auto/news-dev.rst DESTINATION ${DFHACK_USERDOC_DESTINATION})
+ install(FILES docs/changelogs/news.rst docs/changelogs/news-dev.rst DESTINATION ${DFHACK_USERDOC_DESTINATION})
install(FILES "README.html" DESTINATION "${DFHACK_DATA_DESTINATION}")
endif()
@@ -575,7 +644,9 @@ endif()
set(DFHACK_BUILD_ARCH_PREV "${DFHACK_BUILD_ARCH}" CACHE STRING "Previous build architecture" FORCE)
option(BUILD_SIZECHECK "Build the sizecheck library, for research" OFF)
-if(BUILD_SIZECHECK)
+if(BUILD_LIBRARY AND BUILD_SIZECHECK)
add_subdirectory(depends/sizecheck)
add_dependencies(dfhack sizecheck)
endif()
+
+add_subdirectory(package)
diff --git a/CMakeSettings.json b/CMakeSettings.json
index fda8ecfd3d..d1511716f7 100644
--- a/CMakeSettings.json
+++ b/CMakeSettings.json
@@ -1,76 +1,10 @@
{
- "environments": [
- {
- "environment": "msvc_2015_x86",
- "PATH": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64_x86;${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;${env.ProgramFiles(x86)}\\Windows Kits\\10\\bin\\x86;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\bin\\x86;${env.PATH}",
- "VS140COMNTOOLS": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\Common7\\Tools\\",
- "VCINSTALLDIR": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\",
- "WindowsSdkDir": "${env.ProgramFiles(x86)}\\Windows Kits\\10\\",
- "UCRTVersion": "10.0.10240.0",
- "UniversalCRTSdkDir": "${env.ProgramFiles(x86)}\\Windows Kits\\10\\",
- "LIB": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\LIB;${env.ProgramFiles(x86)}\\Windows Kits\\10\\lib\\10.0.10240.0\\ucrt\\x86;${env.ProgramFiles(x86)}\\Windows Kits\\10\\lib\\um\\x86;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x86",
- "INCLUDE": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\INCLUDE;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\shared;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\um;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\winrt;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\Include\\um;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\Include\\shared",
- "LIBPATH": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\LIB"
- },
- {
- "environment": "msvc_2015_x64",
- "PATH": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\BIN;${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\BIN\\1033;${env.ProgramFiles(x86)}\\Windows Kits\\bin\\x64;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\bin\\x64;${env.PATH}",
- "VS140COMNTOOLS": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\Common7\\Tools\\",
- "VCINSTALLDIR": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\",
- "WindowsSdkDir": "${env.ProgramFiles(x86)}\\Windows Kits\\10\\",
- "UCRTVersion": "10.0.10240.0",
- "UniversalCRTSdkDir": "${env.ProgramFiles(x86)}\\Windows Kits\\10\\",
- "LIB": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;${env.ProgramFiles(x86)}\\Windows Kits\\10\\lib\\10.0.10240.0\\ucrt\\x64;${env.ProgramFiles(x86)}\\Windows Kits\\10\\lib\\um\\x64;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x64",
- "INCLUDE": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\INCLUDE;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\shared;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\um;${env.ProgramFiles(x86)}\\Windows Kits\\10\\include\\winrt;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\Include\\um;${env.ProgramFiles(x86)}\\Windows Kits\\8.1\\Include\\shared",
- "LIBPATH": "${env.ProgramFiles(x86)}\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64"
- }
- ],
"configurations": [
- {
- "name": "MSVC 32 Debug",
- "generator": "Ninja",
- "configurationType": "RelWithDebInfo",
- "inheritEnvironments": [ "msvc_x86_x64", "msvc_2015_x86" ],
- "variables": [
- {
- "name": "DFHACK_BUILD_ARCH",
- "value": "32"
- },
- {
- "name": "BUILD_STONESENSE",
- "value": "1"
- },
- {
- "name": "REMOVE_SYMBOLS_FROM_DF_STUBS",
- "value": "0"
- },
- {
- "name": "DFHACK_INCLUDE_CORE",
- "value": "1"
- }
- ]
- },
- {
- "name": "MSVC 32 Release",
- "generator": "Ninja",
- "configurationType": "Release",
- "inheritEnvironments": [ "msvc_x86_x64", "msvc_2015_x86" ],
- "variables": [
- {
- "name": "DFHACK_BUILD_ARCH",
- "value": "32"
- },
- {
- "name": "BUILD_STONESENSE",
- "value": "1"
- }
- ]
- },
{
"name": "MSVC 64 Debug",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
- "inheritEnvironments": [ "msvc_x64_x64", "msvc_2015_x64" ],
+ "inheritEnvironments": [ "msvc_x64_x64" ],
"variables": [
{
"name": "DFHACK_BUILD_ARCH",
@@ -94,7 +28,7 @@
"name": "MSVC 64 Release",
"generator": "Ninja",
"configurationType": "Release",
- "inheritEnvironments": [ "msvc_x64_x64", "msvc_2015_x64" ],
+ "inheritEnvironments": [ "msvc_x64_x64" ],
"variables": [
{
"name": "DFHACK_BUILD_ARCH",
diff --git a/LICENSE.rst b/LICENSE.rst
index 68678dfb34..1ab6a682ee 100644
--- a/LICENSE.rst
+++ b/LICENSE.rst
@@ -4,16 +4,19 @@
Licenses
########
-DFHack is distributed under the Zlib license, with some MIT-
-and BSD-licensed components. These licenses protect your right
-to use DFHack for any purpose, distribute copies, and so on.
+DFHack is distributed under the Zlib license, with some MIT- and BSD-licensed
+components. These licenses protect your right to use DFHack for any purpose,
+distribute copies, and so on.
-The core, plugins, scripts, and other DFHack code all use the
-ZLib license unless noted otherwise. By contributing to DFHack,
-authors release the contributed work under this license.
+The core, plugins, scripts, and other DFHack code all use the ZLib license
+unless noted otherwise. By contributing to DFHack, authors release the
+contributed work under this license.
-DFHack also draws on several external packages.
-Their licenses are summarised here and reproduced below.
+Some graphic assets are derived from vanilla DF assets and used with permission
+from Bay12.
+
+DFHack also draws on several external packages. Their licenses are summarised
+here and reproduced below.
=============== ============= =================================================
Component License Copyright
@@ -31,11 +34,11 @@ luacov_ MIT \(c\) 2007 - 2018 Hisham Muhammad
luafilesystem_ MIT \(c\) 2003-2014, Kepler Project
lua-profiler_ MIT \(c\) 2002,2003,2004 Pepperfish
protobuf_ BSD 3-clause \(c\) 2008, Google Inc.
-tinythread_ Zlib \(c\) 2010, Marcus Geelnard
tinyxml_ Zlib \(c\) 2000-2006, Lee Thomason
UTF-8-decoder_ MIT \(c\) 2008-2010, Bjoern Hoehrmann
xlsxio_ MIT \(c\) 2016-2020, Brecht Sanders
alt-getopt_ MIT \(c\) 2009 Aleksey Cheusov
+googletest_ BSD 3-Clause \(c\) 2008, Google Inc.
=============== ============= =================================================
.. _DFHack: https://github.com/DFHack/dfhack
@@ -51,11 +54,11 @@ alt-getopt_ MIT \(c\) 2009 Aleksey Cheusov
.. _luafilesystem: https://github.com/keplerproject/luafilesystem
.. _lua-profiler: http://lua-users.org/wiki/PepperfishProfiler
.. _protobuf: https://github.com/google/protobuf
-.. _tinythread: http://tinythreadpp.bitsnbites.eu/
.. _tinyxml: http://www.sourceforge.net/projects/tinyxml
.. _UTF-8-decoder: http://bjoern.hoehrmann.de/utf-8/decoder/dfa
.. _xlsxio: https://github.com/brechtsanders/xlsxio
.. _alt-getopt: https://github.com/LuaDist/alt-getopt
+.. _googletest: https://github.com/google/googletest
.. _CC-BY-SA: http://creativecommons.org/licenses/by/3.0/deed.en_US
diff --git a/README.html b/README.html
index b8e15a0d11..4d1b0fd13c 100644
--- a/README.html
+++ b/README.html
@@ -13,4 +13,4 @@
Follow this link to the documentation.
-