flutter打包流程接入jenkins

2022-05-05  本文已影响0人  你飞跃俊杰

iOS命令
python3 ci-build.py build --platform ios --version 1.0.0-SNAPSHOT --output_dir /Users/lvfeijun/Desktop/hqjy/fluttermodule/output_dir --macro_arg local_build

ci-build.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import argparse
import subprocess

def parse_args():
    parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument('action', choices=['build', 'release'], default='build')
    parser.add_argument('--platform', choices=['ios', 'android', 'windows'])
    parser.add_argument('--version')
    parser.add_argument('--output_dir')
    parser.add_argument('--macro_arg')

    return parser.parse_args()

def fetch_submodule(is_develop):
    cmd = 'git submodule update --init'
    if is_develop:
        cmd += ' --remote'
    subprocess.call(cmd.split(' '))

def main():
    print((sys.version_info))
    cfg = parse_args()
    fetch_submodule(cfg.action == 'build')
    from ci_build import ios, android, windows, sync_version
    sync_version.generate_version_header(version=cfg.version)
    locals()[cfg.platform].run(cfg)


if __name__ == '__main__':
    main()

ios.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import glob
import shutil
from . import utils


BUILD_OUT_PATH = 'build/iOS'

POD_PROJECT_PATH = os.path.join(utils.root_path(), '.ios')
DEPENDENCY_PATH = os.path.join(utils.root_path(), 'depends')
FRAMEWORK_PATH = os.path.join(utils.root_path(), 'ios_frameworks')

GEN_IOS_OS_PROJ = 'cmake ../.. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../../ci_build/cmake/ios.toolchain.cmake -DIOS_PLATFORM=OS -DIOS_ARCH="armv7;arm64" -DENABLE_ARC=0 -DENABLE_BITCODE=0 -DENABLE_VISIBILITY=1'

def install_path(project_name):
    return '{}/{}'.format(BUILD_OUT_PATH, project_name)

def run_make(is_simulator):
    platform = 'SIMULATOR' if is_simulator else 'OS'
    archs = '"x86_64"' if is_simulator else '"armv7;arm64"'

    project_path = utils.root_path()
    build_path = os.path.join(project_path, BUILD_OUT_PATH)
    params = {
        'CMAKE_INSTALL_PREFIX': build_path,
        'CMAKE_BUILD_TYPE': 'Release',
        'CMAKE_TOOLCHAIN_FILE': os.path.join(project_path, 'ci_build/cmake/ios.toolchain.cmake'),
        'IOS_DEPLOYMENT_TARGET': '9.0',
        'IOS_PLATFORM': platform,
        'IOS_ARCH': archs,
        'ENABLE_ARC': '1',
        'ENABLE_BITCODE': '0',
        'ENABLE_VISIBLITY': '1'
    }
    cmd = ' '.join(['-D{}={}'.format(k, v) for (k, v) in params.items()])
    cmd = 'cmake {} {} && make -j8 && make install'.format(project_path, cmd)
    print(cmd)
    utils.clean(build_path)
    os.chdir(build_path)
    ret = os.system(cmd)
    os.chdir(project_path)
    return ret == 0

def build(project_name):
    ret = run_make(False)
    if not ret:
        print('!!!!!!!!!!!build os fail!!!!!!!!!!!!!!!')
        return False

    lib_path = install_path(project_name) + '/libs'
    libtool_os_dst_lib = lib_path + '/os'
    if not utils.libtool_libs(glob.glob(lib_path + '/*.a'), libtool_os_dst_lib):
        return False

    ret = run_make(True)
    if not ret:
        print('!!!!!!!!!!!build simulator fail!!!!!!!!!!!!!!!')
        return False

    libtool_simulator_dst_lib = lib_path + '/simulator'
    if not utils.libtool_libs(glob.glob(lib_path + '/*.a'), libtool_simulator_dst_lib):
        return False

    lipo_src_libs = []
    lipo_src_libs.append(libtool_os_dst_lib)
    lipo_src_libs.append(libtool_simulator_dst_lib)
    lipo_dst_lib = lib_path + '/lib{}.a'.format(project_name)

    if not utils.lipo_libs(lipo_src_libs, lipo_dst_lib):
        return False

    if os.path.isfile(libtool_os_dst_lib):
        os.remove(libtool_os_dst_lib)
    if os.path.isfile(libtool_simulator_dst_lib):
        os.remove(libtool_simulator_dst_lib)

    print('==================Output========================')
    print(lipo_dst_lib)
    return True

