Skip to content

Commit

Permalink
Partially unbreak macOS.
Browse files Browse the repository at this point in the history
  • Loading branch information
obilaniu committed Jul 12, 2021
1 parent a94f1ae commit 90e1854
Show file tree
Hide file tree
Showing 15 changed files with 215 additions and 105 deletions.
117 changes: 78 additions & 39 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,84 @@ FUNCP_SIZE = cc.sizeof(FUNCP)
assert(CHARP_SIZE == cxx.sizeof(FUNCP), f'C and C++ compilers disagree on sizeof(@FUNCP@)!')
assert(VOIDP_SIZE == CHARP_SIZE, f'Pointers to void and char not of equal size!')
assert(VOIDP_SIZE == FUNCP_SIZE, f'Pointers to void and function not of equal size!')
add_global_arguments([f'-DGASPOINTERSIZE=@VOIDP_SIZE@',
f'-DGASPOINTERWORD=.@VOIDP_SIZE@byte'], language: ['c','cpp'])


#
# Add predefined macros identifying the:
# - C & C++ compilers
# - CPU family
# - Operating System
#
MACRO_COMPILER_CC = 'BENZINA_COMPILER_'
MACRO_COMPILER_CXX = 'BENZINA_COMPILER_'
MACRO_CPU_FAMILY = 'BENZINA_CPU_FAMILY_'
MACRO_OS = 'BENZINA_OS_'
MACRO_COMPILER_CC += {'clang-cl': 'clang',
'intel-cl': 'intel'}.get(CC_ID, CC_ID)
MACRO_COMPILER_CXX += {'clang-cl': 'clang',
'intel-cl': 'intel'}.get(CXX_ID, CXX_ID)
MACRO_CPU_FAMILY += host_machine.cpu_family()
MACRO_OS += host_machine.system()
MACRO_COMPILER_CC = MACRO_COMPILER_CC .to_upper().underscorify()
MACRO_COMPILER_CXX = MACRO_COMPILER_CXX.to_upper().underscorify()
MACRO_CPU_FAMILY = MACRO_CPU_FAMILY .to_upper().underscorify()
MACRO_OS = MACRO_OS .to_upper().underscorify()
add_global_arguments([f'-D@MACRO_COMPILER_CC@=1'], language: 'c')
add_global_arguments([f'-D@MACRO_COMPILER_CXX@=1'], language: 'cpp')
add_global_arguments([f'-D@MACRO_CPU_FAMILY@=1',
f'-D@MACRO_OS@=1',
f'-DBENZINA_COMPILER_IDENTIFIED=1',
f'-DBENZINA_CPU_FAMILY_IDENTIFIED=1',
f'-DBENZINA_OS_IDENTIFIED=1'], language: ['c', 'cpp'])


