nuget.py 9.04 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#!/usr/bin/env python

############################################################################
# nuget.py
# Copyright (C) 2016  Belledonne Communications, Grenoble France
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
21
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#
############################################################################


import argparse
import glob
import os
import os.path
import shutil
import sys


platforms = ['ARM', 'x64', 'x86']


class PlatformListAction(argparse.Action):

    def __call__(self, parser, namespace, values, option_string=None):
        if values:
            for value in values:
                if value not in platforms:
                    message = ("invalid platform: {0!r} (choose from {1})".format(value, ', '.join([repr(platform) for platform in platforms])))
                    raise argparse.ArgumentError(self, message)
            setattr(namespace, self.dest, values)


def handle_remove_read_only(func, path, exc):
    if not os.access(path, os.W_OK):
        os.chmod(path, stat.S_IWUSR)
        func(path)
    else:
        raise


def main(argv=None):
    if argv is None:
        argv = sys.argv
    argparser = argparse.ArgumentParser(
        description="Generate nuget package of Linphone SDK.")
    argparser.add_argument(
        '-s', '--sdk_dir', default="OUTPUT", help="The path where to find the built SDK", dest='sdk_dir')
Erwan Croze's avatar
Erwan Croze committed
63 64
    argparser.add_argument(
        '-cs', '--cswrapper_dir', default="CsWrapper", help="The path where to find the built C# wrapper", dest='cswrapper_dir')
65 66
    argparser.add_argument(
        '-t', '--target', default="Linphone", help="The target to package (the windows runtime whose metadata will be exported)", dest='target')
67 68
    argparser.add_argument(
        '-v', '--version', default='1.0.0', help="The version of the nuget package to generate", dest='version')
69 70 71 72 73 74 75
    argparser.add_argument(
        '-w', '--work_dir', default="WORK/nuget", help="The path where the work will be done to generate the nuget package", dest='work_dir')
    argparser.add_argument(
        'platform', nargs='*', action=PlatformListAction, default=['ARM', 'x64', 'x86'], help="The platform to build for (default is 'all'). Space separated architectures in list: {0}.".format(', '.join([repr(platform) for platform in platforms])))

    args, additional_args2 = argparser.parse_known_args()

Erwan Croze's avatar
Erwan Croze committed
76
    target_winmd = "Belledonne.Linphone"
77 78 79
    target_id = "LinphoneSDK"
    target_desc = "Linphone SDK"
    if args.target == "LinphoneTesterSDK":
80
        target_winmd = "BelledonneCommunications.Linphone.Tester"
81 82 83
        target_id = "LinphoneTesterSDK"
        target_desc = "Linphone Tester SDK"
    elif args.target == "MS2TesterSDK":
84
        target_winmd = "BelledonneCommunications.Mediastreamer2.Tester"
85 86 87
        target_id = "MS2TesterSDK"
        target_desc = "Mediastreamer2 Tester SDK"
    elif args.target == "BelleSipTesterSDK":
88
        target_winmd = "BelledonneCommunications.BelleSip.Tester"
89 90
        target_id = "BelleSipTesterSDK"
        target_desc = "BelleSip Tester SDK"
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

    # Create work dir structure
    work_dir = os.path.abspath(args.work_dir)
    if os.path.exists(work_dir):
        shutil.rmtree(work_dir, ignore_errors=False, onerror=handle_remove_read_only)
    os.makedirs(os.path.join(work_dir, 'lib', 'uap10.0'))
    for platform in args.platform:
        os.makedirs(os.path.join(work_dir, 'build', 'uap10.0', platform))
        os.makedirs(os.path.join(work_dir, 'runtimes', 'win10-' + platform.lower(), 'native'))

    # Copy SDK content to nuget package structure
    sdk_dir = os.path.abspath(args.sdk_dir)
    winmds_installed = False
    ignored_winmds = []
    for platform in args.platform:
    	platform_dir = 'win10-' + platform.lower()
        dlls = glob.glob(os.path.join(sdk_dir, platform_dir, 'bin', '*.dll'))
        dlls += glob.glob(os.path.join(sdk_dir, platform_dir, 'lib', '*.dll'))
        dlls += glob.glob(os.path.join(sdk_dir, platform_dir, 'lib', 'mediastreamer', 'plugins', '*.dll'))
110
        winmds = glob.glob(os.path.join(sdk_dir, platform_dir, 'lib', '*.winmd'))
111
        winmds += glob.glob(os.path.join(sdk_dir, platform_dir, 'lib', 'mediastreamer', 'plugins','*.winmd'))
112
        pdbs = glob.glob(os.path.join(sdk_dir, platform_dir, 'bin', '*.pdb'))
113
        pdbs += glob.glob(os.path.join(sdk_dir, platform_dir, 'lib', '*.pdb'))