#不需要依赖列表,需要flutter打包 
def dependencies_info_mapper():
    # info_mapper_path = os.path.join(POD_PROJECT_PATH, 'info_mapper.json')
    return True #utils.load_json(info_mapper_path)

def flutter_build_debug():
    print('flutter_build_debug')
    os.chdir(utils.root_path())
    return os.system('flutter build ios --debug --no-codesign')

def flutter_build_release():
    print('flutter_build_release')
    os.chdir(utils.root_path())
    return os.system('flutter build ios --release --no-codesign')

def flutter_build_sh():
    print('flutter_build_sh')
    os.chdir(utils.root_path())
    os.system('ls')
    return os.system('sh ci-build.sh');

def dependency_info(name, version, infos, is_daily_build):
    info = infos.get(name, {
        'name': name,
        'version': version
    }).copy()

    if version and not is_daily_build:
        info['version'] = info['versions'].get(version, version)
    return info

# 不需要pod
# def pod_content(dependencies_info, project_name, is_daily_build):
#     dependencies = []
#     #便利依赖列表
#     # info_mapper = dependencies_info_mapper()
#     # for n, v in dependencies_info.items():
#         # info = dependency_info(n, v, info_mapper, is_daily_build)
#         # print('name : {}, version : {}'.format(info['name'], info['version']))
#         # dependencies.append("pod '{}', '~> {}'".format(info['name'], info['version']))

#     return '''
# source 'https://github.com/CocoaPods/Specs.git'
# source 'https://git.duowan.com/ci_team/Specs.git'

# target '{project_name}' do
#   platform :ios, '9.0'
#   {dependencies}
# end
# '''.format(project_name=project_name, dependencies='\n  '.join(dependencies))


def generate_pod_dependencies(project_info, output_dir, is_daily_build):
    dependencies_info = project_info['dependencies']
    project_name = project_info['name']
    # print('Runner')
    downloader_project = 'Runner'
    #写入 Podfile
    podfile_path = os.path.join(POD_PROJECT_PATH, 'Podfile')
    # utils.write_content(pod_content(dependencies_info, downloader_project, is_daily_build), podfile_path)
    # print('Runner')
    #用来写framework
    # podfile_path = os.path.join(output_dir, 'Podfile')
    # utils.write_content(pod_content(dependencies_info, project_name, is_daily_build), podfile_path)


def find_headers_path(dependency_name):
    public_headers = os.path.join(POD_PROJECT_PATH, 'Pods/Headers/Public/{}'.format(dependency_name))
    if os.path.isdir(public_headers):
        return public_headers
    proj_path = os.path.join(POD_PROJECT_PATH, 'Pods/{}'.format(dependency_name))
    include_path = os.path.join(proj_path, 'include')
    if os.path.isdir(include_path):
        return include_path
    include_paths = glob.glob('{}/libs/*.framework/Headers'.format(proj_path))
    if len(include_paths) > 0:
        return include_paths[0]


