Inform 7 v10's Compile to C question

From your inform/inform directory, create a dir for your games, eg games.
Then from inform/inform/games do:

../inform7/Tangled/inform7 -format=C -release mygame.i7
gcc -I../inform7/Tangled mygame.c -o mygame
1 Like

Is there an option to create C code to compile a standalone executable, or does additional interpreter code need to be added?

I think additional code would need to be added, @Wysardry.

Mr. @zarf has mentioned in this post: Inform 7 v10.1.0 is now open-source - #248 by zarf that this c-code is for putting Inform code into other frameworks like Unreal, not for creating executables.

That’s my ultimate goal, to code a game in Unreal or another engine using primarily Inform 7.

Yesterday I did manage to install Inform 7 to my mac’s terminal, and I got a game to ‘run’ and I think I’m very close to getting that c-output but I’m missing a step somewhere that turns it into an .i7 file first.

I followed Zed’s twitter instructions and he says that my c-code went to the build folder in the project, into the file auto.inf, and I opened that file up and it certainly looked like that had happened, so… I imagine just changing it from auto.inf to auto.c would work, but by then it was 4am and I needed to get some sleep.

My plan is then to stick the very simple, inform basic “hello world” into a game engine, and see if it runs.

Then… the real fun begins.

Inform’s C mode just produces a custom Glk app. There shouldn’t be any reason it couldn’t be compiled with GarGlk, Windows Glk, etc.

jkj yuio just posted how to do it.

You get a standalone executable – no additional code is necessary. You may link it with an external Glk library but by default it will use the built-in “Miniglk”.

I was thinking more along the lines of a DOS console program with no GUI, as I’d like to target retro computers.

I’ve never used Inform and the last time I used a C compiler directly was about 30 years ago, so a lot of info in the documentation (and in this thread) is lost on me.

1 Like

Glk is an I/O spec; it doesn’t imply a GUI. Miniglk only supports things that look like console programs.

But the C that’s produced requires a target that can handle 32-bit words. 16-bit or 8-bit targets could only be supported by compiling to Z-code and using a terp.

I would most likely be using SDCC which supposedly supports 8 to 64 bit and 4 byte data types according to their website.

Although i haven’t tried it, SDCC is likely not to work. I had huge problems compiling the C output. It definitely needs improving as it generates giant function that makes some compilers fall over. For example emscripten cannot compile the C as emitted. I had to break up functions into smaller pieces.

2 Likes

Thanks for letting me know. Can you keep us updated if the situation changes or you find a simpler solution?

I have other options I’m exploring, but compiling C code exported by Inform would likely be the simplest (if it worked).

A mid sized game generates about 16MB of source code into a single file. This is monstrous. The biggest culprit is

void i7_initialiser(i7process_t *proc);

This function alone can be 100,000 lines long. Compilers like to optimise on a function-by-function basis, and this one does have some things to improve it.

It’s clear Inform needs to do some work on the C code emitted. But i can understand the idea was to get it working first then optimise later. Which is the sensible way to go. Hopefully we’ll see an update that is much more optimised. For example, i think i7_initialiser could mostly be a large table.

Nevertheless, i think the C output is most exciting and the way to go for future Inform games.

Much as I dislike using C, I do agree that it was the best choice as the first programming language to export to.

Even if you ignore how many platforms you can get C compilers for, there are also plenty of C translator programs targetting Pascal, Nim, Go, WebAssembly, JavaScript etc.

So I have compiled my very simple “Hello.i7” Which I basically copied from the eg-1:

It has compiled to c with over 86,000 lines of code, turning my 32bit program into a 3mb program, mostly of definitions. I used the -basic command, so I thought it wouldn’t use those, but I guess it’s something that inform does need to translate the english into something the computer will understand.

I did get it to print “hello world” in VS code after a little finagling with paths to inform_clib.
I think I can get it to print to Unreal’s console…

After that I don’t know what to do next, since I am still learning how to make games outside of interactive fiction.

Even without the Parser/World Model, there’s a lot of stuff built into Basic Inform: you have all the infrastructure for relations, tables, rules, rulebooks, activities, and generating adaptive text. For instance, you could write this:

Datum is a kind of object.
The plural of datum is data.

Surveys is a plural-named datum.
Graph is a datum.

To demonstrate is a verb.

To begin:
  say "[The surveys] [demonstrate].";
  now the story tense is future tense;
  say "[The graph] [demonstrate]."

And there’s no attempt to strip unused functions. And the way that Inter is translated into C seems to work a lot like: imagine what glulx bytecode the I6 compiler would generate for this bit of Inter, and then generate C that imitates each of those bytecodes in turn.

With gcc, the program above compiled to a 985K binary, but letting gcc optimize for size and strip unused stuff, it got down to 384K.

gcc -lm -I"inform7/Tangled"  -Os -flto -fdata-sections -ffunction-sections basic.c -o basic  -Wl,--gc-sections
2 Likes

The C output is a great start, but it does need some work. I do think, it could be a lot better. But i understand the first priority is always to get it working.

It looks @inform7tips is no longer on twitter. I was able to retrieve these helpful threads from the Wayback Machine (original thread on compiling Inform to C, another wrinkle on C only sections), and I can’t find a whole lot of info on this topic, so I hope it’s okay if I take the liberty of reposting them here for posterity. (I’m not using the blockquote tag because it gives the regular text and code the same background color, which is harder to read, but, to be clear, everything below was written by @Zed.)


Compiling I7 v10 to C

I’ve mentioned that one can compile Inform7 v10 to C instead of Inform 6. Here’s how. (This one won’t be of much interest to people not using inform7 on the command-line.)

inform7 -format=C -internal "$INFORM7DIR/Internal" -transient /tmp -o project.c -source project.i7

If you omit -o project.c it’ll automatically write a .c file with the basename of the source file to the same directory as the source file.

-transient is specified because if you don’t have a -transient or -external specified, inform7 will create $HOME/Inform if it doesn’t already exist so it has somewhere to create a Telemetry dir. The Project Index isn’t created if you use -source.

Then, for gcc users:

gcc -I "$INFORM7DIR/Tangled" -lm project.c -o project

gcc needs to be able to find inform7_clib.h, -I is one easy way to do it. The math library is needed, hence -lm. If you omit -o project, the executable ends up called a.out.

If you’re familiar with I7’s kits (née the I6 Template Layer) you know that one gets different code depending on whether you’re targeting Z-code or Glulx. Compiling to C means you get Glulx-flavored output with a word size of 4 (i.e., 32-bit); Z-code flavored is not an option. (But there will never be a Glulx interpreter involved, of course.)

I7’s own “Miniglk” is built in. According to the documentation, one could build it with one’s own choice of Glk implementation with some effort, but I haven’t tried that yet.

Instead of specifying the source file with -source, one can use -project, but when you use a project you can’t specify -o. The output file will always be auto.inf in its usual location under project.inform/Build, despite being a C file. So…

inform7 -no-progress -no-census-update -format=C -internal $INFORM7DIR/Internal -transient /tmp -project project.inform

Since gcc normally uses the file suffix to determine the source format, you’ll need to add -x c to tell it this is C.

gcc -I "$INFORM7DIR/Tangled" -lm -x c -o project project.inform/Build/auto.inf

And in either the source or project case one can specify an External directory with -external if there are extensions there you want the compilation to have access to.)

Some references:

inform7 command-line usage

target virtual machines


C only sections

Know how you can put (for glulx only) or (for Z-machine only) at the end of a heading for that passage to be included only when compiling to that target? Well, here’s an undocumented feature: you can also say (not for glulx) or (not for Z-machine).

Given just two choices, this would seem like a candidate for the most trivial factoid I’ve tweeted, but here’s another undocumented feature in v10: you can also say (for C only) or (not for C).

I’ve described compiling to C as being “glulx-flavored”. One of the ramifications of that is that when compiling to C, (for glulx only) passages are included, and, of course (not for glulx) passages are excluded.

So how could you include something when compiling to I6 that would be compiled to glulx but exclude it when compiling to C? You could do, e.g.,

Chapter Foo (for glulx only)

Section Bar (not for C)

[code]

But, of course, these conditionals are more of interest when writing extensions than for an individual game. For your own game, you know what target you want and probably aren’t worried about maintaining the ability to switch among three different choices. So if you did want to have differences between C and ulx, unless you also wanted to be able to compile to the z-machine, you could get by with just (not for C) and (not for glulx).

3 Likes

You can find Inform7tips on Mastodon:

Inform 7 Tips (@inform7tips@mastodon.gamedev.place) - Gamedev Mastodon

1 Like

Following the above instructions, I’ve managed to successfully compile a test project. I did find one issue: the -lm flag has to come after the C source file. The command I used was:

gcc -I /usr/share/inform7-ide/Miscellany project.c -lm -o project

yeah, editing the collective inform7tips twitter and mastodon archives into something useful is on the (very long) list. Thanks for recovering these bits.

2 Likes