114
        pdbs += glob.glob(os.path.join(sdk_dir, platform_dir, 'lib', 'mediastreamer', 'plugins', '*.pdb'))
115
        wrappers = []
Erwan Croze's avatar
Erwan Croze committed
116
        if target_id == "LinphoneSDK":
117 118 119 120
            wrappers += glob.glob(os.path.join(args.cswrapper_dir, 'bin', '*', 'CsWrapper.dll'))
            wrappers += glob.glob(os.path.join(args.cswrapper_dir, 'bin', '*', 'CsWrapper.pdb'))
            wrappers += glob.glob(os.path.join(args.cswrapper_dir, 'bin', '*', 'CsWrapper.XML'))

121 122 123 124 125 126 127

        if not winmds_installed:
            for winmd in winmds:
                basename = os.path.basename(winmd)
                basename_noext = os.path.splitext(basename)[0]
                if basename_noext == target_winmd:
                    shutil.copy(winmd, os.path.join(work_dir, 'lib', 'uap10.0'))
128 129 130
                    xmldoc = os.path.join(os.path.dirname(winmd), basename_noext + '.xml')
                    if os.path.exists(xmldoc):
                        shutil.copy(xmldoc, os.path.join(work_dir, 'lib', 'uap10.0'))
131 132 133 134 135 136 137 138 139 140 141 142
                else:
                    ignored_winmds += [basename_noext]
            winmds_installed = True
        for dll in dlls:
            basename = os.path.basename(dll)
            basename_noext = os.path.splitext(basename)[0]
            winmd = basename_noext + '.winmd'
            if os.path.exists(os.path.join(work_dir, 'lib', 'uap10.0', winmd)):
                shutil.copy(dll, os.path.join(work_dir, 'runtimes', platform_dir, 'native'))
            elif not basename_noext in ignored_winmds:
                shutil.copy(dll, os.path.join(work_dir, 'build', 'uap10.0', platform))
        for pdb in pdbs:
143 144 145 146 147 148 149
            basename = os.path.basename(pdb)
            basename_noext = os.path.splitext(basename)[0]
            winmd = basename_noext + '.winmd'
            if os.path.exists(os.path.join(work_dir, 'lib', 'uap10.0', winmd)):
                shutil.copy(pdb, os.path.join(work_dir, 'runtimes', platform_dir, 'native'))
            elif not basename_noext in ignored_winmds:
                shutil.copy(pdb, os.path.join(work_dir, 'build', 'uap10.0', platform))
150 151 152 153
        for wrap in wrappers:
            if not os.path.exists(os.path.join(work_dir, 'lib', 'uap10.0')):
                os.makedirs(os.path.join(work_dir, 'lib', 'uap10.0'))
            shutil.copy(wrap, os.path.join(work_dir, 'lib', 'uap10.0'))
154 155 156 157 158 159 160 161 162 163 164 165 166 167

    # Write targets file
    targets = """<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Note: This file will be injected into the target project -->
  <!-- Includes the native dll files as content to make sure that they are included in the app package -->
  <Target Name="CopyNativeLibraries" AfterTargets="ResolveAssemblyReferences">
    <ItemGroup>
      <Content Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll;$(MSBuildThisFileDirectory)\$(Platform)\*.pdb">
        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      </Content>
    </ItemGroup>
  </Target>
</Project>"""
168
    f = open(os.path.join(work_dir, 'build', 'uap10.0', target_id + '.targets'), 'w')
169 170 171 172 173 174 175
    f.write(targets)
    f.close()

    # Write nuspec file
    nuspec = """<?xml version="1.0"?>
<package >
  <metadata>
176
    <id>{target_id}</id>
177
    <version>{version}</version>
178 179 180 181
    <authors>Belledonne Communications</authors>
    <owners>Belledonne Communications</owners>
    <licenseUrl>http://www.gnu.org/licenses/old-licenses/gpl-2.0.html</licenseUrl>
    <projectUrl>https://linphone.org/</projectUrl>
Erwan Croze's avatar
Erwan Croze committed
182
    <iconUrl>https://raw.githubusercontent.com/BelledonneCommunications/linphone-windows10/master/Linphone/Assets/logo-BC.png</iconUrl>
183
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
184
    <description>{target_desc}</description>
185
    <releaseNotes>Nothing new</releaseNotes>
186
    <copyright>Copyright 2017 Belledonne Communications</copyright>
187 188 189 190
    <tags>SIP</tags>
    <dependencies>
    </dependencies>
  </metadata>
191 192
</package>""".format(version=args.version, target_id=target_id, target_desc=target_desc)
    f = open(os.path.join(work_dir, target_id + '.nuspec'), 'w')
193 194 195 196 197 198
    f.write(nuspec)
    f.close()


if __name__ == "__main__":
    sys.exit(main())