def download_dependencies(project_info, output_dir, is_daily_build, force_update=False):
    dependencies_info = project_info['dependencies']
    # generate_pod_dependencies(project_info, output_dir, is_daily_build)
    print('POD_PROJECT_PATH')
    # print(os.chdir(POD_PROJECT_PATH))
    os.system('ls')
    print('POD_PROJECT')
    # ret = 0
    # if force_update:
    #     ret = os.system('pod install --repo-update')
    # else:
    #     ret = os.system('pod install')
    flutter_build_debug()
    print('flutter_build_debug success')
    # flutter_build_sh()

    # os.chdir(utils.root_path())
    # if ret != 0:
    #     print('!!!!!!!!!!!download dependencies fail!!!!!!!!!!!!!!!')
    #     return False

    # info_mapper = dependencies_info_mapper()
    # if os.path.exists(DEPENDENCY_PATH):
    #     shutil.rmtree(DEPENDENCY_PATH)
    # os.mkdir(DEPENDENCY_PATH)

    # for n in dependencies_info:
        # info = dependency_info(n, '', info_mapper, is_daily_build)
        # origin_path = find_headers_path(info['name'])
        # if not origin_path:
            # continue

        # target_path = os.path.join(DEPENDENCY_PATH, n)
        # os.mkdir(target_path)
        # target_path = os.path.join(target_path, 'include')
        #遍历依赖库
        # header_dir = info.get('header_dir', '')
        # if len(header_dir) > 0:
        #     os.mkdir(target_path)
        #     target_path = os.path.join(target_path, header_dir)
        # os.symlink(origin_path, target_path)
    return True

# 生产plist
def generate_plist(output_dir, project_name, version):
    content = '''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleShortVersionString</key>
    <string>{version}</string>
    <key>CFBundleVersion</key>
    <string>1</string>
</dict>
</plist>
'''.format(version=version)

    plist_path = '{}/{}-Info.plist'.format(output_dir, project_name)
    utils.write_content(content, plist_path)


def generate_zip(output_dir, project_name):
    product_dir = os.path.join(output_dir, project_name)
    shutil.make_archive(product_dir, 'zip', FRAMEWORK_PATH)
    # shutil.move(install_path(project_name), product_dir)


def pack(cfg, project_name, version):
    generate_plist(cfg.output_dir, project_name, version)
    generate_zip(cfg.output_dir, project_name)


def build_version(cfg, project):
    if cfg.action != 'build' or 'version' not in project:
        return cfg.version
    version = project['version']
    if not version.endswith('-dev'):
        version += '-dev'
    return version


def run(cfg):
    print('--------ios---------')
    project = utils.project_info()
    # print(project)
    # print(cfg)

    flutter_build_sh()

    if not os.path.exists(cfg.output_dir):
        os.makedirs(cfg.output_dir)

    project_name = project['name']
    pack(cfg, project_name, build_version(cfg, project))
    # shutil.copy(FRAMEWORK_PATH,cfg.output_dir)
    # os.system('ls ' + cfg.output_dir)
    # force_update_deps = ('UpdatePod' in cfg.macro_arg)
    # is_daily_build = (cfg.action == 'build')
    
    # if download_dependencies(project, cfg.output_dir, is_daily_build, force_update_deps or not is_daily_build) and build(project_name):
        # pack(cfg, project_name, build_version(cfg, project))
        # os.system('ls ' + cfg.output_dir)
        # print('build success')
        # exit(0)
    # exit(1)

ci-build.sh

if [ -z $out ]; then
    out='ios_frameworks'
fi

echo "准备输出所有文件到目录: $out"

echo "清除所有已编译文件"
find . -d -name build | xargs rm -rf
flutter clean
rm -rf $out
rm -rf build

flutter packages get

addFlag(){
    cat .ios/Podfile > tmp1.txt
    echo "use_frameworks!" >> tmp2.txt
    cat tmp1.txt >> tmp2.txt
    cat tmp2.txt > .ios/Podfile
    rm tmp1.txt tmp2.txt
}

# echo "检查 .ios/Podfile文件状态"
# a=$(cat .ios/Podfile)
# if [[ $a == use* ]]; then
#     echo '已经添加use_frameworks, 不再添加'
# else
#     echo '未添加use_frameworks,准备添加'
#     addFlag
#     echo "添加use_frameworks 完成"
# fi

echo "编译flutter"
flutter build ios --debug --no-codesign
#release下放开下一行注释,注释掉上一行代码
#flutter build ios --release --no-codesign
echo "编译flutter完成"
mkdir $out
cp -r build/ios/Debug-iphoneos/*.framework $out
#release下放开下一行注释,注释掉上一行代码
#cp -r build/ios/Release-iphoneos/*/*.framework $out
# cp -r .ios/Flutter/App.framework $out
# cp -r .ios/Flutter/engine/Flutter.framework $out

