Skip to content

Commit 9c8fc44

Browse files
committed
Get the MSVC build running too.
Files under tectonic/msvc/ directory are taken and adopted from postgresql source code.
1 parent 3de72c6 commit 9c8fc44

15 files changed

+638
-5
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ pkg-config = "^0.3"
3737
regex = "^1.0"
3838
sha2 = "^0.7"
3939

40+
[target.'cfg(target_env = "msvc")'.build-dependencies]
41+
vcpkg = "0.2"
42+
4043
[dependencies]
4144
aho-corasick = "^0.6"
4245
app_dirs = "^1.1"

build.rs

+71-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// TODO: this surely needs to become much smarter and more flexible.
66

77
extern crate cc;
8+
#[cfg(target_env = "msvc")]
9+
extern crate vcpkg;
810
extern crate pkg_config;
911
extern crate regex;
1012
extern crate sha2;
@@ -36,21 +38,75 @@ fn cpp_platform_specifics(cfg: &mut cc::Build) {
3638
cfg.file("tectonic/XeTeXFontMgr_Mac.mm");
3739
}
3840

41+
// Windows platform specifics:
42+
#[cfg(target_os = "windows")]
43+
const LIBS: &'static str = "fontconfig harfbuzz >= 1.4 harfbuzz-icu icu-uc freetype2 graphite2 libpng zlib";
44+
#[cfg(target_os = "windows")]
45+
#[allow(dead_code)]
46+
const VCPKG_LIBS: &[&[&'static str]] = &[
47+
&["fontconfig"], &["harfbuzz"], &["icu"], &["freetype"], &["graphite2"], &["libpng"], &["zlib"]];
48+
//FIXME: it should actually be harfbuzz[icu], but currently vcpkg-rs doesn't support features.
49+
50+
#[cfg(target_os = "windows")]
51+
fn c_platform_specifics(cfg: &mut cc::Build) {
52+
let target = env::var("TARGET").unwrap();
53+
if target.contains("msvc") {
54+
cfg
55+
.file("tectonic/msvc/dirent.c")
56+
.file("tectonic/msvc/getopt.c")
57+
.file("tectonic/msvc/win32error.c")
58+
.include("tectonic/msvc/");
59+
}
60+
}
61+
62+
#[cfg(target_os = "windows")]
63+
fn cpp_platform_specifics(cfg: &mut cc::Build) {
64+
let target = env::var("TARGET").unwrap();
65+
if target.contains("msvc") {
66+
cfg
67+
.include("tectonic/msvc/");
68+
}
69+
cfg.file("tectonic/XeTeXFontMgr_FC.cpp");
70+
}
71+
3972

40-
// Not-MacOS:
73+
// Not-MacOS or Windows:
4174

42-
#[cfg(not(target_os = "macos"))]
75+
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
4376
const LIBS: &'static str = "fontconfig harfbuzz >= 1.4 harfbuzz-icu icu-uc freetype2 graphite2 libpng zlib";
4477

45-
#[cfg(not(target_os = "macos"))]
78+
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
4679
fn c_platform_specifics(_: &mut cc::Build) {
4780
}
4881

49-
#[cfg(not(target_os = "macos"))]
82+
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
5083
fn cpp_platform_specifics(cfg: &mut cc::Build) {
5184
cfg.file("tectonic/XeTeXFontMgr_FC.cpp");
5285
}
5386

87+
#[cfg(target_env = "msvc")]
88+
fn load_vcpkg_deps() {
89+
for dep in VCPKG_LIBS {
90+
if dep.len() <= 1 {
91+
vcpkg::find_package(dep[0]).expect("failed to load package from vcpkg");
92+
} else {
93+
let mut config = vcpkg::Config::new();
94+
for lib in &dep[1..] {
95+
config.lib_name(lib);
96+
}
97+
config.find_package(dep[0]).expect("failed to load package from vcpkg");
98+
}
99+
}
100+
}
101+
102+
#[cfg(not(target_env = "msvc"))]
103+
fn load_vcpkg_deps() {
104+
panic!()
105+
}
106+
107+
fn load_pkg_config_deps() {
108+
pkg_config::Config::new().cargo_metadata(true).probe(LIBS).unwrap();
109+
}
54110

55111
fn main() {
56112
// We (have to) rerun the search again below to emit the metadata at the right time.
@@ -272,11 +328,21 @@ fn main() {
272328
// Now that we've emitted the info for our own libraries, we can emit the
273329
// info for their dependents.
274330

275-
pkg_config::Config::new().cargo_metadata(true).probe(LIBS).unwrap();
331+
if cfg!(target_env = "msvc") {
332+
load_vcpkg_deps();
333+
} else {
334+
load_pkg_config_deps();
335+
}
276336

277337
// Tell cargo to rerun build.rs only if files in the tectonic/ directory have changed.
278338
for file in PathBuf::from("tectonic").read_dir().unwrap() {
279339
let file = file.unwrap();
280340
println!("cargo:rerun-if-changed={}", file.path().display());
281341
}
342+
343+
#[cfg(target_env = "msvc")]
344+
for file in PathBuf::from("tectonic/msvc").read_dir().unwrap() {
345+
let file = file.unwrap();
346+
println!("cargo:rerun-if-changed={}", file.path().display());
347+
}
282348
}

tectonic/XeTeX_ext.c

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ authorization from the copyright holders.
5959

6060
#include "xetexd.h"
6161

62+
#ifdef _MSC_VER
63+
#define strcasecmp _stricmp
64+
#endif
65+
6266

6367
/* OT-related constants we need */
6468
#define kGSUB HB_TAG('G','S','U','B')

tectonic/core-bridge.h

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <stddef.h> /* size_t */
1212
#include <sys/types.h> /* ssize_t */
1313

14+
#if defined(_MSC_VER)
15+
#include <BaseTsd.h>
16+
typedef SSIZE_T ssize_t;
17+
#endif
1418

1519
/* The weird enum values are historical and could be rationalized. But it is
1620
* good to write them explicitly since they must be kept in sync with

tectonic/dpx-dpxfile.c

+18
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,28 @@ dpx_create_temp_file (void)
314314
int _fd = -1;
315315
_tmpd = dpx_get_tmpdir();
316316
tmp = NEW(strlen(_tmpd) + strlen(TEMPLATE) + 1, char);
317+
#ifdef _MSC_VER
318+
_fd == -1;
319+
for(int retry = 0; retry < 10; retry ++) {
320+
strcpy(tmp, _tmpd);
321+
strcat(tmp, TEMPLATE);
322+
mktemp(tmp);
323+
if (strlen(tmp) == 0) {
324+
errno = EEXIST;
325+
break;
326+
}
327+
_fd = open(tmp, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
328+
if (_fd != -1 || errno != EEXIST) {
329+
break;
330+
}
331+
}
332+
free(_tmpd);
333+
#else
317334
strcpy(tmp, _tmpd);
318335
free(_tmpd);
319336
strcat(tmp, TEMPLATE);
320337
_fd = mkstemp(tmp);
338+
#endif
321339
if (_fd != -1) {
322340
close(_fd);
323341
} else {

tectonic/dpx-spc_dvips.c

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
#include "dpx-specials.h"
4949
#include "internals.h"
5050

51+
#ifdef _MSC_VER
52+
#define popen _popen
53+
#define pclose _pclose
54+
#endif
55+
56+
5157
static int block_pending = 0;
5258
static double pending_x = 0.0;
5359
static double pending_y = 0.0;

tectonic/dpx-spc_util.c

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#include "dpx-specials.h"
3636
#include "internals.h"
3737

38+
#ifdef _MSC_VER
39+
#define strcasecmp _stricmp
40+
#endif
3841

3942
#ifndef ISBLANK
4043
#define ISBLANK(c) ((c) == ' ' || (c) == '\t')

tectonic/msvc/dirent.c

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* dirent.c
4+
* opendir/readdir/closedir for win32/msvc
5+
*
6+
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
*
10+
* IDENTIFICATION
11+
* src/port/dirent.c
12+
*
13+
*-------------------------------------------------------------------------
14+
*/
15+
16+
#include <windows.h>
17+
#include <dirent.h>
18+
19+
extern void _dosmaperr(unsigned long);
20+
21+
22+
struct DIR
23+
{
24+
char *dirname;
25+
struct dirent ret; /* Used to return to caller */
26+
HANDLE handle;
27+
};
28+
29+
DIR *
30+
opendir(const char *dirname)
31+
{
32+
DWORD attr;
33+
DIR *d;
34+
35+
/* Make sure it is a directory */
36+
attr = GetFileAttributes(dirname);
37+
if (attr == INVALID_FILE_ATTRIBUTES)
38+
{
39+
errno = ENOENT;
40+
return NULL;
41+
}
42+
if ((attr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
43+
{
44+
errno = ENOTDIR;
45+
return NULL;
46+
}
47+
48+
d = malloc(sizeof(DIR));
49+
if (!d)
50+
{
51+
errno = ENOMEM;
52+
return NULL;
53+
}
54+
d->dirname = malloc(strlen(dirname) + 4);
55+
if (!d->dirname)
56+
{
57+
errno = ENOMEM;
58+
free(d);
59+
return NULL;
60+
}
61+
strcpy(d->dirname, dirname);
62+
if (d->dirname[strlen(d->dirname) - 1] != '/' &&
63+
d->dirname[strlen(d->dirname) - 1] != '\\')
64+
strcat(d->dirname, "\\"); /* Append backslash if not already there */
65+
strcat(d->dirname, "*"); /* Search for entries named anything */
66+
d->handle = INVALID_HANDLE_VALUE;
67+
d->ret.d_ino = 0; /* no inodes on win32 */
68+
d->ret.d_reclen = 0; /* not used on win32 */
69+
70+
return d;
71+
}
72+
73+
struct dirent *
74+
readdir(DIR *d)
75+
{
76+
WIN32_FIND_DATA fd;
77+
78+
if (d->handle == INVALID_HANDLE_VALUE)
79+
{
80+
d->handle = FindFirstFile(d->dirname, &fd);
81+
if (d->handle == INVALID_HANDLE_VALUE)
82+
{
83+
errno = ENOENT;
84+
return NULL;
85+
}
86+
}
87+
else
88+
{
89+
if (!FindNextFile(d->handle, &fd))
90+
{
91+
if (GetLastError() == ERROR_NO_MORE_FILES)
92+
{
93+
/* No more files, force errno=0 (unlike mingw) */
94+
errno = 0;
95+
return NULL;
96+
}
97+
_dosmaperr(GetLastError());
98+
return NULL;
99+
}
100+
}
101+
strcpy(d->ret.d_name, fd.cFileName); /* Both strings are MAX_PATH long */
102+
d->ret.d_namlen = strlen(d->ret.d_name);
103+
104+
return &d->ret;
105+
}
106+
107+
int
108+
closedir(DIR *d)
109+
{
110+
int ret = 0;
111+
112+
if (d->handle != INVALID_HANDLE_VALUE)
113+
ret = !FindClose(d->handle);
114+
free(d->dirname);
115+
free(d);
116+
117+
return ret;
118+
}

tectonic/msvc/dirent.h

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Headers for port/dirent.c, win32 native implementation of dirent functions
3+
*
4+
* src/include/port/win32_msvc/dirent.h
5+
*/
6+
7+
#ifndef _WIN32VC_DIRENT_H
8+
#define _WIN32VC_DIRENT_H
9+
10+
#ifndef MAX_PATH
11+
//tectonic hack: avoid including whole windows.h here.
12+
#define MAX_PATH 260
13+
#endif
14+
15+
struct dirent
16+
{
17+
long d_ino;
18+
unsigned short d_reclen;
19+
unsigned short d_namlen;
20+
char d_name[MAX_PATH];
21+
};
22+
23+
typedef struct DIR DIR;
24+
25+
DIR *opendir(const char *);
26+
struct dirent *readdir(DIR *);
27+
int closedir(DIR *);
28+
29+
#endif

0 commit comments

Comments
 (0)