## 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)
4.7 KiB
Vendored
Generated
c, SPDX-License-Identifier, Title, Section, Source, See-also, Protocol, Added-in
| c | SPDX-License-Identifier | Title | Section | Source | See-also | Protocol | Added-in | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. | curl | CURLOPT_URL | 3 | libcurl |
|
|
7.1 |
NAME
CURLOPT_URL - URL for this transfer
SYNOPSIS
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);
DESCRIPTION
Pass in a pointer to the URL to work with. The parameter should be a char * to a null-terminated string which must be URL-encoded in the following format:
scheme://host:port/path
For a greater explanation of the format please see RFC 3986.
libcurl does not validate the syntax or use the URL until the transfer is started. Even if you set a crazy value here, curl_easy_setopt(3) might still return CURLE_OK.
If the given URL is missing a scheme name (such as http:// or ftp:// etc)
then libcurl guesses based on the host. If the outermost subdomain name
matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that protocol gets used,
otherwise HTTP is used. Scheme guessing can be disabled by setting a default
protocol, see CURLOPT_DEFAULT_PROTOCOL(3) for details.
Should the protocol, either as specified by the URL scheme or deduced by libcurl from the hostname, not be supported by libcurl then CURLE_UNSUPPORTED_PROTOCOL is returned from either the curl_easy_perform(3) or curl_multi_perform(3) functions when you call them. Use curl_version_info(3) for detailed information of which protocols are supported by the build of libcurl you are using.
CURLOPT_PROTOCOLS_STR(3) can be used to limit what protocols libcurl may use for this transfer, independent of what libcurl has been compiled to support. That may be useful if you accept the URL from an external source and want to limit the accessibility.
The CURLOPT_URL(3) string is ignored if CURLOPT_CURLU(3) is set.
Either CURLOPT_URL(3) or CURLOPT_CURLU(3) must be set before a transfer is started.
The application does not have to keep the string around after setting this option.
Using this option multiple times makes the last set string override the previous ones. Set it to NULL to disable its use again. Note however that libcurl needs a URL set to be able to performed a transfer.
The parser used for handling the URL set with CURLOPT_URL(3) is the same that curl_url_set(3) uses.
ENCODING
The string pointed to in the CURLOPT_URL(3) argument is generally expected to be a sequence of characters using an ASCII compatible encoding.
If libcurl is built with IDN support, the server name part of the URL can use an "international name" by using the current encoding (according to locale) or UTF-8 (when WinIDN is used; or a Windows Unicode build using libidn2).
If libcurl is built without IDN support, the server name is used exactly as specified when passed to the name resolver functions.
DEFAULT
NULL. If this option is not set, no transfer can be performed.
SECURITY CONCERNS
Applications may at times find it convenient to allow users to specify URLs for various purposes and that string would then end up fed to this option.
Getting a URL from an external untrusted party brings several security concerns:
If you have an application that runs as or in a server application, getting an unfiltered URL can easily trick your application to access a local resource instead of a remote. Protecting yourself against localhost accesses is hard when accepting user provided URLs.
Such custom URLs can also access other ports than you planned as port numbers are part of the regular URL format. The combination of a local host and a custom port number can allow external users to play tricks with your local services.
Accepting external URLs may also use other protocols than http:// or other
common ones. Restrict what accept with CURLOPT_PROTOCOLS_STR(3).
User provided URLs can also be made to point to sites that redirect further on (possibly to other protocols too). Consider your CURLOPT_FOLLOWLOCATION(3) and CURLOPT_REDIR_PROTOCOLS_STR(3) settings.
%PROTOCOLS%
EXAMPLE
int main(void)
{
CURL *curl = curl_easy_init();
if(curl) {
CURLcode result;
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
result = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
}
%AVAILABILITY%
RETURN VALUE
curl_easy_setopt(3) returns a CURLcode indicating success or error.
CURLE_OK (0) means everything was OK, non-zero means an error occurred, see libcurl-errors(3).
Note that curl_easy_setopt(3) does not parse the given string so given a bad URL, it is not detected until curl_easy_perform(3) or similar is called.