Update doc revision and pdf cover.
[apps/low-level-can-service.git] / libs / nanopb / tests / site_scons / site_tools / nanopb.py
1 '''
2 Scons Builder for nanopb .proto definitions.
3
4 This tool will locate the nanopb generator and use it to generate .pb.c and
5 .pb.h files from the .proto files.
6
7 Basic example
8 -------------
9 # Build myproto.pb.c and myproto.pb.h from myproto.proto
10 myproto = env.NanopbProto("myproto")
11
12 # Link nanopb core to the program
13 env.Append(CPPPATH = "$NANOB")
14 myprog = env.Program(["myprog.c", myproto, "$NANOPB/pb_encode.c", "$NANOPB/pb_decode.c"])
15
16 Configuration options
17 ---------------------
18 Normally, this script is used in the test environment of nanopb and it locates
19 the nanopb generator by a relative path. If this script is used in another
20 application, the path to nanopb root directory has to be defined:
21
22 env.SetDefault(NANOPB = "path/to/nanopb")
23
24 Additionally, the path to protoc and the options to give to protoc can be
25 defined manually:
26
27 env.SetDefault(PROTOC = "path/to/protoc")
28 env.SetDefault(PROTOCFLAGS = "--plugin=protoc-gen-nanopb=path/to/protoc-gen-nanopb")
29 '''
30
31 import SCons.Action
32 import SCons.Builder
33 import SCons.Util
34 import os.path
35
36 class NanopbWarning(SCons.Warnings.Warning):
37     pass
38 SCons.Warnings.enableWarningClass(NanopbWarning)
39
40 def _detect_nanopb(env):
41     '''Find the path to nanopb root directory.'''
42     if env.has_key('NANOPB'):
43         # Use nanopb dir given by user
44         return env['NANOPB']
45     
46     p = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
47     if os.path.isdir(p) and os.path.isfile(os.path.join(p, 'pb.h')):
48         # Assume we are running under tests/site_scons/site_tools
49         return p
50     
51     raise SCons.Errors.StopError(NanopbWarning,
52         "Could not find the nanopb root directory")
53
54 def _detect_protoc(env):
55     '''Find the path to the protoc compiler.'''
56     if env.has_key('PROTOC'):
57         # Use protoc defined by user
58         return env['PROTOC']
59     
60     n = _detect_nanopb(env)
61     p1 = os.path.join(n, 'generator-bin', 'protoc' + env['PROGSUFFIX'])
62     if os.path.exists(p1):
63         # Use protoc bundled with binary package
64         return env['ESCAPE'](p1)
65     
66     p = env.WhereIs('protoc')
67     if p:
68         # Use protoc from path
69         return env['ESCAPE'](p)
70     
71     raise SCons.Errors.StopError(NanopbWarning,
72         "Could not find the protoc compiler")
73
74 def _detect_protocflags(env):
75     '''Find the options to use for protoc.'''
76     if env.has_key('PROTOCFLAGS'):
77         return env['PROTOCFLAGS']
78     
79     p = _detect_protoc(env)
80     n = _detect_nanopb(env)
81     p1 = os.path.join(n, 'generator-bin', 'protoc' + env['PROGSUFFIX'])
82     if p == env['ESCAPE'](p1):
83         # Using the bundled protoc, no options needed
84         return ''
85     
86     e = env['ESCAPE']
87     if env['PLATFORM'] == 'win32':
88         return e('--plugin=protoc-gen-nanopb=' + os.path.join(n, 'generator', 'protoc-gen-nanopb.bat'))
89     else:
90         return e('--plugin=protoc-gen-nanopb=' + os.path.join(n, 'generator', 'protoc-gen-nanopb'))
91
92 def _nanopb_proto_actions(source, target, env, for_signature):
93     esc = env['ESCAPE']
94     dirs = ' '.join(['-I' + esc(env.GetBuildPath(d)) for d in env['PROTOCPATH']])
95     return '$PROTOC $PROTOCFLAGS %s --nanopb_out=. %s' % (dirs, esc(str(source[0])))
96
97 def _nanopb_proto_emitter(target, source, env):
98     basename = os.path.splitext(str(source[0]))[0]
99     target.append(basename + '.pb.h')
100     
101     if os.path.exists(basename + '.options'):
102         source.append(basename + '.options')
103     
104     return target, source
105
106 _nanopb_proto_builder = SCons.Builder.Builder(
107     generator = _nanopb_proto_actions,
108     suffix = '.pb.c',
109     src_suffix = '.proto',
110     emitter = _nanopb_proto_emitter)
111        
112 def generate(env):
113     '''Add Builder for nanopb protos.'''
114     
115     env['NANOPB'] = _detect_nanopb(env)
116     env['PROTOC'] = _detect_protoc(env)
117     env['PROTOCFLAGS'] = _detect_protocflags(env)
118     
119     env.SetDefault(PROTOCPATH = ['.', os.path.join(env['NANOPB'], 'generator', 'proto')])
120     
121     env.SetDefault(NANOPB_PROTO_CMD = '$PROTOC $PROTOCFLAGS --nanopb_out=. $SOURCES')
122     env['BUILDERS']['NanopbProto'] = _nanopb_proto_builder
123     
124 def exists(env):
125     return _detect_protoc(env) and _detect_protoc_opts(env)
126