-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add OS/2 support #14106
base: master
Are you sure you want to change the base?
Add OS/2 support #14106
Changes from all commits
d7d00e0
5c7173f
aec5af3
e9fca3e
e297a07
fb8692a
596ee73
3280893
47863e0
fce7944
56e3d52
4ad62d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -112,7 +112,7 @@ class DFeatures(TypedDict): | |
cs_kwargs) | ||
|
||
known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie', 'vs_module_defs'} | ||
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions', 'rust_abi'} | ||
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions', 'rust_abi', 'shortname'} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'shortname' needs to be added to the documentation for shared_library in the docs section. Additionally, in interpreter/type_checking.py you need to add: KwargInfo('shortname', (str, NoneType), since='1.8') to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I'll try. |
||
known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs', 'rust_abi'} | ||
known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink', 'rust_abi'} | ||
known_jar_kwargs = known_exe_kwargs | {'main_class', 'java_resources'} | ||
|
@@ -2167,14 +2167,16 @@ def post_init(self) -> None: | |
# See our FAQ for more detailed rationale: | ||
# https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa | ||
if not hasattr(self, 'prefix'): | ||
self.prefix = 'lib' | ||
self.prefix = '' if self.environment.machines[self.for_machine].is_os2() else 'lib' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this violate the rational for why we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If meson build system requires 'lib' prefix for a static lib, I'll do. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment above points to https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa which describes the reasoning:
How does OS/2 handle this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On OS/2, there are no official distinctions between static libs and an import libs. However, conventionally gcc + kLIBC uses And linkers search libraries with
If
|
||
if not hasattr(self, 'suffix'): | ||
if self.uses_rust(): | ||
if self.rust_crate_type == 'rlib': | ||
# default Rust static library suffix | ||
self.suffix = 'rlib' | ||
elif self.rust_crate_type == 'staticlib': | ||
self.suffix = 'a' | ||
elif self.environment.machines[self.for_machine].is_os2() and self.get_option(OptionKey('emxomf')): | ||
self.suffix = 'lib' | ||
else: | ||
if 'c' in self.compilers and self.compilers['c'].get_id() == 'tasking': | ||
self.suffix = 'ma' if self.options.get_value('b_lto') and not self.prelink else 'a' | ||
|
@@ -2248,6 +2250,7 @@ def __init__( | |
# Max length 2, first element is compatibility_version, second is current_version | ||
self.darwin_versions: T.Optional[T.Tuple[str, str]] = None | ||
self.vs_module_defs = None | ||
self.shortname = None | ||
# The import library this target will generate | ||
self.import_filename = None | ||
# The debugging information file this target will generate | ||
|
@@ -2372,6 +2375,15 @@ def determine_filenames(self): | |
suffix = 'so' | ||
# Android doesn't support shared_library versioning | ||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' | ||
elif self.environment.machines[self.for_machine].is_os2(): | ||
suffix = 'dll' | ||
# Import library is called foo_dll.a or foo_dll.lib | ||
import_filename_tpl = '{0.name}_dll' | ||
import_filename_tpl += '.lib' if self.environment.coredata.get_option(OptionKey('emxomf')) else '.a' | ||
self.filename_tpl = '{0.shortname}' if self.shortname else '{0.name}' | ||
if self.soversion: | ||
self.filename_tpl += '{0.soversion}' | ||
self.filename_tpl += '.{0.suffix}' | ||
else: | ||
prefix = 'lib' | ||
suffix = 'so' | ||
|
@@ -2389,6 +2401,14 @@ def determine_filenames(self): | |
if self.suffix is None: | ||
self.suffix = suffix | ||
self.filename = self.filename_tpl.format(self) | ||
if self.environment.machines[self.for_machine].is_os2(): | ||
# OS/2 does not allow a longer DLL name than 8 chars | ||
name = os.path.splitext(self.filename)[0] | ||
if len(name) > 8: | ||
name = name[:8] | ||
if self.soversion: | ||
name = name[:-len(self.soversion)] + self.soversion | ||
self.filename = '{}.{}'.format(name, self.suffix) | ||
if import_filename_tpl: | ||
self.import_filename = import_filename_tpl.format(self) | ||
# There may have been more outputs added by the time we get here, so | ||
|
@@ -2418,6 +2438,11 @@ def process_kwargs(self, kwargs): | |
# Visual Studio module-definitions file | ||
self.process_vs_module_defs_kw(kwargs) | ||
|
||
# OS/2 uses a 8.3 name for a DLL | ||
shortname = kwargs.get('shortname') | ||
if shortname: | ||
self.shortname = shortname | ||
Comment on lines
+2442
to
+2444
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason you can't set this when you initially set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No problem. Maybe I followed the coding style around. |
||
|
||
rust_abi = kwargs.get('rust_abi') | ||
rust_crate_type = kwargs.get('rust_crate_type') | ||
if rust_crate_type: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -293,6 +293,8 @@ def are_asserts_disabled(options: KeyedOptionDictType) -> bool: | |
|
||
def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', env: 'Environment') -> T.List[str]: | ||
args: T.List[str] = [] | ||
if mesonlib.is_os2() and options[OptionKey('emxomf')].value: | ||
args += ['-Zomf'] | ||
try: | ||
if options.get_value(OptionKey('b_lto')): | ||
args.extend(compiler.get_lto_compile_args( | ||
|
@@ -342,6 +344,8 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', | |
def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', | ||
is_shared_module: bool, build_dir: str) -> T.List[str]: | ||
args: T.List[str] = [] | ||
if mesonlib.is_os2(): | ||
args += ['-Zomf'] | ||
Comment on lines
+347
to
+348
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should go in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I'll try. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm trying to move those codes to GnuCompiler. However, I don't know how to access to the global options. How can I do that? |
||
try: | ||
if options.get_value('b_lto'): | ||
if options.get_value('werror'): | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -6,6 +6,7 @@ | |||||
from ..mesonlib import ( | ||||||
MesonException, EnvironmentException, MachineChoice, join_args, | ||||||
search_version, is_windows, Popen_safe, Popen_safe_logged, windows_proof_rm, | ||||||
is_os2, | ||||||
) | ||||||
from ..envconfig import BinaryTable | ||||||
from .. import mlog | ||||||
|
@@ -78,6 +79,7 @@ | |||||
defaults['cuda_static_linker'] = ['nvlink'] | ||||||
defaults['gcc_static_linker'] = ['gcc-ar'] | ||||||
defaults['clang_static_linker'] = ['llvm-ar'] | ||||||
defaults['emxomf_static_linker'] = ['emxomfar'] | ||||||
defaults['nasm'] = ['nasm', 'yasm'] | ||||||
|
||||||
|
||||||
|
@@ -156,6 +158,7 @@ def _handle_exceptions( | |||||
def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker: | ||||||
from . import d | ||||||
from ..linkers import linkers | ||||||
from ..options import OptionKey | ||||||
linker = env.lookup_binary_entry(compiler.for_machine, 'ar') | ||||||
if linker is not None: | ||||||
trials = [linker] | ||||||
|
@@ -165,6 +168,8 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker | |||||
trials = [defaults['cuda_static_linker']] + default_linkers | ||||||
elif compiler.get_argument_syntax() == 'msvc': | ||||||
trials = [defaults['vs_static_linker'], defaults['clang_cl_static_linker']] | ||||||
elif is_os2() and env.coredata.get_option(OptionKey('emxomf')): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean I should replace all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I'll try. |
||||||
trials = [defaults['emxomf_static_linker']] + default_linkers | ||||||
elif compiler.id == 'gcc': | ||||||
# Use gcc-ar if available; needed for LTO | ||||||
trials = [defaults['gcc_static_linker']] + default_linkers | ||||||
|
@@ -251,6 +256,8 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker | |||||
return linkers.AIXArLinker(linker) | ||||||
if p.returncode == 1 and err.startswith('ar: bad option: --'): # Solaris | ||||||
return linkers.ArLinker(compiler.for_machine, linker) | ||||||
if p.returncode == 1 and err.startswith('emxomfar'): | ||||||
return linkers.EmxomfArLinker(compiler.for_machine, linker) | ||||||
_handle_exceptions(popen_exceptions, trials, 'linker') | ||||||
raise EnvironmentException('Unreachable code (exception to make mypy happy)') | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -990,9 +990,24 @@ def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: | |
|
||
def _get_patterns(self, env: 'Environment', prefixes: T.List[str], suffixes: T.List[str], shared: bool = False) -> T.List[str]: | ||
patterns: T.List[str] = [] | ||
for p in prefixes: | ||
if env.machines[self.for_machine].is_os2(): | ||
# On OS/2, search order for shared libs is | ||
# 1. libfoo_dll.a | ||
# 2. foo_dll.a | ||
# 3. libfoo.a | ||
# 4. foo.a | ||
# 5. foo.dll | ||
# For static libs, `_s' is used instead of `_dll'. | ||
for s in suffixes: | ||
patterns.append(p + '{}.' + s) | ||
for p in prefixes: | ||
if s.startswith('_dll.') or s.startswith('_s.'): | ||
patterns.append(p + '{}' + s) | ||
else: | ||
patterns.append(p + '{}.' + s) | ||
Comment on lines
1001
to
+1006
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be cleaned up a little and fold the cases together: for s in suffixes
dot = '.' if env[machines][self.for_machine].is_os2() and s.startswith(('_dll.', '_s.'))
for p in prefixes:
patterns.append('p + '{}' + dot + s) edit: fixed copy/paste error in the code snippet There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The last ':' of if statement is necessary? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, no, that was a copy/paste error on my part. I'll edit it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And I had to |
||
else: | ||
for p in prefixes: | ||
for s in suffixes: | ||
patterns.append(p + '{}.' + s) | ||
if shared and env.machines[self.for_machine].is_openbsd(): | ||
# Shared libraries on OpenBSD can be named libfoo.so.X.Y: | ||
# https://www.openbsd.org/faq/ports/specialtopics.html#SharedLibs | ||
|
@@ -1015,7 +1030,9 @@ def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool | |
# people depend on it. Also, some people use prebuilt `foo.so` instead | ||
# of `libfoo.so` for unknown reasons, and may also want to create | ||
# `foo.so` by setting name_prefix to '' | ||
if strict and not isinstance(self, VisualStudioLikeCompiler): # lib prefix is not usually used with msvc | ||
# lib prefix is not usually used with msvc and OS/2 | ||
if strict and not isinstance(self, VisualStudioLikeCompiler) \ | ||
and not env.machines[self.for_machine].is_os2(): | ||
prefixes = ['lib'] | ||
else: | ||
prefixes = ['lib', ''] | ||
|
@@ -1038,6 +1055,14 @@ def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool | |
# TI C28x compilers can use both extensions for static or dynamic libs. | ||
stlibext = ['a', 'lib'] | ||
shlibext = ['dll', 'so'] | ||
elif env.machines[self.for_machine].is_os2(): | ||
from ...options import OptionKey | ||
if env.coredata.get_option(OptionKey('emxomf')): | ||
stlibext = ['_s.lib', '_s.a', 'lib', 'a'] | ||
shlibext = ['_dll.lib', '_dll.a', 'lib', 'a', 'dll'] | ||
else: | ||
stlibext = ['_s.a', 'a'] | ||
shlibext = ['_dll.a', 'a', 'dll'] | ||
else: | ||
# Linux/BSDs | ||
shlibext = ['so'] | ||
|
@@ -1255,6 +1280,8 @@ def thread_flags(self, env: 'Environment') -> T.List[str]: | |
host_m = env.machines[self.for_machine] | ||
if host_m.is_haiku() or host_m.is_darwin(): | ||
return [] | ||
if host_m.is_os2(): | ||
return ['-lpthread'] | ||
return ['-pthread'] | ||
|
||
def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,6 +88,7 @@ class ArgparseKWs(TypedDict, total=False): | |
'pkg_config_path', | ||
'cmake_prefix_path', | ||
'vsenv', | ||
'emxomf', | ||
} | ||
|
||
@total_ordering | ||
|
@@ -647,6 +648,7 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi | |
(OptionKey('wrap_mode'), BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])), | ||
(OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])), | ||
(OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), | ||
(OptionKey('emxomf'), BuiltinOption(UserBooleanOption, "Whether to use OMF format on OS/2", False)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how I feel about configuring the object format from a global option, I need to think more about this, but it might be more appropriate as a compiler option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, it would be coolI if possible to change the object format without modifying meson.build file. And it's possible to prepare compiler options depending on the global option. |
||
|
||
# Pkgconfig module | ||
(OptionKey('pkgconfig.relocatable'), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like you always end up using this rule for dynamic linking on OS/2 paths, am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, in order to build an import library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So can we just have the normal shared_library linking path do this on OS/2, or is there a use of that I missed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to do so, but I'm sorry I have no idea how to do. Any hints ?