waforthc: Support cross-compiling

This commit is contained in:
Remko Tronçon 2022-11-12 16:52:27 +01:00
parent 6e0610dfc4
commit 9dca4fb083
2 changed files with 20 additions and 6 deletions

View file

@ -55,6 +55,10 @@ Contrary to the [standalone native WAForth](https://github.com/remko/waforth/tre
: SAY_BYE ." Bye" CR ;
Compilation is not available in native compiled mode
If you have a cross-compiling C compiler, you can also cross-compile your Forth program to a different architecture:
$ waforthc --cc=arm-linux-gnueabi-gcc --ccflag=-static --output=hello --init=SAY_HELLO hello.fs↩
## How it works
The `waforthc` compiler ([`waforthc.cpp`](https://github.com/remko/waforth/blob/master/src/waforthc/waforthc.cpp)) works as follows:
@ -93,4 +97,4 @@ Currently, all the compiler does is combine the modules generated by WAForth int
- A dead-code elimination pass could remove unnecessary words from the
WAForth core.
Instead of compiling the resulting module to native, it can also be used in e.g. the web environment.
Instead of compiling the resulting module to native, it can also be used in e.g. the web environment.

View file

@ -45,7 +45,8 @@ static std::unique_ptr<wabt::FileStream> stderrStream;
/**
* Compiles a WASM module to a native file named `outfile`.
*/
wabt::Result compileToNative(wabt::Module &mod, const std::string &init, const std::string &outfile) {
wabt::Result compileToNative(wabt::Module &mod, const std::string &init, const std::string &outfile, const std::string &cc,
const std::vector<std::string> &cflags) {
CHECK_RESULT(GenerateNames(&mod));
CHECK_RESULT(ApplyNames(&mod));
// CHECK_RESULT(wabt::ResolveNamesModule(&mod, &errors));
@ -83,7 +84,9 @@ 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));
}
bp::child c(bp::search_path("gcc"), "-o", outfile, (wd / "_waforth_rt.c").string(), (wd / "_waforth.c").string(), (wd / "wasm-rt-impl.c").string(), "-lm");
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) {
@ -324,7 +327,8 @@ wabt::Result compileToModule(std::vector<wabt::Module> &words, const std::vector
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
wabt::Result main_(const std::string &infile, const std::string &outfile, const std::string &init, wabt::Errors &errors) {
wabt::Result main_(const std::string &infile, const std::string &outfile, const std::string &init, const std::string &cc,
const std::vector<std::string> &cflags, wabt::Errors &errors) {
stderrStream = wabt::FileStream::CreateStderr();
std::vector<uint8_t> in;
@ -346,7 +350,7 @@ wabt::Result main_(const std::string &infile, const std::string &outfile, const
if (boost::ends_with(outfile, ".wasm")) {
CHECK_RESULT(writeModule(outfile, compiled));
} else {
CHECK_RESULT(compileToNative(compiled, init, outfile));
CHECK_RESULT(compileToNative(compiled, init, outfile, cc, cflags));
}
return wabt::Result::Ok;
@ -356,11 +360,15 @@ int main(int argc, char *argv[]) {
std::string outfile;
std::string infile;
std::string init;
std::string cc;
std::vector<std::string> ccflags;
bpo::options_description desc("Options");
desc.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.")("input", bpo::value<std::string>(&infile)->required(), "Input file");
@ -379,8 +387,10 @@ int main(int argc, char *argv[]) {
return -1;
}
ccflags.push_back("-lm");
wabt::Errors errors;
if (!Succeeded(main_(infile, outfile, init, errors))) {
if (!Succeeded(main_(infile, outfile, init, cc, ccflags, errors))) {
FormatErrorsToFile(errors, wabt::Location::Type::Binary);
return -1;
}