aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-03-29 15:08:25 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-03-29 15:08:25 +0300
commit6eea9d2f39fb9f4d899efd685c872e4b8ede680f (patch)
treefede9620276c8eafb0c51ff2ddd8e914be89f247
parent5f65d38427c0df2cc82db30c0363c6aa5d4d856e (diff)
downloadydb-6eea9d2f39fb9f4d899efd685c872e4b8ede680f.tar.gz
intermediate changes
ref:b63d6b71507593ba174dde46e5c3aee4e9ccd498
-rw-r--r--build/scripts/export_script_gen.py123
-rw-r--r--cmake/yandex_common.cmake41
2 files changed, 164 insertions, 0 deletions
diff --git a/build/scripts/export_script_gen.py b/build/scripts/export_script_gen.py
new file mode 100644
index 0000000000..269af2e3ca
--- /dev/null
+++ b/build/scripts/export_script_gen.py
@@ -0,0 +1,123 @@
+import argparse
+import collections
+import sys
+
+
+def parse_export_file(src):
+ for line in src:
+ line = line.strip()
+
+ if line and '#' not in line:
+ words = line.split()
+ if len(words) == 2 and words[0] == 'linux_version':
+ yield {'linux_version': words[1]}
+ elif len(words) == 2:
+ yield {'lang': words[0], 'sym': words[1]}
+ elif len(words) == 1:
+ yield {'lang': 'C', 'sym': words[0]}
+ else:
+ raise Exception('unsupported exports line: "{}"'.format(line))
+
+
+def to_c(sym):
+ symbols = collections.deque(sym.split('::'))
+ c_prefixes = [ # demangle prefixes for c++ symbols
+ '_ZN', # namespace
+ '_ZTIN', # typeinfo for
+ '_ZTSN', # typeinfo name for
+ '_ZTTN', # VTT for
+ '_ZTVN', # vtable for
+ '_ZNK', # const methods
+ ]
+ c_sym = ''
+ while symbols:
+ s = symbols.popleft()
+ if s == '*':
+ c_sym += '*'
+ break
+ if '*' in s and len(s) > 1:
+ raise Exception('Unsupported format, cannot guess length of symbol: ' + s)
+ c_sym += str(len(s)) + s
+ if symbols:
+ raise Exception('Unsupported format: ' + sym)
+ if c_sym[-1] != '*':
+ c_sym += 'E*'
+ return ['{prefix}{sym}'.format(prefix=prefix, sym=c_sym) for prefix in c_prefixes]
+
+
+def to_gnu(src, dest):
+ d = collections.defaultdict(list)
+ version = None
+ for item in parse_export_file(src):
+ if item.get('linux_version'):
+ if not version:
+ version = item.get('linux_version')
+ else:
+ raise Exception('More than one linux_version defined')
+ elif item['lang'] == 'C++':
+ d['C'].extend(to_c(item['sym']))
+ else:
+ d[item['lang']].append(item['sym'])
+
+ if version:
+ dest.write('{} {{\nglobal:\n'.format(version))
+ else:
+ dest.write('{\nglobal:\n')
+
+ for k, v in d.items():
+ dest.write(' extern "' + k + '" {\n')
+
+ for x in v:
+ dest.write(' ' + x + ';\n')
+
+ dest.write(' };\n')
+
+ dest.write('local: *;\n};\n')
+
+
+def to_msvc(src, dest):
+ dest.write('EXPORTS\n')
+ for item in parse_export_file(src):
+ if item.get('linux_version'):
+ continue
+ if item.get('lang') == 'C':
+ dest.write(' {}\n'.format(item.get('sym')))
+
+
+def to_darwin(src, dest):
+ for item in parse_export_file(src):
+ if item.get('linux_version'):
+ continue
+
+ if item['lang'] == 'C':
+ dest.write('-Wl,-exported_symbol,_' + item['sym'])
+ elif item['lang'] == 'C++':
+ for sym in to_c(item['sym']):
+ dest.write('-Wl,-exported_symbol,_' + sym)
+ else:
+ raise Exception('unsupported lang: ' + item['lang'])
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Convert self-invented platform independent export file format to the format required by specific linker')
+ parser.add_argument('src', type=argparse.FileType('r', encoding='UTF-8'), help='platform independent export file path')
+ parser.add_argument('dest', type=argparse.FileType('w', encoding='UTF-8'), help='destination export file for required linker')
+ parser.add_argument('--format', help='destination file type format: gnu, msvc or darwin')
+
+ args = parser.parse_args()
+ if args.format == 'gnu':
+ to_gnu(args.src, args.dest)
+ elif args.format == 'msvc':
+ to_msvc(args.src, args.dest)
+ elif args.format == 'darwin':
+ to_darwin(args.src, args.dest)
+ else:
+ print('Unknown destination file format: {}'.format(args.format), file=sys.stderr)
+ sys.exit(1)
+
+ args.src.close()
+ args.dest.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/cmake/yandex_common.cmake b/cmake/yandex_common.cmake
index 4efaad97b4..0701afbda6 100644
--- a/cmake/yandex_common.cmake
+++ b/cmake/yandex_common.cmake
@@ -1,6 +1,7 @@
# Set of common macros
find_package(Python2 REQUIRED)
+find_package(Python3 REQUIRED)
function(target_ragel_lexers TgtName Key Src)
SET(RAGEL_BIN ${CMAKE_BINARY_DIR}/bin/ragel)
@@ -122,3 +123,43 @@ function(resources Tgt Output)
DEPENDS ${RESOURCE_ARGS_INPUTS}
)
endfunction()
+
+function(use_export_script Target ExportFile)
+ get_filename_component(OutName ${ExportFile} NAME)
+ set(OutPath ${CMAKE_CURRENT_BINARY_DIR}/gen_${OutName})
+
+ if (MSVC)
+ target_link_flags(${Target} PRIVATE /DEF:${OutPath})
+ set(EXPORT_SCRIPT_FLAVOR msvc)
+ elseif(APPLE)
+ execute_process(
+ COMMAND Python3_EXECUTABLE ${CMAKE_SOURCE_DIR}/build/scripts/export_script_gen.py ${ExportFile} --format darwin
+ RESULT_VARIABLE _SCRIPT_RES
+ OUTPUT_VARIABLE _SCRIPT_FLAGS
+ ERROR_VARIABLE _SCRIPT_STDERR
+ )
+ if (NOT ${_SCRIPT_RES} EQUAL 0)
+ message(FATAL_ERROR "Failed to parse export symbols from ${ExportFile}:\n${_SCRIPT_STDERR}")
+ return()
+ endif()
+ target_link_flags(${Target} PRIVATE ${_SCRIPT_FLAGS})
+ return()
+ else()
+ set(EXPORT_SCRIPT_FLAVOR gnu)
+ target_link_flags(${Target} PRIVATE -Wl,--gc-sections -rdynamic -Wl,--version-script=${OutPath})
+ endif()
+
+ add_custom_command(
+ OUTPUT ${OutPath}
+ COMMAND
+ Python3::Interpreter ${CMAKE_SOURCE_DIR}/build/scripts/export_script_gen.py ${ExportFile} ${OutPath} --format ${EXPORT_SCRIPT_FLAVOR}
+ DEPENDS ${ExportFile} ${CMAKE_SOURCE_DIR}/build/scripts/export_script_gen.py
+ )
+ target_sources(${Target} PRIVATE ${OutPath})
+ set_property(SOURCE ${OutPath} PROPERTY
+ HEADER_FILE_ONLY On
+ )
+ set_property(TARGET ${Target} APPEND PROPERTY
+ LINK_DEPENDS ${OutPath}
+ )
+endfunction()