mirror of
https://github.com/remko/waforth
synced 2025-01-17 18:11:39 +01:00
waforthc: Clean up dependencies
This commit is contained in:
parent
0751ed383a
commit
1cd666d026
4 changed files with 149 additions and 74 deletions
16
.github/workflows/build-waforthc.yml
vendored
16
.github/workflows/build-waforthc.yml
vendored
|
@ -10,21 +10,21 @@ jobs:
|
|||
build-waforthc:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-18.04, windows-latest]
|
||||
os: [ubuntu-18.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- if: runner.os == 'macOS'
|
||||
run: brew install boost
|
||||
- if: runner.os == 'macOS' || runner.os == 'Windows'
|
||||
run: make -C src/waforthc package
|
||||
shell: bash
|
||||
- if: runner.os == 'Linux'
|
||||
run: sudo apt-get install libboost-dev libboost-filesystem-dev libboost-program-options-dev
|
||||
run: |
|
||||
make -C src/waforthc package \
|
||||
WABT_INCLUDE_DIR=/usr/local/include \
|
||||
WABT_LIB_DIR=/usr/local/lib \
|
||||
WABT_DATA_DIR=/usr/local/share/wabt
|
||||
shell: bash
|
||||
- if: runner.os == 'Windows'
|
||||
run: C:\msys64\usr\bin\pacman -S --noconfirm mingw-w64-x86_64-boost
|
||||
shell: cmd
|
||||
|
||||
- run: make -C src/waforthc package
|
||||
- run: make -C src/waforthc check
|
||||
|
|
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
|
@ -10,12 +10,7 @@
|
|||
"**/node_modules": true
|
||||
},
|
||||
"files.associations": {
|
||||
"*.fr": "forth",
|
||||
"__locale": "c",
|
||||
"ios": "c",
|
||||
"vector": "cpp",
|
||||
"*.ipp": "cpp",
|
||||
"filesystem": "cpp"
|
||||
"*.fr": "forth"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
|
|
|
@ -5,8 +5,9 @@ VERSION?=$(shell cat ../../package.json | grep '"version"' | sed -e 's/.*:.*"\(.
|
|||
ifeq ($(OS),Windows_NT)
|
||||
CXX = g++
|
||||
WABT_DIR = /c/tools/wabt
|
||||
BOOST_LIB_DIR = /mingw64/lib
|
||||
BOOST_INCLUDE_DIR = /mingw64/include
|
||||
WABT_INCLUDE_DIR ?= $(WABT_DIR)/include
|
||||
WABT_LIB_DIR ?= $(WABT_DIR)/lib
|
||||
WABT_DATA_DIR ?= $(WABT_DIR)/share/wabt
|
||||
package: waforthc
|
||||
7z a -tzip waforthc-v$(VERSION)-windows.zip waforthc.exe
|
||||
else # $(OS)
|
||||
|
@ -27,30 +28,26 @@ endif
|
|||
HOMEBREW_DIR = $(shell brew --prefix)
|
||||
# FIXME: When new WABT 1.0.31 is released, we can update this to standard paths
|
||||
WABT_DIR = /usr/local/wabt
|
||||
BOOST_INCLUDE_DIR := $(HOMEBREW_DIR)/include
|
||||
BOOST_LIB_DIR := $(HOMEBREW_DIR)/lib
|
||||
WABT_INCLUDE_DIR = $(WABT_DIR)/include
|
||||
WABT_LIB_DIR = $(WABT_DIR)/lib
|
||||
WABT_DATA_DIR = $(WABT_DIR)/share/wabt
|
||||
LIBS := -mmacosx-version-min=13.0
|
||||
CXXFLAGS := -std=c++17
|
||||
else # $(UNAME_S)
|
||||
WABT_DIR = /usr/local/wabt
|
||||
BOOST_INCLUDE_DIR = /usr/include
|
||||
BOOST_LIB_DIR := /usr/lib/$(shell gcc -dumpmachine)
|
||||
GCC_TARGET_MACHINE = $(shell gcc -dumpmachine)
|
||||
WABT_INCLUDE_DIR ?= /usr/lib/include
|
||||
WABT_LIB_DIR ?= /usr/lib/$(GCC_TARGET_MACHINE)
|
||||
WABT_DATA_DIR ?= /usr/share/wabt
|
||||
PACKAGE_SUFFIX=x86_64-linux
|
||||
endif # $(UNAME_S)
|
||||
package: waforthc
|
||||
$(TAR) czf waforthc-v$(VERSION)-$(PACKAGE_SUFFIX).tgz waforthc
|
||||
endif # $(OS)
|
||||
|
||||
WABT_INCLUDE_DIR := $(WABT_DIR)/include
|
||||
WABT_LIB_DIR := $(WABT_DIR)/lib
|
||||
WABT_DATA_DIR = $(WABT_DIR)/share/wabt
|
||||
|
||||
LIBS := \
|
||||
$(WABT_LIB_DIR)/libwabt.a \
|
||||
$(BOOST_LIB_DIR)/libboost_filesystem.a \
|
||||
$(BOOST_LIB_DIR)/libboost_program_options.a \
|
||||
$(LIBS)
|
||||
CPPFLAGS := -I$(WABT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR)
|
||||
CPPFLAGS := -I$(WABT_INCLUDE_DIR)
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
CXXFLAGS := $(CXXFLAGS) -g
|
||||
|
@ -99,7 +96,7 @@ waforth_core.wasm: ../waforth.wat
|
|||
.PHONY: check
|
||||
check:
|
||||
-rm -f test test.out
|
||||
./waforthc -o test --init=SAY_HELLO ../examples/hello.fs | tee test.out
|
||||
./waforthc --output=test --init=SAY_HELLO ../examples/hello.fs | tee test.out
|
||||
grep -q "Hello, Forth" test.out
|
||||
./test | tee test.out
|
||||
grep -q "Hello, Forth" test.out
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/process.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <wabt/apply-names.h>
|
||||
#include <wabt/binary-reader-ir.h>
|
||||
#include <wabt/binary-reader.h>
|
||||
|
@ -30,8 +33,6 @@
|
|||
#include "waforth_wabt_wasm-rt-impl_h.h"
|
||||
#include "waforth_wabt_wasm-rt_h.h"
|
||||
|
||||
namespace bp = boost::process;
|
||||
namespace bpo = boost::program_options;
|
||||
namespace fs = std::filesystem;
|
||||
namespace wabti = wabt::interp;
|
||||
|
||||
|
@ -46,6 +47,66 @@ static std::unique_ptr<wabt::FileStream> stderrStream;
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool endsWith(const std::string &x, const std::string &y) {
|
||||
return x.size() >= y.size() && x.compare(x.size() - y.size(), std::string::npos, y) == 0;
|
||||
}
|
||||
|
||||
int runChild(const std::vector<std::string> &cmd) {
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||
std::ostringstream cmdss;
|
||||
for (const i = 0; i < cmd.size(); ++i) {
|
||||
if (i > 0) {
|
||||
cmdss << " ";
|
||||
}
|
||||
auto arg = cmd[i];
|
||||
// TODO: Escape
|
||||
cmds << arg;
|
||||
}
|
||||
auto cmdss = cmds.str();
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
if (!CreateProcess(NULL, cmds.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
|
||||
std::cerr << "CreateProcess failed: %d" << GetLastError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
DWORD ret;
|
||||
GetExitCodeProcess(pi.hProcess, &ret);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
std::vector<const char *> argsp;
|
||||
for (const auto &arg : cmd) {
|
||||
argsp.push_back(arg.c_str());
|
||||
}
|
||||
argsp.push_back(nullptr);
|
||||
auto pid = fork();
|
||||
if (pid == 0) {
|
||||
if (execvp(argsp[0], (char **)&argsp[0]) == -1) {
|
||||
std::cerr << "execvp() error" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
if (WIFEXITED(status)) {
|
||||
return WEXITSTATUS(status);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Compiles a WASM module to a native file named `outfile`.
|
||||
*/
|
||||
|
@ -88,16 +149,12 @@ wabt::Result compileToNative(wabt::Module &mod, const std::string &init, const s
|
|||
wabt::FileStream((wd / "wasm-rt.h").string()).WriteData(waforth_wabt_wasm_rt_h, sizeof(waforth_wabt_wasm_rt_h));
|
||||
}
|
||||
|
||||
std::ostringstream cmd;
|
||||
bp::child c(bp::search_path(cc), "-o", outfile, (wd / "_waforth_rt.c").string(), (wd / "_waforth.c").string(), (wd / "wasm-rt-impl.c").string(),
|
||||
bp::args(cflags));
|
||||
c.wait();
|
||||
int result = c.exit_code();
|
||||
if (result != 0) {
|
||||
std::vector<std::string> cmd = {cc, "-o", outfile, (wd / "_waforth_rt.c").string(), (wd / "_waforth.c").string(), (wd / "wasm-rt-impl.c").string()};
|
||||
cmd.insert(cmd.end(), cflags.begin(), cflags.end());
|
||||
if (runChild(cmd) != 0) {
|
||||
std::cerr << "error compiling";
|
||||
return wabt::Result::Error;
|
||||
}
|
||||
|
||||
return wabt::Result::Ok;
|
||||
}
|
||||
|
||||
|
@ -351,7 +408,7 @@ wabt::Result main_(const std::string &infile, const std::string &outfile, const
|
|||
wabt::Module compiled;
|
||||
CHECK_RESULT(compileToModule(words, rresult.data, rresult.dataOffset, rresult.latest, compiled, errors));
|
||||
|
||||
if (boost::ends_with(outfile, ".wasm")) {
|
||||
if (endsWith(outfile, ".wasm")) {
|
||||
CHECK_RESULT(writeModule(outfile, compiled));
|
||||
} else {
|
||||
CHECK_RESULT(compileToNative(compiled, init, outfile, cc, cflags));
|
||||
|
@ -360,44 +417,70 @@ wabt::Result main_(const std::string &infile, const std::string &outfile, const
|
|||
return wabt::Result::Ok;
|
||||
}
|
||||
|
||||
const char help[] = "waforthc " VERSION R"(
|
||||
|
||||
Usage: waforthc [OPTION]... INPUT_FILE
|
||||
|
||||
Options:
|
||||
--help Show this help message
|
||||
--output=FILE Output file (default: "out")
|
||||
If `arg` ends with .wasm, the result will be a
|
||||
WebAssembly module. Otherwise, the result will be
|
||||
a native executable.
|
||||
--cc=CC C compiler (default: "gcc")
|
||||
--ccflag=FLAG C compiler flag
|
||||
--init=PROGRAM Initialization program
|
||||
If specified, PROGRAM will be executed when the
|
||||
resulting executable is run. Otherwise, the
|
||||
resulting executable will start an interactive
|
||||
session.
|
||||
)";
|
||||
|
||||
std::pair<std::string, std::string> splitOption(const std::string &s) {
|
||||
auto i = s.find("=");
|
||||
if (i == std::string::npos) {
|
||||
return std::make_pair(s, "");
|
||||
}
|
||||
return std::make_pair(s.substr(0, i), s.substr(i + 1));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::string outfile;
|
||||
std::string outfile("out");
|
||||
std::string infile;
|
||||
std::string init;
|
||||
std::string cc;
|
||||
std::string cc("gcc");
|
||||
std::vector<std::string> ccflags;
|
||||
|
||||
bpo::options_description odesc("Options");
|
||||
odesc.add_options()("help", "Show this help message")(
|
||||
"output,o", bpo::value<std::string>(&outfile)->default_value("out"),
|
||||
"Output file\nIf `arg` ends with .wasm, the result will be a WebAssembly module. Otherwise, the result will be a native executable.")(
|
||||
"cc", bpo::value<std::string>(&cc)->default_value("gcc"), "C compiler")("ccflag", bpo::value<std::vector<std::string>>(&ccflags),
|
||||
"C compiler flag")(
|
||||
"init", bpo::value<std::string>(&init),
|
||||
"Initialization program\nIf specified, PROGRAM will be executed when the resulting executable is run. Otherwise, the resulting executable will "
|
||||
"start an interactive session.");
|
||||
bpo::options_description idesc("Options");
|
||||
idesc.add_options()("input", bpo::value<std::string>(&infile)->required(), "Input file");
|
||||
bpo::options_description desc;
|
||||
desc.add(odesc).add(idesc);
|
||||
|
||||
bpo::positional_options_description p;
|
||||
p.add("input", 1);
|
||||
bpo::variables_map vm;
|
||||
try {
|
||||
bpo::store(bpo::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
|
||||
if (vm.count("help")) {
|
||||
std::cout << "waforthc " << VERSION << std::endl << std::endl;
|
||||
std::cout << "Usage: " << argv[0] << " [OPTION]... INPUT_FILE" << std::endl << std::endl;
|
||||
std::cout << odesc << std::endl;
|
||||
return 0;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg(argv[i]);
|
||||
if (arg.size() >= 0 && arg[0] == '-') {
|
||||
auto opt = splitOption(arg);
|
||||
if (opt.first == "--help") {
|
||||
std::cout << help;
|
||||
return 0;
|
||||
} else if (opt.first == "--output") {
|
||||
outfile = opt.second;
|
||||
} else if (opt.first == "--init") {
|
||||
init = opt.second;
|
||||
} else if (opt.first == "--cc") {
|
||||
cc = opt.second;
|
||||
} else if (opt.first == "--ccflag") {
|
||||
ccflags.push_back(opt.second);
|
||||
} else {
|
||||
std::cerr << "unrecognized option: " << arg << std::endl;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!infile.empty()) {
|
||||
std::cerr << "only 1 input file supported" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
infile = arg;
|
||||
}
|
||||
bpo::notify(vm);
|
||||
} catch (const bpo::error &e) {
|
||||
std::cout << e.what();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (infile.empty()) {
|
||||
std::cout << help;
|
||||
return 0;
|
||||
}
|
||||
ccflags.push_back("-lm");
|
||||
|
||||
wabt::Errors errors;
|
||||
|
|
Loading…
Reference in a new issue