echo "复制framework库到临时文件夹: $out"

libpath='../'

rm -rf "$libpath/ios_frameworks"
mkdir $libpath
cp -r $out $libpath

echo "复制库文件到: $libpath"

utils.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import shutil
import glob
import json
import subprocess


def root_path():
    return os.path.abspath(os.path.join(__file__, '../..'))


def project_info():
    project_file = os.path.join(root_path(), 'project.json')
    return load_json(project_file)


def load_json(path):
    with open(path) as json_file:
        return json.load(json_file)


def write_content(content, file_path):
    with open(file_path, 'wb') as f:
        f.write(content.encode('utf-8'))
        f.flush()


def libtool_libs(src_libs, dst_lib):
    src_lib_str = ''
    for l in src_libs:
        src_lib_str = '%s %s'%(src_lib_str, l)

    print(src_lib_str)
    ret = os.system('libtool -static -o %s %s' %(dst_lib, src_lib_str))
    if ret != 0:
        print(('!!!!!!!!!!!libtool %s fail!!!!!!!!!!!!!!!' %(dst_lib)))
        return False

    return True


def lipo_libs(src_libs, dst_lib):
    src_lib_str = ''
    for l in src_libs:
        src_lib_str = '%s %s'%(src_lib_str, l)

    cmd = 'lipo -create %s -output %s' %(src_lib_str, dst_lib)
    ret = os.system(cmd)
    if ret != 0:
        print(('!!!!!!!!!!!lipo_libs %s fail, cmd:%s!!!!!!!!!!!!!!!' %(dst_lib, cmd)))
        return False

    return True


def lipo_thin_libs(src_lib, dst_lib, archs):
    tmp_results = []
    for arch in archs:
        if len(archs) == 1:
            tmp_result = dst_lib
        else:
            tmp_result = dst_lib + '.' + arch

        cmd = 'lipo %s -thin %s -output %s' %(src_lib, arch, tmp_result)
        ret = os.system(cmd)
        if ret != 0:
            print(('!!!!!!!!!!!lipo_thin_libs %s fail, cmd:%s!!!!!!!!!!!!!!!' %(tmp_result, cmd)))
            return False
        tmp_results.append(tmp_result)

    if len(archs) == 1:
        return True
    else:
        return lipo_libs(tmp_results, dst_lib)


def remove_cmake_files(path):
    cmake_files = path + '/CMakeFiles'
    if os.path.exists(cmake_files):
        shutil.rmtree(cmake_files)

    make_files = path + '/Makefile'
    if os.path.isfile(make_files):
        os.remove(make_files)

    cmake_cache = path + '/CMakeCache.txt'
    if os.path.isfile(cmake_cache):
        os.remove(cmake_cache)

    for f in glob.glob(path + '/*.a'):
        os.remove(f)
    for f in glob.glob(path + '/*.so'):
        os.remove(f)


def clean(path, incremental=False):
    if not incremental:
        for fpath, dirs, fs in os.walk(path):
            remove_cmake_files(fpath)

    if not os.path.exists(path):
        os.makedirs(path)


def get_git_revision_hash(project_path=None, is_short=False):
    cmds = ['git']
    if project_path:
        cmds.extend(['-C', project_path])
    cmds.append('rev-parse')
    if is_short:
        cmds.append('--short')
    cmds.append('HEAD')
    return subprocess.check_output(cmds).decode('utf-8').strip()

python3 ci-build.py build --platform android --version 1.0.0-SNAPSHOT --output_dir /Users/lvfeijun/Desktop/hqjy/fluttermodule/and_aar --macro_arg local_build

android.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import glob
import shutil
import json
import zipfile
import platform
import xml.etree.cElementTree as ET
if sys.version > '3':
   import urllib.request as urllib2
else:
   import urllib2
from . import utils,sync_version

try:
    NDK_ROOT = os.environ['ANDROID_NDK_HOME']
    ANDROID_HOME = os.environ['ANDROID_HOME']
except KeyError as identifier:
    NDK_ROOT = ''
    ANDROID_HOME = ''

#python ci-build.py build --platform android --version 1.0.0-SNAPSHOT --output_dir /Users/hqwx/new_sdk/build  --macro_arg local_build
CMAKE_PATH = ANDROID_HOME + '/cmake/3.6.4111459/bin/cmake'
BUILD_OUT_PATH = 'build/Android'
ANDROID_BUILD_CMD = '%s %s -DCMAKE_INSTALL_PREFIX=%s -DANDROID_ABI="%s" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=%s/build/cmake/android.toolchain.cmake -DANDROID_TOOLCHAIN=clang -DANDROID_NDK=%s -DANDROID_PLATFORM=android-14 -DANDROID_STL="c++_shared" && %s --build . --config Release -- -j8 && make install'

DEPENDENCY_PATH = os.path.join(utils.root_path(), 'and_aar')

def system_architecture_is64():
    return platform.machine().endswith('64')
#NDK strip
ANDROID_STRIP_FILE = {
        'armeabi': NDK_ROOT + '/toolchains/arm-linux-androideabi-4.9/prebuilt/%s/bin/arm-linux-androideabi-strip',
        'armeabi-v7a': NDK_ROOT + '/toolchains/arm-linux-androideabi-4.9/prebuilt/%s/bin/arm-linux-androideabi-strip',
        'x86': NDK_ROOT + '/toolchains/x86-4.9/prebuilt/%s/bin/i686-linux-android-strip',
        'arm64-v8a': NDK_ROOT + '/toolchains/aarch64-linux-android-4.9/prebuilt/%s/bin/aarch64-linux-android-strip',
        'x86_64': NDK_ROOT + '/toolchains/x86_64-4.9/prebuilt/%s/bin/x86_64-linux-android-strip',
         }

ANDROID_STL_FILE = {
        'armeabi': NDK_ROOT + '/sources/cxx-stl/llvm-libc++/libs/armeabi/libc++_shared.so',
        'armeabi-v7a': NDK_ROOT + '/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so',
        'x86': NDK_ROOT + '/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so',
        'arm64-v8a': NDK_ROOT + '/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so',
        'x86_64': NDK_ROOT + '/sources/cxx-stl/llvm-libc++/libs/x86_64/libc++_shared.so',
        }

def get_android_strip_cmd(arch):

    system_str = platform.system().lower()
    if (system_architecture_is64()):
        system_str = system_str + '-x86_64'
    else:
        pass

    strip_cmd = ANDROID_STRIP_FILE[arch] %(system_str)
    print('Android strip cmd:%s' %(strip_cmd))
    return strip_cmd

def project_info():
    project_file = os.path.join(utils.root_path(), 'android/project.json')
    return load_json(project_file)

def load_json(path):
    with open(path) as json_file:
        return json.load(json_file)

def get_download_url(group, artifact, version, abi, file_name):
    url = 'http://repo.duowan.com:8181/nexus/content/groups/public'
    url = url+'/'+group+'/'+artifact+'/'+version
    url = url + '/' + file_name
    return url

def dependencies_info_mapper():
    info_mapper_path = os.path.join(utils.root_path(), 'ci_build/android_ver_mapper.json')
    return utils.load_json(info_mapper_path)

def download_dependencies_abi(project_info,arch):
    info_mapper = dependencies_info_mapper()
    name_mapper = project_info['name_mapper']
    for info in project_info['dependencies']:
        group = info['group']
        artifact = info['artifact']
        version = info['version']
        if info_mapper.get(artifact) is not None:
            mapper_ver = info_mapper[artifact]["versions"][version]
            if mapper_ver is not None:
                version = mapper_ver
        
        abi = arch
        file_type = info['type']

        is_snapshot = version.endswith("-SNAPSHOT")
        if is_snapshot :
            file_name = "maven-metadata.xml"
        else :
            file_name = artifact + '-' + version + '-' + abi + '.' + file_type

        url = get_download_url(group,artifact,version,abi,file_name)
        print('====== download url =='+url+"======")
        name = name_mapper.get(artifact)
        if name is not None:
            artifact = name
        target_dir = os.path.join(DEPENDENCY_PATH,artifact+"/"+abi)
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)

        ######自定义文件夹
        folder = info.get('folder')
        if folder is not None:
            target_dir = os.path.join(target_dir,folder)
            if not os.path.exists(target_dir):
                os.mkdir(target_dir)
        if file_type == 'so' or file_type == "a":
            file_name = 'lib'+artifact+"."+file_type

        target_path = os.path.join(target_dir,file_name)
        download(url,target_path)

        if is_snapshot : 
            tree = ET.parse(os.path.join(target_dir,"maven-metadata.xml"))
            root = tree.getroot()
            for versioning in root.findall("versioning"):
                for snapshot in versioning.findall("snapshot") :
                    timestamp = snapshot.find("timestamp").text
                    buildNumber = snapshot.find("buildNumber").text
            file_name = artifact + '-' + version.replace("-SNAPSHOT","") + '-' + timestamp + "-" + buildNumber + "-" + abi + '.' + file_type
            url = get_download_url(group,artifact,version,abi,file_name)
            target_path = os.path.join(target_dir,file_name)
            print('====== download url =='+url+"======")
            download(url,target_path)

        if file_type == 'har':
            unzipfile(target_path,target_dir)
            os.remove(target_path)

    return True
    
def download_dependencies(project_info,archs):
    for arch in archs:
        if not download_dependencies_abi(project_info,arch):
            return False
    return True     

def download(url, dst):
    ret = None
    try:
        ret = urllib2.urlopen(url,timeout=30)
    except urllib2.HTTPError as e:
        print('====download HTTPError=====')

    if ret is not None:
        data = ret.read()
        with open(dst, 'wb') as w:
            w.write(data)
        print('download success [%s]'%url)

def unzipfile(file_path, dest_dir):
    if not os.path.exists(dest_dir):
        os.mkdir(dest_dir)

    zf = zipfile.ZipFile(file_path)
    # try:
    zf.extractall(path=dest_dir)
    # except RuntimeError as e:
    #    print(e)
    zf.close()

def build_android_abi(local_build,project,arch):
    utils.clean(BUILD_OUT_PATH)
    os.chdir(BUILD_OUT_PATH)
    project_path = utils.root_path()
    build_path = os.path.join(project_path, BUILD_OUT_PATH+"/"+arch)
    build_cmd = ANDROID_BUILD_CMD %(CMAKE_PATH,project_path,build_path,arch, NDK_ROOT, NDK_ROOT,CMAKE_PATH)
    print(("build cmd:" + build_cmd))
    ret = os.system(build_cmd)
    if ret != 0:
        print('==================build fail========================')
        return False

    #ndk srtip prebuilt 生成正式可用 so
    # lib_path = arch+"/"+project['name'] + '/libs'
    out_lib_path = os.path.join(build_path, project['name'] + '/libs')
    strip_cmd = get_android_strip_cmd(arch)
    for f in glob.glob('%s/*.so' %(out_lib_path)):
        os.system('%s %s' %(strip_cmd, f))

    android_path = os.path.join(project_path,'android')
    print("android_path:" + android_path+",out_lib_path:"+out_lib_path)
    if project['copy_lib'] == 1:
        copy_file(out_lib_path,android_path,arch)
    elif project['copy_lib'] == 2:
        shutil.copy(ANDROID_STL_FILE[arch], out_lib_path)
        copy_file2(out_lib_path,android_path,arch)

    if local_build:
        project_name = project['name']
        if project_name == 'hqwxbase':
            update_dependencies(build_path,'hqwxsignalling',project_name,arch)
            update_dependencies(build_path,'hqwxclassing',project_name,arch)
            update_dependencies(build_path,'hqwxclassroom',project_name,arch)
            update_dependencies(build_path,'hqwxwhiteboard',project_name,arch)
        elif project_name == 'hqwxsignalling':
            update_dependencies(build_path,'hqwxclassroom',project_name,arch)
            update_dependencies(build_path,'hqwxclassing',project_name,arch)
        elif project_name == 'hqwxclassroom':
            update_dependencies(build_path,'hqwxclassing',project_name,arch)
            update_dependencies(build_path,'hqwxwhiteboard',project_name,arch)
            update_dependencies(build_path,'hqwxinteractive',project_name,arch)
        elif project_name == 'hqwxinteractive':
            update_dependencies(build_path,'hqwxclassing',project_name,arch)
        elif project_name == 'hqwxmetrics':
            update_dependencies(build_path,'hqwxclassing',project_name,arch)
            update_dependencies(build_path,'hqwxsignalling',project_name,arch)
            update_dependencies(build_path,'hqwxclassroom',project_name,arch)
            update_dependencies(build_path,'hqwxwhiteboard',project_name,arch)
            update_dependencies(build_path,'hqwxinteractive',project_name,arch)

    return True

def build_android(local_build,project,archs):
    for arch in archs:
        if not build_android_abi(local_build, project,arch):
            return False
    if local_build:
        return True
    project_path = utils.root_path()
    android_path = os.path.join(project_path,'android')
    os.chdir(os.path.join(android_path,'gradle_build'))
    #bash gradlew clean assembleRelease bash gradlew clean publish
    ret = os.system('bash gradlew clean publish')
    if ret:
        print('==================publish fail========================'+android_path)
        return False
    print('==================publish success========================'+android_path)    
    return True        

#本地构建 更新到引用的库
def update_dependencies(build_path,module_name,project_name,arch):
    build_path = build_path+"/"+project_name
    depend_path = os.path.dirname(utils.root_path())+'/'+module_name+'/depends/'+project_name+"/"+arch
    if os.path.exists(depend_path):
        del_file(depend_path)
        shutil.rmtree(depend_path,True)
    os.makedirs(depend_path)
    shutil.copytree(build_path+"/include",depend_path+"/include")
    shutil.copytree(build_path+"/libs",depend_path+"/libs")
    print("===== update "+module_name+" dependencies ===="+build_path)

def del_file(path):
    for i in os.listdir(path):
        path_file = os.path.join(path,i)
        if os.path.isfile(path_file):
            os.remove(path_file)
        else:
            del_file(path_file)

def copy_file(out_lib_path,android_path,arch):
    target_path = os.path.join(android_path,"libs/"+arch)
    if os.path.exists(target_path):
        shutil.rmtree(target_path)
    os.makedirs(target_path)
    flist = os.listdir(out_lib_path)
    for file_name in flist:
        shutil.copyfile(os.path.join(out_lib_path,file_name),os.path.join(target_path,file_name))

    print('========coy_file========'+target_path)
    return target_path

def copy_file2(out_lib_path,android_path,arch):
    target_path = copy_file(out_lib_path,android_path,arch)
    shutil.copyfile(utils.root_path()+"/depends/hqwxsignalling/"+arch+"/libs/libhqwxsignalling.so",os.path.join(target_path,'libhqwxsignalling.so'))
    shutil.copyfile(utils.root_path()+"/depends/hqwxbase/"+arch+"/libs/libhqwxbase.so",os.path.join(target_path,'libhqwxbase.so'))
    #shutil.copyfile(utils.root_path()+"/depends/hqwxclassroom/libs/libhqwxclassroom.so",os.path.join(target_path,'libhqwxclassroom.so'))
    #shutil.copyfile(utils.root_path()+"/depends/hqwxinteractive/libs/libhqwxinteractive.so",os.path.join(target_path,'libhqwxinteractive.so'))
    print('========coy_file2========')

