Skip to content

Commit 3fc15c4

Browse files
committed
add mingw64-windows CI
1 parent 027a7c5 commit 3fc15c4

9 files changed

Lines changed: 75 additions & 44 deletions

File tree

.github/workflows/windows.yml

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ name: CI Windows
44

55
jobs:
66
test-default-windows:
7-
name: Windows default
7+
name: Windows vcpkg (default)
88
runs-on: windows-latest
99
env:
1010
VCPKGRS_DYNAMIC: 1
1111
VCPKG_DEFAULT_TRIPLET: x64-windows
1212
VCPKG_ROOT: C:\vcpkg
1313
steps:
14+
- uses: actions/checkout@v4
1415
- name: Setup vcpkg libxml2 Cache
1516
uses: actions/cache@v4
1617
id: vcpkg-cache
@@ -19,10 +20,39 @@ jobs:
1920
key: vcpkg-libxml2
2021
- name: Install libxml2 with vcpkg
2122
run: |
22-
vcpkg install libxml2
23+
vcpkg install libxml2:x64-windows
2324
vcpkg integrate install
24-
- uses: actions/checkout@v2
2525
- name: run tests
2626
uses: actions-rs/cargo@v1
2727
with:
2828
command: test
29+
30+
test-mingw64-windows:
31+
name: Windows (mingw64)
32+
runs-on: windows-latest
33+
defaults:
34+
run:
35+
shell: msys2 {0}
36+
steps:
37+
- uses: actions/checkout@v4
38+
- uses: msys2/setup-msys2@v2
39+
with:
40+
path-type: minimal
41+
release: false
42+
update: false
43+
msystem: MINGW64
44+
install: >-
45+
mingw64/mingw-w64-x86_64-pkg-config
46+
mingw64/mingw-w64-x86_64-libxml2
47+
- name: Install stable windows-gnu Rust toolchain
48+
uses: actions-rs/toolchain@v1
49+
with:
50+
toolchain: stable-x86_64-pc-windows-gnu
51+
target: x86_64-pc-windows-gnu
52+
override: true
53+
- name: Ensure mingw64 pkg-config is in path
54+
run: echo "C:\msys64\mingw64\bin" >> "$GITHUB_PATH"
55+
- name: run tests
56+
uses: actions-rs/cargo@v1
57+
with:
58+
command: test

build.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn find_libxml2() -> Option<ProbedLib> {
5151
})
5252
}
5353

