Merging gst-build
[platform/upstream/gstreamer.git] / subprojects / gstreamer-sharp / nuget.py
1 #!/usr/bin/python3
2 import argparse
3 import getpass
4 import os
5 import sys
6 import shutil
7 import subprocess
8 from datetime import datetime
9 from urllib.request import urlretrieve
10 from zipfile import ZipFile
11
12 NUSPEC_TEMPLATE = """<?xml version="1.0" encoding="utf-8"?>
13 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
14   <metadata>
15     <id>{package_name}</id>
16     <authors>{author}</authors>
17     <owners>{owner}</owners>
18     <licenseUrl>{license_url}</licenseUrl>
19     <projectUrl>{project_url}</projectUrl>
20     <iconUrl>{icon_url}</iconUrl>
21     <requireLicenseAcceptance>false</requireLicenseAcceptance>
22     <description>{description}.</description>
23     <copyright>{copyright}</copyright>
24     <tags>{tags}</tags>
25     <version>{version}</version>
26     <dependencies>
27 {dependencies}  </dependencies>
28   </metadata>
29   <files>
30 {files}  </files>
31 </package>
32 """
33
34 TARGETS_TEMPLATE = r"""<?xml version="1.0" encoding="utf-8"?>
35 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
36   <Target Name="{package_name}CopyMapConfigs" AfterTargets="AfterBuild">
37     <CreateItem Include="$(MSBuildThisFileDirectory)\{frameworkdir}\*.config">
38       <Output TaskParameter="Include" ItemName="MapConfigs" />
39     </CreateItem>
40
41     <Copy SourceFiles="@(MapConfigs)" DestinationFiles="@(MapConfigs->'$(OutDir)\%(RecursiveDir)%(Filename)%(Extension)')" />
42   </Target>
43 </Project>"""
44
45
46 class Nugetifier:
47     def cleanup_args(self):
48         self.nugetdir = os.path.join(self.builddir,
49                                      self.package_name + 'nupkg')
50         self.frameworkdir = 'net45'
51         self.nuget_build_dir = os.path.join(
52             self.nugetdir, 'build', self.frameworkdir)
53         self.nuget_lib_dir = os.path.join(
54             self.nugetdir, 'lib', self.frameworkdir)
55         self.nuspecfile = os.path.join(
56             self.nugetdir, '%s.nuspec' % self.package_name)
57         self.nugettargets = os.path.join(
58             self.nuget_build_dir, "%s.targets" % self.package_name)
59         self.nuget = shutil.which('nuget')
60         if not self.nuget:
61             print("Could not find the `nuget` tool, install it and retry!")
62             return -1
63
64         for d in [self.nugetdir, self.nuget_lib_dir, self.nuget_build_dir]:
65             os.makedirs(d, exist_ok=True)
66         if not self.description:
67             self.description = "%s c# bindings" % self.package_name
68         if not self.copyright:
69             self.copyright = "Copyright %s" % datetime.now().year
70         if not self.tags:
71             self.tags = self.package_name
72
73         return 0
74
75     def run(self):
76         res = self.cleanup_args()
77         if res:
78             return res
79
80         self.files = ''
81
82         def add_file(path, target="lib"):
83             f = '    <file src="%s" target="%s"/>\n' % (
84                 path, os.path.join(target, os.path.basename(path)))
85             self.files += f
86
87         self.dependencies = ''
88         for dependency in self.dependency:
89             _id, version = dependency.split(":")
90             self.dependencies += '    <dependency id="%s" version="%s" />\n' % (
91                 _id, version)
92
93         for assembly in self.assembly:
94             add_file(assembly, os.path.join('lib', self.frameworkdir))
95
96             for f in [assembly + '.config', assembly[:-3] + 'pdb']:
97                 if os.path.exists(f):
98                     add_file(f, os.path.join('build', self.frameworkdir))
99
100         with open(self.nugettargets, 'w') as _:
101             print(TARGETS_TEMPLATE.format(**self.__dict__), file=_)
102             add_file(self.nugettargets, 'build')
103
104         with open(self.nuspecfile, 'w') as _:
105             print(NUSPEC_TEMPLATE.format(**self.__dict__), file=_)
106
107         subprocess.check_call([self.nuget, 'pack', self.nuspecfile],
108                               cwd=self.builddir)
109
110
111 class NugetDownloader:
112     def reporthook(self, blocknum, blocksize, totalsize):
113         readsofar = blocknum * blocksize
114         if totalsize > 0:
115             percent = readsofar * 1e2 / totalsize
116             s = "\r%5.1f%% %*d / %d" % (
117                 percent, len(str(totalsize)), readsofar, totalsize)
118             sys.stderr.write(s)
119             if readsofar >= totalsize:  # near the end
120                 sys.stderr.write("\n")
121         else:  # total size is unknown
122             sys.stderr.write("read %d\n" % (readsofar,))
123
124     def run(self):
125         url = "https://www.nuget.org/api/v2/package/{nuget_name}/{nuget_version}".format(
126             **self.__dict__)
127         workdir = os.path.join(self.current_builddir,
128                                self.nuget_name, self.nuget_version)
129         os.makedirs(workdir, exist_ok=True)
130
131         try:
132             with open(os.path.join(workdir, 'linkline'), 'r') as f:
133                 print(f.read())
134             return
135         except FileNotFoundError:
136             pass
137         nugetpath = os.path.join(workdir, self.nuget_name) + '.zip'
138         print("Downloading %s into %s" % (url, nugetpath), file=sys.stderr)
139         urlretrieve(url, nugetpath, self.reporthook)
140
141         lib_path = os.path.join('lib', self.csharp_version)
142         dll_path = os.path.join(self.nuget_name, self.nuget_version)
143         extract_dir = os.path.join(self.current_builddir, dll_path)
144         os.makedirs(extract_dir, exist_ok=True)
145         linkline = ''
146
147         print("%s - %s" % (self.builddir, extract_dir), file=sys.stderr)
148         with ZipFile(nugetpath) as zip:
149             for f in zip.infolist():
150                 if f.filename.startswith(lib_path):
151                     zip.extract(f, path=extract_dir)
152                     if f.filename.endswith('.dll'):
153                         linkline += ' -r:' + \
154                             os.path.relpath(os.path.join(
155                                 extract_dir, f.filename), self.builddir)
156
157         with open(os.path.join(workdir, 'linkline'), 'w') as f:
158             print(linkline.strip(), file=f)
159
160         print(linkline.strip())
161
162
163 if __name__ == "__main__":
164     if "get" not in sys.argv:
165         parser = argparse.ArgumentParser()
166         parser.add_argument('--builddir')
167         parser.add_argument('--package-name')
168         parser.add_argument('--author', default=getpass.getuser())
169         parser.add_argument('--owner', default=getpass.getuser())
170         parser.add_argument('--native', action='append', default=[])
171         parser.add_argument('--assembly', action='append', default=[])
172         parser.add_argument('--out')
173         parser.add_argument('--description')
174         parser.add_argument('--copyright')
175         parser.add_argument('--version')
176         parser.add_argument('--icon-url', default='')
177         parser.add_argument('--project-url', default='')
178         parser.add_argument('--license-url', default='')
179         parser.add_argument('--tags', default='')
180         parser.add_argument('--dependency', default=[], action='append')
181
182         runner = Nugetifier()
183     else:
184         sys.argv.remove('get')
185         parser = argparse.ArgumentParser()
186         parser.add_argument('--builddir')
187         parser.add_argument('--current-builddir')
188         parser.add_argument('--nuget-name')
189         parser.add_argument('--nuget-version')
190         parser.add_argument('--csharp-version')
191
192         runner = NugetDownloader()
193
194     options = parser.parse_args(namespace=runner)
195     exit(runner.run())