#
# Add predefined macros for use by the preprocessed assembly code, identifying:
#
# - Pointer size
# - Underscore prefixing
# - Section/segment+section names and attributes
#
# The section names must be <=15 characters long due to
# A) macOS's Mach-O binary format imposing a limitation of 16 characters and
# B) macOS's Mach-O binary format using a naming convention of
# __SEGM,__sect
# which we adhere to by underscorifying the equivalent ELF section name
# and adding an additional prefix underscore.
#
# Because of this, plus other difficulties, we do not currently support
# preloading Lua modules in Lua states on macOS.
#
add_global_arguments([f'-DASM_PTR_SIZE=@VOIDP_SIZE@',
f'-DASM_PTR_DECL=.@VOIDP_SIZE@byte'], language: ['c', 'cpp'])
SECT_DICT = {
'BSS': {'name': '.bss', 'elf_attr': '', 'macho_segm': '__DATA', 'macho_attr': ''},
'CSTRING': {'name': '.rodata.str1.1', 'elf_attr': '"aMS", @progbits, 1', 'macho_segm': '__TEXT', 'macho_attr': 'cstring_literals'},
'LICENSE': {'name': '.license', 'elf_attr': '"a"', 'macho_segm': '__TEXT', 'macho_attr': 'regular, no_dead_strip'},
'RODATALZ4': {'name': '.rodata.lz4', 'elf_attr': '"a"', 'macho_segm': '__TEXT', 'macho_attr': 'regular, no_dead_strip'},
'LZ4CMDARRAY': {'name': '.lz4.cmd_array', 'elf_attr': '"aw"', 'macho_segm': '__DATA', 'macho_attr': 'regular, no_dead_strip'},
'TOOLARRAY': {'name': '.tool_array', 'elf_attr': '"aw"', 'macho_segm': '__DATA', 'macho_attr': 'regular, no_dead_strip'},
'LUAOPENARRAY': {'name': '.lua.open_array', 'elf_attr': '"aw"', 'macho_segm': '__DATA', 'macho_attr': 'regular, no_dead_strip'},
'LUAOPENARRAYPRELOAD': {'name': '.lua.open_array.preload', 'elf_attr': '"aw"', 'macho_segm': '__DATA', 'macho_attr': 'regular, no_dead_strip'},
'LUATEXTARRAY': {'name': '.lua.text_array', 'elf_attr': '"aw"', 'macho_segm': '__DATA', 'macho_attr': 'regular, no_dead_strip'},
}
foreach sect, dict : SECT_DICT
if IS_HOST_DARWIN
sect_name = dict['macho_segm'] + ',_' + {
'LUAOPENARRAYPRELOAD': '.lua.open_array', # Name too long for Mach-O
'CSTRING': '.cstring', # Mach-O uses __cstring for mergeable strings
}.get(sect, dict['name']).underscorify()
sect_attr = dict['macho_attr']
else
sect_name = dict['name']
sect_attr = dict['elf_attr']
endif
sect_attr = sect_attr == '' ? sect_attr : ', '+sect_attr
add_global_arguments([
f'-DASM_SECT_@sect@_NAME="@sect_name@"',
f'-DASM_SECT_@sect@_DECL=.section @sect_name@@sect_attr@',
], language: ['c', 'cpp'])
endforeach


#
Expand Down Expand Up @@ -168,43 +244,6 @@ openmp = dependency('openmp', required: false)
threads = dependency('threads')


#
# Add predefined macros identifying the:
# - C & C++ compilers
# - CPU family
# - Operating System
#
MACRO_COMPILER_CC = 'BENZINA_COMPILER_'
MACRO_COMPILER_CXX = 'BENZINA_COMPILER_'
MACRO_CPU_FAMILY = 'BENZINA_CPU_FAMILY_'
MACRO_OS = 'BENZINA_OS_'
MACRO_COMPILER_CC += {'clang-cl': 'clang',
'intel-cl': 'intel'}.get(CC_ID, CC_ID)
MACRO_COMPILER_CXX += {'clang-cl': 'clang',
'intel-cl': 'intel'}.get(CXX_ID, CXX_ID)
MACRO_CPU_FAMILY += host_machine.cpu_family()
MACRO_OS += host_machine.system()
MACRO_COMPILER_CC = MACRO_COMPILER_CC .to_upper().underscorify()
MACRO_COMPILER_CXX = MACRO_COMPILER_CXX.to_upper().underscorify()
MACRO_CPU_FAMILY = MACRO_CPU_FAMILY .to_upper().underscorify()
MACRO_OS = MACRO_OS .to_upper().underscorify()

add_project_arguments(['-D'+MACRO_COMPILER_CC+'=1',
'-DBENZINA_COMPILER_IDENTIFIED=1'], language: 'c')
add_project_arguments(['-D'+MACRO_COMPILER_CXX+'=1',
'-DBENZINA_COMPILER_IDENTIFIED=1'], language: 'cpp')

add_project_arguments(['-D'+MACRO_CPU_FAMILY+'=1',
'-DBENZINA_CPU_FAMILY_IDENTIFIED=1'], language: 'c')
add_project_arguments(['-D'+MACRO_CPU_FAMILY+'=1',
'-DBENZINA_CPU_FAMILY_IDENTIFIED=1'], language: 'cpp')

