mirror of
https://github.com/open-goal/jak-project
synced 2026-08-06 09:54:10 -04:00
5d5e35fb9b
## Problem Windows builds break with a current local toolchain (Scoop LLVM 22.1.8, CMake 4.4.0, VS 2026), in two independent ways: 1. The build stops at curl's deliberate guard: `#error "no non-blocking method was found/used/set"` in `third-party/curl/lib/nonblock.c`. 2. From the second configure onward, `cmake --build` re-runs CMake in an endless loop (observed 42 consecutive reconfigure cycles in a single build). Likely the same mechanism behind the "endlessly building" VS 2026 note in `docs/setup/dev/vs.md`. ## Root cause 1. `third-party/curl/CMake/CurlTests.c` passes `int *` to `ioctlsocket()`, whose third parameter is `u_long *`. Clang 22 promotes `-Wincompatible-pointer-types` to a hard error in C, so the `HAVE_IOCTLSOCKET_FIONBIO` try_compile silently fails and `curl_config.h` never defines it. Upstream CI does not see this because the windows-2022 runner image ships an older LLVM. GCC 14 promotes the same warning to a hard error, which is very likely the `CurlTests.c.obj` failure reported from MSYS2 in open-goal/jak-project#3551. Upstream curl hit the identical problem with GCC 14 and fixed the probe in curl 8.8.0 (curl/curl#13578). 2. The root CMakeLists copies the build tree's `compile_commands.json` into `<src>/build/` for clangd using `configure_file()`, which registers its input as a configure dependency. CMake rewrites `compile_commands.json` late in every generation, after `CTestTestfile.cmake` and `cmake_install.cmake` (outputs of the same Ninja regen rule), so once the dependency is registered the rule is deterministically dirty and every `ninja` invocation re-runs CMake. A pristine first configure is safe (the file does not exist yet, so the `if(EXISTS ...)` guard skips the copy), which is why the loop looks machine- or IDE-specific. ## Fix 1. Per review, re-vendor `third-party/curl` at the `curl-8_21_0` tag (previously `curl-8_3_0`), which carries the upstream probe fix plus two years of upstream development; `vendor.yaml` updated to match. Adjustments the version jump forced: - curl 8.15 removed the native macOS Secure Transport backend (`CURL_USE_SECTRANSP`), so macOS now builds curl against OpenSSL like Linux. The two macOS workflows install Homebrew `openssl@3` and export `OPENSSL_ROOT_DIR` (keg-only), and the macOS setup docs gained the same two lines. - `CURL_BROTLI` / `CURL_ZSTD` switched to AUTO-detection in curl 8.10; pinned OFF to keep the previous no-compression behavior and avoid silently linking whatever the CI images happen to have. - curl's new top-level `BUILD_EXAMPLES` cache option (default ON) leaked into discord-rpc's identically named option and broke configure at a nonexistent `examples/send-presence` directory; pinned OFF ahead of the third-party subdirectories. The diff is dominated by the mechanical tag-tree swap under `third-party/curl` (linguist-vendored, collapsed in review). The hand-written changes are `CMakeLists.txt`, the two macOS workflows, `docs/setup/system/macos.md`, and `vendor.yaml`. 2. Swap `configure_file()` for `file(COPY ...)`: the same clangd copy with no configure dependency registered. (`file(COPY_FILE ... ONLY_IF_DIFFERENT)` would be cleaner still but requires CMake 3.21, above the declared `cmake_minimum_required(VERSION 3.10)`.) ## Test plan - [x] Fresh `cmake --preset Release-windows-clang` (LLVM 22, no cache seeding) completes and logs `Enabled SSL backends: Schannel`; the FIONBIO probe passes without the previous `#error` - [x] Full Windows Release build from scratch in the branch worktree (all 1422 targets) - [x] goalc-test suite: 1509 passed, 0 failed - [x] Second consecutive configure with `compile_commands.json` present: the regen rule in `build.ninja` has no `compile_commands.json` input; `<src>/build/compile_commands.json` is still refreshed for clangd - [x] Repeated `ninja` invocations after a full build no longer re-run CMake - [x] macOS Intel and ARM CI green (first exercise of the OpenSSL backend switch) --- I work off a self-hosted forge, so this GitHub account is quiet; the configure logs and ninja dirty-node traces from the investigation are available if anyone wants the raw data. (AI-assisted)
210 lines
7.0 KiB
Perl
Vendored
Generated
210 lines
7.0 KiB
Perl
Vendored
Generated
#!/usr/bin/env perl
|
|
#***************************************************************************
|
|
# _ _ ____ _
|
|
# Project ___| | | | _ \| |
|
|
# / __| | | | |_) | |
|
|
# | (__| |_| | _ <| |___
|
|
# \___|\___/|_| \_\_____|
|
|
#
|
|
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
#
|
|
# This software is licensed as described in the file COPYING, which
|
|
# you should have received as part of this distribution. The terms
|
|
# are also available at https://curl.se/docs/copyright.html.
|
|
#
|
|
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
# copies of the Software, and permit persons to whom the Software is
|
|
# furnished to do so, under the terms of the COPYING file.
|
|
#
|
|
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
# KIND, either express or implied.
|
|
#
|
|
# SPDX-License-Identifier: curl
|
|
#
|
|
###########################################################################
|
|
|
|
# Display changes done in the repository from [tag] until now.
|
|
#
|
|
# Uses git for repo data.
|
|
# Uses docs/THANKS and RELEASE-NOTES for current status.
|
|
#
|
|
# In the git clone root, invoke 'scripts/delta [release tag]'
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use POSIX;
|
|
use IPC::Open3;
|
|
use Time::Piece;
|
|
|
|
sub cmd {
|
|
my @out;
|
|
my $as_string = shift if($_[0] eq '$'); # return as string (vs. list of lines)
|
|
my $hideerr = shift if($_[0] eq '2>'); # 2>/dev/null
|
|
my $pid = open3(my $in, my $out, $hideerr ? '>/dev/null' : '>&STDERR', @_);
|
|
close $in;
|
|
push @out, <$out>;
|
|
waitpid($pid, 0);
|
|
return $as_string ? join('', @out) : @out;
|
|
}
|
|
|
|
my $start = $ARGV[0] || '';
|
|
|
|
if($start eq "-h") {
|
|
print "Usage: summary [tag]\n";
|
|
exit;
|
|
}
|
|
elsif($start eq "") {
|
|
my @tags = cmd('git', 'tag', '--sort=taggerdate', '--no-column', '--list', 'curl-*');
|
|
$start = $tags[-1]; # latest tag
|
|
chomp $start;
|
|
}
|
|
|
|
my $commits = cmd('$', 'git', 'rev-list', '--count', "$start..");
|
|
my $committers = cmd('git', 'shortlog', '-s', "$start..");
|
|
my $bcommitters = cmd('git', 'shortlog', '-s', $start);
|
|
|
|
my $acommits = cmd('$', 'git', 'rev-list', '--count', 'HEAD');
|
|
my $acommitters = cmd('git', 'shortlog', '-s', 'HEAD');
|
|
|
|
# delta from now compared to before
|
|
my $ncommitters = $acommitters - $bcommitters;
|
|
|
|
# number of contributors right now
|
|
my $acontribs = cmd('./scripts/contrithanks.sh', 'stdout');
|
|
# number when the tag was set
|
|
my $bcontribs = cmd('$', 'git', 'grep', '-h', '-c', '^[^ ]', "$start:docs/THANKS");
|
|
# delta
|
|
my $contribs = $acontribs - $bcontribs;
|
|
|
|
# number of setops:
|
|
sub setopts {
|
|
my $mode = shift;
|
|
my $opts = 0;
|
|
if(open(H, $mode, @_)) {
|
|
while(<H>) {
|
|
if(/^ CURLOPT(|DEPRECATED)\(/ && ($_ !~ /OBSOLETE/)) {
|
|
$opts++;
|
|
}
|
|
}
|
|
close(H);
|
|
}
|
|
else {
|
|
die join(' ', @_) . ": $!\n";
|
|
}
|
|
return $opts;
|
|
}
|
|
my $asetopts = setopts('<', 'include/curl/curl.h');
|
|
my $bsetopts = setopts('-|', 'git', 'show', "$start:include/curl/curl.h");
|
|
my $nsetopts = $asetopts - $bsetopts;
|
|
|
|
# Number of command line options:
|
|
my $aoptions = cmd('$', '2>', 'git', 'grep', '-h', '-c', '{ *"....--', 'src/tool_listhelp.c');
|
|
my $boptions = cmd('$', '2>', 'git', 'grep', '-h', '-c', '{ *"....--', "$start:src/tool_listhelp.c");
|
|
my $noptions = $aoptions - $boptions;
|
|
|
|
# current local branch
|
|
my $branch = cmd('$', '2>', 'git', 'rev-parse', '--abbrev-ref', 'HEAD');
|
|
chomp $branch;
|
|
# Number of files in git
|
|
my $afiles = cmd('git', 'ls-files');
|
|
my $deletes = cmd('2>', 'git', 'diff-tree', '--diff-filter=A', '-r', '--summary', "origin/$branch", $start);
|
|
my $creates = cmd('2>', 'git', 'diff-tree', '--diff-filter=D', '-r', '--summary', "origin/$branch", $start);
|
|
|
|
# Time since that tag
|
|
sub tagstamp {
|
|
my $col = shift;
|
|
foreach my $line (@_) {
|
|
if(index($line, "$start ") == 0) {
|
|
my @cols = split(/\|/, $line);
|
|
return $cols[$col - 1];
|
|
}
|
|
}
|
|
}
|
|
my @tagged = cmd('git', 'for-each-ref', '--format=%(refname:short) | %(taggerdate:unix) | %(creatordate)', 'refs/tags/*');
|
|
my $tagged = tagstamp(2, @tagged); # Unix timestamp
|
|
my $taggednice = tagstamp(3, @tagged); # human readable time
|
|
chomp $taggednice;
|
|
my $now = POSIX::strftime("%s", localtime());
|
|
my $elapsed = $now - $tagged; # number of seconds since tag
|
|
my $total = $now - Time::Piece->strptime('19980320', '%Y%m%d')->epoch;
|
|
my $totalhttpget = $now - Time::Piece->strptime('19961111', '%Y%m%d')->epoch;
|
|
|
|
# Number of public functions in libcurl
|
|
my $apublic = cmd('git', 'grep', '^CURL_EXTERN', '--', 'include/curl');
|
|
my $bpublic = cmd('git', 'grep', '^CURL_EXTERN', $start, '--', 'include/curl');
|
|
my $public = $apublic - $bpublic;
|
|
|
|
# diffstat
|
|
my ($fileschanged, $insertions, $deletions);
|
|
my @diffstat = cmd('2>', 'git', 'diff', '--stat', "$start..");
|
|
my $diffstat = $diffstat[-1];
|
|
if($diffstat =~ /^ *(\d+) files changed, (\d+) insertions\(\+\), (\d+)/) {
|
|
($fileschanged, $insertions, $deletions) = ($1, $2, $3);
|
|
}
|
|
|
|
# Changes/bug-fixes currently logged
|
|
my $numchanges = 0;
|
|
my $numbugfixes = 0;
|
|
my $numcontributors = 0;
|
|
open(F, "<RELEASE-NOTES");
|
|
my $mode = 0;
|
|
while(<F>) {
|
|
if($_ =~ /following changes:/) {
|
|
$mode = 1;
|
|
}
|
|
elsif($_ =~ /following bugfixes:/) {
|
|
$mode = 2;
|
|
}
|
|
elsif($_ =~ /known bugs:/) {
|
|
$mode = 3;
|
|
}
|
|
elsif($_ =~ /like these:/) {
|
|
$mode = 4;
|
|
}
|
|
if($_ =~ /^ o /) {
|
|
if($mode == 1) {
|
|
$numchanges++;
|
|
}
|
|
elsif($mode == 2) {
|
|
$numbugfixes++;
|
|
}
|
|
}
|
|
if(($mode == 4) && ($_ =~ /^ \((\d+) contributors/)) {
|
|
$numcontributors = $1;
|
|
}
|
|
}
|
|
close(F);
|
|
|
|
########################################################################
|
|
# Produce the summary
|
|
|
|
print "== Since $start $taggednice ==\n";
|
|
my $days = $elapsed / 3600 / 24;
|
|
printf "Elapsed time: %.1f days (total %d / %d)\n",
|
|
$days, $total / 3600 / 24, $totalhttpget / 3600 / 24;
|
|
printf "Commits: %d (total %d)\n",
|
|
$commits, $acommits;
|
|
printf "Commit authors: %d, %d new (total %d)\n",
|
|
$committers, $ncommitters, $acommitters;
|
|
printf "Contributors: %d, %d new (total %d)\n",
|
|
$numcontributors, $contribs, $acontribs;
|
|
printf "New public functions: %d (total %d)\n",
|
|
$public, $apublic;
|
|
printf "New curl_easy_setopt() options: %d (total %d)\n",
|
|
$nsetopts, $asetopts;
|
|
printf "New command line options: %d (total %d)\n",
|
|
$noptions, $aoptions;
|
|
printf "Changes logged: %d\n", $numchanges;
|
|
printf "Bugfixes logged: %d (%.2f per day)\n",
|
|
$numbugfixes, $days ? $numbugfixes / $days : $numbugfixes;
|
|
printf "Added files: %d (total %d)\n",
|
|
$creates, $afiles;
|
|
printf "Deleted files: %d (delta: %d)\n", $deletes,
|
|
$creates - $deletes;
|
|
print "Diffstat:$diffstat" if(!$fileschanged);
|
|
printf "Files changed: %d (%.2f%%)\n", $fileschanged, $fileschanged * 100 / $afiles;
|
|
printf "Lines inserted: %d\n", $insertions;
|
|
printf "Lines deleted: %d (delta: %d)\n", $deletions,
|
|
$insertions - $deletions;
|