Skip to content

Commit cc588fd

Browse files
bluecmdclaude
andauthored
ci: add Windows build (MSYS2/mingw-w64) (#20)
* ci: add Windows build via MSYS2/mingw-w64 Build the netsnmp C extension on Windows using the MSYS2 mingw-w64 toolchain, which provides net-snmp (with net-snmp-config), gcc and a matching Python so setup.py works unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014KG1c9XtKawkvig5PnZjC8 * ci: build net-snmp from source under MSYS2 net-snmp is not packaged for Windows in MSYS2, vcpkg or conda-forge, so build the client library from source into the mingw64 prefix. This puts net-snmp-config on PATH so setup.py works unchanged. Result is cached. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014KG1c9XtKawkvig5PnZjC8 * windows: make setup.py and client_intf.c build under mingw - setup.py: invoke net-snmp-config via sh on Windows (cmd.exe cannot exec the shell script) and link ws2_32 for the winsock symbols. - client_intf.c: use winsock2.h/ws2tcpip.h instead of arpa/inet.h and netdb.h on _WIN32. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014KG1c9XtKawkvig5PnZjC8 * ci: fix net-snmp cache path to runner.temp msys64 location setup-msys2 installs to $RUNNER_TEMP\msys64, not C:\msys64, so the cache never matched and net-snmp was rebuilt every run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014KG1c9XtKawkvig5PnZjC8 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f1b2665 commit cc588fd

3 files changed

Lines changed: 104 additions & 2 deletions

File tree

‎.github/workflows/windows.yml‎

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Windows build
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
env:
10+
NETSNMP_VERSION: "5.9.4"
11+
12+
jobs:
13+
build:
14+
name: Build (MSYS2 / mingw-w64)
15+
runs-on: windows-latest
16+
defaults:
17+
run:
18+
shell: msys2 {0}
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Set up MSYS2
23+
uses: msys2/setup-msys2@v2
24+
with:
25+
msystem: MINGW64
26+
update: true
27+
install: >-
28+
base-devel
29+
mingw-w64-x86_64-gcc
30+
mingw-w64-x86_64-openssl
31+
mingw-w64-x86_64-python
32+
mingw-w64-x86_64-python-setuptools
33+
perl
34+
make
35+
tar
36+
wget
37+
38+
# net-snmp is not packaged in MSYS2/vcpkg/conda-forge for Windows, so
39+
# build the client library from source into the mingw64 prefix. This
40+
# gives us net-snmp-config on PATH, which setup.py relies on.
41+
- name: Cache net-snmp install
42+
id: cache-netsnmp
43+
uses: actions/cache@v4
44+
with:
45+
path: |
46+
${{ runner.temp }}\msys64\mingw64\bin\net-snmp-config
47+
${{ runner.temp }}\msys64\mingw64\bin\libnetsnmp-*.dll
48+
${{ runner.temp }}\msys64\mingw64\lib\libnetsnmp*
49+
${{ runner.temp }}\msys64\mingw64\include\net-snmp
50+
key: netsnmp-${{ env.NETSNMP_VERSION }}-mingw64
51+
52+
- name: Build and install net-snmp
53+
if: steps.cache-netsnmp.outputs.cache-hit != 'true'
54+
run: |
55+
set -euxo pipefail
56+
cd "$RUNNER_TEMP"
57+
wget -q "https://downloads.sourceforge.net/project/net-snmp/net-snmp/${NETSNMP_VERSION}/net-snmp-${NETSNMP_VERSION}.tar.gz"
58+
tar xf "net-snmp-${NETSNMP_VERSION}.tar.gz"
59+
cd "net-snmp-${NETSNMP_VERSION}"
60+
./configure \
61+
--prefix=/mingw64 \
62+
--with-defaults \
63+
--disable-agent \
64+
--disable-applications \
65+
--disable-manuals \
66+
--disable-scripts \
67+
--disable-mibs \
68+
--without-perl-modules \
69+
--disable-embedded-perl \
70+
--with-openssl=/mingw64
71+
make -j$(nproc)
72+
make install
73+
74+
- name: Show toolchain versions
75+
run: |
76+
gcc --version
77+
python --version
78+
net-snmp-config --version
79+
net-snmp-config --libs
80+
81+
- name: Build extension
82+
run: python setup.py build

‎netsnmp/client_intf.c‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,22 @@
44
#include <net-snmp/net-snmp-config.h>
55
#include <net-snmp/net-snmp-includes.h>
66
#include <sys/types.h>
7+
#ifdef _WIN32
8+
/* On Windows the socket API (inet_addr, etc.) lives in winsock, not the
9+
POSIX arpa/inet.h and netdb.h headers. net-snmp-includes.h already pulls
10+
in winsock2.h; ws2tcpip.h provides the address helpers we use. */
11+
#include <winsock2.h>
12+
#include <ws2tcpip.h>
13+
#else
714
#include <arpa/inet.h>
15+
#include <netdb.h>
16+
#endif
817
#include <errno.h>
918
#include <stdio.h>
1019
#include <ctype.h>
1120
#ifdef I_SYS_TIME
1221
#include <sys/time.h>
1322
#endif
14-
#include <netdb.h>
1523
#include <stdlib.h>
1624

1725
#ifdef HAVE_REGEX_H

‎setup.py‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,22 @@
1111
basedir = string.split(arg,'=')[1]
1212
sys.argv.remove(arg)
1313

14-
netsnmp_libs = os.popen('net-snmp-config --libs').read()
14+
def netsnmp_config(flag):
15+
cmd = 'net-snmp-config ' + flag
16+
if sys.platform == 'win32':
17+
# net-snmp-config is a POSIX shell script; on Windows os.popen goes
18+
# through cmd.exe which can't execute it, so run it via sh (available
19+
# in the MSYS2/mingw environment used to build the extension).
20+
cmd = 'sh -c "net-snmp-config %s"' % flag
21+
return os.popen(cmd).read()
22+
23+
netsnmp_libs = netsnmp_config('--libs')
1524
libdirs = re.findall(r" -L(\S+)", netsnmp_libs)
1625
incdirs = []
1726
libs = re.findall(r" -l(\S+)", netsnmp_libs)
27+
if sys.platform == 'win32':
28+
# inet_addr() and the winsock symbols net-snmp relies on come from ws2_32.
29+
libs.append('ws2_32')
1830

1931
setup(
2032
name="python3-netsnmp", version="1.1a2",

0 commit comments

Comments
 (0)