add_project_arguments(['-D'+MACRO_OS+'=1',
'-DBENZINA_OS_IDENTIFIED=1'], language: 'c')
add_project_arguments(['-D'+MACRO_OS+'=1',
'-DBENZINA_OS_IDENTIFIED=1'], language: 'cpp')


#
# Configuration Data
#
Expand Down
18 changes: 9 additions & 9 deletions scripts/lz4-lua-pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

payload_unc = bytearray()
with open(out_S, "w") as f:
f.write('.section .rodata.str1.1, "aMS", @progbits, 1\n')
f.write('ASM_SECT_CSTRING_DECL\n')
for i, name in enumerate(sortednames):
f.write(f' .Lname{i}: .asciz "{name}"\n')
f.write('\n\n')
f.write('.section .bss\n')
f.write('.align 4096\n')
f.write('ASM_SECT_BSS_DECL\n')
f.write('.p2align 12\n')
f.write('.Ldst_start:\n')
for i, name in enumerate(sortednames):
filecontents = open(D[name], "rb").read()
Expand All @@ -26,11 +26,11 @@
f.write(f'.Lend{i}: .skip 1\n')
f.write('.Ldst_end:\n')
f.write(' .skip 8\n')
f.write('.align 4096\n')
f.write('.p2align 12\n')
f.write('\n\n')
f.write('.section .lua.text_array, "aw", @progbits\n')
f.write('ASM_SECT_LUATEXTARRAY_DECL\n')
for i, name in enumerate(sortednames):
f.write(f' GASPOINTERWORD .Lname{i}, .Lstart{i}, .Lend{i}\n')
f.write(f' ASM_PTR_DECL .Lname{i}, .Lstart{i}, .Lend{i}\n')
f.write('\n\n')

#
Expand All @@ -46,11 +46,11 @@
incbinpath = os.path.relpath(out_lz4, os.path.dirname(out_S))
incbinsize = os.stat(out_lz4, follow_symlinks=True).st_size

f.write('.section .rodata.lz4, "a", @progbits\n')
f.write('ASM_SECT_RODATALZ4_DECL\n')
f.write('.Lsrc_start:\n')
f.write(f' .incbin "{incbinpath}", 0, {incbinsize}\n')
f.write('.Lsrc_end:\n')
f.write(' .8byte 0\n')
f.write('\n\n')
f.write('.section .lz4.decompress_array, "aw", @progbits\n')
f.write(' GASPOINTERWORD .Lsrc_start, .Lsrc_end, .Ldst_start, .Ldst_end\n')
f.write('ASM_SECT_LZ4CMDARRAY_DECL\n')
f.write(' ASM_PTR_DECL .Lsrc_start, .Lsrc_end, .Ldst_start, .Ldst_end\n')
45 changes: 23 additions & 22 deletions scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,29 @@ def run(self):
subprocess.check_call(["ninja", "install"],
stdin = subprocess.DEVNULL,
cwd = self.build_meson)
# START HACK
# Due to Meson build-system shenanigans, what actually ends up installed
# does not include the symlinks
# libbenzina.so -> libbenzina.so.X -> libbenzina.so.X.Y.Z
# Instead, they are all regular file copies of libbenzina.so.X.Y.Z.
# Replace them with the desired symlinks.
target_name = "libbenzina.so."
for meson_out_file in self._get_meson_outputs():
if os.path.basename(meson_out_file).startswith(os.path.basename(target_name)):
target_name = meson_out_file
libbenzina_so_x_y_z = target_name
libbenzina_so_x = '.'.join(libbenzina_so_x_y_z.split('.')[:-2])
libbenzina_so = '.'.join(libbenzina_so_x_y_z.split('.')[:-3])
base_libbenzina_so_x_y_z = os.path.basename(libbenzina_so_x_y_z)
base_libbenzina_so_x = os.path.basename(libbenzina_so_x)
build_libbenzina_so_x = os.path.join(self.build_lib, libbenzina_so_x)
build_libbenzina_so = os.path.join(self.build_lib, libbenzina_so)
os.unlink (build_libbenzina_so_x)
os.unlink (build_libbenzina_so)
os.symlink(base_libbenzina_so_x_y_z, build_libbenzina_so_x)
os.symlink(base_libbenzina_so_x, build_libbenzina_so)
# END HACK
if sys.platform != 'darwin':
# START HACK
# Due to Meson build-system shenanigans, what actually ends up installed
# does not include the symlinks
# libbenzina.so -> libbenzina.so.X -> libbenzina.so.X.Y.Z
# Instead, they are all regular file copies of libbenzina.so.X.Y.Z.
# Replace them with the desired symlinks.
target_name = "libbenzina.so."
for meson_out_file in self._get_meson_outputs():
if os.path.basename(meson_out_file).startswith(os.path.basename(target_name)):
target_name = meson_out_file
libbenzina_so_x_y_z = target_name
libbenzina_so_x = '.'.join(libbenzina_so_x_y_z.split('.')[:-2])
libbenzina_so = '.'.join(libbenzina_so_x_y_z.split('.')[:-3])
base_libbenzina_so_x_y_z = os.path.basename(libbenzina_so_x_y_z)
base_libbenzina_so_x = os.path.basename(libbenzina_so_x)
build_libbenzina_so_x = os.path.join(self.build_lib, libbenzina_so_x)
build_libbenzina_so = os.path.join(self.build_lib, libbenzina_so)
os.unlink (build_libbenzina_so_x)
os.unlink (build_libbenzina_so)
os.symlink(base_libbenzina_so_x_y_z, build_libbenzina_so_x)
os.symlink(base_libbenzina_so_x, build_libbenzina_so)
# END HACK
super().run()

