For example GetVolumePathName returns `F:/git_projects` on my computer which
does not fit in a char[4]. As a result GetVolumePathName returns an error and
a std::string is initialized from uninitialized memory which may not contain
a '\0' resulting in out of bounds memory reads.
Joel Rosdahl [Tue, 9 Sep 2025 16:34:34 +0000 (18:34 +0200)]
fix: Avoid expanding symlinks in relative path candidates
Commit 8223ed38abd9cf75ab75cb19dc2081c44bf568d0 changed
make_relative_path to also try matching real_path(path) against the
apparent/actual CWD, assuming that an absolute path p could be
substituted with real_path(p).
This assumption is incorrect for source files: if the source file
includes a file via a relative path, expanding symlinks may cause the
include file to be searched in the wrong directory.
Fix by reverting that change. The new test case "Symlink to source file,
longer symlink path" fails without this fix.
Joel Rosdahl [Sun, 7 Sep 2025 17:10:47 +0000 (19:10 +0200)]
fix: Hash specs file actually used by GCC
"gcc -specs=foo" (when "foo" doesn't include a slash) makes GCC search
in various system directories for the file, so ccache fails to hash the
file if it's found in such a directory.
Fix this by asking the compiler (using "-print-file-name") which file it
will actually read.
fix: Fix bad conversion from UTF-16 in util::read_file on Windows (#1627)
When interpreting a char* string that is null terminated as wchar* string
it is not guaranteed that the wchar* string is also null terminated. A char[3]
string/memeory region with the content ['a', '\0', '\0', 100] interpreted as
wchar* has no ending null character resulting in out of bounds memory reads
when trying to construct a std::wstring from it.
Joel Rosdahl [Sun, 10 Aug 2025 08:56:19 +0000 (10:56 +0200)]
ci: Improve binary build jobs
For x86_64, build in an Alma Linux 8 container since RHEL 8 is the
oldest still active LTS mainstream Linux distribution to my knowledge.
For aarch64, cross compile in an x86_64 environment instead of in a
native aarch64 environment. This is because I want to be able to build
release binaries locally on my x86_64 machine if there is some problem
with the CI environment and it feels good to match that in CI. The build
is still on Ubuntu 22.04 – I made a quick attempt to get
cross-compilation working in Alma Linux 8 working but gave up.
Martin Storsjö [Tue, 12 Aug 2025 18:10:40 +0000 (21:10 +0300)]
ci: Enable tests in the msys2 mingw64+clang configuration (#1618)
Instead of disabling tests altogether, pass the -Wno-deprecated
option, working around https://github.com/doctest/doctest/issues/900
in a different fashion.
Martin Storsjö [Tue, 10 Jun 2025 10:53:41 +0000 (13:53 +0300)]
ci: Add jobs for building binaries for Windows and Linux
Build binaries for x86_64 and aarch64 on Linux, and i686, x86_64
and aarch64 for Windows.
The Windows binaries are cross compiled from Linux. For x86, it
uses distro provided compilers, while it uses llvm-mingw installed
separately for targeting aarch64. (Most distros don't have packages
for mingw cross compilers for targeting Windows on aarch64 yet. GCC
isn't mature for this target yet, but Clang has supported this
target for many years now. Llvm-mingw is essentially the same toolchain
setup as MSYS2 uses in their clangarm64 environment, but available
as a standalone cross compiler too.)
Martin Storsjö [Wed, 30 Jul 2025 09:05:22 +0000 (12:05 +0300)]
ci: Add a toolchain file for (cross) compilation for aarch64-w64-mingw32
Contrary to the existing toolchain files, this doesn't hardcode
CMAKE_FIND_ROOT_PATH to a location in /usr, but locates the
compiler from the path, and picks a sysroot adjacent to it - allowing
using a compiler installed in any path.
This uses a compiler named "${TOOLCHAIN_PREFIX}-gcc" - toolchains
such as llvm-mingw do provide cross tools named "-gcc" for
compatibility, even if they use Clang.
Martin Storsjö [Tue, 10 Jun 2025 10:31:42 +0000 (13:31 +0300)]
ci: Extend the msys2 testing to the "clangarm64" environment
The clangarm64 msys environment doesn't have a "gcc" command
by default, unless the "gcc-compat" package is installed.
One may consider using "cc" as well, which is available when
the "toolchain" package is installed in each environment, but
that tool in clang environments fails the "direct" test case.
Martin Storsjö [Tue, 10 Jun 2025 10:28:53 +0000 (13:28 +0300)]
ci: Use pacboy to simplify installation of msys2 packages
See [1] and [2] for reference on using pacboy to simplify installing
mingw packages in msys2. The relevant bit to know is that by
specifying plain package names with a ":p" suffix, in the "pacboy"
section in msys2/setup-msys2, those packages are installed within
the current msys2 environment.
This avoids needing to specify the long package prefix like
"mingw-w64-x86_64". For other environments like "ucrt64", "clang64"
and "clangarm64", the prefix is even longer and less obvious.
Martin Storsjö [Tue, 10 Jun 2025 10:55:00 +0000 (13:55 +0300)]
ci: Stop manually installing Ninja on Linux and macOS
Since https://github.com/actions/runner-images/pull/11706,
https://github.com/actions/runner-images/pull/11707 and
https://github.com/actions/runner-images/pull/11737, ninja is
preinstalled in the Ubuntu, macOS and x86 Windows runner images.
Joel Rosdahl [Sun, 3 Aug 2025 16:04:29 +0000 (18:04 +0200)]
ci: Declare downloaded zstd as EXCLUDE_FROM_ALL
8648532e3cdcd6a0c4fb12b65e1ca9a8972a1e06 removed usage of
FetchContent_Populate to avoid warnings from newer CMake versions, but
the EXCLUDE_FROM_ALL part got lost in translation.
Corresponding semantics is available by passing EXCLUDE_FROM_ALL to
FetchContent_Declare, but only since CMake 3.28 so we need to add some
backward compatibility goo.
Joel Rosdahl [Sun, 20 Jul 2025 13:41:44 +0000 (15:41 +0200)]
fix: Keep original order of compiler arguments
Now when CCACHE_NOCPP2 (run_second_cpp = false) has been removed (see fd9de83446aeaf1eb1b33a2d900ea1ff757c4509) we can simplify compiler
argument juggling: instead of partitioning arguments into different
lists and reassemble them later, we can build up the preprocessor and
compiler command lines while we go, thus keeping the original order of
arguments.
Joel Rosdahl [Sat, 19 Jul 2025 18:43:32 +0000 (20:43 +0200)]
chore: Remove ability to avoid 2nd call to preprocessor (run_second_cpp)
ccache before version 1.6 (2002) always sent precompiled source to the
compiler as an optimization to avoid running the preprocessor a second
time. ccache 1.6 (2002) introduced CCACHE_CPP2 to optionally disable
this optimization. This seemed to work well until mid 2010s when
compilers started to behave differently when compiling preprocessed and
non-preprocessed source code. Thus, ccache 3.3 (2016) flipped the
default to make the optimization opt-in via CCACHE_NOCPP2 (or
"run_second_cpp = false").
Fast forward to 2025:
- As far as I can tell, CCACHE_NOCPP2 is used by essentially nobody
which isn't surprising since it generally doesn't work well.
- The feature comes with increased code complexity. The most painful
part is that compiler arguments need to be carefully filtered and sent
to only the preprocessor, only the compiler or both, depending on
whether run_second_cpp is true or false. And it can be forced to true
in the middle of argument parsing when an argument that is
incompatible with "run_second_cpp = false" is found.
- There have been a non-trivial amount of bugs related to CCACHE_NOCPP2
during the years due to the added complexity and due to new compiler
behavior that is incompatible with the mode.a
- The depend mode is a more performant alternative to "run_second_cpp =
false" since ccache 3.6 (2019), though with different tradeoffs.
Thus it's time to make the code less complex and more maintainable:
remove the optimization to send the precompiled source code to the
compiler.
This opens up making argument juggling simpler and fixing bug #738.