66ERLANG_HOME_ENV_VAR = "ERLANG_HOME"
77DEFAULT_ERL_PATH = "/usr/bin/erl"
88
9- _EXTERNAL_ERLANG_PACKAGE = "external"
9+ _DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME = "external"
10+
11+ INSTALLATION_TYPE_EXTERNAL = "external"
12+ INSTALLATION_TYPE_INTERNAL = "internal"
1013
1114def _impl (repository_ctx ):
1215 rules_erlang_workspace = repository_ctx .attr .rules_erlang_workspace
1316
14- erlang_installations = {}
15-
16- if ERLANG_HOME_ENV_VAR in repository_ctx .os .environ :
17- erlang_home = repository_ctx .os .environ [ERLANG_HOME_ENV_VAR ]
18- else :
19- if repository_ctx .os .name .find ("windows" ) > 0 :
20- erl_path = repository_ctx .which ("erl.exe" )
21- else :
22- erl_path = repository_ctx .which ("erl" )
23- if erl_path == None :
24- erl_path = repository_ctx .path (DEFAULT_ERL_PATH )
25- erlang_home = str (erl_path .dirname .dirname )
26-
27- erl_path = path_join (erlang_home , "bin" , "erl" )
28- version = repository_ctx .execute (
29- [
30- erl_path ,
31- "-noshell" ,
32- "-eval" ,
33- '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' ,
34- ],
35- timeout = 10 ,
36- )
37- if version .return_code == 0 :
38- erlang_version = version .stdout .strip ("\n " )
39- (major , _ , _ ) = erlang_version .partition ("." )
40- erlang_installations [_EXTERNAL_ERLANG_PACKAGE ] = major
41- repository_ctx .template (
42- "{}/BUILD.bazel" .format (_EXTERNAL_ERLANG_PACKAGE ),
43- Label ("//repositories:BUILD_external.tpl" ),
44- {
45- "%{ERLANG_HOME}" : erlang_home ,
46- "%{ERLANG_VERSION}" : erlang_version ,
47- "%{ERLANG_MAJOR}" : major ,
48- "%{RULES_ERLANG_WORKSPACE}" : rules_erlang_workspace ,
49- },
50- False ,
51- )
52-
53- for name in repository_ctx .attr .versions .keys ():
54- if name == _EXTERNAL_ERLANG_PACKAGE :
55- fail ("'{}' is not allowed as an internal erlang name" .format (
56- _EXTERNAL_ERLANG_PACKAGE ,
17+ erlang_installations = _default_erlang_dict (repository_ctx )
18+ for name in repository_ctx .attr .types .keys ():
19+ if name == _DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME :
20+ fail ("'{}' is reserved as an erlang name" .format (
21+ _DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME ,
5722 ))
58-
59- version = repository_ctx .attr .versions .get (name )
23+ version = repository_ctx .attr .versions [name ]
6024 (major , _ , _ ) = version .partition ("." )
61- erlang_installations [name ] = major
62-
63- repository_ctx .template (
64- "{}/BUILD.bazel" .format (name ),
65- Label ("//repositories:BUILD_internal.tpl" ),
66- {
67- "%{ERLANG_VERSION}" : version ,
68- "%{URL}" : repository_ctx .attr .urls .get (name ),
69- "%{STRIP_PREFIX}" : repository_ctx .attr .strip_prefixs .get (name , "" ),
70- "%{SHA_256}" : repository_ctx .attr .sha256s .get (name , "" ),
71- "%{ERLANG_MAJOR}" : major ,
72- "%{RULES_ERLANG_WORKSPACE}" : rules_erlang_workspace ,
73- },
74- False ,
25+ erlang_installations [name ] = struct (
26+ type = repository_ctx .attr .types [name ],
27+ version = version ,
28+ major = major ,
29+ url = repository_ctx .attr .urls .get (name , None ),
30+ strip_prefix = repository_ctx .attr .strip_prefixs .get (name , None ),
31+ sha256 = repository_ctx .attr .sha256s .get (name , None ),
32+ erlang_home = repository_ctx .attr .erlang_homes .get (name , None ),
7533 )
7634
35+ for (name , props ) in erlang_installations .items ():
36+ if props .type == INSTALLATION_TYPE_EXTERNAL :
37+ repository_ctx .template (
38+ "{}/BUILD.bazel" .format (name ),
39+ Label ("//repositories:BUILD_external.tpl" ),
40+ {
41+ "%{ERLANG_HOME}" : props .erlang_home ,
42+ "%{ERLANG_VERSION}" : props .version ,
43+ "%{ERLANG_MAJOR}" : props .major ,
44+ "%{RULES_ERLANG_WORKSPACE}" : rules_erlang_workspace ,
45+ },
46+ False ,
47+ )
48+ else :
49+ repository_ctx .template (
50+ "{}/BUILD.bazel" .format (name ),
51+ Label ("//repositories:BUILD_internal.tpl" ),
52+ {
53+ "%{ERLANG_VERSION}" : props .version ,
54+ "%{URL}" : props .url ,
55+ "%{STRIP_PREFIX}" : props .strip_prefix or "" ,
56+ "%{SHA_256}" : props .sha256 or "" ,
57+ "%{ERLANG_MAJOR}" : props .major ,
58+ "%{RULES_ERLANG_WORKSPACE}" : rules_erlang_workspace ,
59+ },
60+ False ,
61+ )
62+
63+ if len (erlang_installations ) == 0 :
64+ fail ("No erlang installations configured" )
65+
7766 repository_ctx .file (
7867 "BUILD.bazel" ,
7968 _build_file_content (erlang_installations ),
@@ -101,23 +90,67 @@ erlang_config = repository_rule(
10190 implementation = _impl ,
10291 attrs = {
10392 "rules_erlang_workspace" : attr .string (),
93+ "types" : attr .string_dict (),
10494 "versions" : attr .string_dict (),
10595 "urls" : attr .string_dict (),
10696 "strip_prefixs" : attr .string_dict (),
10797 "sha256s" : attr .string_dict (),
98+ "erlang_homes" : attr .string_dict (),
10899 },
109100 environ = [
110101 "ERLANG_HOME" ,
111102 ],
112103)
113104
105+ def _default_erlang_dict (repository_ctx ):
106+ if ERLANG_HOME_ENV_VAR in repository_ctx .os .environ :
107+ erlang_home = repository_ctx .os .environ [ERLANG_HOME_ENV_VAR ]
108+ else :
109+ if repository_ctx .os .name .find ("windows" ) > 0 :
110+ erl_path = repository_ctx .which ("erl.exe" )
111+ else :
112+ erl_path = repository_ctx .which ("erl" )
113+ if erl_path == None :
114+ erl_path = repository_ctx .path (DEFAULT_ERL_PATH )
115+ erlang_home = str (erl_path .dirname .dirname )
116+
117+ erl_path = path_join (erlang_home , "bin" , "erl" )
118+ version = repository_ctx .execute (
119+ [
120+ erl_path ,
121+ "-noshell" ,
122+ "-eval" ,
123+ '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' ,
124+ ],
125+ timeout = 10 ,
126+ )
127+ if version .return_code == 0 :
128+ version = version .stdout .strip ("\n " )
129+ (major , _ , _ ) = version .partition ("." )
130+ return {
131+ _DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME : struct (
132+ type = INSTALLATION_TYPE_EXTERNAL ,
133+ version = version ,
134+ major = major ,
135+ erlang_home = erlang_home ,
136+ ),
137+ }
138+ else :
139+ return {}
140+
114141def _build_file_content (erlang_installations ):
115- if _EXTERNAL_ERLANG_PACKAGE in erlang_installations :
116- default_internal_external = "external"
117- default_major = erlang_installations [_EXTERNAL_ERLANG_PACKAGE ]
142+ external_installations = {
143+ name : props
144+ for (name , props ) in erlang_installations .items ()
145+ if props .type == INSTALLATION_TYPE_EXTERNAL
146+ }
147+
148+ if _DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME in erlang_installations :
149+ default_installation = erlang_installations [_DEFAULT_EXTERNAL_ERLANG_PACKAGE_NAME ]
150+ elif len (external_installations ) > 0 :
151+ default_installation = external_installations [0 ]
118152 else :
119- default_internal_external = "internal"
120- default_major = erlang_installations [0 ]
153+ default_installation = erlang_installations [0 ]
121154
122155 build_file_content = """\
123156 package(
@@ -135,17 +168,12 @@ constraint_setting(
135168)
136169
137170""" .format (
138- default_internal_external = default_internal_external ,
139- default_major = default_major ,
171+ default_internal_external = default_installation . type ,
172+ default_major = default_installation . major ,
140173 )
141174
142- should_have_external = False
143- should_have_internal = False
144- if _EXTERNAL_ERLANG_PACKAGE in erlang_installations :
145- should_have_external = True
146- should_have_internal = len (erlang_installations ) > 1
147- else :
148- should_have_internal = len (erlang_installations ) > 0
175+ should_have_external = len (external_installations ) > 0
176+ should_have_internal = len (erlang_installations ) > len (external_installations )
149177
150178 if should_have_external :
151179 build_file_content += """\
@@ -166,8 +194,8 @@ constraint_value(
166194"""
167195
168196 unique_majors = {
169- v : n
170- for (n , v ) in erlang_installations .items ()
197+ props . major : name
198+ for (name , props ) in erlang_installations .items ()
171199 }.keys ()
172200 for major in unique_majors :
173201 build_file_content += """\
0 commit comments