1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-22 21:23:16 +00:00

Add API version checking for modules.

Checking now actively implemented for dynamic modules
in a fully backwards compatible way.
This commit is contained in:
Calvin Rose 2019-05-29 21:57:03 -04:00
parent c8c6419013
commit bcbe42ab23
5 changed files with 66 additions and 25 deletions

View File

@ -1,6 +1,10 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## Unreleased
- Add API compatibility checking for modules. This will let native modules not load
when the host program is not of a compatible version or configuration.
## 0.6.0 - 2019-05-29 ## 0.6.0 - 2019-05-29
- `file/close` returns exit code when closing file opened with `file/popen`. - `file/close` returns exit code when closing file opened with `file/popen`.
- Add `os/rename` - Add `os/rename`

View File

@ -26,14 +26,15 @@
#include "fiber.h" #include "fiber.h"
#endif #endif
static JanetBuildConfig *api_build_config = &(JanetBuildConfig) { static const JanetBuildConfig api_build_config = (JanetBuildConfig) {
.api_version = JANET_API_VERSION, JANET_VERSION_MAJOR,
.single_threaded = JANET_SINGLE_THREADED_BIT, JANET_VERSION_MINOR,
.nanbox = JANET_NANBOX_BIT JANET_VERSION_PATCH,
JANET_CURRENT_CONFIG_BITS
}; };
const JanetBuildConfig *janet_build_config() { const JanetBuildConfig *janet_config_host(void) {
return api_build_config; return &api_build_config;
} }
void janet_panicv(Janet message) { void janet_panicv(Janet message) {

View File

@ -63,7 +63,30 @@ JanetModule janet_native(const char *name, const uint8_t **error) {
} }
init = (JanetModule) symbol_clib(lib, "_janet_init"); init = (JanetModule) symbol_clib(lib, "_janet_init");
if (!init) { if (!init) {
*error = janet_cstring("could not find _janet_init symbol"); *error = janet_cstring("could not find the _janet_init symbol");
return NULL;
}
JanetBuildConfig(*modconf_getter)(void) = symbol_clib(lib, "_janet_mod_config");
if (!modconf_getter) {
*error = janet_cstring("could not find the _janet_mod_config symbol");
return NULL;
}
JanetBuildConfig modconf = modconf_getter();
JanetBuildConfig host = janet_config_current();
if (host.major != modconf.major ||
host.minor < modconf.minor ||
host.bits != modconf.bits) {
char errbuf[128];
sprintf(errbuf, "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)",
host.major,
host.minor,
host.patch,
host.bits,
modconf.major,
modconf.minor,
modconf.patch,
modconf.bits);
*error = janet_cstring(errbuf);
return NULL; return NULL;
} }
return init; return init;
@ -830,6 +853,9 @@ JanetTable *janet_core_env(JanetTable *replacements) {
JDOC("The version number of the running janet program.")); JDOC("The version number of the running janet program."));
janet_def(env, "janet/build", janet_cstringv(JANET_BUILD), janet_def(env, "janet/build", janet_cstringv(JANET_BUILD),
JDOC("The build identifier of the running janet program.")); JDOC("The build identifier of the running janet program."));
janet_def(env, "janet/config-bits", janet_wrap_integer(JANET_CURRENT_CONFIG_BITS),
JDOC("The flag set of config options from janetconf.h which is used to check "
"if native modules are compatible with the host program."));
/* Allow references to the environment */ /* Allow references to the environment */
janet_def(env, "_env", janet_wrap_table(env), JDOC("The environment table for the current scope.")); janet_def(env, "_env", janet_wrap_table(env), JDOC("The environment table for the current scope."));

View File

@ -31,8 +31,6 @@ extern "C" {
#include "janetconf.h" #include "janetconf.h"
#define JANET_API_VERSION 1
#ifndef JANET_VERSION #ifndef JANET_VERSION
#define JANET_VERSION "latest" #define JANET_VERSION "latest"
#endif #endif
@ -186,26 +184,38 @@ extern "C" {
#endif #endif
#endif #endif
/* Runtime config constants */ /* Runtime config constants */
#ifdef JANET_NO_NANBOX #ifdef JANET_NO_NANBOX
#define JANET_NANBOX_BIT 0 #define JANET_NANBOX_BIT 0
#else #else
#define JANET_NANBOX_BIT 1 #define JANET_NANBOX_BIT 0x1
#endif #endif
#ifdef JANET_SINGLE_THREADED #ifdef JANET_SINGLE_THREADED
#define JANET_SINGLE_THREADED_BIT 1 #define JANET_SINGLE_THREADED_BIT 0x2
#else #else
#define JANET_SINGLE_THREADED_BIT 0 #define JANET_SINGLE_THREADED_BIT 0
#endif #endif
#define JANET_CURRENT_CONFIG_BITS \
(JANET_SINGLE_THREADED_BIT | \
JANET_NANBOX_BIT)
/* Represents the settings used to compile Janet, as well as the version */
typedef struct { typedef struct {
int api_version; unsigned major;
int single_threaded : 1; unsigned minor;
int nanbox : 1; unsigned patch;
unsigned bits;
} JanetBuildConfig; } JanetBuildConfig;
/* Get config of current compilation unit. */
#define janet_config_current() ((JanetBuildConfig){ \
JANET_VERSION_MAJOR, \
JANET_VERSION_MINOR, \
JANET_VERSION_PATCH, \
JANET_CURRENT_CONFIG_BITS })
/***** END SECTION CONFIG *****/ /***** END SECTION CONFIG *****/
/***** START SECTION TYPES *****/ /***** START SECTION TYPES *****/
@ -1276,15 +1286,11 @@ JANET_API void janet_register(const char *name, JanetCFunction cfun);
/* New C API */ /* New C API */
#define JANET_MODULE_ENTRY JANET_API void _janet_init #define JANET_MODULE_ENTRY \
JANET_API JanetBuildConfig _janet_mod_config(void) { \
JANET_API int janet_api_version(); return janet_config_current(); \
JANET_API const JanetBuildConfig *janet_build_config(); } \
JANET_API void _janet_init
#define janet_api_compatible() \
((janet_api_build_config()->api_version == JANET_API_VERSION) \
&& (janet_api_build_config()->nanbox == JANET_NANBOX_BIT) \
&& (janet_api_build_config()->single_threaded == JANET_SINGLE_THREADED_BIT))
JANET_API void janet_panicv(Janet message); JANET_API void janet_panicv(Janet message);
JANET_API void janet_panic(const char *message); JANET_API void janet_panic(const char *message);

View File

@ -25,7 +25,11 @@
#ifndef JANETCONF_H #ifndef JANETCONF_H
#define JANETCONF_H #define JANETCONF_H
#define JANET_VERSION "0.6.0" #define JANET_VERSION_MAJOR 0
#define JANET_VERSION_MINOR 6
#define JANET_VERSION_PATCH 0
#define JANET_VERSION_EXTRA "-dev"
#define JANET_VERSION "0.6.0-dev"
/* #define JANET_BUILD "local" */ /* #define JANET_BUILD "local" */