1313# limitations under the License.
1414
1515load ("@bazel_tools//tools/build_defs/repo:utils.bzl" , "read_netrc" , "use_netrc" )
16- load ("//toolchain/internal:common.bzl" , _arch = "arch" , _attr_dict = "attr_dict" , _exec_os_arch_dict_value = "exec_os_arch_dict_value" , _os = "os" )
17- load ("//toolchain/internal:release_name.bzl" , _llvm_release_name = "llvm_release_name" , _llvm_release_name_19 = "llvm_release_name_19" )
16+ load (
17+ "//toolchain/internal:common.bzl" ,
18+ "attr_dict" ,
19+ "exec_os_arch_dict_value" ,
20+ "host_info" ,
21+ )
22+ load (
23+ "//toolchain/internal:release_name.bzl" ,
24+ "llvm_release_name_context" ,
25+ "llvm_release_name_host_info" ,
26+ )
1827
1928# If a new LLVM version is missing from this list, please add the shasums here
2029# and the new version in toolchain/internal/llvm_distributions.golden.txt.
@@ -672,6 +681,7 @@ def _get_auth(ctx, urls):
672681 return {}
673682
674683def download_llvm (rctx ):
684+ """Download the LLVM distribution for the given context."""
675685 urls = []
676686 sha256 = None
677687 strip_prefix = None
@@ -699,13 +709,13 @@ def download_llvm(rctx):
699709 lib_path = clang_version .get_child ("lib" , lib_name )
700710 rctx .file (lib_path , libclang_rt_content , legacy_utf8 = False )
701711
702- updated_attrs = _attr_dict (rctx .attr )
712+ updated_attrs = attr_dict (rctx .attr )
703713 if update_sha256 :
704714 updated_attrs ["sha256" ].update ([(key , res .sha256 )])
705715 return updated_attrs
706716
707717def _urls (rctx ):
708- (key , urls ) = _exec_os_arch_dict_value (rctx , "urls" , debug = False )
718+ (key , urls ) = exec_os_arch_dict_value (rctx , "urls" , debug = False )
709719 if not urls :
710720 print ("LLVM archive URLs missing and no default fallback provided; will try 'distribution' attribute" ) # buildifier: disable=print
711721
@@ -719,23 +729,31 @@ def _get_llvm_version(rctx):
719729 return rctx .attr .llvm_version
720730 if not rctx .attr .llvm_versions :
721731 fail ("Neither 'llvm_version' nor 'llvm_versions' given." )
722- (_ , llvm_version ) = _exec_os_arch_dict_value (rctx , "llvm_versions" )
732+ (_ , llvm_version ) = exec_os_arch_dict_value (rctx , "llvm_versions" )
723733 if not llvm_version :
724- fail ("LLVM version string missing for ({os}, {arch})" , os = _os (rctx ), arch = _arch (rctx ))
734+ info = host_info (rctx )
735+ fail (
736+ "LLVM version string missing for ({os}/{dist_name}/{dist_verison}, {arch})" ,
737+ os = info .os ,
738+ dist_name = info .dist .name ,
739+ dist_version = info .dist .version ,
740+ arch = info .arch ,
741+ )
725742 return llvm_version
726743
727- def _find_llvm_basename_list (llvm_version , arch , os ):
744+ def _find_llvm_basename_list (llvm_version , host_info ):
728745 """Lookup (llvm_version, arch, os) in the list of basenames in `_llvm_distributions.`"""
729- name = _llvm_release_name_19 (llvm_version , arch , os )
746+ name , _ = llvm_release_name_host_info (llvm_version , host_info )
730747 if name in _llvm_distributions :
731748 return [name ]
732749 return []
733750
734751def _distribution_urls (rctx ):
752+ """Return LLVM `urls`, `shha256` and `strip_prefix` for the given context."""
735753 llvm_version = _get_llvm_version (rctx )
736754
737755 if rctx .attr .distribution == "auto" :
738- basename = _llvm_release_name (rctx , llvm_version )
756+ basename = llvm_release_name_context (rctx , llvm_version )
739757 else :
740758 basename = rctx .attr .distribution
741759
@@ -769,8 +787,8 @@ def _distribution_urls(rctx):
769787def _parse_version (v ):
770788 return tuple ([int (s ) for s in v .split ("." )])
771789
772- def _version_ge ( lhs , rhs ):
773- return _parse_version ( lhs ) >= _parse_version ( rhs )
790+ def _version_string ( version ):
791+ return "." . join ([ str ( v ) for v in version ] )
774792
775793def _write_distributions_impl (ctx ):
776794 """Analyze the configured versions and write to a file for test consumption.
@@ -785,70 +803,167 @@ def _write_distributions_impl(ctx):
785803 """
786804 arch_list = [
787805 "aarch64" ,
806+ "armv7a" ,
807+ "mips" ,
808+ "mipsel" ,
809+ "powerpc64" ,
810+ "powerpc64le" ,
811+ "sparcv9" ,
812+ "x86_32" ,
788813 "x86_64" ,
789814 ]
790815 os_list = [
791816 "darwin" ,
792817 "linux" ,
793- "raspbian" ,
794818 "windows" ,
795819 ]
820+ ANY_VERSION = "0" # Version does not matter, but must be a valid integer
821+ dist_dict_list = {
822+ "linux" : [
823+ # struct(name = "ibm-aix", version = "7.2"), unreachable
824+ # keep sorted
825+ struct (name = "amzn" , version = ANY_VERSION ),
826+ struct (name = "arch" , version = ANY_VERSION ),
827+ struct (name = "centos" , version = "6" ),
828+ struct (name = "centos" , version = "7" ),
829+ struct (name = "debian" , version = "0" ),
830+ struct (name = "debian" , version = "8" ),
831+ struct (name = "debian" , version = "9" ),
832+ struct (name = "fedora" , version = "26" ),
833+ struct (name = "fedora" , version = "27" ),
834+ struct (name = "fedora" , version = "42" ),
835+ struct (name = "freebsd" , version = "10" ),
836+ struct (name = "freebsd" , version = "11" ),
837+ struct (name = "freebsd" , version = "12" ),
838+ struct (name = "freebsd" , version = "13" ),
839+ struct (name = "linuxmint" , version = "18" ),
840+ struct (name = "linuxmint" , version = "19" ),
841+ struct (name = "pc-solaris" , version = "2.11" ),
842+ struct (name = "raspbian" , version = ANY_VERSION ),
843+ struct (name = "rhel" , version = ANY_VERSION ),
844+ struct (name = "sun-solaris" , version = "2.11" ),
845+ struct (name = "suse" , version = "11.3" ),
846+ struct (name = "suse" , version = "12.2" ),
847+ struct (name = "suse" , version = "12.3" ),
848+ struct (name = "suse" , version = "12.4" ),
849+ struct (name = "suse" , version = "15.5" ),
850+ struct (name = "suse" , version = "16.0" ),
851+ struct (name = "suse" , version = "17.0" ),
852+ struct (name = "ubuntu" , version = "14.04" ),
853+ struct (name = "ubuntu" , version = "16.04" ),
854+ struct (name = "ubuntu" , version = "18.04.5" ),
855+ struct (name = "ubuntu" , version = "18.04.6" ),
856+ struct (name = "ubuntu" , version = "18.04" ),
857+ struct (name = "ubuntu" , version = "20.04" ),
858+ struct (name = "ubuntu" , version = "20.10" ),
859+ struct (name = "ubuntu" , version = "22.04" ),
860+ struct (name = "ubuntu" , version = "24.04" ),
861+ ],
862+ }
796863
797864 # Compute all unique version strings starting with `MIN_VERSION`.
798- MIN_VERSION = "19.0.0"
865+ MIN_VERSION = _parse_version ("6.0.0" )
866+ MAX_VERSION = _parse_version ("20.1.3" )
799867 version_list = []
800868 for name in _llvm_distributions .keys ():
801869 for prefix in ["LLVM-" , "clang+llvm-" ]:
802870 if name .startswith (prefix ):
803- version = name .split ("-" , 2 )[1 ]
804- if not _version_ge ( version , MIN_VERSION ) :
805- continue
806- version_list . append ( version )
807- for version in _llvm_distributions_base_url .keys ():
808- if not _version_ge ( version , MIN_VERSION ):
809- continue
810- version_list .append (version )
871+ version = _parse_version ( name .split ("-" , 2 )[1 ])
872+ if version >= MIN_VERSION :
873+ version_list . append ( version )
874+ break
875+ for v in _llvm_distributions_base_url .keys ():
876+ version = _parse_version ( v )
877+ if version >= MIN_VERSION :
878+ version_list .append (version )
811879 versions = {v : None for v in version_list }
812880
813881 # Write versions to output to check which versions we take into account.
814882 output = []
883+ select = []
815884 for version in versions .keys ():
816- output .append ("version: " + version )
885+ output .append ("version: " + _version_string ( version ) )
817886
818887 # We keep track of versions in `not_found` and remove the ones we found.
819888 # So at the end all version that were not found remain, hence the name.
820889 not_found = {
821890 k : v
822891 for k , v in _llvm_distributions .items ()
823- if _version_ge (k .split ("-" )[1 ], MIN_VERSION )
892+ if _parse_version (k .split ("-" )[1 ]) >= MIN_VERSION
824893 }
825894
826895 # While computing we add predicted versions that are not configured as True.
827896 # At the end we add the not-found versions as False.
828897 result = {}
829898
899+ # Collect cases that produce duplicates (or multiple) basenames.
900+ dupes = []
901+
830902 # For all versions X arch X os check if we can compute the distribution.
831903 for version in versions .keys ():
832904 for arch in arch_list :
833905 for os in os_list :
834- basenames = _find_llvm_basename_list (version , arch , os )
835- if len (basenames ) != 1 :
836- continue
837- basename = basenames [0 ]
838- if basename in _llvm_distributions :
839- if basename in not_found :
840- not_found .pop (basename )
841- else :
842- result [basename ] = True
906+ dist_list = dist_dict_list .get (os , [struct (name = os , version = "" )])
907+ for dist in dist_list :
908+ host_info = struct (
909+ arch = arch ,
910+ os = os ,
911+ dist = dist ,
912+ )
913+ basenames = _find_llvm_basename_list (_version_string (version ), host_info )
914+ if version <= MAX_VERSION :
915+ predicted , error = llvm_release_name_host_info (
916+ _version_string (version ),
917+ host_info ,
918+ )
919+ if not error :
920+ if predicted .endswith (".exe" ):
921+ error = "ERROR: Windows .exe is not supported: " + predicted
922+ elif predicted not in _llvm_distributions :
923+ error = "ERROR: Unavailable prediction: " + predicted
924+ else :
925+ arch_found = [arch for arch in arch_list if arch in predicted ]
926+ if len (arch_found ) == 1 and arch_found [0 ] != arch :
927+ error = "ERROR: Bad arch selection: " + predicted
928+ select .append ("{version}-{arch}-{os}/{dist_name}/{dist_version} -> {basename}" .format (
929+ version = _version_string (version ),
930+ arch = arch ,
931+ os = os ,
932+ dist_name = dist .name ,
933+ dist_version = dist .version ,
934+ basename = error or predicted ,
935+ ))
936+ if len (basenames ) != 1 :
937+ if basenames :
938+ dupes .append ("dup: {version}-{arch}-{os}-{dist_name}-{dist_version} -> {count}" .format (
939+ version = _version_string (version ),
940+ arch = arch ,
941+ os = os ,
942+ dist_name = dist .name ,
943+ dist_version = dist .version ,
944+ count = len (basenames ),
945+ ))
946+ dupes .extend ([" : " + basename for basename in basenames ])
947+ continue
948+ basename = basenames [0 ]
949+ if basename in _llvm_distributions :
950+ if basename in not_found :
951+ not_found .pop (basename )
952+ else :
953+ result [basename ] = True
843954
844955 # Build result
845956 for dist in not_found :
846957 result [dist ] = False
847958 output += [("add: " if found else "del: " ) + dist for dist , found in result .items ()]
848- out = ctx . actions . declare_file ( ctx . label . name + ".out" )
849- ctx .actions .write (out , "\n " .join (output ) + "\n " )
850- return [ DefaultInfo ( files = depset ([ out ]))]
959+ output += dupes
960+ ctx .actions .write (ctx . outputs . output , "\n " .join (output ) + "\n " )
961+ ctx . actions . write ( ctx . outputs . select , " \n " . join ( select ) + " \n " )
851962
852963write_distributions = rule (
853964 implementation = _write_distributions_impl ,
965+ attrs = {
966+ "output" : attr .output (mandatory = True ),
967+ "select" : attr .output (mandatory = True ),
968+ },
854969)
0 commit comments