54-
#[cfg(target_family = "windows")]
54+
#[cfg(all(target_family = "windows", target_env = "msvc"))]
5555
{
5656
if let Some(meta) = vcpkg_dep::vcpkg_find_libxml2() {
5757
return Some(meta);
@@ -113,8 +113,9 @@ fn main() {
113113
mod vcpkg_dep {
114114
use crate::ProbedLib;
115115
pub fn vcpkg_find_libxml2() -> Option<ProbedLib> {
116-
if let Ok(metadata) = vcpkg::find_package("libxml2") {
117-
Some(ProbedLib { version: vcpkg_version(), include_paths: metadata.include_paths })
116+
if let Ok(metadata) = vcpkg::Config::new()
117+
.find_package("libxml2") {
118+
Some(ProbedLib { version: vcpkg_version(), include_paths: dbg!(metadata).include_paths })
118119
} else {
119120
None
120121
}

src/c_helpers.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,18 @@ pub fn xmlXPathObjectNumberOfNodes(val: xmlXPathObjectPtr) -> c_int {
143143
pub fn xmlXPathObjectGetNodes(val: xmlXPathObjectPtr, size: size_t) -> Vec<xmlNodePtr> {
144144
unsafe { slice::from_raw_parts((*(*val).nodesetval).nodeTab, size).to_vec() }
145145
}
146+
147+
#[cfg(any(target_family = "unix", target_os = "macos", all(target_family="windows", target_env="gnu")))]
148+
pub fn bindgenFree(val: *mut c_void) {
149+
unsafe {
150+
if let Some(xml_free_fn) = xmlFree {
151+
xml_free_fn(val);
152+
} else {
153+
libc::free(val);
154+
}
155+
}
156+
}
157+
#[cfg(all(target_family="windows", target_env="msvc"))]
158+
pub fn bindgenFree(val: *mut c_void) {
159+
unsafe { libc::free(val as *mut c_void); }
160+
}

src/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::slice;
1717
use std::str;
1818
use std::sync::Once;
1919

20-
static INIT_LIBXML_PARSER: Once = Once::new();
20+
pub(crate) static INIT_LIBXML_PARSER: Once = Once::new();
2121

2222
enum XmlParserOption {
2323
Recover = 1,

src/readonly/tree.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,7 @@ impl RoNode {
212212
}
213213
let c_string = unsafe { CStr::from_ptr(content_ptr as *const c_char) };
214214
let rust_utf8 = c_string.to_string_lossy().into_owned();
215-
unsafe {
216-
libc::free(content_ptr as *mut c_void);
217-
}
215+
bindgenFree(content_ptr as *mut c_void);
218216
rust_utf8
219217
}
220218

@@ -227,10 +225,7 @@ impl RoNode {
227225
}
228226
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
229227
let prop_str = c_value_string.to_string_lossy().into_owned();
230-
// A safe way to free the memory is using libc::free -- I have experienced that xmlFree from libxml2 is not reliable
231-
unsafe {
232-
libc::free(value_ptr as *mut c_void);
233-
}
228+
bindgenFree(value_ptr as *mut c_void);
234229
Some(prop_str)
235230
}
236231

@@ -245,9 +240,7 @@ impl RoNode {
245240
}
246241
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
247242
let prop_str = c_value_string.to_string_lossy().into_owned();
248-
unsafe {
249-
libc::free(value_ptr as *mut c_void);
250-
}
243+
bindgenFree(value_ptr as *mut c_void);
251244
Some(prop_str)
252245
}
253246

@@ -260,9 +253,7 @@ impl RoNode {
260253
}
261254
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
262255
let prop_str = c_value_string.to_string_lossy().into_owned();
263-
unsafe {
264-
libc::free(value_ptr as *mut c_void);
265-
}
256+
bindgenFree(value_ptr as *mut c_void);
266257
Some(prop_str)
267258
}
268259

src/tree/document.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,14 @@ impl fmt::Display for Document {
8484
impl Document {
8585
/// Creates a new empty libxml2 document
8686
pub fn new() -> Result<Self, ()> {
87+
// initialize the parser context
88+
crate::parser::INIT_LIBXML_PARSER.call_once(|| unsafe {
89+
crate::bindings::xmlInitParser();
90+
});
8791
unsafe {
8892
let c_version = CString::new("1.0").unwrap();
89-
let doc_ptr = xmlNewDoc(c_version.as_bytes().as_ptr());
93+
let c_version_bytes = c_version.as_bytes();
94+
let doc_ptr = xmlNewDoc(c_version_bytes.as_ptr());
9095
if doc_ptr.is_null() {
9196
Err(())
9297
} else {
@@ -290,12 +295,14 @@ impl Document {
290295
pub fn create_processing_instruction(&mut self, name: &str, content: &str) -> Result<Node, ()> {
291296
unsafe {
292297
let c_name = CString::new(name).unwrap();
298+
let c_name_bytes = c_name.as_bytes();
293299
let c_content = CString::new(content).unwrap();
300+
let c_content_bytes = c_content.as_bytes();
294301

295302
let node_ptr: xmlNodePtr = xmlNewDocPI(
296303
self.doc_ptr(),
297-
c_name.as_bytes().as_ptr(),
298-
c_content.as_bytes().as_ptr(),
304+
c_name_bytes.as_ptr(),
305+
c_content_bytes.as_ptr(),
299306
);
300307
if node_ptr.is_null() {
301308
Err(())

src/tree/node.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,7 @@ impl Node {
406406
}
407407
let c_string = unsafe { CStr::from_ptr(content_ptr as *const c_char) };
408408
let rust_utf8 = c_string.to_string_lossy().into_owned();
409-
unsafe {
410-
libc::free(content_ptr as *mut c_void);
411-
}
409+
bindgenFree(content_ptr as *mut c_void);
412410
rust_utf8
413411
}
414412

@@ -428,10 +426,7 @@ impl Node {
428426
}
429427
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
430428
let prop_str = c_value_string.to_string_lossy().into_owned();
431-
// A safe way to free the memory is using libc::free -- I have experienced that xmlFree from libxml2 is not reliable
432-
unsafe {
433-
libc::free(value_ptr as *mut c_void);
434-
}
429+
bindgenFree(value_ptr as *mut c_void);
435430
Some(prop_str)
436431
}
437432

@@ -451,9 +446,7 @@ impl Node {
451446
}
452447
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
453448
let prop_str = c_value_string.to_string_lossy().into_owned();
454-
unsafe {
455-
libc::free(value_ptr as *mut c_void);
456-
}
449+
bindgenFree(value_ptr as *mut c_void);
457450
Some(prop_str)
458451
}
459452

@@ -466,9 +459,7 @@ impl Node {
466459
}
467460
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
468461
let prop_str = c_value_string.to_string_lossy().into_owned();
469-
unsafe {
470-
libc::free(value_ptr as *mut c_void);
471-
}
462+
bindgenFree(value_ptr as *mut c_void);
472463
Some(prop_str)
473464
}
474465

src/xpath.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,7 @@ impl Object {
262262
let value_ptr = unsafe { xmlXPathCastNodeToString(ptr) };
263263
let c_value_string = unsafe { CStr::from_ptr(value_ptr as *const c_char) };
264264
let ready_str = c_value_string.to_string_lossy().into_owned();
265-
unsafe {
266-
libc::free(value_ptr as *mut c_void);
267-
}
265+
bindgenFree(value_ptr as *mut c_void);
268266
vec.push(ready_str);
269267
}
270268
vec
@@ -279,7 +277,7 @@ impl fmt::Display for Object {
279277
let receiver = xmlXPathCastToString(self.ptr);
280278
let c_string = CStr::from_ptr(receiver as *const c_char);
281279
let rust_string = str::from_utf8(c_string.to_bytes()).unwrap().to_owned();
282-
libc::free(receiver as *mut c_void);
280+
bindgenFree(receiver as *mut c_void);
283281
write!(f, "{}", rust_string)
284282
}
285283
}
@@ -294,9 +292,7 @@ pub fn is_well_formed_xpath(xpath: &str) -> bool {
294292
if xml_xpath_comp_expr_ptr.is_null() {
295293
false
296294
} else {
297-
unsafe {
298-
libc::free(xml_xpath_comp_expr_ptr as *mut c_void);
299-
}
295+
bindgenFree(xml_xpath_comp_expr_ptr as *mut c_void);
300296
true
301297
}
302298
}

tests/base_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ fn html_fragment() {
177177
let parser = Parser::default_html();
178178
let document = parser
179179
.parse_string_with_options(
180-
&fragment,
180+
fragment,
181181
ParserOptions {
182182
no_def_dtd: true,
183183
no_implied: true,

0 commit comments

Comments
 (0)