Unify output directory handling in builder
authorXiretza <xiretza@xiretza.xyz>
Wed, 12 Feb 2020 13:35:23 +0000 (14:35 +0100)
committerXiretza <xiretza@xiretza.xyz>
Wed, 12 Feb 2020 14:47:16 +0000 (15:47 +0100)
litex/soc/integration/builder.py

index 06678bcb88222294db1599c0840e7d074fc2bec2..4c8df1aa9976b1bfd72dd41aded2e13e4c5ca87a 100644 (file)
@@ -36,18 +36,25 @@ def _makefile_escape(s):
 
 
 class Builder:
-    def __init__(self, soc, output_dir=None,
+    def __init__(self, soc,
+                 output_dir=None,
+                 gateware_dir=None,
+                 software_dir=None,
+                 include_dir=None,
+                 generated_dir=None,
                  compile_software=True, compile_gateware=True,
                  gateware_toolchain_path=None,
                  csr_json=None, csr_csv=None):
         self.soc = soc
-        if output_dir is None:
-            output_dir = "soc_{}_{}".format(
-                soc.__class__.__name__.lower(),
-                soc.platform.name)
+
         # From Python doc: makedirs() will become confused if the path
         # elements to create include '..'
-        self.output_dir = os.path.abspath(output_dir)
+        self.output_dir    = os.path.abspath(output_dir or "soc_{}_{}".format(soc.__class__.__name__.lower(), soc.platform.name))
+        self.gateware_dir  = os.path.abspath(gateware_dir or os.path.join(self.output_dir, "gateware"))
+        self.software_dir  = os.path.abspath(software_dir or os.path.join(self.output_dir, "software"))
+        self.include_dir   = os.path.abspath(include_dir or os.path.join(self.software_dir, "include"))
+        self.generated_dir = os.path.abspath(generated_dir or os.path.join(self.include_dir, "generated"))
+
         self.compile_software = compile_software
         self.compile_gateware = compile_gateware
         self.gateware_toolchain_path = gateware_toolchain_path
@@ -64,14 +71,14 @@ class Builder:
         self.software_packages.append((name, src_dir))
 
     def _generate_includes(self):
-        buildinc_dir  = os.path.join(self.output_dir, "software", "include")
-        generated_dir = os.path.join(buildinc_dir, "generated")
-        os.makedirs(generated_dir, exist_ok=True)
+        os.makedirs(self.include_dir, exist_ok=True)
+        os.makedirs(self.generated_dir, exist_ok=True)
 
         if self.soc.cpu_type is not None:
             variables_contents = []
             def define(k, v):
                 variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
+
             for k, v in cpu_interface.get_cpu_mak(self.soc.cpu, self.compile_software):
                 define(k, v)
             # Distinguish between LiteX and MiSoC.
@@ -90,37 +97,39 @@ class Builder:
                 define(k, v)
             define("SOC_DIRECTORY", soc_directory)
             variables_contents.append("export BUILDINC_DIRECTORY\n")
-            define("BUILDINC_DIRECTORY", buildinc_dir)
+            define("BUILDINC_DIRECTORY", self.include_dir)
             for name, src_dir in self.software_packages:
                 define(name.upper() + "_DIRECTORY", src_dir)
+
             write_to_file(
-                os.path.join(generated_dir, "variables.mak"),
+                os.path.join(self.generated_dir, "variables.mak"),
                 "".join(variables_contents))
             write_to_file(
-                os.path.join(generated_dir, "output_format.ld"),
+                os.path.join(self.generated_dir, "output_format.ld"),
                 cpu_interface.get_linker_output_format(self.soc.cpu))
             write_to_file(
-                os.path.join(generated_dir, "regions.ld"),
+                os.path.join(self.generated_dir, "regions.ld"),
                 cpu_interface.get_linker_regions(self.soc.mem_regions))
+
         write_to_file(
-            os.path.join(generated_dir, "mem.h"),
+            os.path.join(self.generated_dir, "mem.h"),
             cpu_interface.get_mem_header(self.soc.mem_regions))
         write_to_file(
-            os.path.join(generated_dir, "soc.h"),
+            os.path.join(self.generated_dir, "soc.h"),
             cpu_interface.get_soc_header(self.soc.constants))
         write_to_file(
-            os.path.join(generated_dir, "csr.h"),
+            os.path.join(self.generated_dir, "csr.h"),
             cpu_interface.get_csr_header(self.soc.csr_regions,
                                          self.soc.constants)
         )
         write_to_file(
-            os.path.join(generated_dir, "git.h"),
+            os.path.join(self.generated_dir, "git.h"),
             cpu_interface.get_git_header()
         )
 
         if hasattr(self.soc, "sdram"):
             from litedram.init import get_sdram_phy_c_header
-            write_to_file(os.path.join(generated_dir, "sdram_phy.h"),
+            write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"),
                 get_sdram_phy_c_header(
                     self.soc.sdram.controller.settings.phy,
                     self.soc.sdram.controller.settings.timing))
@@ -138,7 +147,7 @@ class Builder:
 
     def _prepare_software(self):
         for name, src_dir in self.software_packages:
-            dst_dir = os.path.join(self.output_dir, "software", name)
+            dst_dir = os.path.join(self.software_dir, name)
             os.makedirs(dst_dir, exist_ok=True)
 
     def _generate_software(self, compile_bios=True):
@@ -146,20 +155,20 @@ class Builder:
             if name == "bios" and not compile_bios:
                 pass
             else:
-                dst_dir = os.path.join(self.output_dir, "software", name)
+                dst_dir = os.path.join(self.software_dir, name)
                 makefile = os.path.join(src_dir, "Makefile")
                 if self.compile_software:
                     subprocess.check_call(["make", "-C", dst_dir, "-f", makefile])
 
     def _initialize_rom(self):
-        bios_file = os.path.join(self.output_dir, "software", "bios","bios.bin")
+        bios_file = os.path.join(self.software_dir, "bios", "bios.bin")
         bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness)
         self.soc.initialize_rom(bios_data)
 
     def build(self, toolchain_path=None, **kwargs):
         self.soc.platform.output_dir = self.output_dir
