nimbus-eth2/tools/generate_makefile.nim

94 lines
2.8 KiB
Nim
Raw Normal View History

# Copyright (c) 2020-2024 Status Research & Development GmbH
2020-11-27 01:29:06 +00:00
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
# Generate a Makefile from the JSON file produce by the Nim compiler with
# "--compileOnly". Suitable for Make-controlled parallelisation, down to the GCC
# LTO level.
import std/[json, os, strutils]
2020-11-27 01:29:06 +00:00
# Ripped off from Nim's `linkViaResponseFile()` in "compiler/extccomp.nim".
# It lets us get around a command line length limit on Windows.
proc processLinkCmd(cmd, linkerArgs: string): string =
# Extracting the linker.exe here is a bit hacky but the best solution
# given ``buildLib``'s design.
var
i = 0
last = 0
if cmd.len > 0 and cmd[0] == '"':
inc i
while i < cmd.len and cmd[i] != '"': inc i
last = i
inc i
else:
while i < cmd.len and cmd[i] != ' ': inc i
last = i
while i < cmd.len and cmd[i] == ' ': inc i
let args = cmd.substr(i)
writeFile(linkerArgs, args.replace('\\', '/'))
return cmd.substr(0, last) & " @" & linkerArgs
proc main() =
let nrParams = paramCount()
if nrParams != 2:
echo "Usage: ", paramStr(0), " input.json output.makefile"
quit(QuitFailure)
let
jsonPath = paramStr(1)
makefilePath = paramStr(2)
if not fileExists(jsonPath):
echo "No such file: ", jsonPath
quit(QuitFailure)
let
data = json.parseFile(jsonPath)
makefile = open(makefilePath, fmWrite)
defer:
makefile.close()
var
objectPath: string
found: bool
cmd: string
for compile in data["compile"]:
cmd = compile[1].getStr().replace('\\', '/')
2020-11-27 01:29:06 +00:00
objectPath = ""
found = false
for token in split(cmd, Whitespace + {'\''}):
2020-11-27 01:29:06 +00:00
if found and token.len > 0 and token.endsWith(".o"):
objectPath = token
break
if token == "-o":
found = true
if found == false or objectPath == "":
echo "Could not find the object file in this command: ", cmd
quit(QuitFailure)
makefile.writeLine("$#: $#" % [objectPath.replace('\\', '/'), compile[0].getStr().replace('\\', '/')])
2020-11-27 01:29:06 +00:00
makefile.writeLine("\t+ $#\n" % cmd)
var objects: seq[string]
for obj in data["link"]:
objects.add(obj.getStr().replace('\\', '/'))
2020-11-27 01:29:06 +00:00
makefile.writeLine("OBJECTS := $#\n" % objects.join(" \\\n"))
makefile.writeLine(".PHONY: build")
makefile.writeLine("build: $(OBJECTS)")
makefile.writeLine("\t+ $#" % processLinkCmd(data["linkcmd"].getStr().replace('\\', '/'), makefilePath & ".linkerArgs"))
2020-11-27 01:29:06 +00:00
if data.hasKey("extraCmds"):
for cmd in data["extraCmds"]:
makefile.writeLine("\t+ $#" % cmd.getStr().replace('\\', '/'))
2020-11-27 01:29:06 +00:00
main()