Skip to content

Instantly share code, notes, and snippets.

@tonogram
Last active November 2, 2021 21:23
Show Gist options
  • Save tonogram/151a286bde2f2c69f1b6edecc40b2e67 to your computer and use it in GitHub Desktop.
Save tonogram/151a286bde2f2c69f1b6edecc40b2e67 to your computer and use it in GitHub Desktop.
You can use this build script to compile a NimGL/ImGui project on MacOS.
import strutils, osproc, jsony, os
# The path of the main entrypoint of your program.
const MAIN_PATH = "./src/main.nim"
#[
The `--compileOnly:on` flag tells Nim to generate C++ source files, but
not to assemble or link them. We set the Nimcache to the current directory
because we're going to need to assemble and link them ourselves.
]#
doAssert execCmd("nim cpp --nimcache:\"./.nimcache\" --compileOnly:on " & MAIN_PATH) == 0
#[
The C++ compiler won't let you have arrays of undefined size, but by default,
SEQ_DECL_SIZE (nimbase.h), which is used to set the size of these arrays,
is not defined. To get around this issue, simply replace the sizes of these
tables with 1. This works because C++ does not perform any bounds checking.
]#
let cpp_main = "./.nimcache/@m$1.cpp" % splitPath(MAIN_PATH).tail
writeFile(cpp_main,
readFile(cpp_main).multiReplace(
("ImGuiTable Data[SEQ_DECL_SIZE];", "ImGuiTable Data[1];"),
("ImGuiTableTempData Data[SEQ_DECL_SIZE];", "ImGuiTableTempData Data[1];"),
("ImGuiOldColumns Data[SEQ_DECL_SIZE];", "ImGuiOldColumns Data[1];")
)
)
#[
The Nim compiler generates a JSON file containing all of the commands needed
to assemble and link our program, so we don't actually have to figure out
the commands we need. We just need to remove the `-std=gnu++14` compiler
flag when compiling an Objective-C (.m) source file.
We use Jsony to parse the JSON so we don't have to manually get each field.
(nimble install jsony)
]#
# This object describes all of the fields provided in the generated JSON file.
type BuildInstructions = object
outputFile: string
compile: seq[seq[string]]
link: seq[string]
linkcmd: string
extraCmds: seq[string]
stdinInput: bool
# Use Jsony to parse the generated JSON file into our object.
let json_path = splitPath(MAIN_PATH).tail.changeFileExt("json")
let b = readFile("./.nimcache" / json_path).fromJson(BuildInstructions)
#[
The JSON file generated by the Nim compiler contains a list of pairs of
file paths and compiler commands. We can just loop over this list, check
if the file path is an Objective-C (.m) source file, and if so, remove the
incorrect compiler flag from the command.
]#
for i, cmd in b.compile:
if cmd[0].endsWith(".m"):
doAssert execCmd(cmd[1].replace("-std=gnu++14", "")) == 0
else:
doAssert execCmd(cmd[1]) == 0
#[
We use the linker command provided by the Nim compiler to take all of the
object files we created and link them together into a single executable.
]#
doAssert execCmd(
#[
Make sure the direction of the slashes is consistent, as inconsistent
slashes will confuse the compiler.
NOTE: This simple string replacement will break for directories that
contain spaces in their names. You can fix that yourself.
]#
b.linkcmd.replace("\\", "/")
) == 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment