Skip to content

Conversation

@fxlb
Copy link
Member

@fxlb fxlb commented Nov 7, 2025

Avoid the SDK 10.0.26100.0. Use an older SDK: 10.0.22621.0.

The problem first appeared on 2025-11-07, after the 2025-11-06
image update (Visual Studio 2019/2022).

The errors were:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um\winnt.h
(6343,27): warning C4013: '_CountOneBits64' undefined; assuming extern
returning int

When it was OK:
cmake version 4.1.0
-- The C compiler identification is MSVC 19.29.30159.0

Current:
cmake version 4.1.0
-- Selecting Windows SDK version 10.0.26100.0 to target Windows 10.0.17763.
-- The C compiler identification is MSVC 19.29.30159.0

@fxlb
Copy link
Member Author

fxlb commented Nov 7, 2025

Test with the last Appveyor OK (like 730a8db).

@fxlb fxlb force-pushed the last_Appveyor_ok branch 2 times, most recently from 183c4e1 to 98dbc4a Compare November 7, 2025 23:11
@fxlb
Copy link
Member Author

fxlb commented Nov 7, 2025

Squashed. Seems ok. Waiting for a new Appveyor full run.

@fxlb
Copy link
Member Author

fxlb commented Nov 7, 2025

If it's run OK, Ii will be rebased on top of master before a merge.

@infrastation
Copy link
Member

I will wait until it has settled.

@fxlb
Copy link
Member Author

fxlb commented Nov 7, 2025

I will wait until it has settled.

OK. The reason of the break is still unknown. With the same head commit, it is now broken (before my hack) but worked before...

@infrastation
Copy link
Member

It looks worth asking Appveyor support about it.

@fxlb fxlb force-pushed the last_Appveyor_ok branch from 98dbc4a to bc08d43 Compare November 8, 2025 08:48
@fxlb fxlb changed the title [Appveyor check ONLY] Remove the earlier IPv4/IPv6-specific AND reduc… AppVeyor: Add workaround for build with Visual Studio 2019 on ARM64 Nov 8, 2025
@fxlb
Copy link
Member Author

fxlb commented Nov 8, 2025

Something has changed in the AppVeyor build system.

When it was OK:
cmake version 4.1.0
-- The C compiler identification is MSVC 19.29.30159.0

Current:
cmake version 4.1.0
-- Selecting Windows SDK version 10.0.26100.0 to target Windows 10.0.17763.
-- The C compiler identification is MSVC 19.29.30159.0

@fxlb fxlb force-pushed the last_Appveyor_ok branch from bc08d43 to 9b500ea Compare November 8, 2025 09:48
@fxlb fxlb marked this pull request as draft November 8, 2025 09:50
@guyharris
Copy link
Member

Is actions/runner-images#11684 related to this?

@fxlb fxlb force-pushed the last_Appveyor_ok branch from 9b500ea to 164f809 Compare November 8, 2025 12:12
@fxlb
Copy link
Member Author

fxlb commented Nov 8, 2025

Is actions/runner-images#11684 related to this?

It seems similar in another context.

@fxlb
Copy link
Member Author

fxlb commented Nov 8, 2025

Workaround v2, simpler, already used in other projects.

@fxlb fxlb force-pushed the last_Appveyor_ok branch from 164f809 to 44bf5ef Compare November 8, 2025 13:31
@fxlb
Copy link
Member Author

fxlb commented Nov 8, 2025

@fxlb
Copy link
Member Author

fxlb commented Nov 8, 2025

I wiil try:
image: Previous Visual Studio 2019.

@fxlb fxlb force-pushed the last_Appveyor_ok branch 2 times, most recently from 0326443 to 66205e0 Compare November 8, 2025 14:44
@fxlb
Copy link
Member Author

fxlb commented Nov 8, 2025

On test. The problem with image: Previous Visual Studio 2019 is that it could break at next update. No sure we keep it.

