1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
import os
import osproc
import streams
import strformat
import strtabs
import strutils
from nimpb_buildpkg/plugin import processFileDescriptorSet, ServiceGenerator, Service, ServiceMethod
export Service, ServiceMethod
when defined(windows):
const compilerId = "win32"
elif defined(linux):
when defined(i386):
const arch = "x86_32"
elif defined(amd64):
const arch = "x86_64"
elif defined(arm64):
const arch = "aarch_64"
else:
{.fatal:"unsupported architecture".}
const compilerId = "linux-" & arch
elif defined(macosx):
when defined(amd64):
const arch = "x86_64"
else:
{.fatal:"unsupported architecture".}
const compilerId = "osx-" & arch
else:
{.fatal:"unsupported platform".}
when defined(windows):
const exeSuffix = ".exe"
else:
const exeSuffix = ""
proc findCompiler(): string =
let
compilerName = &"protoc-{compilerId}{exeSuffix}"
paths = @[
getAppDir() / "src" / "nimpb_buildpkg" / "protobuf",
getAppDir() / "nimpb_buildpkg" / "protobuf",
parentDir(currentSourcePath()) / "nimpb_buildpkg" / "protobuf",
]
for path in paths:
if fileExists(path / compilerName):
return path / compilerName
raise newException(Exception, &"{compilerName} not found!")
proc builtinIncludeDir(compilerPath: string): string =
parentDir(compilerPath) / "include"
template verboseEcho(x: untyped): untyped =
if verbose:
echo(x)
proc myTempDir(): string =
result = getTempDir() / "nimpb_build_tmp"
proc compileProtos*(protos: openArray[string],
includes: openArray[string],
outdir: string,
serviceGenerator: ServiceGenerator = nil) =
let command = findCompiler()
var args: seq[string] = @[]
var outputFilename = myTempDir() / "file-descriptor-set"
createDir(myTempDir())
add(args, "--include_imports")
add(args, "--include_source_info")
add(args, &"-o{outputFilename}")
for incdir in includes:
add(args, &"-I{incdir}")
add(args, &"-I{builtinIncludeDir(command)}")
for proto in protos:
add(args, proto)
var cmdline: string = quoteShell(command)
for arg in args:
cmdline &= " " & quoteShell(arg)
let (outp, rc) = execCmdEx(cmdline)
if rc != 0:
raise newException(Exception, outp)
processFileDescriptorSet(outputFilename, outdir, protos, serviceGenerator)
when isMainModule:
proc usage() {.noreturn.} =
echo(&"""
{getAppFilename()} --out=OUTDIR [-IPATH [-IPATH]...] PROTOFILE...
--out The output directory for the generated files
-I Add a path to the set of include paths
""")
quit(QuitFailure)
var includes: seq[string] = @[]
var protos: seq[string] = @[]
var outdir: string
if paramCount() == 0:
usage()
for idx in 1..paramCount():
let param = paramStr(idx)
if param.startsWith("-I"):
add(includes, param[2..^1])
elif param.startsWith("--out="):
outdir = param[6..^1]
elif param == "--help":
usage()
else:
add(protos, param)
if outdir == nil:
echo("error: --out is required")
quit(QuitFailure)
if len(protos) == 0:
echo("error: no input files")
quit(QuitFailure)
compileProtos(protos, includes, outdir)
|