Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build windows x86_64 binary #329

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/crosscompile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
set -euo pipefail

declare -ar TARGETS=(
x86_64-unknown-windows-gnu
x86_64-unknown-linux-musl
x86_64-apple-darwin-none
aarch64-unknown-linux-musl
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,20 @@ jobs:
if: ${{ runner.arch == 'ARM64' }}
working-directory: ${{steps.download.outputs.download-path}}/artifact

run-win32:
name: Run win32
needs:
- tests
runs-on:
windows-latest
steps:
- uses: actions/download-artifact@v4
id: download
- run: ls
working-directory: ${{steps.download.outputs.download-path}}/artifact
- run: "./scalals-windows-x86_64 -lh"
working-directory: ${{steps.download.outputs.download-path}}/artifact

release:
if: github.ref == 'refs/heads/main'
needs:
Expand Down
52 changes: 49 additions & 3 deletions native/src/main/resources/scala-native/terminal.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,57 @@
#include <stdbool.h>

#if defined(_WIN32)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <io.h>

long int scalanative_consoleWidth() {
CONSOLE_SCREEN_BUFFER_INFO csbi;

if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
return csbi.srWindow.Right - csbi.srWindow.Left + 1;
} else {
return 80;
}
}

#else /* Unix */

#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdbool.h>

