Skip to content

Instantly share code, notes, and snippets.

@0x1306a94
Created September 21, 2023 08:12
Show Gist options
  • Save 0x1306a94/7720b9b70e5666e63366c2a908d20e23 to your computer and use it in GitHub Desktop.
Save 0x1306a94/7720b9b70e5666e63366c2a908d20e23 to your computer and use it in GitHub Desktop.
mars build xcframework
#!/usr/bin/env python
import os
import sys
import glob
from mars_utils import *
SCRIPT_PATH = os.path.split(os.path.realpath(__file__))[0]
BUILD_OUT_PATH = 'cmake_build/iOS'
INSTALL_PATH = BUILD_OUT_PATH + '/iOS.out'
IOS_BUILD_SIMULATOR_CMD = 'cmake ../.. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../../ios.toolchain.cmake -DPLATFORM=SIMULATOR64 -DENABLE_ARC=0 -DENABLE_BITCODE=0 -DENABLE_VISIBILITY=1 && make -j8 && make install'
IOS_BUILD_SIMULATOR_ARM64_CMD = 'cmake ../.. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../../ios.toolchain.cmake -DPLATFORM=SIMULATORARM64 -DENABLE_ARC=0 -DENABLE_BITCODE=0 -DENABLE_VISIBILITY=1 && make -j8 && make install'
IOS_BUILD_OS_CMD = 'cmake ../.. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../../ios.toolchain.cmake -DPLATFORM=OS64 -DENABLE_ARC=0 -DENABLE_BITCODE=0 -DENABLE_VISIBILITY=1 && make -j8 && make install'
GEN_IOS_OS_PROJ = 'cmake ../.. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../../ios.toolchain.cmake -DPLATFORM=OS -DIOS_ARCH="arm64" -DENABLE_ARC=0 -DENABLE_BITCODE=0 -DENABLE_VISIBILITY=1'
OPEN_SSL_ARCHS = ['x86_64', 'arm64']
def build_ios(tag=''):
gen_mars_revision_file('comm', tag)
clean(BUILD_OUT_PATH)
os.chdir(BUILD_OUT_PATH)
ret = os.system(IOS_BUILD_OS_CMD)
os.chdir(SCRIPT_PATH)
if ret != 0:
print('!!!!!!!!!!!build os fail!!!!!!!!!!!!!!!')
return False
libtool_os_dst_lib = INSTALL_PATH + '/os'
libtool_src_lib = glob.glob(INSTALL_PATH + '/*.a')
libtool_src_lib.append(BUILD_OUT_PATH + '/zstd/libzstd.a')
if not libtool_libs(libtool_src_lib, libtool_os_dst_lib):
return False
clean(BUILD_OUT_PATH)
os.chdir(BUILD_OUT_PATH)
ret = os.system(IOS_BUILD_SIMULATOR_CMD)
os.chdir(SCRIPT_PATH)
if ret != 0:
print('!!!!!!!!!!!build simulator fail!!!!!!!!!!!!!!!')
return False
libtool_simulator_dst_lib = INSTALL_PATH + '/simulator'
if not libtool_libs(libtool_src_lib, 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)
ssl_lib = INSTALL_PATH + '/ssl'
if not lipo_thin_libs('openssl/openssl_lib_iOS/libssl.a', ssl_lib, OPEN_SSL_ARCHS):
return False
crypto_lib = INSTALL_PATH + '/crypto'
if not lipo_thin_libs('openssl/openssl_lib_iOS/libcrypto.a', crypto_lib, OPEN_SSL_ARCHS):
return False
lipo_src_libs.append(ssl_lib)
lipo_src_libs.append(crypto_lib)
lipo_dst_lib = INSTALL_PATH + '/mars'
if not libtool_libs(lipo_src_libs, lipo_dst_lib):
return False
dst_framework_path = INSTALL_PATH + '/mars.framework'
make_static_framework(lipo_dst_lib, dst_framework_path, COMM_COPY_HEADER_FILES, '../')
print('==================Output========================')
print(dst_framework_path)
return True
def build_ios_xlog(tag=''):
gen_mars_revision_file('comm', tag)
clean(BUILD_OUT_PATH)
os.chdir(BUILD_OUT_PATH)
ret = os.system(IOS_BUILD_OS_CMD)
os.chdir(SCRIPT_PATH)
if ret != 0:
print('!!!!!!!!!!!build os fail!!!!!!!!!!!!!!!')
return False
libtool_os_dst_lib = INSTALL_PATH + '/mars'
libtool_src_libs = [INSTALL_PATH + '/libcomm.a',
INSTALL_PATH + '/libmars-boost.a',
INSTALL_PATH + '/libxlog.a',
BUILD_OUT_PATH + '/zstd/libzstd.a']
if not libtool_libs(libtool_src_libs, libtool_os_dst_lib):
return False
dst_os_framework_path = INSTALL_PATH + '/iphoneos/mars.framework'
make_static_framework(libtool_os_dst_lib, dst_os_framework_path, XLOG_COPY_HEADER_FILES, '../')
clean(BUILD_OUT_PATH)
os.chdir(BUILD_OUT_PATH)
ret = os.system(IOS_BUILD_SIMULATOR_CMD)
os.chdir(SCRIPT_PATH)
if ret != 0:
print('!!!!!!!!!!!build simulator fail!!!!!!!!!!!!!!!')
return False
libtool_simulator_dst_lib = INSTALL_PATH + '/mars_sim_x86_64'
if not libtool_libs(libtool_src_libs, libtool_simulator_dst_lib):
return False
clean(BUILD_OUT_PATH)
os.chdir(BUILD_OUT_PATH)
ret = os.system(IOS_BUILD_SIMULATOR_ARM64_CMD)
os.chdir(SCRIPT_PATH)
if ret != 0:
print('!!!!!!!!!!!build simulator fail!!!!!!!!!!!!!!!')
return False
libtool_simulator_arm64_dst_lib = INSTALL_PATH + '/mars_sim_arm64'
if not libtool_libs(libtool_src_libs, libtool_simulator_arm64_dst_lib):
return False
sim_all_libs = [
libtool_simulator_dst_lib,
libtool_simulator_arm64_dst_lib,
]
libtool_simulator_merge_dst_lib = INSTALL_PATH + '/mars'
if not lipo_libs(sim_all_libs, libtool_simulator_merge_dst_lib):
return False
dst_sim_framework_path = INSTALL_PATH + '/iphonesimulator/mars.framework'
make_static_framework(libtool_simulator_merge_dst_lib, dst_sim_framework_path, XLOG_COPY_HEADER_FILES, '../')
print('==================Output framework========================')
print(dst_os_framework_path)
print(dst_sim_framework_path)
dst_xcframework = INSTALL_PATH + '/mars.xcframework'
make_static_xcframework([dst_os_framework_path,dst_sim_framework_path], dst_xcframework)
print('==================Output xcframework========================')
print(dst_xcframework)
def gen_ios_project():
gen_mars_revision_file('comm')
clean(BUILD_OUT_PATH)
os.chdir(BUILD_OUT_PATH)
ret = os.system(GEN_IOS_OS_PROJ)
os.chdir(SCRIPT_PATH)
if ret != 0:
print('!!!!!!!!!!!gen fail!!!!!!!!!!!!!!!')
return False
print('==================Output========================')
print('project file: %s/%s' %(SCRIPT_PATH, BUILD_OUT_PATH))
return True
def main():
while True:
if len(sys.argv) >= 2:
build_ios(sys.argv[1])
break
else:
num = input('Enter menu:\n1. Clean && build mars.\n2. Clean && build xlog.\n3. Gen iOS mars Project.\n4. Exit\n')
if num == '1':
build_ios()
break
if num == '2':
build_ios_xlog()
break
elif num == '3':
gen_ios_project()
break
elif num == '4':
break
else:
build_ios()
break
if __name__ == '__main__':
main()
#!/usr/bin/env python
import os
import shutil
import time
import subprocess
COMM_COPY_HEADER_FILES = {
"mars/comm/verinfo.h": "comm",
"mars/comm/autobuffer.h": "comm",
"mars/comm/http.h": "comm",
"mars/comm/time_utils.h": "comm",
"mars/comm/strutil.h": "comm",
"mars/comm/string_cast.h": "comm",
"mars/comm/comm_data.h": "comm",
"mars/comm/projdef.h": "comm",
"mars/comm/platform_comm.h": "comm",
"mars/comm/socket/local_ipstack.h": "comm",
"mars/comm/socket/nat64_prefix_util.h": "comm",
"mars/comm/has_member.h" : "comm",
"mars/comm/objc/scope_autoreleasepool.h": "comm",
"mars/comm/objc/ThreadOperationQueue.h": "comm",
"mars/stn/stn.h": "stn",
"mars/stn/stn_logic.h": "stn",
"mars/stn/proto/stnproto_logic.h": "stn",
"mars/baseevent/base_logic.h": "baseevent",
"mars/comm/xlogger/preprocessor.h": "xlog",
"mars/comm/xlogger/xloggerbase.h": "xlog",
"mars/comm/xlogger/xlogger.h": "xlog",
"mars/log/appender.h": "xlog",
"mars/log/xlogger_interface.h": "xlog",
"mars/app/app.h": "app",
"mars/app/app_logic.h": "app",
"mars/sdt/sdt.h": "sdt",
"mars/sdt/sdt_logic.h": "sdt",
"mars/sdt/constants.h": "sdt",
"mars/sdt/netchecker_profile.h": "sdt",
"mars/stn/proto/longlink_packer.h": "stn/proto",
}
WIN_COPY_EXT_FILES = {
"mars/comm/platform_comm.h": "comm",
"mars/comm/windows/projdef.h": "comm/windows",
"mars/comm/windows/sys/cdefs.h": "comm/windows/sys",
"mars/comm/windows/sys/time.h": "comm/windows/sys",
"mars/comm/platform_comm.h": "comm",
}
XLOG_COPY_HEADER_FILES = {
"mars/comm/verinfo.h": "comm",
"mars/comm/autobuffer.h": "comm",
"mars/comm/http.h": "comm",
"mars/comm/time_utils.h": "comm",
"mars/comm/strutil.h": "comm",
"mars/comm/string_cast.h": "comm",
"mars/comm/comm_data.h": "comm",
"mars/comm/projdef.h": "comm",
"mars/comm/socket/local_ipstack.h": "comm",
"mars/comm/socket/nat64_prefix_util.h": "comm",
"mars/comm/has_member.h" : "comm",
"mars/comm/objc/scope_autoreleasepool.h": "comm",
"mars/comm/objc/ThreadOperationQueue.h": "comm",
"mars/comm/xlogger/preprocessor.h": "xlog",
"mars/comm/xlogger/xloggerbase.h": "xlog",
"mars/comm/xlogger/xlogger.h": "xlog",
"mars/log/appender.h": "xlog",
"mars/log/xlogger_interface.h": "xlog",
}
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
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 -no_warning_for_no_symbols -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 = u''
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)
GENERATE_DSYM_FILE_CMD = 'dsymutil %s -o %s'
def gen_dwarf_with_dsym(src_dylib, dst_dsym):
os.system(GENERATE_DSYM_FILE_CMD %(src_dylib, dst_dsym))
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_except(path, except_list):
for fpath, dirs, fs in os.walk(path):
in_except = False
for exc in except_list:
if exc in fpath:
in_except = True
break
if not in_except:
remove_cmake_files(fpath)
if not os.path.exists(path):
os.makedirs(path)
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 clean_windows(path, incremental):
if not os.path.exists(path):
os.makedirs(path)
return
if incremental:
return;
try:
if os.path.exists(path):
shutil.rmtree(path)
if not os.path.exists(path):
os.makedirs(path)
except Exception:
pass
def copy_windows_pdb(cmake_out, sub_folder, config, dst_folder):
for sf in sub_folder:
# src_file = "%s/%s/" %(cmake_out, sf)
# dirs = glob.glob(src_file + "*.dir")
# if len(dirs) != 1:
# print("Warning: %s path error." %src_file)
# continue
src_file = "%s/%s/%s" %(cmake_out, sf, config)
pdbs = glob.glob(src_file + "/*.pdb")
if len(pdbs) != 1:
print("Warning: %s path error." %src_file)
continue
pdb = pdbs[0]
if os.path.isfile(pdb):
shutil.copy(pdb, dst_folder)
else:
print("%s not exists" %pdb)
def copy_file(src, dst):
if not os.path.isfile(src):
print('Warning: %s not exist cwd %s' %(src, os.getcwd()))
return;
if dst.rfind("/") != -1 and not os.path.exists(dst[:dst.rfind("/")]):
os.makedirs(dst[:dst.rfind("/")])
shutil.copy(src, dst)
def copy_file_mapping(header_file_mappings, header_files_src_base, header_files_dst_end):
for (src, dst) in header_file_mappings.items():
copy_file(header_files_src_base + src, header_files_dst_end + "/" + dst + '/' + src[src.rfind("/"):])
def make_static_framework(src_lib, dst_framework, header_file_mappings, header_files_src_base='./'):
if os.path.exists(dst_framework):
shutil.rmtree(dst_framework)
os.makedirs(dst_framework)
shutil.copy(src_lib, dst_framework)
framework_path = dst_framework + '/Headers'
for (src, dst) in header_file_mappings.items():
copy_file(header_files_src_base + src, framework_path + "/" + dst + '/' + src[src.rfind("/"):])
return True
def make_static_xcframework(src_frameworks, dst_xcframework):
if os.path.exists(dst_xcframework):
shutil.rmtree(dst_xcframework)
cmd = 'xcodebuild -create-xcframework'
for f in src_frameworks:
cmd = '%s -framework %s' % (cmd, f)
cmd = '%s -output %s' % (cmd, dst_xcframework)
print('==================create xcframework========================')
print(cmd)
os.system(cmd)
def check_ndk_env():
try:
ndk_path = os.environ['NDK_ROOT']
except KeyError as identifier:
print("Error: ndk does not exist or you do not set it into NDK_ROOT.")
return False
if ndk_path is not None and ndk_path.strip():
print("ndk path:%s"%ndk_path)
if not ndk_path:
print("Error: ndk does not exist or you do not set it into NDK_ROOT.")
return False
if not os.path.isfile(os.path.join(ndk_path, "source.properties")):
print("Error: source.properties does not exist, make sure ndk's version==r16b")
return False
ndk_revision = None
f = open(os.path.join(ndk_path, "source.properties"))
line = f.readline()
while line:
if line.startswith("Pkg.Revision") and len(line.split("=")) == 2:
ndk_revision = line.split("=")[1].strip()
line = f.readline()
f.close()
if not ndk_revision or len(ndk_revision) < 4:
print("Error: parse source.properties fail")
return False
if ndk_revision[:4] >= "16.1":
return True
print("Error: make sure ndk's version >= r16b")
return False
html_css = '''
<style type="text/css">
.description table {
margin: 10px 0 15px 0;
border-collapse: collapse;
font-family: Helvetica, "Hiragino Sans GB", Arial, sans-serif;
font-size: 11px;
line-height: 16px;
color: #737373;
background-color: white;
margin: 10px 12px 10px 12px;
}
.description td,th { border: 1px solid #ddd; padding: 3px 10px; }
.description th { padding: 5px 10px; }
.description a { color: #0069d6; }
.description a:hover { color: #0050a3; text-decoration: none; }
.description h5 { font-size: 14px; }
</style>
'''
html_table_template = '''
<div class="description">
<h5>{title}</h5>
<table>
<thead>
<tr>
<th align="left">KEY</th>
<th align="left">VALUE</th>
</tr>
</thead>
{table_rows}
</table>
</div>
'''
html_row_template = '''
<tr>
<td align="left">{key}</td>
<td align="left">{value}</td>
</tr>
'''
def parse_as_git(path):
curdir = os.getcwd()
os.chdir(path)
revision = os.popen('git rev-parse --short HEAD').read().strip()
path = os.popen('git rev-parse --abbrev-ref HEAD').read().strip()
url = ''
os.chdir(curdir)
return revision, path, url
def gen_mars_revision_file(version_file_path, tag=''):
revision, path, url = parse_as_git(version_file_path)
build_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
contents = '''
#ifndef Mars_verinfo_h
#define Mars_verinfo_h
#define MARS_REVISION "%s"
#define MARS_PATH "%s"
#define MARS_URL "%s"
#define MARS_BUILD_TIME "%s"
#define MARS_TAG "%s"
#endif
''' % (revision, path, url, build_time, tag)
with open('%s/verinfo.h' % version_file_path, 'wb') as f:
f.write(contents.encode())
f.flush()
version_data = {
'PublicComponent': {
'Branch': path,
'Revision': revision,
'BuildTag': tag,
'BuildTime': build_time
}
}
output = '[[==BUILD_DESCRIPTION==]]Revision: %s %s' % (
version_data['PublicComponent']['Revision'],
'&nbsp;' * 18)
html = html_css
data_type = 'PublicComponent'
html_rows = ''
for key in sorted(version_data[data_type].keys()):
html_rows += html_row_template.format(key=key, value=version_data[data_type][key])
html += html_table_template.format(title=data_type, table_rows=html_rows)
output += html
print (''.join(output.splitlines()))
def check_vs_env():
vs_tool_dir = os.getenv("VS140COMNTOOLS")
if not vs_tool_dir:
print("You must install visual studio 2015 for build.")
return False
print('vs.dir: ' + vs_tool_dir)
envbat = vs_tool_dir + "../../vc/vcvarsall.bat"
print('vsvar.dir: ' + envbat)
p = subprocess.Popen(envbat)
p.wait()
return True
def merge_win_static_libs(src_libs, dst_lib):
vs_tool_dir = os.getenv("VS140COMNTOOLS")
lib_cmd = vs_tool_dir + '/../../VC/bin/lib.exe'
print('lib cmd:' + lib_cmd)
src_libs.insert(0, '/OUT:' + dst_lib)
src_libs.insert(0, lib_cmd)
p = subprocess.Popen(src_libs)
p.wait()
if p.returncode != 0:
print('!!!!!!!!!!!lib.exe %s fail!!!!!!!!!!!!!!!' %(dst_lib))
return False
return True
import glob
if __name__ == '__main__':
lipo_thin_libs(u'/Users/garry/Documents/gitcode/mmnet/mars/openssl/openssl_lib_iOS/libcrypto.a', u'/Users/garry/Documents/gitcode/mmnet/mars/openssl/openssl_lib_iOS/libcrypto_test.a', ['x86_64', 'arm64'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment