Warning C4013: 'ms_snprintf' undefined;

There are three warnings for this

C:\dev-MSVC-PR\swipl-devel\src\pl-write.c(216,7): warning C4013: ‘ms_snprintf’
C:\dev-MSVC-PR\swipl-devel\src\pl-thread.c(1969,3): warning C4013: ‘ms_snprintf’
C:\dev-MSVC-PR\swipl-devel\src\os\pl-text.c(1103,5): warning C4013: ‘ms_snprintf’

As near as I can tell ms_snprintf is not a real function name.

I’ll just let you fix it and I will test it.

Thanks.

The problem is/was that M$ snprintf() and friends were not C99 compliant as the referenced article says. They seem to have fixed that now, _snprintf() still behaving the old M$ way and snprintf() the C99 way. Problem is that we cannot really be sure against which runtime library we will be executing, so I fear that for the time being our ms_snprintf(), which should have been called c99_snprintf() is the only reliable way around :frowning:

Pushed fixes that renames this function and make sure it is defined everywhere.

1 Like

Thanks.

If you’d rather, feel free to ignore my PRs related to the warnings (or even delete them). The same list of warnings is already in the document I sent by email. :slightly_smiling_face:

I think all your PRs and messages have been dealt with. The main thing useful is to complete the MSVC section in cmake/BuildType.cmake such that just using -DCMAKE_BUILD_TYPE=... does the job rather than having to add additional options for C/CXXFLAGS, etc. The toolchain should probably not be part of this as people might want to use something different and it might be installed elsewhere. Could you do that?

Cmake and me are not friends either, as are most build systems.

I’ll see what I can do.

Is your request to modify this

cmake .. -G "Visual Studio 18 2026" -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake -DPython_EXECUTABLE="C:/Users/Eric/AppData/Local/Programs/Python/Python313/python.exe" -DBDB_LIBRARY=C:/dev/vcpkg/installed/x64-windows/lib/libdb48.lib

so that

-G "Visual Studio 18 2026" -A x64

is not needed?

In reading

starting with section Using Microsoft Visual C++ (MSVC) my guess is that you would like those instructions to work.

I don’t think you need these anyway. If you use the right cmd.exe or PowerShell for running the 64 bit version of MSVC and the vcpkg.cmake toolchain these are probably default. We definitely do not want -A x64 and this will probably also build on arm64.

I think the release build is actually fine. It would be nice if the other build types work as

cmake -DCMAKE_BUILD_TYPE=Debug ...
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ...
cmake -DCMAKE_BUILD_TYPE=Sanitize ...

These all set CMAKE_C_FLAGS_<type> and CXXMAKE_C_FLAGS_<type> to get the desired build. Most of it should be a fairly trivial copy/paste from one of the other compilers and update the actual flags. The other compilers use mostly the same flags. MSVC will be quite different here.

1 Like

Example created by ChatGPT (not Claude this time), just trying to figure out if I am headed in the right direction. The example below has not been tested and is in a reveal section so that Google and such will not index it for search results.

cmake/BuildType.cmake (click triangle to expand)
elseif(MSVC)
  # Common MSVC flags
  set(_SWI_MSVC_C_COMMON   "/nologo")
  set(_SWI_MSVC_CXX_COMMON "/nologo /EHsc")   # /EHsc for consistent C++ exception semantics

  # Debug flags: no optimization + full symbols + SWI debug macros
  set(CMAKE_C_FLAGS_DEBUG
      "${_SWI_MSVC_C_COMMON} /D_DEBUG /DO_DEBUG /DO_DEBUG_ATOMGC /Od /Zi"
      CACHE STRING "CFLAGS for a Debug build" FORCE)
  set(CMAKE_CXX_FLAGS_DEBUG
      "${_SWI_MSVC_CXX_COMMON} /D_DEBUG /DO_DEBUG /DO_DEBUG_ATOMGC /Od /Zi $ENV{CXXFLAGS}"
      CACHE STRING "CXXFLAGS for a Debug build" FORCE)

  # RelWithDebInfo: optimization + symbols
  set(CMAKE_C_FLAGS_RELWITHDEBINFO
      "${_SWI_MSVC_C_COMMON} /O2 /Zi"
      CACHE STRING "CFLAGS for a RelWithDebInfo build" FORCE)
  set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
      "${_SWI_MSVC_CXX_COMMON} /O2 /Zi $ENV{CXXFLAGS}"
      CACHE STRING "CXXFLAGS for a RelWithDebInfo build" FORCE)

  # Release: optimization, no debug macros
  set(CMAKE_C_FLAGS_RELEASE
      "${_SWI_MSVC_C_COMMON} /O2"
      CACHE STRING "CFLAGS for a Release build" FORCE)
  set(CMAKE_CXX_FLAGS_RELEASE
      "${_SWI_MSVC_CXX_COMMON} /O2 $ENV{CXXFLAGS}"
      CACHE STRING "CXXFLAGS for a Release build" FORCE)

  # MinSizeRel: size-oriented optimization
  set(CMAKE_C_FLAGS_MINSIZEREL
      "${_SWI_MSVC_C_COMMON} /O1"
      CACHE STRING "CFLAGS for a MinSizeRel build" FORCE)
  set(CMAKE_CXX_FLAGS_MINSIZEREL
      "${_SWI_MSVC_CXX_COMMON} /O1 $ENV{CXXFLAGS}"
      CACHE STRING "CXXFLAGS for a MinSizeRel build" FORCE)

  # Optional: Sanitize build type (if you intend to support it on MSVC)
  # MSVC uses /fsanitize=address (requires installed VS components).
  set(CMAKE_C_FLAGS_SANITIZE
      "${_SWI_MSVC_C_COMMON} /D_DEBUG /DO_DEBUG /Od /Zi /fsanitize=address"
      CACHE STRING "CFLAGS for a Sanitize build" FORCE)
  set(CMAKE_CXX_FLAGS_SANITIZE
      "${_SWI_MSVC_CXX_COMMON} /D_DEBUG /DO_DEBUG /Od /Zi /fsanitize=address $ENV{CXXFLAGS}"
      CACHE STRING "CXXFLAGS for a Sanitize build" FORCE)

  # Optional: linker flags for sanitize (sometimes needed to avoid incremental link issues)
  set(CMAKE_EXE_LINKER_FLAGS_SANITIZE
      "/INCREMENTAL:NO"
      CACHE STRING "LDFLAGS for a Sanitize build" FORCE)
  set(CMAKE_SHARED_LINKER_FLAGS_SANITIZE
      "/INCREMENTAL:NO"
      CACHE STRING "LDFLAGS for a Sanitize build" FORCE)

Makes a lot of sense. I’m not familiar with most of the MSVC flags, so you might be better to judge from your experience. Also figuring out the right optimization level might be useful. For example, up till GCC 14, -O2 was typically best on GCC. As of GCC 14 -O3 produces significantly faster code, so the default is switched.

Ideally you’d support PGO (Profile Guided Optimization) if MSVC can. Also there it is unclear. It doesn’t help noticeable for Clang, but does help significantly on GCC.

1 Like

This is the shared link to the ChatGPT conversation helping me.

https://chatgpt.com/share/6989f685-6c94-8013-8dfe-cfe4187337e3

If you want me to ask a question just let me know.

Note: Not sure if ChatGPT shared links update when more content is added so will need feedback to know.


The shared link should have section at the end starting with

PGO (Profile-Guided Optimization) is a two-phase build:

build an instrumented binary

run representative workloads to collect profile data

rebuild using that profile to guide inlining, code layout, branch prediction, indirect call promotion, etc.

What Jan is flagging is that your CMake “PGO” build type currently only exists for GCC, and even there it’s only “flags”, not the workflow. Extending PGO support to MSVC is possible, but the mechanics differ a lot by compiler.

If you do use the link and can not see that let me know. I can paste it all here but it is long.

While working on updates in cmake/BuildType.cmake—specifically the elseif(MSVC) section—I had to step back and re-examine the CMake configuration phase of the build. In testing different CMake configurations for MSVC on Windows, it became clear that many apparent successes or failures were determined before CMake ever ran.

On Windows using MSVC, starting the build from the “x64 Native Tools Command Prompt” should be treated as the first step of any supported build process.

As noted in several of my earlier steps and reports
(see: Windows native build with ASan - Claude AI notes: ASan found a heap-use-after-free bug - #60 by EricGT), I consistently use the x64 Native Tools Command Prompt for Visual Studio as the entry point. This ensures that the required compiler, linker, SDK, and toolchain environment variables are initialized before invoking CMake.

Would you be okay with “x64 Native Tools Command Prompt” as a required first step when building SWI-Prolog on Windows with MSVC?

Note: The x64 Native Tools Command Prompt is installed automatically as a Windows shortcut when installing the Microsoft C++ Build Tools.

From the Microsoft documentation:

To work correctly, the tools require several specific environment variables to be set. These variables are used to add the tools to the path, and to set the locations of include files, library files, and SDKs. To make it easy to set these environment variables, the installer creates customized command files , or batch files, during installation. You can run one of these command files to set a specific host and target build architecture, Windows SDK version, and platform toolset. For convenience, the installer also creates shortcuts in your Start menu. The shortcuts open developer command prompt windows by using these command files for specific combinations of host and target. These shortcuts ensure all the required environment variables are set and ready to use.

If there are questions or concerns about this requirement, I’m happy to clarify or provide additional detail.

I inserted the suggestions by ChatGPT, which seems a good start. I also updated boot/build_home.pl to facilitate multi-config generators in general. That now also works on Linux using -G "Ninja Multi-Config". Hope I didn’t break anything for Windows. Note that PGO building requires more. I tried to include that into the Ninja multi config, but that does not work. Might be possible to fix, might also not be so easy. Not interesting enough …

If you means me, I don’t know. I used that, but there might be alternatives. I don’t feel at home facing a Windows desktop :slight_smile:

1 Like

I’ll test.

OK, found the cmake/BuildType.cmake changes, hiding as More boolean types..


The ChatGPT share/link I provided most likely did not give the remainder of the ChatGPT conversation, spent a few hours and checking things and learned lots.

I have not done PGO with MSVC but will be following up on that hopefully in the next few days.


I am more than happy to try the alternatives, just let me know, need details like the command line or combinations you would like tried.


Same for me using macOS, not so bad using Ubuntu.



Here is a little table that ChatGPT created which helped me, maybe it will help others.

Category Windows (MSVC) Windows (MSYS2) Linux macOS
Compiler MSVC (cl.exe) GCC / Clang (mingw-w64) GCC / Clang Apple Clang
Install method Visual Studio Installer pacman distro package manager (apt, dnf, pacman, etc.) Xcode / Command Line Tools
Package manager vcpkg (common) pacman system pkg mgr Homebrew / MacPorts
CMake install VS Installer / cmake.org pacman -S cmake distro pkg mgr Homebrew / Xcode
On PATH? No (unless env set) Yes (inside MSYS shell) Yes Yes
Environment setup x64 Native Tools / VsDevCmd.bat MSYS2 shell (mingw64.exe, etc.) None None
Default CMake generator Visual Studio Ninja / Unix Makefiles Unix Makefiles / Ninja Unix Makefiles / Ninja
Generator model Multi-config Single-config Single-config Single-config
C runtime MSVCRT / UCRT mingw-w64 CRT glibc / musl libc
C++ runtime MSVC STL libstdc++ / libc++ libstdc++ / libc++ libc++
Linker link.exe ld / lld ld / lld ld64
Shared libraries .dll .dll .so .dylib
Static libraries .lib .a .a .a
Output format PE/COFF PE/COFF ELF Mach-O
Debug symbols .pdb DWARF DWARF DWARF
Headers / libs location VS + Windows SDK dirs /mingw64/include, /mingw64/lib /usr/include, /usr/lib* SDK + /usr/include
RPATH needed? No No Often Often
ABI stability High (MSVC-locked) Depends on toolchain Stable per distro Stable per OS
Typical build dir build.vs/ build/ build/ build/
Configure command cmake -G “Visual Studio …” -A x64 cmake -G Ninja cmake cmake
Build command cmake --build . --config Release cmake --build . cmake --build . cmake --build .
Test command ctest -C Release ctest ctest ctest

In my own testing I instinctively start from the x64 Native Tools Command Prompt for VS, but that isn’t a realistic “first-time user” scenario—many people won’t know to do that as an initial step.

What would you expect others to do by default, and what would you try yourself? If you can suggest one or more concrete variations of the three CMake/CTest commands (configure, build, test), I can run them and report back.

I also expect some users will want the generated .sln / .vcxproj files, so I’ll note how to obtain those as part of the results. In addition, I’ll try the variations implied by the updated cmake/BuildType.cmake. This will likely take most, if not all, of the day.

I have no clue. Any Windows users?

Cross-compile from Linux :slight_smile: Preferably on a real Linux machine, but using WSL probably does the job as well. Builds several times faster and the result performs about twice as good :slight_smile: Well, unless the latest MSVC made some big steps. From the data points I have, GCC made a lot more progress over the last 15 years than MSVC did. My Windows development setup:

  • Linux host (Fedora 43)
  • Docker image for building SWI-Prolog in the same source directory I also use for developing the Linux version. That allows me to test Windows and Linux builds in various configurations from the same source, so I do not need to synchronize sources.
  • Partial testing by running it under Wine (ctest works fine). Most issues reproduce under Wine. Some not and debugging is lousy, so plan B …
  • VirtualBox VM running Windows 11 with access to the source directory as shared folder can be used to run the system under Windows without installing. MSYS-2 gdb can be used for debugging (the debugging experience is not great, so that is a last resort for Windows specific bugs).

Still the work on such a port is useful. It may help people who, for some reason, need to stick with Microsoft native tool chains (I met them), it found some bugs and it generalized some code and build tooling. So, thanks!

1 Like

OK.

I’ll proceed with the builds using my current workflow, along with a few variations I picked up yesterday, and document the commands used with additional notes for anyone who wants to reproduce the results.

While starting the first build, I ran into a linker warning. I’m having Claude work on a PR for that issue as I write this.