forked from Mirror/wren
Add a minimal path manipulation C module.
This is just for the VM's own internal use, for resolving relative imports. Also added a tiny unit test framework for writing tests of low-level C functionality that isn't exposed directly by the language or VM.
This commit is contained in:
26
Makefile
26
Makefile
@ -49,23 +49,23 @@ all: debug release
|
||||
ci: ci_32 ci_64
|
||||
|
||||
ci_32:
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=32 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=32 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=d-32 $(suite)
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=32 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=32 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=d-cpp-32 $(suite)
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=32 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=32 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=-32 $(suite)
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=32 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=32 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=-cpp-32 $(suite)
|
||||
|
||||
ci_64:
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=64 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=c ARCH=64 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=d-64 $(suite)
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=64 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug LANG=cpp ARCH=64 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=d-cpp-64 $(suite)
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=64 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=c ARCH=64 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=-64 $(suite)
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=64 vm cli test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=release LANG=cpp ARCH=64 vm cli api_test
|
||||
$(V) ./util/test.py --suffix=-cpp-64 $(suite)
|
||||
|
||||
# Remove all build outputs and intermediate files. Does not remove downloaded
|
||||
@ -77,13 +77,17 @@ clean:
|
||||
|
||||
# Run the tests against the debug build of Wren.
|
||||
test: debug
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug test
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug api_test
|
||||
$(V) ./util/test.py $(suite)
|
||||
|
||||
benchmark: release
|
||||
$(V) $(MAKE) -f util/wren.mk test
|
||||
$(V) $(MAKE) -f util/wren.mk api_test
|
||||
$(V) ./util/benchmark.py -l wren $(suite)
|
||||
|
||||
unit_test:
|
||||
$(V) $(MAKE) -f util/wren.mk MODE=debug unit_test
|
||||
$(V) ./build/debug/test/unit_wrend
|
||||
|
||||
# Generate the Wren site.
|
||||
docs:
|
||||
$(V) ./util/generate_docs.py
|
||||
@ -104,4 +108,4 @@ gh-pages: docs
|
||||
amalgamation: src/include/wren.h src/vm/*.h src/vm/*.c
|
||||
./util/generate_amalgamation.py > build/wren.c
|
||||
|
||||
.PHONY: all amalgamation builtin clean debug docs gh-pages release test vm watchdocs ci ci_32 ci_64
|
||||
.PHONY: all amalgamation benchmark builtin clean debug docs gh-pages release test vm watchdocs ci ci_32 ci_64
|
||||
|
||||
254
src/cli/path.c
Normal file
254
src/cli/path.c
Normal file
@ -0,0 +1,254 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "path.h"
|
||||
|
||||
// The maximum number of components in a path. We can't normalize a path that
|
||||
// contains more than this number of parts. The number here assumes a max path
|
||||
// length of 4096, which is common on Linux, and then assumes each component is
|
||||
// at least two characters, "/", and a single-letter directory name.
|
||||
#define MAX_COMPONENTS 2048
|
||||
|
||||
typedef struct {
|
||||
const char* start;
|
||||
const char* end;
|
||||
} Slice;
|
||||
|
||||
static void ensureCapacity(Path* path, size_t capacity)
|
||||
{
|
||||
// Capacity always needs to be one greater than the actual length to have
|
||||
// room for the null byte, which is stored in the buffer, but not counted in
|
||||
// the length. A zero-character path still needs a one-character array to
|
||||
// store the '\0'.
|
||||
capacity++;
|
||||
|
||||
if (path->capacity >= capacity) return;
|
||||
|
||||
// Grow by doubling in size.
|
||||
size_t newCapacity = 16;
|
||||
while (newCapacity < capacity) newCapacity *= 2;
|
||||
|
||||
path->chars = (char*)realloc(path->chars, newCapacity);
|
||||
path->capacity = newCapacity;
|
||||
}
|
||||
|
||||
static void appendSlice(Path* path, Slice slice)
|
||||
{
|
||||
size_t length = slice.end - slice.start;
|
||||
ensureCapacity(path, path->length + length);
|
||||
memcpy(path->chars + path->length, slice.start, length);
|
||||
path->length += length;
|
||||
path->chars[path->length] = '\0';
|
||||
}
|
||||
|
||||
Path* pathNew(const char* string)
|
||||
{
|
||||
Path* path = (Path*)malloc(sizeof(Path));
|
||||
path->chars = (char*)malloc(1);
|
||||
path->chars[0] = '\0';
|
||||
path->length = 0;
|
||||
path->capacity = 0;
|
||||
|
||||
pathAppendString(path, string);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void pathFree(Path* path)
|
||||
{
|
||||
if (path->chars) free(path->chars);
|
||||
free(path);
|
||||
}
|
||||
|
||||
void pathDirName(Path* path)
|
||||
{
|
||||
// Find the last path separator.
|
||||
for (size_t i = path->length - 1; i < path->length; i--)
|
||||
{
|
||||
if (path->chars[i] == '/')
|
||||
{
|
||||
path->length = i;
|
||||
path->chars[i] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, there was no separator so it must be a single component.
|
||||
path->length = 0;
|
||||
path->chars[0] = '\0';
|
||||
}
|
||||
|
||||
void pathRemoveExtension(Path* path)
|
||||
{
|
||||
for (size_t i = path->length - 1; i < path->length; i--)
|
||||
{
|
||||
// If we hit a path separator before finding the extension, then the last
|
||||
// component doesn't have one.
|
||||
if (path->chars[i] == '/') return;
|
||||
|
||||
if (path->chars[i] == '.')
|
||||
{
|
||||
path->length = i;
|
||||
path->chars[path->length] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pathJoin(Path* path, const char* string)
|
||||
{
|
||||
if (path->length > 0 && path->chars[path->length - 1] != '/')
|
||||
{
|
||||
pathAppendChar(path, '/');
|
||||
}
|
||||
|
||||
pathAppendString(path, string);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
static bool isDriveLetter(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
#endif
|
||||
|
||||
bool pathIsAbsolute(Path* path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Absolute path in the current drive.
|
||||
if (path->length >= 1 && path->chars[0] == '\\') return true;
|
||||
|
||||
// Drive letter.
|
||||
if (path->length >= 3 &&
|
||||
isDriveLetter(path->chars[0]) &&
|
||||
path->chars[1] == ':' &&
|
||||
path->chars[2] == '\\')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// UNC path.
|
||||
return path->length >= 2 && path->chars[0] == '\\' && path->chars[1] == '\\';
|
||||
#else
|
||||
// Otherwise, assume POSIX-style paths.
|
||||
return path->length >= 1 && path->chars[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
void pathAppendChar(Path* path, char c)
|
||||
{
|
||||
ensureCapacity(path, path->length + 1);
|
||||
path->chars[path->length++] = c;
|
||||
path->chars[path->length] = '\0';
|
||||
}
|
||||
|
||||
void pathAppendString(Path* path, const char* string)
|
||||
{
|
||||
Slice slice;
|
||||
slice.start = string;
|
||||
slice.end = string + strlen(string);
|
||||
appendSlice(path, slice);
|
||||
}
|
||||
|
||||
Path* pathNormalize(Path* path)
|
||||
{
|
||||
Path* result = pathNew("");
|
||||
|
||||
// Split the path into components.
|
||||
Slice components[MAX_COMPONENTS];
|
||||
int numComponents = 0;
|
||||
|
||||
char* start = path->chars;
|
||||
char* end = path->chars;
|
||||
|
||||
// Split into parts and handle "." and "..".
|
||||
int leadingDoubles = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (*end == '\0' || *end == '/')
|
||||
{
|
||||
// Add the current component.
|
||||
if (start != end)
|
||||
{
|
||||
size_t length = end - start;
|
||||
if (length == 1 && start[0] == '.')
|
||||
{
|
||||
// Skip "." components.
|
||||
}
|
||||
else if (length == 2 && start[0] == '.' && start[1] == '.')
|
||||
{
|
||||
// Walk out of directories on "..".
|
||||
if (numComponents > 0)
|
||||
{
|
||||
// Discard the previous component.
|
||||
numComponents--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't back out any further, so preserve the "..".
|
||||
leadingDoubles++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numComponents >= MAX_COMPONENTS)
|
||||
{
|
||||
fprintf(stderr, "Path cannot have more than %d path components.\n",
|
||||
MAX_COMPONENTS);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
components[numComponents].start = start;
|
||||
components[numComponents].end = end;
|
||||
numComponents++;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip over separators.
|
||||
while (*end != '\0' && *end == '/') end++;
|
||||
|
||||
start = end;
|
||||
if (*end == '\0') break;
|
||||
}
|
||||
|
||||
end++;
|
||||
}
|
||||
|
||||
// Preserve the absolute prefix, if any.
|
||||
bool needsSeparator = false;
|
||||
if (path->length > 0 && path->chars[0] == '/')
|
||||
{
|
||||
pathAppendChar(result, '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add any leading "..".
|
||||
for (int i = 0; i < leadingDoubles; i++)
|
||||
{
|
||||
if (needsSeparator) pathAppendChar(result, '/');
|
||||
pathAppendString(result, "..");
|
||||
needsSeparator = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numComponents; i++)
|
||||
{
|
||||
if (needsSeparator) pathAppendChar(result, '/');
|
||||
appendSlice(result, components[i]);
|
||||
needsSeparator = true;
|
||||
}
|
||||
|
||||
if (result->length == 0) pathAppendChar(result, '.');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char* pathToString(Path* path)
|
||||
{
|
||||
char* string = (char*)malloc(path->length + 1);
|
||||
memcpy(string, path->chars, path->length);
|
||||
string[path->length] = '\0';
|
||||
return string;
|
||||
}
|
||||
52
src/cli/path.h
Normal file
52
src/cli/path.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef path_h
|
||||
#define path_h
|
||||
|
||||
// Path manipulation functions.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Dynamically allocated array of characters.
|
||||
char* chars;
|
||||
|
||||
// The number of characters currently in use in [chars], not including the
|
||||
// null terminator.
|
||||
size_t length;
|
||||
|
||||
// Size of the allocated [chars] buffer.
|
||||
size_t capacity;
|
||||
} Path;
|
||||
|
||||
// Creates a new empty path.
|
||||
Path* pathNew(const char* string);
|
||||
|
||||
// Releases the method associated with [path].
|
||||
void pathFree(Path* path);
|
||||
|
||||
// Strips off the last component of the path name.
|
||||
void pathDirName(Path* path);
|
||||
|
||||
// Strips off the file extension from the last component of the path.
|
||||
void pathRemoveExtension(Path* path);
|
||||
|
||||
// Appends [string] to [path].
|
||||
void pathJoin(Path* path, const char* string);
|
||||
|
||||
// Return true if [path] is an absolute path for the host operating system.
|
||||
bool pathIsAbsolute(Path* path);
|
||||
|
||||
// Appends [c] to the path, growing the buffer if needed.
|
||||
void pathAppendChar(Path* path, char c);
|
||||
|
||||
// Appends [string] to the path, growing the buffer if needed.
|
||||
void pathAppendString(Path* path, const char* string);
|
||||
|
||||
// Simplifies the path string as much as possible.
|
||||
//
|
||||
// Applies and removes any "." or ".." components, collapses redundant "/"
|
||||
// characters, etc.
|
||||
Path* pathNormalize(Path* path);
|
||||
|
||||
// Allocates a new string exactly the right length and copies this path to it.
|
||||
char* pathToString(Path* path);
|
||||
|
||||
#endif
|
||||
9
test/unit/main.c
Normal file
9
test/unit/main.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "path_test.h"
|
||||
#include "test.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
testPath();
|
||||
|
||||
return showTestResults();
|
||||
}
|
||||
105
test/unit/path_test.c
Normal file
105
test/unit/path_test.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "path.h"
|
||||
#include "test.h"
|
||||
|
||||
static void expectNormalize(const char* input, const char* expected)
|
||||
{
|
||||
Path* path = pathNew(input);
|
||||
Path* result = pathNormalize(path);
|
||||
|
||||
if (strcmp(result->chars, expected) != 0)
|
||||
{
|
||||
printf("FAIL %-30s Want %s\n", input, expected);
|
||||
printf(" Got %s\n\n", result->chars);
|
||||
fail();
|
||||
}
|
||||
else
|
||||
{
|
||||
#if SHOW_PASSES
|
||||
printf("PASS %-30s -> %s\n", input, result->chars);
|
||||
#endif
|
||||
pass();
|
||||
}
|
||||
|
||||
pathFree(path);
|
||||
pathFree(result);
|
||||
}
|
||||
|
||||
static void testNormalize()
|
||||
{
|
||||
// simple cases
|
||||
expectNormalize("", ".");
|
||||
expectNormalize(".", ".");
|
||||
expectNormalize("..", "..");
|
||||
expectNormalize("a", "a");
|
||||
expectNormalize("/", "/");
|
||||
|
||||
// collapses redundant separators
|
||||
expectNormalize("a/b/c", "a/b/c");
|
||||
expectNormalize("a//b///c////d", "a/b/c/d");
|
||||
|
||||
// eliminates "." parts
|
||||
expectNormalize("./", ".");
|
||||
expectNormalize("/.", "/");
|
||||
expectNormalize("/./", "/");
|
||||
expectNormalize("./.", ".");
|
||||
expectNormalize("a/./b", "a/b");
|
||||
expectNormalize("a/.b/c", "a/.b/c");
|
||||
expectNormalize("a/././b/./c", "a/b/c");
|
||||
expectNormalize("././a", "a");
|
||||
expectNormalize("a/./.", "a");
|
||||
|
||||
// eliminates ".." parts
|
||||
expectNormalize("..", "..");
|
||||
expectNormalize("../", "..");
|
||||
expectNormalize("../../..", "../../..");
|
||||
expectNormalize("../../../", "../../..");
|
||||
expectNormalize("/..", "/");
|
||||
expectNormalize("/../../..", "/");
|
||||
expectNormalize("/../../../a", "/a");
|
||||
expectNormalize("a/..", ".");
|
||||
expectNormalize("a/b/..", "a");
|
||||
expectNormalize("a/../b", "b");
|
||||
expectNormalize("a/./../b", "b");
|
||||
expectNormalize("a/b/c/../../d/e/..", "a/d");
|
||||
expectNormalize("a/b/../../../../c", "../../c");
|
||||
|
||||
// does not walk before root on absolute paths
|
||||
expectNormalize("..", "..");
|
||||
expectNormalize("../", "..");
|
||||
expectNormalize("/..", "/");
|
||||
expectNormalize("a/..", ".");
|
||||
expectNormalize("../a", "../a");
|
||||
expectNormalize("/../a", "/a");
|
||||
expectNormalize("/../a", "/a");
|
||||
expectNormalize("a/b/..", "a");
|
||||
expectNormalize("../a/b/..", "../a");
|
||||
expectNormalize("a/../b", "b");
|
||||
expectNormalize("a/./../b", "b");
|
||||
expectNormalize("a/b/c/../../d/e/..", "a/d");
|
||||
expectNormalize("a/b/../../../../c", "../../c");
|
||||
expectNormalize("a/b/c/../../..d/./.e/f././", "a/..d/.e/f.");
|
||||
|
||||
// removes trailing separators
|
||||
expectNormalize("./", ".");
|
||||
expectNormalize(".//", ".");
|
||||
expectNormalize("a/", "a");
|
||||
expectNormalize("a/b/", "a/b");
|
||||
expectNormalize("a/b///", "a/b");
|
||||
|
||||
expectNormalize("foo/bar/baz", "foo/bar/baz");
|
||||
expectNormalize("foo", "foo");
|
||||
expectNormalize("foo/bar/", "foo/bar");
|
||||
expectNormalize("./foo/././bar/././", "foo/bar");
|
||||
}
|
||||
|
||||
void testPath()
|
||||
{
|
||||
// TODO: Test other functions.
|
||||
testNormalize();
|
||||
}
|
||||
|
||||
1
test/unit/path_test.h
Normal file
1
test/unit/path_test.h
Normal file
@ -0,0 +1 @@
|
||||
void testPath();
|
||||
29
test/unit/test.c
Normal file
29
test/unit/test.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
int passes = 0;
|
||||
int failures = 0;
|
||||
|
||||
void pass()
|
||||
{
|
||||
passes++;
|
||||
}
|
||||
|
||||
void fail()
|
||||
{
|
||||
failures++;
|
||||
}
|
||||
|
||||
int showTestResults()
|
||||
{
|
||||
if (failures > 0)
|
||||
{
|
||||
printf("%d out of %d tests failed. :(\n", failures, passes + failures);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("All %d tests passed!\n", passes + failures);
|
||||
return 0;
|
||||
}
|
||||
|
||||
7
test/unit/test.h
Normal file
7
test/unit/test.h
Normal file
@ -0,0 +1,7 @@
|
||||
// Set this to 1 to output passing tests.
|
||||
#define SHOW_PASSES 0
|
||||
|
||||
void pass();
|
||||
void fail();
|
||||
|
||||
int showTestResults();
|
||||
@ -154,7 +154,7 @@ def run_trial(benchmark, language):
|
||||
# of the normal Wren build.
|
||||
if benchmark[0].startswith("api_"):
|
||||
executable_args = [
|
||||
os.path.join(WREN_DIR, "build", "release", "test", "wren")
|
||||
os.path.join(WREN_DIR, "build", "release", "test", "api_wren")
|
||||
]
|
||||
|
||||
args = []
|
||||
|
||||
@ -25,7 +25,7 @@ config_dir = ("debug" if is_debug else "release") + config
|
||||
|
||||
WREN_DIR = dirname(dirname(realpath(__file__)))
|
||||
WREN_APP = join(WREN_DIR, 'bin', 'wren' + args.suffix)
|
||||
TEST_APP = join(WREN_DIR, 'build', config_dir, 'test', 'wren' + args.suffix)
|
||||
TEST_APP = join(WREN_DIR, 'build', config_dir, 'test', 'api_wren' + args.suffix)
|
||||
|
||||
EXPECT_PATTERN = re.compile(r'// expect: ?(.*)')
|
||||
EXPECT_ERROR_PATTERN = re.compile(r'// expect error(?! line)')
|
||||
|
||||
49
util/wren.mk
49
util/wren.mk
@ -31,8 +31,11 @@ MODULE_SOURCES := $(wildcard src/module/*.c)
|
||||
VM_HEADERS := $(wildcard src/vm/*.h) $(wildcard src/vm/*.wren.inc)
|
||||
VM_SOURCES := $(wildcard src/vm/*.c)
|
||||
|
||||
TEST_HEADERS := $(wildcard test/api/*.h)
|
||||
TEST_SOURCES := $(wildcard test/api/*.c)
|
||||
API_TEST_HEADERS := $(wildcard test/api/*.h)
|
||||
API_TEST_SOURCES := $(wildcard test/api/*.c)
|
||||
|
||||
UNIT_TEST_HEADERS := $(wildcard test/unit/*.h)
|
||||
UNIT_TEST_SOURCES := $(wildcard test/unit/*.c)
|
||||
|
||||
BUILD_DIR := build
|
||||
|
||||
@ -124,7 +127,8 @@ OPT_OBJECTS := $(addprefix $(BUILD_DIR)/optional/, $(notdir $(OPT_SOURCES:.c=
|
||||
CLI_OBJECTS := $(addprefix $(BUILD_DIR)/cli/, $(notdir $(CLI_SOURCES:.c=.o)))
|
||||
MODULE_OBJECTS := $(addprefix $(BUILD_DIR)/module/, $(notdir $(MODULE_SOURCES:.c=.o)))
|
||||
VM_OBJECTS := $(addprefix $(BUILD_DIR)/vm/, $(notdir $(VM_SOURCES:.c=.o)))
|
||||
TEST_OBJECTS := $(patsubst test/api/%.c, $(BUILD_DIR)/test/%.o, $(TEST_SOURCES))
|
||||
API_TEST_OBJECTS := $(patsubst test/api/%.c, $(BUILD_DIR)/test/api/%.o, $(API_TEST_SOURCES))
|
||||
UNIT_TEST_OBJECTS := $(patsubst test/unit/%.c, $(BUILD_DIR)/test/unit/%.o, $(UNIT_TEST_SOURCES))
|
||||
|
||||
LIBUV_DIR := deps/libuv
|
||||
LIBUV := build/libuv$(LIBUV_ARCH).a
|
||||
@ -152,7 +156,10 @@ static: lib/lib$(WREN).a
|
||||
cli: bin/$(WREN)
|
||||
|
||||
# Builds the API test executable.
|
||||
test: $(BUILD_DIR)/test/$(WREN)
|
||||
api_test: $(BUILD_DIR)/test/api_$(WREN)
|
||||
|
||||
# Builds the unit test executable.
|
||||
unit_test: $(BUILD_DIR)/test/unit_$(WREN)
|
||||
|
||||
# Command-line interpreter.
|
||||
bin/$(WREN): $(OPT_OBJECTS) $(CLI_OBJECTS) $(MODULE_OBJECTS) $(VM_OBJECTS) \
|
||||
@ -173,13 +180,22 @@ lib/lib$(WREN).$(SHARED_EXT): $(OPT_OBJECTS) $(VM_OBJECTS)
|
||||
$(V) mkdir -p lib
|
||||
$(V) $(CC) $(CFLAGS) -shared $(SHARED_LIB_FLAGS) -o $@ $^
|
||||
|
||||
# Test executable.
|
||||
$(BUILD_DIR)/test/$(WREN): $(OPT_OBJECTS) $(MODULE_OBJECTS) $(TEST_OBJECTS) \
|
||||
$(VM_OBJECTS) $(BUILD_DIR)/cli/modules.o $(BUILD_DIR)/cli/vm.o $(LIBUV)
|
||||
# API test executable.
|
||||
$(BUILD_DIR)/test/api_$(WREN): $(OPT_OBJECTS) $(MODULE_OBJECTS) $(API_TEST_OBJECTS) \
|
||||
$(VM_OBJECTS) $(BUILD_DIR)/cli/modules.o $(BUILD_DIR)/cli/vm.o \
|
||||
$(BUILD_DIR)/cli/path.o $(LIBUV)
|
||||
@ printf "%10s %-30s %s\n" $(CC) $@ "$(C_OPTIONS)"
|
||||
$(V) mkdir -p $(BUILD_DIR)/test
|
||||
$(V) mkdir -p $(BUILD_DIR)/test/api
|
||||
$(V) $(CC) $(CFLAGS) $^ -o $@ -lm $(LIBUV_LIBS)
|
||||
|
||||
# Unit test executable.
|
||||
$(BUILD_DIR)/test/unit_$(WREN): $(OPT_OBJECTS) $(MODULE_OBJECTS) $(UNIT_TEST_OBJECTS) \
|
||||
$(VM_OBJECTS) $(BUILD_DIR)/cli/modules.o $(BUILD_DIR)/cli/vm.o \
|
||||
$(BUILD_DIR)/cli/path.o $(LIBUV)
|
||||
@ printf "%10s %-30s %s\n" $(CC) $@ "$(C_OPTIONS)"
|
||||
$(V) mkdir -p $(BUILD_DIR)/test/unit
|
||||
$(V) $(CC) $(CFLAGS) $^ -o $@
|
||||
|
||||
# CLI object files.
|
||||
$(BUILD_DIR)/cli/%.o: src/cli/%.c $(CLI_HEADERS) $(MODULE_HEADERS) \
|
||||
$(VM_HEADERS) $(LIBUV)
|
||||
@ -194,7 +210,7 @@ $(BUILD_DIR)/module/%.o: src/module/%.c $(CLI_HEADERS) $(MODULE_HEADERS) \
|
||||
$(V) mkdir -p $(BUILD_DIR)/module
|
||||
$(V) $(CC) -c $(CFLAGS) $(CLI_FLAGS) -o $@ $(FILE_FLAG) $<
|
||||
|
||||
# Aux object files.
|
||||
# Optional object files.
|
||||
$(BUILD_DIR)/optional/%.o: src/optional/%.c $(VM_HEADERS) $(OPT_HEADERS)
|
||||
@ printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
|
||||
$(V) mkdir -p $(BUILD_DIR)/optional
|
||||
@ -206,9 +222,16 @@ $(BUILD_DIR)/vm/%.o: src/vm/%.c $(VM_HEADERS)
|
||||
$(V) mkdir -p $(BUILD_DIR)/vm
|
||||
$(V) $(CC) -c $(CFLAGS) -Isrc/include -Isrc/optional -Isrc/vm -o $@ $(FILE_FLAG) $<
|
||||
|
||||
# Test object files.
|
||||
$(BUILD_DIR)/test/%.o: test/api/%.c $(OPT_HEADERS) $(MODULE_HEADERS) \
|
||||
$(VM_HEADERS) $(TEST_HEADERS) $(LIBUV)
|
||||
# API test object files.
|
||||
$(BUILD_DIR)/test/api/%.o: test/api/%.c $(OPT_HEADERS) $(MODULE_HEADERS) \
|
||||
$(VM_HEADERS) $(API_TEST_HEADERS) $(LIBUV)
|
||||
@ printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
|
||||
$(V) mkdir -p $(dir $@)
|
||||
$(V) $(CC) -c $(CFLAGS) $(CLI_FLAGS) -o $@ $(FILE_FLAG) $<
|
||||
|
||||
# Unit test object files.
|
||||
$(BUILD_DIR)/test/unit/%.o: test/unit/%.c $(OPT_HEADERS) $(MODULE_HEADERS) \
|
||||
$(VM_HEADERS) $(UNIT_TEST_HEADERS) $(LIBUV)
|
||||
@ printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
|
||||
$(V) mkdir -p $(dir $@)
|
||||
$(V) $(CC) -c $(CFLAGS) $(CLI_FLAGS) -o $@ $(FILE_FLAG) $<
|
||||
@ -231,4 +254,4 @@ src/module/%.wren.inc: src/module/%.wren util/wren_to_c_string.py
|
||||
@ printf "%10s %-30s %s\n" str $<
|
||||
$(V) ./util/wren_to_c_string.py $@ $<
|
||||
|
||||
.PHONY: all cli test vm
|
||||
.PHONY: all api_test cli unit_test vm
|
||||
|
||||
@ -24,9 +24,14 @@
|
||||
293B255A1CEFD8C7005D9537 /* repl.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 293B25561CEFD8C7005D9537 /* repl.wren.inc */; };
|
||||
293D46961BB43F9900200083 /* call.c in Sources */ = {isa = PBXBuildFile; fileRef = 293D46941BB43F9900200083 /* call.c */; };
|
||||
2940E98D2063EC030054503C /* resolution.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E98B2063EC020054503C /* resolution.c */; };
|
||||
2940E9BB2066067D0054503C /* path_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E9BA2066067D0054503C /* path_test.c */; };
|
||||
2940E9BC206607830054503C /* path.c in Sources */ = {isa = PBXBuildFile; fileRef = 2952CD1B1FA9941700985F5F /* path.c */; };
|
||||
2940E9BE2066C3300054503C /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E9BD2066C3300054503C /* main.c */; };
|
||||
2940E9C12066C35E0054503C /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = 2940E9BF2066C35E0054503C /* test.c */; };
|
||||
2949AA8D1C2F14F000B106BA /* get_variable.c in Sources */ = {isa = PBXBuildFile; fileRef = 2949AA8B1C2F14F000B106BA /* get_variable.c */; };
|
||||
29512C811B91F8EB008C10E6 /* libuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29512C801B91F8EB008C10E6 /* libuv.a */; };
|
||||
29512C821B91F901008C10E6 /* libuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29512C801B91F8EB008C10E6 /* libuv.a */; };
|
||||
2952CD1D1FA9941700985F5F /* path.c in Sources */ = {isa = PBXBuildFile; fileRef = 2952CD1B1FA9941700985F5F /* path.c */; };
|
||||
29729F311BA70A620099CA20 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29729F2E1BA70A620099CA20 /* io.c */; };
|
||||
29729F321BA70A620099CA20 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29729F2E1BA70A620099CA20 /* io.c */; };
|
||||
29729F331BA70A620099CA20 /* io.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 29729F301BA70A620099CA20 /* io.wren.inc */; };
|
||||
@ -68,6 +73,15 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
2940E9B4206605DE0054503C /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
29AB1F041816E3AD004B501E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -118,10 +132,18 @@
|
||||
293D46951BB43F9900200083 /* call.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = call.h; path = ../../test/api/call.h; sourceTree = "<group>"; };
|
||||
2940E98B2063EC020054503C /* resolution.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = resolution.c; path = ../../test/api/resolution.c; sourceTree = "<group>"; };
|
||||
2940E98C2063EC020054503C /* resolution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = resolution.h; path = ../../test/api/resolution.h; sourceTree = "<group>"; };
|
||||
2940E9B8206605DE0054503C /* unit_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unit_test; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2940E9B92066067D0054503C /* path_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path_test.h; path = ../../../test/unit/path_test.h; sourceTree = "<group>"; };
|
||||
2940E9BA2066067D0054503C /* path_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = path_test.c; path = ../../../test/unit/path_test.c; sourceTree = "<group>"; };
|
||||
2940E9BD2066C3300054503C /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../../../test/unit/main.c; sourceTree = "<group>"; };
|
||||
2940E9BF2066C35E0054503C /* test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = test.c; path = ../../../test/unit/test.c; sourceTree = "<group>"; };
|
||||
2940E9C02066C35E0054503C /* test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test.h; path = ../../../test/unit/test.h; sourceTree = "<group>"; };
|
||||
2949AA8B1C2F14F000B106BA /* get_variable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = get_variable.c; path = ../../test/api/get_variable.c; sourceTree = "<group>"; };
|
||||
2949AA8C1C2F14F000B106BA /* get_variable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = get_variable.h; path = ../../test/api/get_variable.h; sourceTree = "<group>"; };
|
||||
29512C7F1B91F86E008C10E6 /* api_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = api_test; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
29512C801B91F8EB008C10E6 /* libuv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libuv.a; path = ../../build/libuv.a; sourceTree = "<group>"; };
|
||||
2952CD1B1FA9941700985F5F /* path.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = path.c; path = ../../src/cli/path.c; sourceTree = "<group>"; };
|
||||
2952CD1C1FA9941700985F5F /* path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path.h; path = ../../src/cli/path.h; sourceTree = "<group>"; };
|
||||
296371B31AC713D000079FDA /* wren_opcodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_opcodes.h; path = ../../src/vm/wren_opcodes.h; sourceTree = "<group>"; };
|
||||
29729F2E1BA70A620099CA20 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = io.c; path = ../../src/module/io.c; sourceTree = "<group>"; };
|
||||
29729F301BA70A620099CA20 /* io.wren.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = io.wren.inc; path = ../../src/module/io.wren.inc; sourceTree = "<group>"; };
|
||||
@ -164,6 +186,13 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
2940E9B2206605DE0054503C /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
29AB1F031816E3AD004B501E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -233,6 +262,8 @@
|
||||
29205C8E1AB4E5C90073018D /* main.c */,
|
||||
291647C61BA5EC5E006142EE /* modules.h */,
|
||||
291647C51BA5EC5E006142EE /* modules.c */,
|
||||
2952CD1C1FA9941700985F5F /* path.h */,
|
||||
2952CD1B1FA9941700985F5F /* path.c */,
|
||||
29C8A9321AB71FFF00DEC81D /* vm.h */,
|
||||
29C8A9311AB71FFF00DEC81D /* vm.c */,
|
||||
);
|
||||
@ -247,6 +278,18 @@
|
||||
name = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2940E98E206605CB0054503C /* unit_test */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2940E9BD2066C3300054503C /* main.c */,
|
||||
2940E9BA2066067D0054503C /* path_test.c */,
|
||||
2940E9B92066067D0054503C /* path_test.h */,
|
||||
2940E9BF2066C35E0054503C /* test.c */,
|
||||
2940E9C02066C35E0054503C /* test.h */,
|
||||
);
|
||||
path = unit_test;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
29AB1EFD1816E3AD004B501E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -256,6 +299,7 @@
|
||||
29AF31EE1BD2E37F00AAD156 /* optional */,
|
||||
29205CA01AB4E6470073018D /* vm */,
|
||||
29D0099A1B7E394F000CE58C /* api_test */,
|
||||
2940E98E206605CB0054503C /* unit_test */,
|
||||
29512C801B91F8EB008C10E6 /* libuv.a */,
|
||||
29AB1F071816E3AD004B501E /* Products */,
|
||||
);
|
||||
@ -266,6 +310,7 @@
|
||||
children = (
|
||||
29AB1F061816E3AD004B501E /* wren */,
|
||||
29512C7F1B91F86E008C10E6 /* api_test */,
|
||||
2940E9B8206605DE0054503C /* unit_test */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -320,6 +365,23 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
2940E98F206605DE0054503C /* unit_test */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 2940E9B5206605DE0054503C /* Build configuration list for PBXNativeTarget "unit_test" */;
|
||||
buildPhases = (
|
||||
2940E990206605DE0054503C /* Sources */,
|
||||
2940E9B2206605DE0054503C /* Frameworks */,
|
||||
2940E9B4206605DE0054503C /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = unit_test;
|
||||
productName = api_test;
|
||||
productReference = 2940E9B8206605DE0054503C /* unit_test */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
29AB1F051816E3AD004B501E /* wren */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 29AB1F0F1816E3AD004B501E /* Build configuration list for PBXNativeTarget "wren" */;
|
||||
@ -382,11 +444,23 @@
|
||||
targets = (
|
||||
29AB1F051816E3AD004B501E /* wren */,
|
||||
29D0099E1B7E397D000CE58C /* api_test */,
|
||||
2940E98F206605DE0054503C /* unit_test */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
2940E990206605DE0054503C /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2940E9BC206607830054503C /* path.c in Sources */,
|
||||
2940E9BB2066067D0054503C /* path_test.c in Sources */,
|
||||
2940E9BE2066C3300054503C /* main.c in Sources */,
|
||||
2940E9C12066C35E0054503C /* test.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
29AB1F021816E3AD004B501E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -395,6 +469,7 @@
|
||||
29205C991AB4E6430073018D /* wren_compiler.c in Sources */,
|
||||
2986F6D71ACF93BA00BCE26C /* wren_primitive.c in Sources */,
|
||||
291647C71BA5EC5E006142EE /* modules.c in Sources */,
|
||||
2952CD1D1FA9941700985F5F /* path.c in Sources */,
|
||||
29A4273A1BDBE435001E6E22 /* wren_opt_random.wren.inc in Sources */,
|
||||
29205C9A1AB4E6430073018D /* wren_core.c in Sources */,
|
||||
2901D7641B74F4050083A2C8 /* timer.c in Sources */,
|
||||
@ -460,6 +535,50 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
2940E9B6206605DE0054503C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_PEDANTIC = NO;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
LIBRARY_SEARCH_PATHS = ../../build;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
2940E9B7206605DE0054503C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_PEDANTIC = NO;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
LIBRARY_SEARCH_PATHS = ../../build;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
29AB1F0D1816E3AD004B501E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -605,6 +724,15 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
2940E9B5206605DE0054503C /* Build configuration list for PBXNativeTarget "unit_test" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
2940E9B6206605DE0054503C /* Debug */,
|
||||
2940E9B7206605DE0054503C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
29AB1F011816E3AD004B501E /* Build configuration list for PBXProject "wren" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
Reference in New Issue
Block a user