jolt 0.9.419__py3-none-any.whl → 0.9.430__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. jolt/cache.py +19 -0
  2. jolt/cli.py +3 -2
  3. jolt/filesystem.py +2 -2
  4. jolt/log.py +12 -2
  5. jolt/pkgs/abseil.py +42 -0
  6. jolt/pkgs/asio.py +25 -0
  7. jolt/pkgs/autoconf.py +41 -0
  8. jolt/pkgs/automake.py +41 -0
  9. jolt/pkgs/b2.py +31 -0
  10. jolt/pkgs/boost.py +111 -0
  11. jolt/pkgs/boringssl.py +32 -0
  12. jolt/pkgs/busybox.py +39 -0
  13. jolt/pkgs/bzip2.py +43 -0
  14. jolt/pkgs/cares.py +29 -0
  15. jolt/pkgs/catch2.py +36 -0
  16. jolt/pkgs/cbindgen.py +17 -0
  17. jolt/pkgs/cista.py +19 -0
  18. jolt/pkgs/clang.py +44 -0
  19. jolt/pkgs/cli11.py +23 -0
  20. jolt/pkgs/cmake.py +48 -0
  21. jolt/pkgs/cpython.py +196 -0
  22. jolt/pkgs/crun.py +29 -0
  23. jolt/pkgs/curl.py +38 -0
  24. jolt/pkgs/dbus.py +18 -0
  25. jolt/pkgs/double_conversion.py +24 -0
  26. jolt/pkgs/fastfloat.py +21 -0
  27. jolt/pkgs/ffmpeg.py +28 -0
  28. jolt/pkgs/flatbuffers.py +29 -0
  29. jolt/pkgs/fmt.py +27 -0
  30. jolt/pkgs/fstree.py +20 -0
  31. jolt/pkgs/gflags.py +18 -0
  32. jolt/pkgs/glib.py +18 -0
  33. jolt/pkgs/glog.py +25 -0
  34. jolt/pkgs/glslang.py +21 -0
  35. jolt/pkgs/golang.py +16 -11
  36. jolt/pkgs/googlebenchmark.py +18 -0
  37. jolt/pkgs/googletest.py +46 -0
  38. jolt/pkgs/gperf.py +15 -0
  39. jolt/pkgs/grpc.py +73 -0
  40. jolt/pkgs/hdf5.py +19 -0
  41. jolt/pkgs/help2man.py +14 -0
  42. jolt/pkgs/inja.py +28 -0
  43. jolt/pkgs/jsoncpp.py +31 -0
  44. jolt/pkgs/libarchive.py +43 -0
  45. jolt/pkgs/libcap.py +44 -0
  46. jolt/pkgs/libdrm.py +44 -0
  47. jolt/pkgs/libedit.py +42 -0
  48. jolt/pkgs/libevent.py +31 -0
  49. jolt/pkgs/libexpat.py +27 -0
  50. jolt/pkgs/libfastjson.py +21 -0
  51. jolt/pkgs/libffi.py +16 -0
  52. jolt/pkgs/libglvnd.py +30 -0
  53. jolt/pkgs/libogg.py +28 -0
  54. jolt/pkgs/libpciaccess.py +18 -0
  55. jolt/pkgs/libseccomp.py +21 -0
  56. jolt/pkgs/libtirpc.py +24 -0
  57. jolt/pkgs/libtool.py +42 -0
  58. jolt/pkgs/libunwind.py +35 -0
  59. jolt/pkgs/libva.py +18 -0
  60. jolt/pkgs/libvorbis.py +33 -0
  61. jolt/pkgs/libxml2.py +35 -0
  62. jolt/pkgs/libxslt.py +17 -0
  63. jolt/pkgs/libyajl.py +16 -0
  64. jolt/pkgs/llvm.py +81 -0
  65. jolt/pkgs/lua.py +54 -0
  66. jolt/pkgs/lz4.py +26 -0
  67. jolt/pkgs/m4.py +14 -0
  68. jolt/pkgs/make.py +17 -0
  69. jolt/pkgs/mesa.py +81 -0
  70. jolt/pkgs/meson.py +17 -0
  71. jolt/pkgs/mstch.py +28 -0
  72. jolt/pkgs/mysql.py +60 -0
  73. jolt/pkgs/nasm.py +49 -0
  74. jolt/pkgs/ncurses.py +30 -0
  75. jolt/pkgs/ng_log.py +25 -0
  76. jolt/pkgs/ninja.py +45 -0
  77. jolt/pkgs/nlohmann_json.py +25 -0
  78. jolt/pkgs/nodejs.py +19 -11
  79. jolt/pkgs/opencv.py +24 -0
  80. jolt/pkgs/openjdk.py +26 -0
  81. jolt/pkgs/openssl.py +103 -0
  82. jolt/pkgs/paho.py +76 -0
  83. jolt/pkgs/patchelf.py +16 -0
  84. jolt/pkgs/perl.py +42 -0
  85. jolt/pkgs/pkgconfig.py +64 -0
  86. jolt/pkgs/poco.py +39 -0
  87. jolt/pkgs/protobuf.py +77 -0
  88. jolt/pkgs/pugixml.py +27 -0
  89. jolt/pkgs/python.py +19 -0
  90. jolt/pkgs/qt.py +35 -0
  91. jolt/pkgs/rapidjson.py +26 -0
  92. jolt/pkgs/rapidyaml.py +28 -0
  93. jolt/pkgs/re2.py +30 -0
  94. jolt/pkgs/re2c.py +17 -0
  95. jolt/pkgs/readline.py +15 -0
  96. jolt/pkgs/rust.py +41 -0
  97. jolt/pkgs/sdl.py +28 -0
  98. jolt/pkgs/simdjson.py +27 -0
  99. jolt/pkgs/soci.py +46 -0
  100. jolt/pkgs/spdlog.py +29 -0
  101. jolt/pkgs/spirv_llvm.py +21 -0
  102. jolt/pkgs/spirv_tools.py +24 -0
  103. jolt/pkgs/sqlite.py +83 -0
  104. jolt/pkgs/ssl.py +12 -0
  105. jolt/pkgs/texinfo.py +15 -0
  106. jolt/pkgs/tomlplusplus.py +22 -0
  107. jolt/pkgs/wayland.py +26 -0
  108. jolt/pkgs/x11.py +58 -0
  109. jolt/pkgs/xerces_c.py +20 -0
  110. jolt/pkgs/xorg.py +360 -0
  111. jolt/pkgs/xz.py +29 -0
  112. jolt/pkgs/yamlcpp.py +30 -0
  113. jolt/pkgs/zeromq.py +47 -0
  114. jolt/pkgs/zlib.py +69 -0
  115. jolt/pkgs/zstd.py +33 -0
  116. jolt/plugins/autotools.py +66 -0
  117. jolt/plugins/cmake.py +74 -6
  118. jolt/plugins/cxxinfo.py +7 -0
  119. jolt/plugins/fetch.py +141 -0
  120. jolt/plugins/git.py +33 -11
  121. jolt/plugins/libtool.py +63 -0
  122. jolt/plugins/meson.py +61 -0
  123. jolt/plugins/ninja.py +236 -17
  124. jolt/plugins/pkgconfig.py +219 -0
  125. jolt/plugins/python.py +137 -0
  126. jolt/plugins/rust.py +25 -0
  127. jolt/plugins/selfdeploy/setup.py +1 -0
  128. jolt/tasks.py +79 -14
  129. jolt/tools.py +86 -42
  130. jolt/utils.py +6 -0
  131. jolt/version.py +1 -1
  132. {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/METADATA +19 -2
  133. jolt-0.9.430.dist-info/RECORD +207 -0
  134. jolt-0.9.419.dist-info/RECORD +0 -92
  135. {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/WHEEL +0 -0
  136. {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/entry_points.txt +0 -0
  137. {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/top_level.txt +0 -0
jolt/plugins/ninja.py CHANGED
@@ -4,6 +4,7 @@ import copy
4
4
  import functools
5
5
  from ninja import ninja_syntax as ninja
6
6
  import os
7
+ import platform
7
8
  import re
8
9
  import sys
9
10
 
@@ -21,6 +22,12 @@ from jolt.error import raise_task_error_if
21
22
  from jolt.error import JoltError, JoltCommandError
22
23
 
23
24
 
25
+ c_standard_default = 17
26
+ cxx_standard_default = 17
27
+ c_standards_list = [90, 99, 11, 17, 23]
28
+ cxx_standards_list = [98, 11, 14, 17, 20, 23, 26]
29
+
30
+
24
31
  class CompileError(JoltError):
25
32
  def __init__(self, error):
26
33
  if error:
@@ -751,6 +758,54 @@ class ProjectVariable(Variable):
751
758
  return "PV: default={},attrib={}".format(self._default, self._attrib)
752
759
 
753
760
 
761
+ class StdVariable(Variable):
762
+ def __init__(self, lang, flagfmt, values, supported=None, default=None):
763
+ self._lang = lang
764
+ self._flagfmt = flagfmt
765
+ self._values = values
766
+ self._supported = supported or values
767
+ self._default = default
768
+
769
+ def create(self, project, writer, deps, tools):
770
+ value = getattr(project, self.name, self._default) or self._default
771
+ if not value:
772
+ return
773
+ raise_task_error_if(
774
+ type(value) is not int,
775
+ project,
776
+ f"Illegal {self._lang} language standard: '{value}'. Expected integer."
777
+ )
778
+ raise_task_error_if(
779
+ value not in self._values,
780
+ project,
781
+ f"Illegal {self._lang} language standard: '{value}'. Expected one of: {', '.join([str(v) for v in self._values])}"
782
+ )
783
+
784
+ if value not in self._supported:
785
+ new_value = min(self._supported, key=lambda n: abs(n - value))
786
+ project.warning(f"{self._lang}{value} is not supported. Using {self._lang}{new_value} instead.")
787
+ value = new_value
788
+
789
+ writer.variable(self.name, self._flagfmt.format(value))
790
+
791
+
792
+ class OptimizationVariable(Variable):
793
+ def __init__(self, default, values, name=None):
794
+ self.name = name
795
+ self._default = default
796
+ self._values = values
797
+ assert type(values) is dict, "Optimization values must be dict with compiler flag mapping"
798
+
799
+ def create(self, project, writer, deps, tools):
800
+ value = str(getattr(project, "optimize", self._default))
801
+ raise_task_error_if(
802
+ value not in self._values,
803
+ project,
804
+ f"Illegal value assigned to 'optimize' ({value}). Expected: 'none', 'debug', 'size', or 'release'."
805
+ )
806
+ writer.variable(self.name, self._values[value])
807
+
808
+
754
809
  class SharedLibraryVariable(Variable):
755
810
  def __init__(self, name=None, default=None):
756
811
  self.name = name
@@ -1153,7 +1208,8 @@ class Skip(Rule):
1153
1208
 
1154
1209
  @task_attributes.system
1155
1210
  class MakeDirectory(Rule):
1156
- command_linux = "mkdir -p $out"
1211
+ command_darwin = "mkdir -p $out"
1212
+ command_linux = command_darwin
1157
1213
  command_windows = "if not exist $out mkdir $out"
1158
1214
 
1159
1215
  def __init__(self, name):
@@ -1539,7 +1595,17 @@ class GNUToolchain(Toolchain):
1539
1595
  cxxwrap = EnvironmentVariable(default="")
1540
1596
  flatc = ToolEnvironmentVariable(default="flatc", envname="FLATC", abspath=True)
1541
1597
  protoc = ToolEnvironmentVariable(default="protoc", envname="PROTOC", abspath=True)
1542
-
1598
+ strip = ToolEnvironmentVariable(default="strip", envname="STRIP", abspath=True)
1599
+
1600
+ cstd = StdVariable("C", "-std=c{}", values=c_standards_list, default=c_standard_default)
1601
+ cxxstd = StdVariable("C++", "-std=c++{}", values=cxx_standards_list, default=cxx_standard_default)
1602
+ optflag = OptimizationVariable(default="release", values={
1603
+ "none": "-O0",
1604
+ "debug": "-Og",
1605
+ "size": "-Os",
1606
+ "release": "-O2",
1607
+ None: "-O0",
1608
+ })
1543
1609
  asflags = EnvironmentVariable(default="")
1544
1610
  cflags = EnvironmentVariable(default="")
1545
1611
  cxxflags = EnvironmentVariable(default="")
@@ -1570,7 +1636,7 @@ class GNUToolchain(Toolchain):
1570
1636
  mkdir_debug = MakeDirectory(name="$outdir_rel/.debug")
1571
1637
 
1572
1638
  compile_pch = GNUCompiler(
1573
- command="$cxxwrap $cxx -x c++-header $cxxflags $shared_flags $imported_cxxflags $extra_cxxflags $covflags $macros $incpaths -MMD -MF $out.d -c $in -o $out",
1639
+ command="$cxxwrap $cxx -x c++-header $cxxstd $optflag $cxxflags $shared_flags $imported_cxxflags $extra_cxxflags $covflags $macros $incpaths -MMD -MF $out.d -c $in -o $out",
1574
1640
  deps="gcc",
1575
1641
  depfile="$out.d",
1576
1642
  infiles=[GNUPCHVariables.pch_ext],
@@ -1579,7 +1645,7 @@ class GNUToolchain(Toolchain):
1579
1645
  variables={"desc": "[PCH] {in_base}{in_ext}"})
1580
1646
 
1581
1647
  compile_c = GNUCompiler(
1582
- command="$ccwrap $cc -x c $pch_flags $cflags $shared_flags $imported_cflags $extra_cflags $covflags $macros $incpaths -MMD -MF $out.d -c $in -o $out",
1648
+ command="$ccwrap $cc -x c $cstd $pch_flags $optflag $cflags $shared_flags $imported_cflags $extra_cflags $covflags $macros $incpaths -MMD -MF $out.d -c $in -o $out",
1583
1649
  deps="gcc",
1584
1650
  depfile="$out.d",
1585
1651
  infiles=[".c"],
@@ -1589,7 +1655,7 @@ class GNUToolchain(Toolchain):
1589
1655
  implicit=["$cc_path"])
1590
1656
 
1591
1657
  compile_cxx = GNUCompiler(
1592
- command="$cxxwrap $cxx -x c++ $pch_flags $cxxflags $shared_flags $imported_cxxflags $extra_cxxflags $covflags $macros $incpaths -MMD -MF $out.d -c $in -o $out",
1658
+ command="$cxxwrap $cxx -x c++ $cxxstd $pch_flags $optflag $cxxflags $shared_flags $imported_cxxflags $extra_cxxflags $covflags $macros $incpaths -MMD -MF $out.d -c $in -o $out",
1593
1659
  deps="gcc",
1594
1660
  depfile="$out.d",
1595
1661
  infiles=[".cc", ".cpp", ".cxx"],
@@ -1658,6 +1724,55 @@ class GNUToolchain(Toolchain):
1658
1724
  suffix=".a")
1659
1725
 
1660
1726
 
1727
+ class BSDArchiver(Rule):
1728
+ def __init__(self, *args, **kwargs):
1729
+ super(BSDArchiver, self).__init__(*args, aggregate=True, **kwargs)
1730
+
1731
+ def build(self, project, writer, infiles, implicit=None, order_only=None):
1732
+ writer._objects = infiles
1733
+ project._binaries, _ = self._out(project, project.binary)
1734
+ file_list = FileListWriter("objects", project._binaries)
1735
+ file_list.build(project, writer, infiles)
1736
+ super().build(project, writer, infiles, implicit=writer.depimports, order_only=order_only)
1737
+
1738
+ def get_influence(self, task):
1739
+ return "BSDArchiver" + super().get_influence(task)
1740
+
1741
+
1742
+ class DarwinGNUToolchain(GNUToolchain):
1743
+ libtool = ToolEnvironmentVariable(default="libtool", envname="LIBTOOL", abspath=True)
1744
+ dsymutil = ToolEnvironmentVariable(default="dsymutil", envname="DSYMUTIL", abspath=True)
1745
+
1746
+ linker = GNULinker(
1747
+ command=" && ".join([
1748
+ "$ld $ldflags $imported_ldflags $extra_ldflags $covflags $libpaths @$outdir_rel/objects.list -o $out $libraries",
1749
+ "$dsymutil $out -o $outdir_rel/.debug/$binary.dSYM",
1750
+ "$strip $out",
1751
+ ]),
1752
+ infiles=[".o", ".obj", ".a"],
1753
+ outfiles=["{outdir}/{binary}"],
1754
+ variables={"desc": "[LINK] {binary}"},
1755
+ implicit=["$ld_path", "$dsymutil_path", "$strip_path", "$outdir_rel/.debug"])
1756
+
1757
+ dynlinker = GNULinker(
1758
+ command=" && ".join([
1759
+ "$ld $ldflags -shared $imported_ldflags $extra_ldflags $covflags $libpaths @$outdir_rel/objects.list -o $out $libraries",
1760
+ "$dsymutil $out -o $outdir_rel/.debug/$binary.dSYM",
1761
+ "$strip $out",
1762
+ ]),
1763
+ infiles=[".o", ".obj", ".a"],
1764
+ outfiles=["{outdir}/lib{binary}.so"],
1765
+ variables={"desc": "[LINK] {binary}"},
1766
+ implicit=["$ld_path", "$dsymutil_path", "$strip_path", "$outdir_rel/.debug"])
1767
+
1768
+ archiver = BSDArchiver(
1769
+ command="$libtool -static -o $out @$outdir_rel/objects.list && $ranlib $out",
1770
+ infiles=[".o", ".obj", ".a"],
1771
+ outfiles=["{outdir}/lib{binary}.a"],
1772
+ variables={"desc": "[AR] lib{binary}.a"},
1773
+ implicit=["$libtool_path", "$ranlib_path"])
1774
+
1775
+
1661
1776
  class MinGWToolchain(GNUToolchain):
1662
1777
  linker = GNULinker(
1663
1778
  command=" && ".join([
@@ -1686,6 +1801,62 @@ class MSVCArchiver(Rule):
1686
1801
  return "MSVCArchiver" + super().get_influence(task)
1687
1802
 
1688
1803
 
1804
+ class MSVCCRT(Variable):
1805
+ def __init__(self, default="/MD", flagsfn=None):
1806
+ self.default = default
1807
+ self.flagsfn = flagsfn
1808
+
1809
+ def _combine(self, project, crt1, crt2):
1810
+ if crt1 is None:
1811
+ return crt2
1812
+ if crt2 is None:
1813
+ return crt1
1814
+ raise_task_error_if(crt1 != crt2, project, "Mismatching Windows CRT library types (/MT vs /MD)")
1815
+ return crt1
1816
+
1817
+ def _select_flag(self, flags):
1818
+ """ Look for /Mxx flag in the list of flags """
1819
+ if flags is None:
1820
+ return None
1821
+ if "Static" in flags:
1822
+ return "/MT"
1823
+ if "StaticDebug" in flags:
1824
+ return "/MTd"
1825
+ if "Dynamic" in flags:
1826
+ return "/MD"
1827
+ if "DynamicDebug" in flags:
1828
+ return "/MDd"
1829
+ if "/MT" in flags:
1830
+ return "/MT"
1831
+ if "/MTd" in flags:
1832
+ return "/MTd"
1833
+ if "/MD" in flags:
1834
+ return "/MD"
1835
+ if "/MDd" in flags:
1836
+ return "/MDd"
1837
+ return None
1838
+
1839
+ def _select_dep_flags(self, project, dep):
1840
+ crt = self._select_flag(dep.cxxinfo.asflags.items())
1841
+ if hasattr(dep.cxxinfo, "crt"):
1842
+ crt = self._combine(project, crt, self._select_flag([str(dep.cxxinfo.crt)]))
1843
+ crt = self._combine(project, crt, self._select_flag(dep.cxxinfo.cflags.items()))
1844
+ return self._combine(project, crt, self._select_flag(dep.cxxinfo.cxxflags.items()))
1845
+
1846
+ def create(self, project, writer, deps, tools):
1847
+ crt = self._select_flag(getattr(project, "crt", None))
1848
+ crt = self._combine(project, crt, self._select_flag(project._asflags()))
1849
+ crt = self._combine(project, crt, self._select_flag(project._cflags()))
1850
+ crt = self._combine(project, crt, self._select_flag(project._cxxflags()))
1851
+ for _, artifact in deps.items():
1852
+ crt = self._combine(project, crt, self._select_dep_flags(project, artifact))
1853
+ writer.variable(self.name, crt or self.default)
1854
+
1855
+ @utils.cached.instance
1856
+ def get_influence(self, task):
1857
+ return "CRT"
1858
+
1859
+
1689
1860
  MSVCCompiler = GNUCompiler
1690
1861
  MSVCLinker = GNULinker
1691
1862
  MSVCDepImporter = GNUDepImporter
@@ -1695,9 +1866,10 @@ class MSVCToolchain(Toolchain):
1695
1866
  hh = Skip(infiles=[".h", ".hh", ".hpp", ".hxx"])
1696
1867
  bin = Skip(infiles=[".dll", ".exe"])
1697
1868
 
1698
- builddir = ProjectVariable(attrib="outdir")
1699
1869
  joltdir = ProjectVariable()
1870
+ builddir = ProjectVariable(attrib="outdir")
1700
1871
  outdir = ProjectVariable()
1872
+ outdir_rel = ProjectVariable()
1701
1873
  binary = ProjectVariable()
1702
1874
 
1703
1875
  cl = ToolEnvironmentVariable(default="cl", envname="cl_exe", abspath=True)
@@ -1706,13 +1878,25 @@ class MSVCToolchain(Toolchain):
1706
1878
  flatc = ToolEnvironmentVariable(default="flatc", envname="FLATC", abspath=True)
1707
1879
  protoc = ToolEnvironmentVariable(default="protoc", envname="PROTOC", abspath=True)
1708
1880
 
1881
+ cstd = StdVariable("C", "/std:c{}", values=c_standards_list, supported=[11, 17], default=c_standard_default)
1882
+ cxxstd = StdVariable("C++", "/std:c++{}", values=cxx_standards_list, supported=[14, 17, 20], default=cxx_standard_default)
1883
+ optflag = OptimizationVariable(default="speed", values={
1884
+ "none": "/Od",
1885
+ "debug": "/Od /Zi",
1886
+ "size": "/O1",
1887
+ "release": "/O2 /DNDEBUG",
1888
+ None: "/0d",
1889
+ })
1890
+ win32flags = Variable("/DWIN32 /D_WINDOWS /D_WIN32_WINNT=0x0601 /EHsc")
1709
1891
  asflags = EnvironmentVariable(default="")
1710
- cflags = EnvironmentVariable(default="/EHsc")
1711
- cxxflags = EnvironmentVariable(default="/EHsc")
1892
+ cflags = EnvironmentVariable(default="")
1893
+ cxxflags = EnvironmentVariable(default="")
1712
1894
  fbflags = EnvironmentVariable(default="")
1713
1895
  ldflags = EnvironmentVariable(default="")
1714
1896
  protoflags = EnvironmentVariable(default="")
1715
1897
 
1898
+ crt = MSVCCRT()
1899
+
1716
1900
  extra_asflags = ProjectVariable(attrib="asflags")
1717
1901
  extra_cflags = ProjectVariable(attrib="cflags")
1718
1902
  extra_cxxflags = ProjectVariable(attrib="cxxflags")
@@ -1727,26 +1911,26 @@ class MSVCToolchain(Toolchain):
1727
1911
  libraries = Libraries(suffix=".lib")
1728
1912
 
1729
1913
  compile_asm = MSVCCompiler(
1730
- command="$cl /nologo /showIncludes $asflags $extra_asflags $macros $incpaths /c /Tc$in /Fo$out",
1914
+ command="$cl /nologo /showIncludes $crt $win32flags $asflags $extra_asflags $macros $incpaths /c /Tc$in /Fo$out",
1731
1915
  deps="msvc",
1732
1916
  infiles=[".asm", ".s", ".S"],
1733
- outfiles=["{outdir}/{binary}.dir/{in_path}/{in_base}.obj"],
1917
+ outfiles=["{outdir}/{binary}.dir/{in_path}/{in_base}{in_ext}.obj"],
1734
1918
  variables={"desc": "[ASM] {in_base}{in_ext}"},
1735
1919
  implicit=["$cl_path"])
1736
1920
 
1737
1921
  compile_c = MSVCCompiler(
1738
- command="$cl /nologo /showIncludes $cxxflags $extra_cxxflags $macros $incpaths /c /Tc$in /Fo$out",
1922
+ command="$cl /nologo /showIncludes $cstd $crt $win32flags $optflag $cflags $extra_cflags $macros $incpaths /c /Tc$in /Fo$out",
1739
1923
  deps="msvc",
1740
1924
  infiles=[".c"],
1741
- outfiles=["{outdir}/{binary}.dir/{in_path}/{in_base}.obj"],
1925
+ outfiles=["{outdir}/{binary}.dir/{in_path}/{in_base}{in_ext}.obj"],
1742
1926
  variables={"desc": "[C] {in_base}{in_ext}"},
1743
1927
  implicit=["$cl_path"])
1744
1928
 
1745
1929
  compile_cxx = MSVCCompiler(
1746
- command="$cl /nologo /showIncludes $cxxflags $extra_cxxflags $macros $incpaths /c /Tp$in /Fo$out",
1930
+ command="$cl /nologo /showIncludes $cxxstd $crt $win32flags $optflag $cxxflags $extra_cxxflags $macros $incpaths /c /Tp$in /Fo$out",
1747
1931
  deps="msvc",
1748
1932
  infiles=[".cc", ".cpp", ".cxx"],
1749
- outfiles=["{outdir}/{binary}.dir/{in_path}/{in_base}.obj"],
1933
+ outfiles=["{outdir}/{binary}.dir/{in_path}/{in_base}{in_ext}.obj"],
1750
1934
  variables={"desc": "[CXX] {in_base}{in_ext}"},
1751
1935
  implicit=["$cl_path"])
1752
1936
 
@@ -1774,11 +1958,15 @@ class MSVCToolchain(Toolchain):
1774
1958
 
1775
1959
  _toolchains = {
1776
1960
  GNUToolchain: GNUToolchain(),
1961
+ DarwinGNUToolchain: DarwinGNUToolchain(),
1777
1962
  MSVCToolchain: MSVCToolchain(),
1778
1963
  }
1779
1964
 
1780
- if os.name == "nt":
1965
+ _system = platform.system()
1966
+ if _system == "Windows":
1781
1967
  toolchain = _toolchains[MSVCToolchain]
1968
+ elif _system == "Darwin":
1969
+ toolchain = _toolchains[DarwinGNUToolchain]
1782
1970
  else:
1783
1971
  toolchain = _toolchains[GNUToolchain]
1784
1972
 
@@ -1818,9 +2006,23 @@ class CXXProject(Task):
1818
2006
  cflags = []
1819
2007
  """ A list of compiler flags used when compiling C files. """
1820
2008
 
2009
+ cstd = None
2010
+ """
2011
+ C language standard to use (int). Default: 17
2012
+
2013
+ If the chosen standard is not supported, the nearest supported standard is selected.
2014
+ """
2015
+
1821
2016
  cxxflags = []
1822
2017
  """ A list of compiler flags used when compiling C++ files. """
1823
2018
 
2019
+ cxxstd = None
2020
+ """
2021
+ C++ language standard to use (int). Default: 17
2022
+
2023
+ If the chosen standard is not supported, the nearest supported standard is selected.
2024
+ """
2025
+
1824
2026
  depimports = []
1825
2027
  """ List of implicit dependencies """
1826
2028
 
@@ -1839,6 +2041,18 @@ class CXXProject(Task):
1839
2041
  macros = []
1840
2042
  """ List of preprocessor macros to set """
1841
2043
 
2044
+ optimize = "release"
2045
+ """
2046
+ Compiler optimization level.
2047
+
2048
+ Supported values are:
2049
+
2050
+ - "none" / None
2051
+ - "debug"
2052
+ - "size"
2053
+ - "release"
2054
+ """
2055
+
1842
2056
  sources = []
1843
2057
  """ A list of sources to compile.
1844
2058
 
@@ -2266,7 +2480,10 @@ if __name__ == "__main__":
2266
2480
  except JoltCommandError as e:
2267
2481
  self.buildlog = "\n".join(e.stdout)
2268
2482
  report = self._report_errors(self.buildlog)
2269
- raise CompileError(self._first_reported_error(report))
2483
+ error = self._first_reported_error(report)
2484
+ if error:
2485
+ raise CompileError(error)
2486
+ raise e
2270
2487
 
2271
2488
  if bool(getattr(self, "coverage", False)):
2272
2489
  self.covdatadir = tools.builddir("coverage-data")
@@ -2351,13 +2568,15 @@ if __name__ == "__main__":
2351
2568
  # LLVM linker errors
2352
2569
  report.add_regex_errors(
2353
2570
  "Linker Error",
2354
- r"^(?P<location>ld(\.lld)?): (error|warning): (?P<message>.*)",
2571
+ r"^(?P<location>(.*?)ld(\.lld)?): (error|warning): (?P<message>.*)",
2355
2572
  logbuffer)
2356
2573
 
2357
2574
  return report
2358
2575
 
2359
2576
  def _first_reported_error(self, report):
2360
2577
  """ Returns the first reported error or None if no errors were reported. """
2578
+ if report is None:
2579
+ return None
2361
2580
  for error in report.errors:
2362
2581
  return error
2363
2582
 
@@ -0,0 +1,219 @@
1
+ from jolt import attributes
2
+ from jolt import filesystem as fs
3
+ from jolt import log
4
+ from jolt import utils
5
+ from jolt.error import raise_error_if
6
+
7
+
8
+ class PkgConfigHelper(object):
9
+
10
+ TEMPLATE_PKGCONFIG = """
11
+ prefix={{ artifact.final_path }}
12
+
13
+ Name: {{ pkgname }}
14
+ Description: {{ pkgname }} package
15
+ Version: {{ artifact.identity }}
16
+
17
+ Cflags: {% for flag in cxxflags %}{{ flag }} {% endfor %}{% for inc in incpaths %}-I${prefix}/{{ inc }} {% endfor %}{% for macro in macros %}-D{{ macro }} {% endfor %}
18
+
19
+ Libs: {% for flag in ldflags %}{{ flag }} {% endfor %}{% for libpath in libpaths %}-L${prefix}/{{ libpath }} {% endfor %}{% for library in libraries %}-l{{ library }} {% endfor %}
20
+
21
+ """
22
+
23
+ def __init__(self, artifact, tools):
24
+ self.artifact = artifact
25
+ self.tools = tools
26
+
27
+ def _mkpath(self, path):
28
+ if fs.path.commonpath([path, self.artifact.path]) != self.artifact.path:
29
+ return path
30
+ return fs.path.relpath(path, self.artifact.path)
31
+
32
+ def cflags(self, package):
33
+ package = " ".join(utils.as_list(package))
34
+ try:
35
+ with self.tools.environ(**self.environ):
36
+ output = self.tools.run("{} --maximum-traverse-depth=1 --cflags-only-other {}", self.pkgconfig, package, output=False)
37
+ return output.strip().split()
38
+ except Exception as e:
39
+ log.debug("PkgConfig.cflags: {}", str(e))
40
+ return []
41
+
42
+ def incpaths(self, package):
43
+ package = " ".join(utils.as_list(package))
44
+ try:
45
+ with self.tools.environ(**self.environ):
46
+ output = self.tools.run("{} --maximum-traverse-depth=1 --cflags-only-I {}", self.pkgconfig, package, output=False)
47
+ return [self._mkpath(inc[2:]) for inc in output.strip().split()]
48
+ except Exception as e:
49
+ log.debug("PkgConfig.incpaths: {}", str(e))
50
+ return []
51
+
52
+ def linkflags(self, package):
53
+ package = " ".join(utils.as_list(package))
54
+ try:
55
+ with self.tools.environ(**self.environ):
56
+ output = self.tools.run("{} --maximum-traverse-depth=1 --libs-only-other {}", self.pkgconfig, package, output=False)
57
+ return output.strip().split()
58
+ except Exception as e:
59
+ log.debug("PkgConfig.linkflags: {}", str(e))
60
+ return []
61
+
62
+ def libpaths(self, package):
63
+ package = " ".join(utils.as_list(package))
64
+ try:
65
+ with self.tools.environ(**self.environ):
66
+ output = self.tools.run("{} --maximum-traverse-depth=1 --libs-only-L {}", self.pkgconfig, package, output=False)
67
+ return [self._mkpath(lib[2:]) for lib in output.strip().split()]
68
+ except Exception as e:
69
+ log.debug("PkgConfig.libpaths: {}", str(e))
70
+ return []
71
+
72
+ def libraries(self, package):
73
+ package = " ".join(utils.as_list(package))
74
+ try:
75
+ with self.tools.environ(**self.environ):
76
+ output = self.tools.run("{} --maximum-traverse-depth=1 --libs-only-l {}", self.pkgconfig, package, output=False)
77
+ return [lib[2:] for lib in output.strip().split()]
78
+ except Exception as e:
79
+ log.debug("PkgConfig.libraries: {}", str(e))
80
+ return []
81
+
82
+ def write_pc(self, package):
83
+ with self.tools.tmpdir() as tmpdir, self.tools.cwd(tmpdir):
84
+ content = self.tools.render(
85
+ self.TEMPLATE_PKGCONFIG,
86
+ artifact=self.artifact,
87
+ pkgname=package,
88
+ macros=list(self.artifact.cxxinfo.macros),
89
+ incpaths=list(self.artifact.cxxinfo.incpaths),
90
+ libpaths=list(self.artifact.cxxinfo.libpaths),
91
+ libraries=list(self.artifact.cxxinfo.libraries),
92
+ )
93
+ print(content)
94
+ self.tools.write_file(f"{package}.pc", content, expand=False)
95
+ self.artifact.collect(f"{package}.pc", "lib/pkgconfig/")
96
+
97
+ @property
98
+ def pkgconfig(self):
99
+ pkgconf = self.tools.which(self.tools.getenv("PKG_CONFIG", "pkg-config"))
100
+ raise_error_if(not pkgconf, "No pkg-config tool found in PATH")
101
+ return pkgconf
102
+
103
+ @property
104
+ def environ(self):
105
+ path = self.artifact.environ.get("PKG_CONFIG_PATH")
106
+ if path is None:
107
+ self.tools._task.verbose("No PKG_CONFIG_PATH in artifact environment")
108
+
109
+ # Path from the artifact environment
110
+ path = str(path).split(fs.pathsep)
111
+ path = fs.pathsep.join(fs.path.join(self.artifact.path, p) for p in path)
112
+
113
+ # Append existing PKG_CONFIG_PATH from the tools environment
114
+ if self.tools.getenv("PKG_CONFIG_PATH"):
115
+ path = path + fs.pathsep + self.tools.getenv("PKG_CONFIG_PATH")
116
+
117
+ return {"PKG_CONFIG_PATH": path}
118
+
119
+
120
+ def to_cxxinfo(
121
+ pkg: list | str,
122
+ cflags: bool = True,
123
+ cxxflags: bool = True,
124
+ incpaths: bool = True,
125
+ ldflags: bool = True,
126
+ libpaths: bool = True,
127
+ libraries: bool = True,
128
+ ):
129
+ """
130
+ Decorator to add pkg-config information to cxxinfo metadata of an artifact.
131
+
132
+ The decorator enables interoperability between libraries built with Jolt's
133
+ Ninja plugin and external packages that provide pkg-config files.
134
+
135
+ It uses the pkg-config tool to query for compiler and linker flags,
136
+ include paths, library paths, and libraries associated with a given package.
137
+ If the relevant flags are found, they are appended to the corresponding fields
138
+ in the artifact's cxxinfo metadata.
139
+
140
+ Args:
141
+ pkg (str): The name of the pkg-config package to be added to cxxinfo.
142
+ cflags (bool): Whether to add C compiler flags from pkg-config.
143
+ cxxflags (bool): Whether to add C++ compiler flags from pkg-config.
144
+ incpaths (bool): Whether to add include paths from pkg-config.
145
+ ldflags (bool): Whether to add linker flags from pkg-config.
146
+ libpaths (bool): Whether to add library paths from pkg-config.
147
+ libraries (bool): Whether to add libraries from pkg-config.
148
+ """
149
+
150
+ def decorate(cls):
151
+ original_publish = cls.publish
152
+
153
+ def publish(self, artifact, tools):
154
+ original_publish(self, artifact, tools)
155
+
156
+ pc = PkgConfigHelper(artifact, tools)
157
+ if not pc.environ:
158
+ self.verbose("Skipping pkg-config cxxinfo addition due to missing PKG_CONFIG_PATH.")
159
+ return
160
+
161
+ if cflags:
162
+ artifact.cxxinfo.cflags.extend(pc.cflags(pkg))
163
+ if cxxflags:
164
+ artifact.cxxinfo.cxxflags.extend(pc.cflags(pkg))
165
+ if incpaths:
166
+ artifact.cxxinfo.incpaths.extend(pc.incpaths(pkg))
167
+ if ldflags:
168
+ artifact.cxxinfo.ldflags.extend(pc.linkflags(pkg))
169
+ if libpaths:
170
+ artifact.cxxinfo.libpaths.extend(pc.libpaths(pkg))
171
+ if libraries:
172
+ artifact.cxxinfo.libraries.extend(pc.libraries(pkg))
173
+
174
+ cls.publish = publish
175
+ return cls
176
+
177
+ return decorate
178
+
179
+
180
+ def from_cxxinfo(package):
181
+ """
182
+ Decorator to write a pkg-config file for the given package
183
+ based on the cxxinfo metadata of the artifact.
184
+ """
185
+
186
+ def decorate(cls):
187
+ original_publish = cls.publish
188
+ original_unpack = cls.unpack
189
+
190
+ def publish(self, artifact, tools):
191
+ original_publish(self, artifact, tools)
192
+
193
+ pc = PkgConfigHelper(artifact, tools)
194
+ pc.write_pc(package)
195
+
196
+ def unpack(self, artifact, tools):
197
+ original_unpack(self, artifact, tools)
198
+
199
+ pc = PkgConfigHelper(artifact, tools)
200
+ pc.write_pc(package)
201
+
202
+ cls.publish = publish
203
+ cls.unpack = unpack
204
+ return cls
205
+
206
+ return decorate
207
+
208
+
209
+ def requires():
210
+ """ Decorator to add pkg-config requirements to a task. """
211
+
212
+ import jolt.pkgs.pkgconfig
213
+
214
+ def decorate(cls):
215
+ cls = attributes.requires("requires_pkgconf")(cls)
216
+ cls.requires_pkgconf = ["pkgconf"]
217
+ return cls
218
+
219
+ return decorate