long int scalanative_tiocgwinsize() {
return TIOCGWINSZ;
long int scalanative_consoleWidth() {
struct winsize winsz;
unsigned int cols;
int tty = open("/dev/tty", O_RDWR, 0u);

if (tty == -1) {
tty = STDOUT_FILENO;
}

if (ioctl(tty, TIOCGWINSZ, &winsz) >= 0) {
cols = winsz.ws_col;
} else {
const char* columns = getenv("COLUMNS");
if (!columns || (cols = atoi(columns)) == 0) {
cols = 80;
}
}

if (tty != STDOUT_FILENO) {
close(tty);
}
return cols;
}

#endif

bool scalanative_isatty(int fd) {
#ifdef _WIN32
return _isatty(fd);
#else
return isatty(fd);
#endif
}
225 changes: 225 additions & 0 deletions native/src/main/resources/scala-native/win32_compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
#ifdef _WIN32

/* limits.c */

#include <limits.h>

int scalanative_path_max() { return PATH_MAX; }

/* sys/stat.h */

//
/** "../types.h" --> */

#ifndef __TYPES_H
#define __TYPES_H

// types used in pwd.c and sys/stat.c

typedef unsigned long scalanative_dev_t;
typedef unsigned int scalanative_mode_t;
typedef unsigned long long scalanative_ino_t;
typedef unsigned int scalanative_uid_t;
typedef unsigned int scalanative_gid_t;
typedef long long scalanative_off_t;
typedef long int scalanative_time_t;
typedef long long scalanative_blkcnt_t;
typedef long scalanative_blksize_t;
typedef unsigned long scalanative_nlink_t;

typedef unsigned long scalanative_fsblkcnt_t;
typedef unsigned long scalanative_fsfilcnt_t;

#endif // __TYPES_H

/** <-- */

#include <sys/stat.h>

// We don't use the "standard" types such as `dev_t` for instance
// because these have different sizes on eg. Linux and OSX. We use the
// smallest type that can hold all the possible values for the different
// systems.
struct scalanative_stat {
scalanative_dev_t st_dev; /** Device ID of device containing file. */
scalanative_dev_t st_rdev; /** Device ID (if file is character or block
special). */
scalanative_ino_t st_ino; /** File serial number. */
scalanative_uid_t st_uid; /** User ID of file. */
scalanative_gid_t st_gid; /** Group ID of file. */
scalanative_off_t st_size; /** For regular files, the file size in bytes.
For symbolic links, the length in bytes of
the pathname contained in the symbolic
link. For a shared memory object, the
length in bytes. For a typed memory object,
the length in bytes. For other file types,
the use of this field is unspecified. */
scalanative_time_t _st_atime; /** Time of last access. */
scalanative_time_t _st_mtime; /** Time of last data modification. */
scalanative_time_t _st_ctime; /** Time of last status change. */
scalanative_blkcnt_t st_blocks; /** Number of blocks allocated for this
object. */
scalanative_blksize_t st_blksize; /** A file system-specific preferred I/O
block size for this object. In some
file system types, this may vary from
file to file. */
scalanative_nlink_t st_nlink; /** Number of hard links to the file. */
scalanative_mode_t st_mode; /** Mode of file (see below). */
};

void scalanative_stat_init(struct stat *stat,
struct scalanative_stat *my_stat) {
my_stat->st_dev = stat->st_dev;
my_stat->st_rdev = stat->st_rdev;
my_stat->st_ino = stat->st_ino;
my_stat->st_uid = stat->st_uid;
my_stat->st_gid = stat->st_gid;
my_stat->st_size = stat->st_size;
my_stat->_st_atime = stat->st_atime;
my_stat->_st_mtime = stat->st_mtime;
my_stat->_st_ctime = stat->st_ctime;
my_stat->st_blksize = 0;
my_stat->st_blocks = 0;
my_stat->st_nlink = stat->st_nlink;
my_stat->st_mode = stat->st_mode;
}

int scalanative_stat(char *path, struct scalanative_stat *buf) {
struct stat orig_buf;
if (stat(path, &orig_buf) == 0) {
scalanative_stat_init(&orig_buf, buf);
return 0;
} else {
return 1;
}
}

int scalanative_fstat(int fildes, struct scalanative_stat *buf) {
struct stat orig_buf;
if (fstat(fildes, &orig_buf) == 0) {
scalanative_stat_init(&orig_buf, buf);
return 0;
} else {
return 1;
}
}

int scalanative_lstat(char *path, struct scalanative_stat *buf) {
struct stat orig_buf;
if (stat(path, &orig_buf) == 0) {
scalanative_stat_init(&orig_buf, buf);
return 0;
} else {
return 1;
}
}

int scalanative_mkdir(char *path, mode_t mode) { return mkdir(path); }

int scalanative_chmod(char *pathname, mode_t mode) {
return chmod(pathname, mode);
}

int scalanative_fchmod(int fd, mode_t mode) { return -1; }

mode_t scalanative_s_isuid() { return 0; }

mode_t scalanative_s_isgid() { return 0; }

mode_t scalanative_s_isvtx() { return 0; }

mode_t scalanative_s_irusr() { return S_IRUSR; }

mode_t scalanative_s_iwusr() { return S_IWUSR; }

mode_t scalanative_s_ixusr() { return S_IXUSR; }

mode_t scalanative_s_irgrp() { return S_IRGRP; }

mode_t scalanative_s_iwgrp() { return S_IWGRP; }

mode_t scalanative_s_ixgrp() { return S_IXGRP; }

mode_t scalanative_s_iroth() { return S_IROTH; }

mode_t scalanative_s_iwoth() { return S_IWOTH; }

mode_t scalanative_s_ixoth() { return S_IXOTH; }

int scalanative_s_isdir(mode_t mode) { return S_ISDIR(mode); }

int scalanative_s_isreg(mode_t mode) { return S_ISREG(mode); }

int scalanative_s_ischr(mode_t mode) { return S_ISCHR(mode); }

int scalanative_s_isblk(mode_t mode) { return S_ISBLK(mode); }

int scalanative_s_isfifo(mode_t mode) { return S_ISFIFO(mode); }

int scalanative_s_islnk(mode_t mode) { return 0; }

int scalanative_s_issock(mode_t mode) { return 0; }

/* unistd.c */

#include <unistd.h>

int scalanative_stdin_fileno() { return STDIN_FILENO; }

int scalanative_stdout_fileno() { return STDOUT_FILENO; }

int scalanative_stderr_fileno() { return STDERR_FILENO; }

/* grp.c */

struct scalanative_group {
char *gr_name; /** The name of the group. */
scalanative_gid_t gr_gid; /** Numerical group ID. */
char **gr_mem; /** Pointer to a null-terminated array of character
pointers to member names. */
};

int scalanative_getgrgid(scalanative_gid_t gid, struct scalanative_group *buf) {
return 1;
}

int scalanative_getgrnam(char *name, struct scalanative_group *buf) {
return 1;
}

/* pwd.c */

#include <stdlib.h>

// We don't use the "standard" types such as `dev_t` for instance
// because these have different sizes on eg. Linux and OSX. We use the
// smallest type that can hold all the possible values for the different
// systems.

struct scalanative_passwd {
char *pw_name; /** User's login name. */
scalanative_uid_t pw_uid; /** Numerical user ID. */
scalanative_gid_t pw_gid; /** Numerical group ID. */
char *pw_dir; /** Initial working directory. */
char *pw_shell; /** Program to use as shell. */
};

int scalanative_getpwuid(scalanative_uid_t uid,
struct scalanative_passwd *buf) {
return 1;
}

int scalanative_getpwnam(char *name, struct scalanative_passwd *buf) {
return 1;
}

#include <locale.h>

int scalanative_lc_all() {
return LC_ALL;
}

///include <accctrl.h>
///int scalanative_se_file_object() { return SE_FILE_OBJECT; }

#endif // _WIN32
42 changes: 4 additions & 38 deletions native/src/main/scala/de/bley/scalals/Terminal.scala
Original file line number Diff line number Diff line change
@@ -1,51 +1,17 @@
package de.bley.scalals

import scala.scalanative.libc.stdio.perror
import scala.scalanative.unsigned.*
import scala.scalanative.unsafe.*
import scala.scalanative.posix.unistd.STDOUT_FILENO
import scala.scalanative.posix.fcntl.*
import scala.scalanative.posix.unistd.close
import scala.scalanative.posix.sys.ioctl.*

@extern
object termios:
@name("scalanative_tiocgwinsize")
def TIOCGWINSZ: CLongInt = extern
@name("scalanative_consoleWidth")
def consoleWidth: CLongInt = extern

@extern
object xunistd:
@name("scalanative_isatty")
def isatty(fileno: CInt): Boolean = extern

object types:
/*
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel; /* unused */
unsigned short ws_ypixel; /* unused */
};
*/
type winsize = CStruct4[UShort, UShort, UShort, UShort]
end types

object Terminal:
def isTTYOutput: Boolean = xunistd.isatty(STDOUT_FILENO)

def width: Int =
val winsz = stackalloc[types.winsize]()

var tty = open(c"/dev/tty", O_RDWR, 0.toUInt)
try
if tty == -1 then tty = STDOUT_FILENO
def isTTYOutput: Boolean = termios.isatty(STDOUT_FILENO)

if ioctl(tty, termios.TIOCGWINSZ, winsz.asInstanceOf[Ptr[Byte]]) >= 0 then (winsz._2).toInt
else sys.env.get("COLUMNS").map(_.toInt).getOrElse(80)
finally
if tty != STDOUT_FILENO then
val ret = close(tty)
if ret != 0 then perror(c"close tty")
end try
end width
def width: Int = termios.consoleWidth.toInt
end Terminal
Loading