diff options
author | Jakob Odersky <jodersky@gmail.com> | 2014-01-13 17:40:34 +0100 |
---|---|---|
committer | Jakob Odersky <jodersky@gmail.com> | 2014-01-14 15:43:00 +0100 |
commit | 5c94ee017051d51f51e06a61a8bc4e70a15e36da (patch) | |
tree | 2e48701ebb4177557234dbbd22b3b7058cad36de | |
parent | 84f640208ed6e4e155e87ebcb73a82c021174ea7 (diff) | |
download | akka-serial-5c94ee017051d51f51e06a61a8bc4e70a15e36da.tar.gz akka-serial-5c94ee017051d51f51e06a61a8bc4e70a15e36da.tar.bz2 akka-serial-5c94ee017051d51f51e06a61a8bc4e70a15e36da.zip |
enable easier cross-compilation
-rw-r--r-- | flow-binaries/linux/amd64/libflow.so.1.0 | bin | 13683 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/linux/amd64/libflow.so.1.1 | bin | 13734 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/linux/amd64/libflow.so.2.0 | bin | 17830 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/linux/amd64/libflow.so.2.1 | bin | 17830 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/linux/arm/libflow.so.2.1 | bin | 13462 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/linux/i386/libflow.so.2.1 | bin | 12273 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/macosx/x86_64/libflow.jnilib.1.1 | bin | 14360 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/macosx/x86_64/libflow.jnilib.2.0 | bin | 14360 -> 0 bytes | |||
-rw-r--r-- | flow-binaries/macosx/x86_64/libflow.jnilib.2.1 | bin | 14360 -> 0 bytes | |||
-rw-r--r-- | flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/ConsoleReader.scala (renamed from flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/ConsoleReader.scala) | 0 | ||||
-rw-r--r-- | flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Main.scala (renamed from flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Main.scala) | 0 | ||||
-rw-r--r-- | flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Terminal.scala (renamed from flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Terminal.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java (renamed from flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java) | 0 | ||||
-rw-r--r-- | flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h | 79 | ||||
-rw-r--r-- | flow/src/main/native/include/flow.h (renamed from flow-native/shared/include/flow.h) | 0 | ||||
-rw-r--r-- | flow/src/main/native/posix/flow.c (renamed from flow-native/unix/src/flow.c) | 0 | ||||
-rw-r--r-- | flow/src/main/native/windows/README | 1 | ||||
-rw-r--r-- | flow/src/main/native/windows/flow.c.disabled | 416 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/Parity.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/Parity.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/Serial.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/SerialExt.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/SerialExt.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/SerialManager.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/SerialOperator.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/SerialSettings.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/SerialSettings.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/exceptions.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/exceptions.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/internal/InternalSerial.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/internal/InternalSerial.scala) | 0 | ||||
-rw-r--r-- | flow/src/main/scala/com/github/jodersky/flow/internal/NativeLoader.scala (renamed from flow-main/src/main/scala/com/github/jodersky/flow/internal/NativeLoader.scala) | 2 | ||||
-rw-r--r-- | project/FlowBuild.scala | 216 | ||||
-rw-r--r-- | project/jni.scala | 27 | ||||
-rw-r--r-- | project/native.scala | 207 | ||||
-rw-r--r-- | project/nativefat.scala.disabled | 47 |
31 files changed, 746 insertions, 249 deletions
diff --git a/flow-binaries/linux/amd64/libflow.so.1.0 b/flow-binaries/linux/amd64/libflow.so.1.0 Binary files differdeleted file mode 100644 index 8a02fed..0000000 --- a/flow-binaries/linux/amd64/libflow.so.1.0 +++ /dev/null diff --git a/flow-binaries/linux/amd64/libflow.so.1.1 b/flow-binaries/linux/amd64/libflow.so.1.1 Binary files differdeleted file mode 100644 index ed82d57..0000000 --- a/flow-binaries/linux/amd64/libflow.so.1.1 +++ /dev/null diff --git a/flow-binaries/linux/amd64/libflow.so.2.0 b/flow-binaries/linux/amd64/libflow.so.2.0 Binary files differdeleted file mode 100644 index 9d3912f..0000000 --- a/flow-binaries/linux/amd64/libflow.so.2.0 +++ /dev/null diff --git a/flow-binaries/linux/amd64/libflow.so.2.1 b/flow-binaries/linux/amd64/libflow.so.2.1 Binary files differdeleted file mode 100644 index 509e468..0000000 --- a/flow-binaries/linux/amd64/libflow.so.2.1 +++ /dev/null diff --git a/flow-binaries/linux/arm/libflow.so.2.1 b/flow-binaries/linux/arm/libflow.so.2.1 Binary files differdeleted file mode 100644 index 99a2672..0000000 --- a/flow-binaries/linux/arm/libflow.so.2.1 +++ /dev/null diff --git a/flow-binaries/linux/i386/libflow.so.2.1 b/flow-binaries/linux/i386/libflow.so.2.1 Binary files differdeleted file mode 100644 index 6e2a58f..0000000 --- a/flow-binaries/linux/i386/libflow.so.2.1 +++ /dev/null diff --git a/flow-binaries/macosx/x86_64/libflow.jnilib.1.1 b/flow-binaries/macosx/x86_64/libflow.jnilib.1.1 Binary files differdeleted file mode 100644 index 76961f0..0000000 --- a/flow-binaries/macosx/x86_64/libflow.jnilib.1.1 +++ /dev/null diff --git a/flow-binaries/macosx/x86_64/libflow.jnilib.2.0 b/flow-binaries/macosx/x86_64/libflow.jnilib.2.0 Binary files differdeleted file mode 100644 index e9076cd..0000000 --- a/flow-binaries/macosx/x86_64/libflow.jnilib.2.0 +++ /dev/null diff --git a/flow-binaries/macosx/x86_64/libflow.jnilib.2.1 b/flow-binaries/macosx/x86_64/libflow.jnilib.2.1 Binary files differdeleted file mode 100644 index 80d0fec..0000000 --- a/flow-binaries/macosx/x86_64/libflow.jnilib.2.1 +++ /dev/null diff --git a/flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/ConsoleReader.scala b/flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/ConsoleReader.scala index c4401e7..c4401e7 100644 --- a/flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/ConsoleReader.scala +++ b/flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/ConsoleReader.scala diff --git a/flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Main.scala b/flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Main.scala index 27686ce..27686ce 100644 --- a/flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Main.scala +++ b/flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Main.scala diff --git a/flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Terminal.scala b/flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Terminal.scala index 3c1eee6..3c1eee6 100644 --- a/flow-samples/terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Terminal.scala +++ b/flow-samples/flow-samples-terminal/src/main/scala/com/github/jodersky/flow/samples/terminal/Terminal.scala diff --git a/flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java b/flow/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java index 524803e..524803e 100644 --- a/flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java +++ b/flow/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java diff --git a/flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h b/flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h new file mode 100644 index 0000000..1c71688 --- /dev/null +++ b/flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h @@ -0,0 +1,79 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_github_jodersky_flow_internal_NativeSerial */ + +#ifndef _Included_com_github_jodersky_flow_internal_NativeSerial +#define _Included_com_github_jodersky_flow_internal_NativeSerial +#ifdef __cplusplus +extern "C" { +#endif +#undef com_github_jodersky_flow_internal_NativeSerial_E_IO +#define com_github_jodersky_flow_internal_NativeSerial_E_IO -1L +#undef com_github_jodersky_flow_internal_NativeSerial_E_ACCESS_DENIED +#define com_github_jodersky_flow_internal_NativeSerial_E_ACCESS_DENIED -2L +#undef com_github_jodersky_flow_internal_NativeSerial_E_BUSY +#define com_github_jodersky_flow_internal_NativeSerial_E_BUSY -3L +#undef com_github_jodersky_flow_internal_NativeSerial_E_INVALID_SETTINGS +#define com_github_jodersky_flow_internal_NativeSerial_E_INVALID_SETTINGS -4L +#undef com_github_jodersky_flow_internal_NativeSerial_E_INTERRUPT +#define com_github_jodersky_flow_internal_NativeSerial_E_INTERRUPT -5L +#undef com_github_jodersky_flow_internal_NativeSerial_E_NO_PORT +#define com_github_jodersky_flow_internal_NativeSerial_E_NO_PORT -6L +#undef com_github_jodersky_flow_internal_NativeSerial_PARITY_NONE +#define com_github_jodersky_flow_internal_NativeSerial_PARITY_NONE 0L +#undef com_github_jodersky_flow_internal_NativeSerial_PARITY_ODD +#define com_github_jodersky_flow_internal_NativeSerial_PARITY_ODD 1L +#undef com_github_jodersky_flow_internal_NativeSerial_PARITY_EVEN +#define com_github_jodersky_flow_internal_NativeSerial_PARITY_EVEN 2L +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: open + * Signature: (Ljava/lang/String;IIZI[J)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_open + (JNIEnv *, jclass, jstring, jint, jint, jboolean, jint, jlongArray); + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: read + * Signature: (J[B)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_read + (JNIEnv *, jclass, jlong, jbyteArray); + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: write + * Signature: (J[B)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_write + (JNIEnv *, jclass, jlong, jbyteArray); + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: interrupt + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_interrupt + (JNIEnv *, jclass, jlong); + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: close + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_close + (JNIEnv *, jclass, jlong); + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: debug + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_debug + (JNIEnv *, jclass, jboolean); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/flow-native/shared/include/flow.h b/flow/src/main/native/include/flow.h index ebb845a..ebb845a 100644 --- a/flow-native/shared/include/flow.h +++ b/flow/src/main/native/include/flow.h diff --git a/flow-native/unix/src/flow.c b/flow/src/main/native/posix/flow.c index caf7b9b..caf7b9b 100644 --- a/flow-native/unix/src/flow.c +++ b/flow/src/main/native/posix/flow.c diff --git a/flow/src/main/native/windows/README b/flow/src/main/native/windows/README new file mode 100644 index 0000000..3d24410 --- /dev/null +++ b/flow/src/main/native/windows/README @@ -0,0 +1 @@ +The contents of the file flow.c were found in the avrdude project. They look like they may be a good starting point for serial communication on windows. diff --git a/flow/src/main/native/windows/flow.c.disabled b/flow/src/main/native/windows/flow.c.disabled new file mode 100644 index 0000000..86a267c --- /dev/null +++ b/flow/src/main/native/windows/flow.c.disabled @@ -0,0 +1,416 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de> + * Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* $Id$ */ + +/* + * Native Win32 serial interface for avrdude. + */ + +#include "avrdude.h" + +#if defined(WIN32NATIVE) + +#include <windows.h> +#include <stdio.h> +#include <ctype.h> /* for isprint */ + +#include "serial.h" + +long serial_recv_timeout = 5000; /* ms */ + +#define W32SERBUFSIZE 1024 + +struct baud_mapping { + long baud; + DWORD speed; +}; + +/* HANDLE hComPort=INVALID_HANDLE_VALUE; */ + +static struct baud_mapping baud_lookup_table [] = { + { 1200, CBR_1200 }, + { 2400, CBR_2400 }, + { 4800, CBR_4800 }, + { 9600, CBR_9600 }, + { 19200, CBR_19200 }, + { 38400, CBR_38400 }, + { 57600, CBR_57600 }, + { 115200, CBR_115200 }, + { 0, 0 } /* Terminator. */ +}; + +static DWORD serial_baud_lookup(long baud) +{ + struct baud_mapping *map = baud_lookup_table; + + while (map->baud) { + if (map->baud == baud) + return map->speed; + map++; + } + + /* + * If a non-standard BAUD rate is used, issue + * a warning (if we are verbose) and return the raw rate + */ + if (verbose > 0) + fprintf(stderr, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld", + progname, baud); + + return baud; +} + + +static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms +{ + COMMTIMEOUTS ctmo; + ZeroMemory (&ctmo, sizeof(COMMTIMEOUTS)); + ctmo.ReadIntervalTimeout = timeout; + ctmo.ReadTotalTimeoutMultiplier = timeout; + ctmo.ReadTotalTimeoutConstant = timeout; + + return SetCommTimeouts(hComPort, &ctmo); +} + +static int ser_setspeed(union filedescriptor *fd, long baud) +{ + DCB dcb; + HANDLE hComPort = (HANDLE)fd->pfd; + + ZeroMemory (&dcb, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = serial_baud_lookup (baud); + dcb.fBinary = 1; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + + if (!SetCommState(hComPort, &dcb)) + return -1; + + return 0; +} + + +static int ser_open(char * port, long baud, union filedescriptor *fdp) +{ + LPVOID lpMsgBuf; + HANDLE hComPort=INVALID_HANDLE_VALUE; + char *newname = 0; + + /* + * If the port is of the form "net:<host>:<port>", then + * handle it as a TCP connection to a terminal server. + * + * This is curently not implemented for Win32. + */ + if (strncmp(port, "net:", strlen("net:")) == 0) { + fprintf(stderr, + "%s: ser_open(): network connects are currently not" + "implemented for Win32 environments\n", + progname); + return -1; + } + + if (strncasecmp(port, "com", strlen("com")) == 0) { + + // prepend "\\\\.\\" to name, required for port # >= 10 + newname = malloc(strlen("\\\\.\\") + strlen(port) + 1); + + if (newname == 0) { + fprintf(stderr, + "%s: ser_open(): out of memory\n", + progname); + exit(1); + } + strcpy(newname, "\\\\.\\"); + strcat(newname, port); + + port = newname; + } + + hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hComPort == INVALID_HANDLE_VALUE) { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n", + progname, port, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + return -1; + } + + if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set buffers for \"%s\"\n", + progname, port); + return -1; + } + + fdp->pfd = (void *)hComPort; + if (ser_setspeed(fdp, baud) != 0) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set com-state for \"%s\"\n", + progname, port); + return -1; + } + + if (!serial_w32SetTimeOut(hComPort,0)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: ser_open(): can't set initial timeout for \"%s\"\n", + progname, port); + return -1; + } + + if (newname != 0) { + free(newname); + } + return 0; +} + + +static void ser_close(union filedescriptor *fd) +{ + HANDLE hComPort=(HANDLE)fd->pfd; + if (hComPort != INVALID_HANDLE_VALUE) + CloseHandle (hComPort); + + hComPort = INVALID_HANDLE_VALUE; +} + +static int ser_set_dtr_rts(union filedescriptor *fd, int is_on) +{ + HANDLE hComPort=(HANDLE)fd->pfd; + + if (is_on) { + EscapeCommFunction(hComPort, SETDTR); + EscapeCommFunction(hComPort, SETRTS); + } else { + EscapeCommFunction(hComPort, CLRDTR); + EscapeCommFunction(hComPort, CLRRTS); + } + return 0; +} + + +static int ser_send(union filedescriptor *fd, unsigned char * buf, size_t buflen) +{ + size_t len = buflen; + unsigned char c='\0'; + DWORD written; + unsigned char * b = buf; + + HANDLE hComPort=(HANDLE)fd->pfd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: ser_send(): port not open\n", + progname); + exit(1); + } + + if (!len) + return 0; + + if (verbose > 3) + { + fprintf(stderr, "%s: Send: ", progname); + + while (len) { + c = *b; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + b++; + len--; + } + fprintf(stderr, "\n"); + } + + serial_w32SetTimeOut(hComPort,500); + + if (!WriteFile (hComPort, buf, buflen, &written, NULL)) { + fprintf(stderr, "%s: ser_send(): write error: %s\n", + progname, "sorry no info avail"); // TODO + exit(1); + } + + if (written != buflen) { + fprintf(stderr, "%s: ser_send(): size/send mismatch\n", + progname); + exit(1); + } + + return 0; +} + + +static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen) +{ + unsigned char c; + unsigned char * p = buf; + DWORD read; + + HANDLE hComPort=(HANDLE)fd->pfd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: ser_read(): port not open\n", + progname); + exit(1); + } + + serial_w32SetTimeOut(hComPort, serial_recv_timeout); + + if (!ReadFile(hComPort, buf, buflen, &read, NULL)) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + fprintf(stderr, "%s: ser_recv(): read error: %s\n", + progname, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + exit(1); + } + + /* time out detected */ + if (read == 0) { + if (verbose > 1) + fprintf(stderr, + "%s: ser_recv(): programmer is not responding\n", + progname); + return -1; + } + + p = buf; + + if (verbose > 3) + { + fprintf(stderr, "%s: Recv: ", progname); + + while (read) { + c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + read--; + } + fprintf(stderr, "\n"); + } + return 0; +} + + +static int ser_drain(union filedescriptor *fd, int display) +{ + // int rc; + unsigned char buf[10]; + BOOL readres; + DWORD read; + + HANDLE hComPort=(HANDLE)fd->pfd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: ser_drain(): port not open\n", + progname); + exit(1); + } + + serial_w32SetTimeOut(hComPort,250); + + if (display) { + fprintf(stderr, "drain>"); + } + + while (1) { + readres=ReadFile(hComPort, buf, 1, &read, NULL); + if (!readres) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + fprintf(stderr, "%s: ser_drain(): read error: %s\n", + progname, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + exit(1); + } + + if (read) { // data avail + if (display) fprintf(stderr, "%02x ", buf[0]); + } + else { // no more data + if (display) fprintf(stderr, "<drain\n"); + break; + } + } // while + return 0; +} + +struct serial_device serial_serdev = +{ + .open = ser_open, + .setspeed = ser_setspeed, + .close = ser_close, + .send = ser_send, + .recv = ser_recv, + .drain = ser_drain, + .set_dtr_rts = ser_set_dtr_rts, + .flags = SERDEV_FL_CANSETSPEED, +}; + +struct serial_device *serdev = &serial_serdev; + +#endif /* WIN32NATIVE */ diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/Parity.scala b/flow/src/main/scala/com/github/jodersky/flow/Parity.scala index 9bf52a6..9bf52a6 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/Parity.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/Parity.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala b/flow/src/main/scala/com/github/jodersky/flow/Serial.scala index abc8f39..abc8f39 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/Serial.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/SerialExt.scala b/flow/src/main/scala/com/github/jodersky/flow/SerialExt.scala index 826a4e9..826a4e9 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/SerialExt.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/SerialExt.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala b/flow/src/main/scala/com/github/jodersky/flow/SerialManager.scala index b3128ac..b3128ac 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/SerialManager.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala b/flow/src/main/scala/com/github/jodersky/flow/SerialOperator.scala index 3ac50c0..3ac50c0 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/SerialOperator.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/SerialSettings.scala b/flow/src/main/scala/com/github/jodersky/flow/SerialSettings.scala index a3bc5e4..a3bc5e4 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/SerialSettings.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/SerialSettings.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/exceptions.scala b/flow/src/main/scala/com/github/jodersky/flow/exceptions.scala index 5923ba6..5923ba6 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/exceptions.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/exceptions.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/internal/InternalSerial.scala b/flow/src/main/scala/com/github/jodersky/flow/internal/InternalSerial.scala index e69f91a..e69f91a 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/internal/InternalSerial.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/internal/InternalSerial.scala diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/internal/NativeLoader.scala b/flow/src/main/scala/com/github/jodersky/flow/internal/NativeLoader.scala index 81f51b4..034be96 100644 --- a/flow-main/src/main/scala/com/github/jodersky/flow/internal/NativeLoader.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/internal/NativeLoader.scala @@ -14,7 +14,7 @@ object NativeLoader { val arch = System.getProperty("os.arch").toLowerCase val fqlib = System.mapLibraryName("flow") //fully qualified library name - val in = NativeLoader.getClass().getResourceAsStream(s"/native/${os}/${arch}/${fqlib}") + val in = NativeLoader.getClass().getResourceAsStream(s"/native/${arch}-${os}/${fqlib}") if (in == null) return None val temp = Path.createTempFile() diff --git a/project/FlowBuild.scala b/project/FlowBuild.scala index 087ff6f..fcf4d10 100644 --- a/project/FlowBuild.scala +++ b/project/FlowBuild.scala @@ -1,21 +1,25 @@ import sbt._ import Keys._ - -import NativeKeys._ -import NativeDefaults._ import JniKeys._ +import NativeKeys._ object FlowBuild extends Build { val Organization = "com.github.jodersky" - val Version = "1.0.1-SNAPSHOT" //version of flow library - val BinaryMajorVersion = 2 //binary major version used to select shared libraries when publishing (needs to be incremented if API changes are made to flow.h or NativeSerial.java) val ScalaVersion = "2.10.3" - //see native settings down below + val Version = "1.1.1" //version of flow library + val NativeMajorVersion = 2 //major version of native API + val NativeMinorVersionPosix = 0 //minor version of native posix implementation + val NativeVersionPosix = NativeMajorVersion + "." + NativeMinorVersionPosix + + val release = settingKey[Boolean]("Indicates if this build is a release.") + val gitHeadCommitSha = settingKey[String]("Current commit sha.") lazy val commonSettings: Seq[Setting[_]] = Seq( organization := Organization, - version := Version, scalaVersion := ScalaVersion, + release in ThisBuild := sys.props("release") == true, + gitHeadCommitSha in ThisBuild := Process("git rev-parse HEAD").lines.head, + version in ThisBuild:= { if (release.value ) Version else Version + "-" + gitHeadCommitSha.value }, licenses := Seq(("BSD-3-Clause", url("http://opensource.org/licenses/BSD-3-Clause"))), resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/", scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature")) @@ -25,138 +29,106 @@ object FlowBuild extends Build { connectInput in run := true, outputStrategy := Some(StdoutOutput) ) + + lazy val root: Project = ( + Project("root", file(".")).aggregate(flow) + settings( + publish := (), + publishLocal := () + ) + ) - lazy val main: Project = ( - Project("flow", file("flow-main")) + lazy val flow: Project = ( + Project("flow", file("flow")) settings (commonSettings: _*) - settings ( + settings (JniDefaults.settings: _*) + settings (NativeDefaults.settings: _*) + settings (selectHost().settings: _*) + settings( + nativeIncludeDirectories += (sourceDirectory in Compile).value / "native" / "include", + nativeIncludeDirectories ++= jdkHome.value.map(jdk => jdk / "include").toSeq, + javahClasses := Seq("com.github.jodersky.flow.internal.NativeSerial"), + javahHeaderDirectory := (sourceDirectory in Compile).value / "native" / "include", + compileOrder in Compile := CompileOrder.Mixed, libraryDependencies ++= Seq( Dependencies.akkaActor, Dependencies.ioCore, - Dependencies.ioFile), - compileOrder in Compile := CompileOrder.Mixed, - resourceGenerators in Compile <+= (resourceManaged in Compile, binariesDirectory in ThisBuild) map { (resDir, binDir) => - val binaries: Seq[(File, File)] = getLatestBinaries(binDir, BinaryMajorVersion) - val resources = for (binary <- binaries) yield { - val versionedBinary = binary._1 - val unversionedBinary = binary._2 - - val relative = (unversionedBinary relativeTo binDir).get.getPath - - val resource = resDir / "native" / relative - IO.copyFile(versionedBinary, resource) - resource - } - resources - } + Dependencies.ioFile) ) ) - //returns latest, major version-compatible binaries for every OS and architecture combination - //tuples returned (file with binary version appended, file without version string) - def getLatestBinaries(base: File, majorVersion: Int): Seq[(File, File)] = { - def latest(platform: File) = { - val Pattern = "(.+)\\.(\\d+)\\.(\\d+)".r - val MajorVersion = majorVersion.toString - val majorCompatible = platform.listFiles.map(_.getAbsolutePath) collect { - case path @ Pattern(strippedPath, MajorVersion, minorVersion) => (path, strippedPath, minorVersion) - } - val latestMinor = majorCompatible.sortBy(_._3).lastOption - latestMinor map { case (path, strippedPath, _) => - (file(path), file(strippedPath)) - } - } - - val oSs = IO.listFiles(base).filter(file => !file.name.startsWith(".")) - val platforms = oSs.flatMap(_.listFiles) - - platforms.flatMap(latest(_)) - } - lazy val samplesTerminal = ( - Project("flow-samples-terminal", file("flow-samples") / "terminal") + Project("flow-samples-terminal", file("flow-samples") / "flow-samples-terminal") settings(commonSettings: _*) settings(runSettings: _*) - dependsOn(main) - ) - - - //--- native settings and projects -------------------------------------------------- - - val binariesDirectory = settingKey[File]("Directory containing published native binaries.") - override lazy val settings = super.settings ++ Seq( - (binariesDirectory in ThisBuild) := (baseDirectory in ThisBuild).value / "flow-binaries" + dependsOn(flow) ) - - def canonicalBinaryPath(base: File, binaryName: String) = { - base / sys.props("os.name").toLowerCase.filter(_ != ' ') / sys.props("os.arch").toLowerCase / binaryName - } - val publishNative = taskKey[File]("Publish native binary compiled on current OS to flow-binaries project so that it may be packaged in a distribution of flow.") - val publishNativeImpl = Def.task{ - val in = (link in Native).value - val out = canonicalBinaryPath((binariesDirectory in ThisBuild).value, in.getName) - IO.copyFile(in, out) - out - } - lazy val commonNativeSettings: Seq[Setting[_]] = Seq( - nativeSource in Native := baseDirectory.value / "src", - includeDirectories in Native += file("flow-native") / "shared" / "include", - nativeCompile in Native := ((nativeCompile in Native) dependsOn (compile in Compile in main)).value, - publishNative := publishNativeImpl.value, - javahClasspath := Seq((classDirectory in Compile in main).value), - javahClasses := Seq("com.github.jodersky.flow.internal.NativeSerial")) ++ JniDefaults.defaultSettings - - //--- native unix-like settings and projects ---------------------------------------- - - val UnixBinaryMinorVersion = 1 - - lazy val unixNativeSettings: Seq[Setting[_]] = commonNativeSettings ++ Seq( - flags in Native := Seq("-fPIC", "-O2") + //the current operating system used to run the native compile + trait Host{ def settings: Seq[Setting[_]] } + + object Linux extends Host { + + val compiler = "gcc" + val linker = compiler + val cFlags = Seq("-O2", "-fPIC") + val linkerFlags = Seq("-shared", s"-Wl,-soname,libflow.so.${NativeMajorVersion}") + val binary = s"libflow.so" + + val builds = List( + NativeBuild("amd64-linux", "gcc", cFlags :+ "-m64", "gcc", linkerFlags :+ "-m64", binary), + NativeBuild("x86-linux", "gcc", cFlags :+ "-m32", "gcc", linkerFlags :+ "-m32", binary), + NativeBuild("arm-linux", "arm-linux-gnueabi-gcc", cFlags, "arm-linux-gnueabi-gcc", linkerFlags, binary) + //add other build configurations here or adapt existing ones to your needs ) - lazy val nativeLinux = ( - NativeProject("flow-native-linux", file("flow-native") / "unix") - settings (unixNativeSettings: _*) - settings ( - target := baseDirectory.value / "target" / "linux", - includeDirectories in Native ++= jdkHome.value.map(jdk => jdk / "include" / "linux").toSeq, - linkFlags in Native ++= Seq("-shared", s"-Wl,-soname,libflow.so.${BinaryMajorVersion}"), - binaryName in Native := s"libflow.so.${BinaryMajorVersion}.${UnixBinaryMinorVersion}" + lazy val settings = Seq( + nativeVersion := NativeVersionPosix, + nativeIncludeDirectories ++= jdkHome.value.map(jdk => jdk / "include" / "linux").toSeq, + nativeSource := nativeSource.value / "posix", + nativeBuilds := builds ) - dependsOn(main) - ) - - lazy val nativeMacOSX = ( - NativeProject("flow-native-macosx", file("flow-native") / "unix") - settings (unixNativeSettings: _*) - settings ( - target := baseDirectory.value / "target" / "macosx", - includeDirectories in Native += file("/System/Library/Frameworks/JavaVM.framework/Headers/jni.h"), - includeDirectories in Native += file("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers"), - linkFlags in Native ++= Seq("-dynamiclib"), - binaryName in Native := s"libflow.jnilib.${BinaryMajorVersion}.${UnixBinaryMinorVersion}" + + } + + //stub, not sure if this works + object MacOSX extends Host { + + val compiler = "gcc" + val linker = compiler + val cFlags = Seq("-O2", "-fPIC") + val linkerFlags = Seq("-dynamiclib") + val binary = s"libflow.jnilib" + + val localBuild = NativeBuild( + "amd64-macosx", + compiler, + cFlags, + linker, + linkerFlags, + binary ) - dependsOn (main) - ) - - - /* stub for native project on windows, I don't know if this would actually work... - * - * val WindowsBinaryMinorVersion = 0 - * - lazy val nativeWindows = ( - NativeProject("flow-native-windows", file("flow-native") / "windows") - settings ( - //windows is not a unix-like OS, several default settings need to be changed - cCompiler in Native := "???", - flags in Native := Seq("-fPIC", "-O2"), - linkFlags in Native ++= ???, - binaryName in Native := s"flow.dll.${BinaryMajorVersion}.${WindowsBinaryMinorVersion}" - includeDirectories in Native += jdkHome.value / "include" / "windows" + + lazy val settings = Seq( + nativeVersion := NativeVersionPosix, + nativeIncludeDirectories += file("/System/Library/Frameworks/JavaVM.framework/Headers/jni.h"), + nativeIncludeDirectories += file("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers"), + nativeSource := nativeSource.value / "posix", + nativeBuilds := Seq(localBuild) ) - dependsOn (main) - )*/ - + + } + + private def osError = throw new RuntimeException("Sorry, native compilation under the current OS is not supported.") + def selectHost() = System.getProperty("os.name").toLowerCase match { + case "linux" => Linux + case "macosx" => MacOSX + case _ => new Host{ + val settings = Seq( + nativeCompile := osError, + nativeLink := osError + ) + } + } } diff --git a/project/jni.scala b/project/jni.scala index 5e248f2..e87f0c7 100644 --- a/project/jni.scala +++ b/project/jni.scala @@ -1,11 +1,9 @@ import sbt._ import Keys._ -import NativeKeys._ import scala.util.Try object JniKeys { val jdkHome = settingKey[Option[File]]("Home of JDK.") - val jdkHomeNotFound = taskKey[Unit]("Utility task that informs user that no JDK was found.") val javahHeaderDirectory = settingKey[File]("Directory where generated javah header files are placed.") val javahClasses = settingKey[Seq[String]]("Fully qualified names of classes containing native declarations.") val javahClasspath = taskKey[Seq[File]]("Classpath to use in javah.") @@ -15,27 +13,16 @@ object JniKeys { object JniDefaults { import JniKeys._ - val defaultSettings: Seq[Setting[_]] = Seq( + val settings: Seq[Setting[_]] = Seq( jdkHome := Try(file(sys.env("JAVA_HOME"))).toOption, - jdkHomeNotFound := jdkHomeNotFoundImpl.value, - nativeCompile in Native := ((nativeCompile in Native) dependsOn jdkHomeNotFound).value, - javahHeaderDirectory := (sourceManaged in Native).value / "javah", - javah := javahImpl.value, - sourceGenerators in Native <+= javah map { headers => headers}, - includeDirectories in Native += javahHeaderDirectory.value, - includeDirectories in Native ++= jdkHome.value.map( jdk => jdk / "include").toSeq) + javahHeaderDirectory := baseDirectory.value, + javahClasspath := Seq((classDirectory in Compile).value), + javah := javahImpl.value + ) - def jdkHomeNotFoundImpl = Def.task { - if (jdkHome.value == None) { - streams.value.log.warn( - "No JDK home directory found, any native code using JNI may not compile. Please set JAVA_HOME environment variable.") - } - () - } - def javahImpl = Def.task { - val cps = javahClasspath.value - val cp = cps.mkString(":") + val jcp = javahClasspath.value + val cp = jcp.mkString(":") for (clazz <- javahClasses.value) { val parts = Seq( "javah", diff --git a/project/native.scala b/project/native.scala index 5c84f11..68c970e 100644 --- a/project/native.scala +++ b/project/native.scala @@ -3,32 +3,35 @@ import Keys._ import java.io.File import scala.collection.mutable.HashSet +case class NativeBuild( + name: String, + cCompiler: String, + cFlags: Seq[String], + linker: String, + linkerFlags: Seq[String], + binary: String) + object NativeKeys { - val Native = config("native") - - //compilation - val cCompiler = settingKey[String]("Default c compiler.") - val cppCompiler = settingKey[String]("Default c++ comppiler.") - val cFlags = settingKey[Seq[String]]("Default flags for c compiler.") - val cppFlags = settingKey[Seq[String]]("Default flags for c++ compiler.") - val flags = settingKey[Seq[String]]("Default flags prepended to c and c++ flags.") - val nativeCompile = taskKey[Seq[File]]("Compile native sources.") - - val linker = settingKey[String]("Linker used in project.") - val linkFlags = settingKey[Seq[String]]("Default options for linker.") - val libraryNames = settingKey[Seq[String]]("Default names of libraries to use during linking.") - val binaryName = settingKey[String]("Final binary product.") - val link = taskKey[File]("Link compiled objects to a final product.") + //build settings + val nativeBuilds = taskKey[Seq[NativeBuild]]("All native build configurations, including cross-compilation.") + val nativeVersion = settingKey[String]("Version of native binary") + //compile settings + val nativeIncludeDirectories = settingKey[Seq[File]]("Directories to include during build (gcc -I option)") + + //link settings + val nativeLibraries = settingKey[Seq[String]]("Default names of libraries to use during linking.") + val nativeLibraryDirectories = settingKey[Seq[File]]("Directories to search for libraries (gcc -L option)") + //directories val nativeSource = settingKey[File]("Lowest level directory containing all native sources.") - val cSources = taskKey[Seq[File]]("All c source files, managed and unmanaged.") - val cppSources = taskKey[Seq[File]]("All c++ source files, managed and unmanaged.") - val includeDirectories = settingKey[Seq[File]]("Directories to include during build (gcc -I option)") - val libraryDirectories = settingKey[Seq[File]]("Directories to search for libraries (gcc -L option)") - val objectDirectory = settingKey[File]("Directory containing all compiled objects.") - //val objects = taskKey[Seq[File]]("Object files generated from source files. Note: there should be a one-to-one mapping between source and object files.") + val nativeCSources = taskKey[Seq[File]]("All c source files.") + val nativeTargetDirectory = settingKey[File]("Directory containing all compiled and linked files.") + + //tasks + val nativeCompile = taskKey[Map[NativeBuild, Seq[File]]]("Compile all native build configurations.") + val nativeLink = taskKey[Map[NativeBuild, File]]("Link all native build configurations.") } @@ -37,102 +40,94 @@ object NativeDefaults { private def generate(generators: SettingKey[Seq[Task[Seq[File]]]]) = generators { _.join.map(_.flatten) } - def compileImpl = Def.task { - implicit val log = streams.value.log - - def compile(compiler: String, flags: Seq[String], src: File) = { - val obj = objectDirectory.value / (src.base + ".o") - IO.createDirectory(obj.getParentFile()) - val parts: Seq[String] = Seq(compiler) ++ - flags ++ - includeDirectories.value.map("-I" + _.getAbsolutePath) ++ - Seq("-o", obj.getAbsolutePath()) ++ - Seq("-c", src.getAbsolutePath()) - - val cmd = parts.mkString(" ") - log.info(cmd) - val ev = Process(cmd) ! log - if (ev != 0) throw new RuntimeException(s"compilation of ${src.getAbsoluteFile()} failed") - obj - } + private def compile(logger: Logger, compiler: String, flags: Seq[String], includeDirectories: Seq[File], src: File, out: File): File = { + IO.createDirectory(out.getParentFile) + val parts: Seq[String] = + Seq(compiler) ++ + flags ++ + includeDirectories.map("-I" + _.getAbsolutePath) ++ + Seq("-o", out.getAbsolutePath) ++ + Seq("-c", src.getAbsolutePath) - cSources.value.map { src => - compile(cCompiler.value, cFlags.value, src) - } ++ - cppSources.value.map { src => - compile(cppCompiler.value, cppFlags.value, src) - } + val cmd = parts.mkString(" ") + logger.info(cmd) + val ev = Process(cmd) ! logger + if (ev != 0) throw new RuntimeException(s"Compilation of ${src.getAbsoluteFile()} failed.") + out } - def linkImpl = Def.task { - implicit val log = streams.value.log - - val out = (target.value / binaryName.value) - val parts: Seq[String] = Seq(linker.value) ++ - linkFlags.value ++ + private def link(logger: Logger, linker: String, flags: Seq[String], libraryDirectories: Seq[File], libraries: Seq[String], in: Seq[File], out: File): File = { + val parts: Seq[String] = + Seq(linker) ++ + flags ++ Seq("-o", out.getAbsolutePath) ++ - nativeCompile.value.map(_.getAbsolutePath) ++ - libraryDirectories.value.map("-L" + _.getAbsolutePath) ++ - libraryNames.value.map("-l" + _) + in.map(_.getAbsolutePath) ++ + libraryDirectories.map("-L" + _.getAbsolutePath) ++ + libraries.map("-l" + _) val cmd = parts.mkString(" ") - log.info(cmd) - val ev = Process(cmd) ! log - if (ev != 0) throw new RuntimeException(s"linking of ${out.getAbsoluteFile()} failed") + logger.info(cmd) + val ev = Process(cmd) ! logger + if (ev != 0) throw new RuntimeException(s"Linking of ${out.getAbsoluteFile()} failed.") out } - val compileSettings: Seq[Setting[_]] = inConfig(Native)(Seq( - cCompiler := "gcc", - cppCompiler := "g++", - cFlags := flags.value, - cppFlags := flags.value, - flags := Seq("-fPIC", "-O2"), - nativeCompile := compileImpl.value, - sourceGenerators := Seq())) - - val linkSettings: Seq[Setting[_]] = inConfig(Native)(Seq( - linker := "gcc", - linkFlags := Seq(), - libraryNames := Seq(), - binaryName := binaryName.value, - link := linkImpl.value)) - - val fileSettings: Seq[Setting[_]] = inConfig(Native)(Seq( - target := (target in Compile).value / "native", - nativeSource := (sourceDirectory in Compile).value / "native", - sourceManaged := target.value / "src_managed", - unmanagedSources := (nativeSource.value ** (includeFilter in unmanagedSources).value).get, - managedSources := (generate(sourceGenerators).value ** (includeFilter in managedSources).value).get, - sources := unmanagedSources.value ++ managedSources.value, - cSources := sources.value.filter(src => (includeFilter in cSources).value accept src), - cppSources := sources.value.filter(src => (includeFilter in cppSources).value accept src), - includeFilter in (unmanagedSources) := ("*.c" || "*.cpp" || "*.cxx" || "*.cc"), - includeFilter in (managedSources) := (includeFilter in unmanagedSources).value, - includeFilter in cSources := "*.c", - includeFilter in cppSources := "*.cpp" || "*.cc" || "*.cxx", - objectDirectory := target.value / "objects", - includeDirectories := Seq(nativeSource.value, sourceManaged.value), - libraryDirectories := Seq(), - binaryName := (name in Compile).value)) - - val defaultSettings: Seq[Setting[_]] = inConfig(Native)( - compileSettings ++ - linkSettings ++ - fileSettings) - - implicit class RichNativeProject(project: Project) { - def dependsOnNative(other: Project): Project = { - val newSettings: Seq[Setting[_]] = inConfig(Native)(Seq( - link in project := ((link in project) dependsOn (link in other)).value, - includeDirectories in project ++= (includeDirectories in other).value, - libraryDirectories in project += (target in other).value - )) - project.settings(newSettings: _*) + + def nativeCompileImpl() = Def.task { + val logger = streams.value.log + val builds = nativeBuilds.value + val outDir = nativeTargetDirectory.value + val includeDirs = nativeIncludeDirectories.value + val csrcs = nativeCSources.value + + val compilations = for (build <- builds) yield { + logger.info("Compiling configuration " + build.name) + val objects = for (src <- csrcs) yield { + compile(logger, build.cCompiler, build.cFlags, includeDirs, src, outDir / build.name / "objects" / (src.base + ".o")) + } + build -> objects + } + compilations.toMap + } + + lazy val nativeLinkImpl = Def.task { + val logger = streams.value.log + val builds = nativeBuilds.value + val outDir = nativeTargetDirectory.value + val libDirs = nativeLibraryDirectories.value + val libs = nativeLibraries.value + val compilations = nativeCompile.value + val version = nativeVersion.value + + val linkages = for (build <- builds) yield { + logger.info("Linking configuration " + build.name) + val objects = compilations(build) + val binary = link(logger, build.linker, build.linkerFlags, libDirs, libs, objects, outDir / build.name / build.binary) + build -> binary } - + linkages.toMap } - def NativeProject(id: String, base: File) = Project(id, base).settings(NativeDefaults.defaultSettings: _*) + def localPlatform = try { + Process("gcc -dumpmachine").lines.headOption + } catch { + case ex: Exception => None + } + + + val settings: Seq[Setting[_]] = Seq( + //nativeBuilds := + + nativeSource := (sourceDirectory in Compile).value / "native", + includeFilter in nativeCSources := "*.c", + nativeCSources := (nativeSource.value ** (includeFilter in nativeCSources).value).get, + nativeTargetDirectory := target.value / "native", + + nativeIncludeDirectories := Seq(nativeSource.value, nativeSource.value / "include"), + nativeLibraries := Seq(), + nativeLibraryDirectories := Seq(), + nativeCompile := nativeCompileImpl.value, + nativeLink := nativeLinkImpl.value + ) } diff --git a/project/nativefat.scala.disabled b/project/nativefat.scala.disabled new file mode 100644 index 0000000..e1cfcd3 --- /dev/null +++ b/project/nativefat.scala.disabled @@ -0,0 +1,47 @@ +import sbt._ +import Keys._ +import NativeKeys._ +import java.io.File +import scala.collection.mutable.HashSet + +object NativeFatKeys { + + val NativeFat = config("nativeFat") + + +} + +object NativeFatDefaults { + import NativeFatKeys._ + + def highest(files: Seq[File], separator: String) = { + files.sortBy{f => + f.getName.split(separator) match { + case Array(name, version) => version + case _ => throw new RuntimeException("Error parsing file version string: " + f.getName) + } + }.last + } + + val gen = taskKey[Seq[File]]("") + + val genImpl = Def.task { + val resDir = (resourceManaged).value + val binDir = nativeTargetDirectory.value + val binarises = nativeLink.value + + val resources = for ((_, binary) <- binarises) yield { + val relative = (binary relativeTo binDir).get.getPath + val resource = resDir / "native" / relative + IO.copyFile(binary, resource) + resource + } + resources.toSeq + } + + val settings = Seq( + gen := genImpl.value, + resourceGenerators in NativeFat := Seq(genImpl) + ) + +}
\ No newline at end of file |