def version_header_content(project_info, file_name):
    _name = project_info.get('name')
    _version_name = _name.upper()
    _version = project_info.get('version', '1.0.0-dev')
    _version = dependencies_info_mapper().get(_name).get('versions').get(_version)
    _build_num = os.environ.get('BUILD_NUMBER', 1)
    _commit_id = utils.get_git_revision_hash(project_path=utils.root_path(), is_short=True)
    return '''#ifndef {file_name}_h
#define {file_name}_h
#define {version_name}_VERSION "{version}"
#define {version_name}_BUILD_NUM {build_num}
#define {version_name}_COMMIT_ID "{commit_id}"
#endif /* {file_name}_h */
'''.format(file_name=file_name, version_name=_version_name, version=_version, build_num=_build_num, commit_id=_commit_id)

def flutter_build_sh():
    print('ci-build-and')
    os.chdir(utils.root_path())
    os.system('ls')
    return os.system('sh ci-build-and.sh');

def flutter_build_aar():
    print('flutter_build_aar')
    os.chdir(utils.root_path())
    return os.system('flutter build aar')

def flutter_build_apk():
    print('flutter_build_apk')
    os.chdir(utils.root_path())
    return os.system('flutter build apk')

def generate_zip(output_dir, project_name):
    product_dir = os.path.join(output_dir, project_name)
    shutil.make_archive(product_dir, 'zip', DEPENDENCY_PATH)

def run(cfg):
    print('--------android---------')
    print(cfg)
    project = utils.project_info()


    if not os.path.exists(cfg.output_dir):
        os.makedirs(cfg.output_dir)

    flutter_build_sh()

    project_name = project['name']
    print(project_name)
    generate_zip(cfg.output_dir, project_name)



    # local_bool = cfg.macro_arg == "local_build"

    # project = project_info()
    # file_name = '{}_version'.format(project.get('name'))
    # content = version_header_content(project, file_name)
    # file_path = os.path.join(utils.root_path(), 'src/{}.h'.format(file_name))
    # utils.write_content(content, file_path)
    # archs = set(["arm64-v8a","armeabi-v7a"])
    # if local_bool :
    #     if os.path.exists(DEPENDENCY_PATH):
    #         build_android(local_bool,project,archs)
    #     else:
    #         project = project_info()
    #         print(project)
    #         os.mkdir(DEPENDENCY_PATH)
    #         if download_dependencies(project,archs) and build_android(local_bool,project,archs):
    #             print('==================output========================')
    #             exit(0)
    #         exit(1)
    # else:
    #     if os.path.exists(DEPENDENCY_PATH):
    #         shutil.rmtree(DEPENDENCY_PATH)
    #     os.mkdir(DEPENDENCY_PATH)
    #     print(project)
    #     if download_dependencies(project,archs) and build_android(local_bool,project,archs):
    #         print('==================output========================')
    #         exit(0)
    #     exit(1)

ci-build-and.sh

if [ -z $out ]; then
    out='and_aar'
fi

echo "准备输出所有文件到目录: $out"

echo "清除所有已编译文件"
find . -d -name build | xargs rm -rf
flutter clean
rm -rf $out
rm -rf build

flutter packages get

addFlag(){
    cat .ios/Podfile > tmp1.txt
    echo "and_aar!" >> tmp2.txt
    cat tmp1.txt >> tmp2.txt
    cat tmp2.txt > .android/gradlew
    rm tmp1.txt tmp2.txt
}

# echo "检查 .ios/Podfile文件状态"
# a=$(cat .ios/Podfile)
# if [[ $a == use* ]]; then
#     echo '已经添加use_frameworks, 不再添加'
# else
#     echo '未添加use_frameworks,准备添加'
#     addFlag
#     echo "添加use_frameworks 完成"
# fi

echo "编译flutter"
flutter build aar  
# flutter build apk
echo "编译flutter完成"
mkdir $out
cp -r build/host/outputs/* $out
#release下放开下一行注释,注释掉上一行代码
#cp -r build/ios/Release-iphoneos/*/*.framework $out
# cp -r .ios/Flutter/App.framework $out
# cp -r .ios/Flutter/engine/Flutter.framework $out

echo "复制aar库到临时文件夹: $out"

libpath='../'

rm -rf "$libpath/and_aar"
mkdir $libpath
cp -r $out $libpath

echo "复制库文件到: $libpath"

上一篇 下一篇

猜你喜欢

热点阅读