-        os.makedirs(os.path.join(self.output_dir, "gateware"), exist_ok=True)
-        os.makedirs(os.path.join(self.output_dir, "software"), exist_ok=True)
+        os.makedirs(self.gateware_dir, exist_ok=True)
+        os.makedirs(self.software_dir, exist_ok=True)
 
         self.soc.finalize()
 
@@ -178,7 +187,7 @@ class Builder:
 
         if "run" not in kwargs:
             kwargs["run"] = self.compile_gateware
-        vns = self.soc.build(build_dir=os.path.join(self.output_dir, "gateware"),
+        vns = self.soc.build(build_dir=self.gateware_dir,
                              toolchain_path=toolchain_path, **kwargs)
         self.soc.do_exit(vns=vns)
         return vns
@@ -186,8 +195,17 @@ class Builder:
 
 def builder_args(parser):
     parser.add_argument("--output-dir", default=None,
-                        help="output directory for generated "
-                             "source files and binaries")
+                        help="base output directory for generated "
+                             "source files and binaries (customizable "
+                             "with --{gateware,software,include,generated}-dir)")
+    parser.add_argument("--gateware-dir", default=None,
+                        help="output directory for gateware files")
+    parser.add_argument("--software-dir", default=None,
+                        help="base output directory for software files")
+    parser.add_argument("--include-dir", default=None,
+                        help="output directory for header files")
+    parser.add_argument("--generated-dir", default=None,
+                        help="output directory for various generated files")
     parser.add_argument("--no-compile-software", action="store_true",
                         help="do not compile the software, only generate "
                              "build infrastructure")
@@ -208,6 +226,10 @@ def builder_args(parser):
 def builder_argdict(args):
     return {
         "output_dir": args.output_dir,
+        "gateware_dir": args.gateware_dir,
+        "software_dir": args.software_dir,
+        "include_dir": args.include_dir,
+        "generated_dir": args.generated_dir,
         "compile_software": not args.no_compile_software,
         "compile_gateware": not args.no_compile_gateware,
         "gateware_toolchain_path": args.gateware_toolchain_path,