Avoid the SDK 10.0.26100.0. Use an older SDK: 10.0.22621.0.

The problem first appeared on 2025-11-07, after the 2025-11-06
image update (Visual Studio 2019/2022).

The errors were:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um\winnt.h
(6343,27): warning C4013: '_CountOneBits64' undefined; assuming extern
returning int

When it was OK:
cmake version 4.1.0
-- The C compiler identification is MSVC 19.29.30159.0

Current:
cmake version 4.1.0
-- Selecting Windows SDK version 10.0.26100.0 to target Windows 10.0.17763.
-- The C compiler identification is MSVC 19.29.30159.0

[skip ci]
@fxlb fxlb force-pushed the last_Appveyor_ok branch from 66205e0 to 5ee0310 Compare November 8, 2025 19:02
@fxlb
Copy link
Member Author

fxlb commented Nov 8, 2025

Don't work, Back to v2.

@infrastation
Copy link
Member

Thank you for debugging this.

@fxlb fxlb force-pushed the last_Appveyor_ok branch 2 times, most recently from 894a4c7 to 5ee0310 Compare November 8, 2025 22:09
@guyharris
Copy link
Member

Microsoft's documentation for Visual Studio 2019 and for Visual Studio 2022 seems to indicate that _CountOneBits64() is available for ARM64 if intrin.h is included.

However, somebody named Google McGemini (I'm guessing the AI summaries for Google searches are from Gemini) says, in response to [this Google search]("visual studio 2019" "arm64" "_CountOneBits64" "undefined"), that

The _CountOneBits64 intrinsic function may be undefined for the ARM64 architecture when using Visual Studio 2019, leading to linking errors. While it is listed as an intrinsic available for ARM64 in some documentation, it might not have had a concrete implementation or correct header definition in the VS2019 toolset.

The issue was reportedly fixed in Visual Studio 2022 Update 1. In Visual Studio 2019, the intrinsic was likely missing for the ARM64 target.

and has a workaround that provides an inline _CountOneBits64() function for Visual Studio prior to 2022.

McGemini links to Bit.h from the Nvidia Carbonite SDK, which does the same workaround, with what it labels as a "Naive impl".

I'm not sure whether the problem is that 1) Microsoft's documentation is wrong about VS 2019 or 2) some versions of VS 2019 have a bug in which they don't supply _CountOneBits64().

@guyharris
Copy link
Member

The Nvidia code links to https://developercommunity.visualstudio.com/t/-countonebits-intrinsics-are-not-defined-for-arm64/957551, in which somebody from Microsoft says

The _CountOneBits ‘intrinsic’ is a bit different from the other _Count* intrinsics as it does not map to a single instruction on ARM or ARM64, which is why it didn’t get ported to ARM64. That said, we will likely be adding an ARM64 implementation for this as c++20 includes std::popcount which does exactly that.

This somewhat misunderstands the full purpose of these sort of things - "as it does not map to a single instruction on XXX" is not a reason not to implement it; these intrinsics are intended to implement operations on all platforms, so they can be used in portable code (at least if the target platform has a compiler that supports the intrinsic in question), and uses whatever instruction sequence does them best on that platform, whether it's a single-instruction implementation or not. At least they seem to acknowledge that not implementing it wasn't the right thing to do.

That still doesn't explain why this only showed up recently, if it was working before with VS 2019.

@guyharris
Copy link
Member

@fxlb
Copy link
Member Author

fxlb commented Nov 9, 2025

That still doesn't explain why this only showed up recently, if it was working before with VS 2019.

It seems that the SDK upgrade from 10.0.22621.X to 10.0.26100.0 add a problem.

@fxlb
Copy link
Member Author

fxlb commented Nov 9, 2025

I currently see 3 options

  1. Use the current patch to build with the SDK 10.0.22621.0.
    Knowing that:
    SDK 22621 End of support 2025-11-12
    (https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/)

  2. Use the first workaround I test

