Add the ability to separate architecture in path scheme (#4329)
* Add format to separate target and os for path
spec format can now handle separations of target and os for setting
up the path.
* Added ${PLATFORM} et al to spec.format()
${PLATFORM}, ${OS}, ${TARGET}
* Update tests
Updated tests and got rid of unnecessary code.
* Also update documentation to reflect this new ability.
* Add default path scheme to config.yaml
Added default path scheme to config.yaml. Users can overwrite this
section if they want.
			
			
This commit is contained in:
		@@ -22,6 +22,9 @@ config:
 | 
			
		||||
  template_dirs:
 | 
			
		||||
    - $spack/templates
 | 
			
		||||
 | 
			
		||||
  # default directory layout
 | 
			
		||||
  directory_layout: "${ARCHITECTURE}/${COMPILERNAME}-${COMPILERVER}/${PACKAGE}-${VERSION}-${HASH}"
 | 
			
		||||
 | 
			
		||||
  # Locations where different types of modules should be installed.
 | 
			
		||||
  module_roots:
 | 
			
		||||
    tcl:    $spack/share/spack/modules
 | 
			
		||||
 
 | 
			
		||||
@@ -2905,6 +2905,9 @@ def format(self, format_string='$_$@$%@+$+$=', **kwargs):
 | 
			
		||||
            ${COMPILERFLAGS} Compiler flags
 | 
			
		||||
            ${OPTIONS}       Options
 | 
			
		||||
            ${ARCHITECTURE}  Architecture
 | 
			
		||||
            ${PLATFORM}      Platform
 | 
			
		||||
            ${OS}            Operating System
 | 
			
		||||
            ${TARGET}        Target
 | 
			
		||||
            ${SHA1}          Dependencies 8-char sha1 prefix
 | 
			
		||||
            ${HASH:len}      DAG hash with optional length specifier
 | 
			
		||||
 | 
			
		||||
@@ -3062,12 +3065,22 @@ def write(s, c):
 | 
			
		||||
                elif named_str == 'OPTIONS':
 | 
			
		||||
                    if self.variants:
 | 
			
		||||
                        write(fmt % token_transform(str(self.variants)), '+')
 | 
			
		||||
                elif named_str == 'ARCHITECTURE':
 | 
			
		||||
                elif named_str in ["ARCHITECTURE", "PLATFORM", "TARGET", "OS"]:
 | 
			
		||||
                    if self.architecture and str(self.architecture):
 | 
			
		||||
                        write(
 | 
			
		||||
                            fmt % token_transform(str(self.architecture)),
 | 
			
		||||
                            '='
 | 
			
		||||
                        )
 | 
			
		||||
                        if named_str == "ARCHITECTURE":
 | 
			
		||||
                            write(
 | 
			
		||||
                                fmt % token_transform(str(self.architecture)),
 | 
			
		||||
                                '='
 | 
			
		||||
                            )
 | 
			
		||||
                        elif named_str == "PLATFORM":
 | 
			
		||||
                            platform = str(self.architecture.platform)
 | 
			
		||||
                            write(fmt % token_transform(platform), '=')
 | 
			
		||||
                        elif named_str == "OS":
 | 
			
		||||
                            operating_sys = str(self.architecture.platform_os)
 | 
			
		||||
                            write(fmt % token_transform(operating_sys), '=')
 | 
			
		||||
                        elif named_str == "TARGET":
 | 
			
		||||
                            target = str(self.architecture.target)
 | 
			
		||||
                            write(fmt % token_transform(target), '=')
 | 
			
		||||
                elif named_str == 'SHA1':
 | 
			
		||||
                    if self.dependencies:
 | 
			
		||||
                        out.write(fmt % token_transform(str(self.dag_hash(7))))
 | 
			
		||||
 
 | 
			
		||||
@@ -74,13 +74,19 @@ def test_yaml_directory_layout_parameters(
 | 
			
		||||
    # Test path_scheme
 | 
			
		||||
    arch, compiler, package7 = path_7.split('/')
 | 
			
		||||
    scheme_package7 = "${PACKAGE}-${VERSION}-${HASH:7}"
 | 
			
		||||
 | 
			
		||||
    layout_package7 = YamlDirectoryLayout(str(tmpdir),
 | 
			
		||||
                                          path_scheme=scheme_package7)
 | 
			
		||||
    path_package7 = layout_package7.relative_path_for_spec(spec)
 | 
			
		||||
 | 
			
		||||
    assert(package7 == path_package7)
 | 
			
		||||
 | 
			
		||||
    # Test separation of architecture
 | 
			
		||||
    arch_scheme_package = "${PLATFORM}/${TARGET}/${OS}/${PACKAGE}/${VERSION}/${HASH:7}"   # NOQA: ignore=E501
 | 
			
		||||
    layout_arch_package = YamlDirectoryLayout(str(tmpdir),
 | 
			
		||||
                                              path_scheme=arch_scheme_package)
 | 
			
		||||
    arch_path_package = layout_arch_package.relative_path_for_spec(spec)
 | 
			
		||||
    assert(arch_path_package == spec.format(arch_scheme_package))
 | 
			
		||||
 | 
			
		||||
    # Ensure conflicting parameters caught
 | 
			
		||||
    with pytest.raises(InvalidDirectoryLayoutParametersError):
 | 
			
		||||
        YamlDirectoryLayout(str(tmpdir),
 | 
			
		||||
 
 | 
			
		||||
@@ -720,3 +720,45 @@ def test_exceptional_paths_for_constructor(self):
 | 
			
		||||
 | 
			
		||||
        with pytest.raises(ValueError):
 | 
			
		||||
            Spec('libelf foo')
 | 
			
		||||
 | 
			
		||||
    def test_spec_formatting(self):
 | 
			
		||||
        spec = Spec("libelf cflags=-O2")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
 | 
			
		||||
        # Since the default is the full spec see if the string rep of
 | 
			
		||||
        # spec is the same as the output of spec.format()
 | 
			
		||||
        # ignoring whitespace (though should we?)
 | 
			
		||||
        assert str(spec) == spec.format().strip()
 | 
			
		||||
 | 
			
		||||
        # Testing named strings ie ${STRING} and whether we get
 | 
			
		||||
        # the correct component
 | 
			
		||||
        package_segments = [("${PACKAGE}", "name"),
 | 
			
		||||
                            ("${VERSION}", "versions"),
 | 
			
		||||
                            ("${COMPILER}", "compiler"),
 | 
			
		||||
                            ("${COMPILERFLAGS}", "compiler_flags"),
 | 
			
		||||
                            ("${OPTIONS}", "variants"),
 | 
			
		||||
                            ("${ARCHITECTURE}", "architecture")]
 | 
			
		||||
 | 
			
		||||
        compiler_segments = [("${COMPILERNAME}", "name"),
 | 
			
		||||
                             ("${COMPILERVER}", "versions")]
 | 
			
		||||
 | 
			
		||||
        architecture_segments = [("${PLATFORM}", "platform"),
 | 
			
		||||
                                 ("${OS}", "platform_os"),
 | 
			
		||||
                                 ("${TARGET}", "target")]
 | 
			
		||||
 | 
			
		||||
        for named_str, prop in package_segments:
 | 
			
		||||
            expected = getattr(spec, prop, "")
 | 
			
		||||
            actual = spec.format(named_str)
 | 
			
		||||
            assert str(expected) == actual
 | 
			
		||||
 | 
			
		||||
        compiler = spec.compiler
 | 
			
		||||
        for named_str, prop in compiler_segments:
 | 
			
		||||
            expected = getattr(compiler, prop, "")
 | 
			
		||||
            actual = spec.format(named_str)
 | 
			
		||||
            assert str(expected) == actual
 | 
			
		||||
 | 
			
		||||
        arch = spec.architecture
 | 
			
		||||
        for named_str, prop in architecture_segments:
 | 
			
		||||
            expected = getattr(arch, prop, "")
 | 
			
		||||
            actual = spec.format(named_str)
 | 
			
		||||
            assert str(expected) == actual
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user