def copy_extensions_to_source(self):
Expand Down
4 changes: 2 additions & 2 deletions src/libbenzina/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ BENZINA_STATIC void benz_init_lz4(void){
LZ4F_decompressOptions_t dopt = {.stableDst=1};
size_t dO, dB, dM, sO, sB, sM;

for(p=__lz4_decompress_array_start;
p<__lz4_decompress_array_end; p++){
for(p=__lz4_cmd_array_start;
p<__lz4_cmd_array_end; p++){
if(p->src_end>p->src_start && p->dst_end>p->dst_start){
sB = sM = p->src_end - p->src_start;
dB = dM = p->dst_end - p->dst_start;
Expand Down
12 changes: 6 additions & 6 deletions src/libbenzina/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@
#define __BENZINA_REGISTER(a) ___BENZINA_REGISTER(a, __COUNTER__)
#define BENZINA_LUAOPEN_REGISTER(name, func) \
BENZINA_ATTRIBUTE_USED \
BENZINA_ATTRIBUTE_SECTION(".lua.open_array") \
BENZINA_ATTRIBUTE_SECTION(ASM_SECT_LUAOPENARRAY_NAME) \
static const luaL_Reg __BENZINA_REGISTER(__benz_luaopen_entry_) = {("" name),(func)};
#define BENZINA_LUAOPEN_REGISTER_PRELOAD(name, func) \
BENZINA_ATTRIBUTE_USED \
BENZINA_ATTRIBUTE_SECTION(".lua.open_array.preload") \
BENZINA_ATTRIBUTE_SECTION(ASM_SECT_LUAOPENARRAYPRELOAD_NAME) \
static const luaL_Reg __BENZINA_REGISTER(__benz_luaopen_entry_) = {("" name),(func)};
#define BENZINA_TOOL_REGISTER(name, func) \
BENZINA_ATTRIBUTE_USED \
BENZINA_ATTRIBUTE_SECTION(".tool_array") \
BENZINA_ATTRIBUTE_SECTION(ASM_SECT_TOOLARRAY_NAME) \
static const BENZ_TOOL_ENTRY __BENZINA_REGISTER(__benz_tool_entry_) = {("" name),(func)};


Expand All @@ -83,14 +83,14 @@
BENZINA_HIDDEN extern const char license_benzina[];


/*** .lz4.decompress_array ***/
/*** .lz4.cmd_array ***/
typedef struct BENZ_LZ4_ENTRY BENZ_LZ4_ENTRY;
struct BENZ_LZ4_ENTRY{
const char* src_start, *src_end;
char* dst_start, *dst_end;
};
BENZINA_HIDDEN extern const BENZ_LZ4_ENTRY __lz4_decompress_array_start[];
BENZINA_HIDDEN extern const BENZ_LZ4_ENTRY __lz4_decompress_array_end[];
BENZINA_HIDDEN extern const BENZ_LZ4_ENTRY __lz4_cmd_array_start[];
BENZINA_HIDDEN extern const BENZ_LZ4_ENTRY __lz4_cmd_array_end[];


/*** .tool_array ***/
Expand Down
38 changes: 37 additions & 1 deletion src/libbenzina/internal.noarch.S
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
.section .license, "a"
ASM_SECT_LICENSE_DECL
.incbin "../../LICENSE.md"
.ascii "\n\n"

#if BENZINA_OS_DARWIN
#
# On Darwin-based systems, we cannot make use of linker scripts because the
# system linker, ld64, doesn't support them.
#
# We declare here certain "magic" symbols and make them global.
# Then, we define them in terms of section start and end addresses,
# synthesized by the linker.
#
.globl _license_benzina
.globl ___lz4_cmd_array_start
.globl ___lz4_cmd_array_end
.globl ___tool_array_start
.globl ___tool_array_end
.globl ___lua_open_array_start
.globl ___lua_open_array_preload_start
.globl ___lua_open_array_preload_end
.globl ___lua_open_array_end
.globl ___lua_text_array_start
.globl ___lua_text_array_end

.set _license_benzina, section$start$__TEXT$__license
.set ___lz4_cmd_array_start, section$start$__DATA$__lz4_cmd_array
.set ___lz4_cmd_array_end, section$start$__DATA$__lz4_cmd_array
.set ___tool_array_start, section$start$__DATA$__tool_array
.set ___tool_array_end, section$start$__DATA$__tool_array
.set ___lua_open_array_start, section$start$__DATA$__lua_open_array
# Mach-O doesn't support sections with >16-character names, so we disable
# support for that sub-array. The following two entries are *not* mistakes!
.set ___lua_open_array_preload_start, section$start$__DATA$__lua_open_array
.set ___lua_open_array_preload_end, section$start$__DATA$__lua_open_array
.set ___lua_open_array_end, section$end$__DATA$__lua_open_array
.set ___lua_text_array_start, section$start$__DATA$__lua_text_array
.set ___lua_text_array_end, section$end$__DATA$__lua_text_array
#endif
14 changes: 7 additions & 7 deletions src/libbenzina/libbenzina.lds
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
* - Linker script terminates string concatenation with a NUL byte to make
* the symbol above usable as a C string.
*
* .section .lz4.decompress_array, "aw"
* .section .lz4.cmd_array, "aw"
* - A concatenation of entries
* struct lz4_entry{const char* src_start, *src_end;
* char* dst_start, *dst_end;};
* somewhat modelled on .init_array.
* - Array start: lz4_entry __lz4_decompress_array_start[]
* - Array end: lz4_entry __lz4_decompress_array_end[]
* - Array start: lz4_entry __lz4_cmd_array_start[]
* - Array end: lz4_entry __lz4_cmd_array_end[]
* - Every entry represents one decompression order.
*
* .section .tool_array, "aw"
Expand Down Expand Up @@ -80,10 +80,10 @@ SECTIONS {
} INSERT AFTER .rodata;

SECTIONS {
.lz4.decompress_array : ALIGN(32) {
HIDDEN(__lz4_decompress_array_start = .);
KEEP(*(.lz4.decompress_array .lz4.decompress_array.*));
HIDDEN(__lz4_decompress_array_end = .);
.lz4.cmd_array : ALIGN(32) {
HIDDEN(__lz4_cmd_array_start = .);
KEEP(*(.lz4.cmd_array .lz4.cmd_array.*));
HIDDEN(__lz4_cmd_array_end = .);
QUAD(0); QUAD(0); QUAD(0); QUAD(0); /* NULL sentinel */
}
.tool_array : ALIGN(16) {
Expand Down

0 comments on commit 90e1854

Please sign in to comment.