diff --git a/.appveyor.yml b/.appveyor.yml
index ed2861f9..24d55ce9 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -95,12 +95,14 @@ environment:
       PLATFORM: ARM64
       SDK: npcap-sdk
       REMOTE: -DENABLE_REMOTE=NO
+      POPULATIONCOUNT64: -DPOPULATIONCOUNT64=1
       # VS 2019, Npcap, 64-bit ARM, with remote
     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
       GENERATOR: "Visual Studio 16 2019"
       PLATFORM: ARM64
       SDK: npcap-sdk
       OPENSSL_ROOT_DIR: -DOPENSSL_ROOT_DIR=C:\OpenSSL-v33-Win64\bin
+      POPULATIONCOUNT64: -DPOPULATIONCOUNT64=1
       # VS 2022, WinPcap, 32-bit and 64-bit x86, without remote
     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
       GENERATOR: "Visual Studio 17 2022"
@@ -167,5 +169,5 @@ build_script:
   - md build
   - cd build
   - cmake --version
-  - cmake %REMOTE% %OPENSSL_ROOT_DIR% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -G"%GENERATOR%" -A %PLATFORM% ..
+  - cmake %POPULATIONCOUNT64% %REMOTE% %OPENSSL_ROOT_DIR% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -G"%GENERATOR%" -A %PLATFORM% ..
   - msbuild /m /nologo /p:Configuration=Release pcap.sln
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 55199378..45112f69 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -656,6 +656,9 @@ endif(WIN32)
 if(MSVC)
     add_definitions(-D__STDC__)
     add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+    if(DEFINED POPULATIONCOUNT64)
+        add_compile_definitions(PopulationCount64=${POPULATIONCOUNT64})
+    endif()
 endif(MSVC)
 
 if(USE_STATIC_RT)

Knowing that:
I don't know why this woraround, used on some projects, works, i.e. exact link between PopulationCount64 and _CountOneBits64.
It need a little update on cmake defines.

  1. Stop building for ARM64 with MSVC 19.

@guyharris
Copy link
Member

guyharris commented Nov 9, 2025

For what it's worth, for

#include <intrin.h>

unsigned long long bitcnt(unsigned long long w)
{
    return _CountOneBits64(w);
}

Mike Godbolt's Compiler Explorer shows, for ARM64 Visual Studio 16.11 - according to the Wikipedia article on Visual Studio, that's a version of VS 2019 - with /O2:

       IMPORT  |_CountOneBits64|

        ;Flags[SingleProEpi] functionLength[20] RegF[0] RegI[0] H[0] frameChainReturn[UnChainedSavedLR] frameSize[16]

|bitcnt| PROC
|$LN4|
        str         lr,[sp,#-0x10]!
        bl          _CountOneBits64
        sxtw        x0,w0
        ldr         lr,[sp],#0x10
        ret

        ENDP  ; |bitcnt|

and, for Visual Studio 17.14 - according to the Wikipedia article on Visual Studio, that's a version of VS 2022:

        ;ARM64

|bitcnt| PROC
        fmov        d16,x0
        cnt         v16.8b,v16.8b
        addv        b16,v16.8b
        fmov        w0,s16
        ret

        ENDP  ; |bitcnt|

It looks, from the Armv8.9 documentation, the cnt instruction was first mentioned in Armv8.9, as optional in Arm8.7 and required in Armv8.9. This page on the Arm CSSC (Common Short Sequence Compression) says that, prior to that, there was a version of cnt that acted on what I'm guessing from the "v" were vector registers, and the CSSC extension adds versions that act on general registers.

The generated code is using the vector (SIMD) cnt.

@fxlb
Copy link
Member Author

fxlb commented Nov 16, 2025

Any thoughts on the three options suggested, or another suggestion?

@infrastation
Copy link
Member

No opinion from me: the last time I compiled anything on Windows was about 25 years ago.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants