Merge pull request #417 from nirbheek/dll-paths
Fix filenames and paths used in DLL shared library generation
This commit is contained in:
commit
64919b1c74
|
@ -110,9 +110,13 @@ class Backend():
|
|||
# On some platforms (msvc for instance), the file that is used for
|
||||
# dynamic linking is not the same as the dynamic library itself. This
|
||||
# file is called an import library, and we want to link against that.
|
||||
# On platforms where this distinction is not important, the import
|
||||
# library is the same as the dynamic library itself.
|
||||
return os.path.join(self.get_target_dir(target), target.get_import_filename())
|
||||
# On all other platforms, we link to the library directly.
|
||||
if isinstance(target, build.SharedLibrary):
|
||||
link_lib = target.get_import_filename() or target.get_filename()
|
||||
return os.path.join(self.get_target_dir(target), link_lib)
|
||||
elif isinstance(target, build.StaticLibrary):
|
||||
return os.path.join(self.get_target_dir(target), target.get_filename())
|
||||
raise AssertionError('BUG: Tried to link to something that\'s not a library')
|
||||
|
||||
def get_target_dir(self, target):
|
||||
if self.environment.coredata.get_builtin_option('layout') == 'mirror':
|
||||
|
@ -496,11 +500,19 @@ class Backend():
|
|||
if isinstance(i, build.Executable):
|
||||
cmd += self.exe_object_to_cmd_array(i)
|
||||
continue
|
||||
if isinstance(i, build.CustomTarget):
|
||||
elif isinstance(i, build.CustomTarget):
|
||||
# GIR scanner will attempt to execute this binary but
|
||||
# it assumes that it is in path, so always give it a full path.
|
||||
tmp = i.get_filename()[0]
|
||||
i = os.path.join(self.get_target_dir(i), tmp)
|
||||
elif isinstance(i, mesonlib.File):
|
||||
i = os.path.join(i.subdir, i.fname)
|
||||
if absolute_paths:
|
||||
i = os.path.join(self.environment.get_build_dir(), i)
|
||||
# FIXME: str types are blindly added and ignore the 'absolute_paths' argument
|
||||
elif not isinstance(i, str):
|
||||
err_msg = 'Argument {0} is of unknown type {1}'
|
||||
raise RuntimeError(err_msg.format(str(i), str(type(i))))
|
||||
for (j, src) in enumerate(srcs):
|
||||
i = i.replace('@INPUT%d@' % j, src)
|
||||
for (j, res) in enumerate(ofilenames):
|
||||
|
|
|
@ -496,18 +496,33 @@ int dummy;
|
|||
pickle.dump(d, ofile)
|
||||
|
||||
def generate_target_install(self, d):
|
||||
libdir = self.environment.get_libdir()
|
||||
bindir = self.environment.get_bindir()
|
||||
|
||||
should_strip = self.environment.coredata.get_builtin_option('strip')
|
||||
for t in self.build.get_targets().values():
|
||||
if t.should_install():
|
||||
# Find the installation directory
|
||||
outdir = t.get_custom_install_dir()
|
||||
if outdir is None:
|
||||
if isinstance(t, build.Executable):
|
||||
outdir = bindir
|
||||
else:
|
||||
outdir = libdir
|
||||
if outdir is not None:
|
||||
pass
|
||||
elif isinstance(t, build.SharedLibrary):
|
||||
# For toolchains/platforms that need an import library for
|
||||
# linking (separate from the shared library with all the
|
||||
# code), we need to install the import library (dll.a/.lib)
|
||||
if t.get_import_filename():
|
||||
# Install the import library.
|
||||
i = [self.get_target_filename_for_linking(t),
|
||||
self.environment.get_import_lib_dir(),
|
||||
# It has no aliases, should not be stripped, and
|
||||
# doesn't have an install_rpath
|
||||
[], False, '']
|
||||
d.targets.append(i)
|
||||
outdir = self.environment.get_shared_lib_dir()
|
||||
elif isinstance(t, build.SharedLibrary):
|
||||
outdir = self.environment.get_static_lib_dir()
|
||||
elif isinstance(t, build.Executable):
|
||||
outdir = self.environment.get_bindir()
|
||||
else:
|
||||
# XXX: Add BuildTarget-specific install dir cases here
|
||||
outdir = self.environment.get_libdir()
|
||||
i = [self.get_target_filename(t), outdir, t.get_aliaslist(),\
|
||||
should_strip, t.install_rpath]
|
||||
d.targets.append(i)
|
||||
|
@ -1665,8 +1680,12 @@ rule FORTRAN_DEP_HACK
|
|||
else:
|
||||
soversion = None
|
||||
commands += linker.get_soname_args(target.name, abspath, soversion)
|
||||
# This is only visited when using the Visual Studio toolchain
|
||||
if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'):
|
||||
commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src))
|
||||
# This is only visited when building for Windows using either MinGW/GCC or Visual Studio
|
||||
if target.import_filename:
|
||||
commands += linker.gen_import_library_args(os.path.join(target.subdir, target.import_filename))
|
||||
elif isinstance(target, build.StaticLibrary):
|
||||
commands += linker.get_std_link_args()
|
||||
else:
|
||||
|
|
|
@ -28,6 +28,27 @@ import xml.dom.minidom
|
|||
from ..mesonlib import MesonException
|
||||
from ..environment import Environment
|
||||
|
||||
def split_o_flags_args(args):
|
||||
"""
|
||||
Splits any /O args and returns them. Does not take care of flags overriding
|
||||
previous ones. Skips non-O flag arguments.
|
||||
|
||||
['/Ox', '/Ob1'] returns ['/Ox', '/Ob1']
|
||||
['/Oxj', '/MP'] returns ['/Ox', '/Oj']
|
||||
"""
|
||||
o_flags = []
|
||||
for arg in args:
|
||||
if not arg.startswith('/O'):
|
||||
continue
|
||||
flags = list(arg[2:])
|
||||
# Assume that this one can't be clumped with the others since it takes
|
||||
# an argument itself
|
||||
if 'b' in flags:
|
||||
o_flags.append(arg)
|
||||
else:
|
||||
o_flags += ['/O' + f for f in flags]
|
||||
return o_flags
|
||||
|
||||
class RegenInfo():
|
||||
def __init__(self, source_dir, build_dir, depfiles):
|
||||
self.source_dir = source_dir
|
||||
|
@ -76,9 +97,14 @@ class Vs2010Backend(backends.Backend):
|
|||
outputs = []
|
||||
custom_target_include_dirs = []
|
||||
custom_target_output_files = []
|
||||
target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))
|
||||
down = self.target_to_build_root(target)
|
||||
for genlist in target.get_generated_sources():
|
||||
if isinstance(genlist, build.CustomTarget):
|
||||
custom_target_output_files += [os.path.join(self.get_target_dir(genlist), i) for i in genlist.output]
|
||||
for i in genlist.output:
|
||||
# Path to the generated source from the current vcxproj dir via the build root
|
||||
ipath = os.path.join(down, self.get_target_dir(genlist), i)
|
||||
custom_target_output_files.append(ipath)
|
||||
idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target))
|
||||
if idir not in custom_target_include_dirs:
|
||||
custom_target_include_dirs.append(idir)
|
||||
|
@ -89,7 +115,6 @@ class Vs2010Backend(backends.Backend):
|
|||
outfilelist = genlist.get_outfilelist()
|
||||
exe_arr = self.exe_object_to_cmd_array(exe)
|
||||
base_args = generator.get_arglist()
|
||||
target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))
|
||||
for i in range(len(infilelist)):
|
||||
if len(infilelist) == len(outfilelist):
|
||||
sole_output = os.path.join(target_private_dir, outfilelist[i])
|
||||
|
@ -123,7 +148,17 @@ class Vs2010Backend(backends.Backend):
|
|||
def generate(self, interp):
|
||||
self.resolve_source_conflicts()
|
||||
self.interpreter = interp
|
||||
self.platform = 'Win32'
|
||||
target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None)
|
||||
if target_machine.endswith('64'):
|
||||
# amd64 or x86_64
|
||||
self.platform = 'x64'
|
||||
elif target_machine == 'x86':
|
||||
# x86
|
||||
self.platform = 'Win32'
|
||||
elif 'arm' in target_machine.lower():
|
||||
self.platform = 'ARM'
|
||||
else:
|
||||
raise MesonException('Unsupported Visual Studio platform: ' + target_machine)
|
||||
self.buildtype = self.environment.coredata.get_builtin_option('buildtype')
|
||||
sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln')
|
||||
projlist = self.generate_projects()
|
||||
|
@ -404,6 +439,37 @@ class Vs2010Backend(backends.Backend):
|
|||
def quote_define_cmdline(cls, arg):
|
||||
return re.sub(r'^([-/])D(.*?)="(.*)"$', r'\1D\2=\"\3\"', arg)
|
||||
|
||||
@staticmethod
|
||||
def split_link_args(args):
|
||||
"""
|
||||
Split a list of link arguments into three lists:
|
||||
* library search paths
|
||||
* library filenames (or paths)
|
||||
* other link arguments
|
||||
"""
|
||||
lpaths = []
|
||||
libs = []
|
||||
other = []
|
||||
for arg in args:
|
||||
if arg.startswith('/LIBPATH:'):
|
||||
lpath = arg[9:]
|
||||
# De-dup library search paths by removing older entries when
|
||||
# a new one is found. This is necessary because unlike other
|
||||
# search paths such as the include path, the library is
|
||||
# searched for in the newest (right-most) search path first.
|
||||
if lpath in lpaths:
|
||||
lpaths.remove(lpath)
|
||||
lpaths.append(lpath)
|
||||
# It's ok if we miss libraries with non-standard extensions here.
|
||||
# They will go into the general link arguments.
|
||||
elif arg.endswith('.lib') or arg.endswith('.a'):
|
||||
# De-dup
|
||||
if arg not in libs:
|
||||
libs.append(arg)
|
||||
else:
|
||||
other.append(arg)
|
||||
return (lpaths, libs, other)
|
||||
|
||||
def gen_vcxproj(self, target, ofname, guid, compiler):
|
||||
mlog.debug('Generating vcxproj %s.' % target.name)
|
||||
entrypoint = 'WinMainCRTStartup'
|
||||
|
@ -424,11 +490,15 @@ class Vs2010Backend(backends.Backend):
|
|||
return self.gen_run_target_vcxproj(target, ofname, guid)
|
||||
else:
|
||||
raise MesonException('Unknown target type for %s' % target.get_basename())
|
||||
# Prefix to use to access the build root from the vcxproj dir
|
||||
down = self.target_to_build_root(target)
|
||||
# Prefix to use to access the source tree's root from the vcxproj dir
|
||||
proj_to_src_root = os.path.join(down, self.build_to_src)
|
||||
# Prefix to use to access the source tree's subdir from the vcxproj dir
|
||||
proj_to_src_dir = os.path.join(proj_to_src_root, target.subdir)
|
||||
(sources, headers, objects, languages) = self.split_sources(target.sources)
|
||||
buildtype = self.buildtype
|
||||
buildtype_args = compiler.get_buildtype_args(self.buildtype)
|
||||
buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype)
|
||||
project_name = target.name
|
||||
target_name = target.name
|
||||
root = ET.Element('Project', {'DefaultTargets' : "Build",
|
||||
|
@ -438,9 +508,10 @@ class Vs2010Backend(backends.Backend):
|
|||
prjconf = ET.SubElement(confitems, 'ProjectConfiguration',
|
||||
{'Include' : self.buildtype + '|' + self.platform})
|
||||
p = ET.SubElement(prjconf, 'Configuration')
|
||||
p.text= buildtype
|
||||
p.text= self.buildtype
|
||||
pl = ET.SubElement(prjconf, 'Platform')
|
||||
pl.text = self.platform
|
||||
# Globals
|
||||
globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals')
|
||||
guidelem = ET.SubElement(globalgroup, 'ProjectGuid')
|
||||
guidelem.text = guid
|
||||
|
@ -453,13 +524,68 @@ class Vs2010Backend(backends.Backend):
|
|||
pname= ET.SubElement(globalgroup, 'ProjectName')
|
||||
pname.text = project_name
|
||||
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props')
|
||||
# Start configuration
|
||||
type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration')
|
||||
ET.SubElement(type_config, 'ConfigurationType').text = conftype
|
||||
ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
|
||||
if self.platform_toolset:
|
||||
ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset
|
||||
# FIXME: Meson's LTO support needs to be integrated here
|
||||
ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false'
|
||||
ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
|
||||
# Let VS auto-set the RTC level
|
||||
ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'Default'
|
||||
o_flags = split_o_flags_args(buildtype_args)
|
||||
if '/Oi' in o_flags:
|
||||
ET.SubElement(type_config, 'IntrinsicFunctions').text = 'true'
|
||||
if '/Ob1' in o_flags:
|
||||
ET.SubElement(type_config, 'InlineFunctionExpansion').text = 'OnlyExplicitInline'
|
||||
elif '/Ob2' in o_flags:
|
||||
ET.SubElement(type_config, 'InlineFunctionExpansion').text = 'AnySuitable'
|
||||
# Size-preserving flags
|
||||
if '/Os' in o_flags:
|
||||
ET.SubElement(type_config, 'FavorSizeOrSpeed').text = 'Size'
|
||||
else:
|
||||
ET.SubElement(type_config, 'FavorSizeOrSpeed').text = 'Speed'
|
||||
# Incremental linking increases code size
|
||||
if '/INCREMENTAL:NO' in buildtype_link_args:
|
||||
ET.SubElement(type_config, 'LinkIncremental').text = 'false'
|
||||
# CRT type; debug or release
|
||||
if '/MDd' in buildtype_args:
|
||||
ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
|
||||
ET.SubElement(type_config, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL'
|
||||
else:
|
||||
ET.SubElement(type_config, 'UseDebugLibraries').text = 'false'
|
||||
ET.SubElement(type_config, 'RuntimeLibrary').text = 'MultiThreadedDLL'
|
||||
# Debug format
|
||||
if '/ZI' in buildtype_args:
|
||||
ET.SubElement(type_config, 'DebugInformationFormat').text = 'EditAndContinue'
|
||||
elif '/Zi' in buildtype_args:
|
||||
ET.SubElement(type_config, 'DebugInformationFormat').text = 'ProgramDatabase'
|
||||
elif '/Z7' in buildtype_args:
|
||||
ET.SubElement(type_config, 'DebugInformationFormat').text = 'OldStyle'
|
||||
# Generate Debug info
|
||||
if '/DEBUG' in buildtype_link_args:
|
||||
ET.SubElement(type_config, 'GenerateDebugInformation').text = 'true'
|
||||
# Runtime checks
|
||||
if '/RTC1' in buildtype_args:
|
||||
ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'EnableFastChecks'
|
||||
elif '/RTCu' in buildtype_args:
|
||||
ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'UninitializedLocalUsageCheck'
|
||||
elif '/RTCs' in buildtype_args:
|
||||
ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'StackFrameRuntimeCheck'
|
||||
# Optimization flags
|
||||
if '/Ox' in o_flags:
|
||||
ET.SubElement(type_config, 'Optimization').text = 'Full'
|
||||
elif '/O2' in o_flags:
|
||||
ET.SubElement(type_config, 'Optimization').text = 'MaxSpeed'
|
||||
elif '/O1' in o_flags:
|
||||
ET.SubElement(type_config, 'Optimization').text = 'MinSpace'
|
||||
elif '/Od' in o_flags:
|
||||
ET.SubElement(type_config, 'Optimization').text = 'Disabled'
|
||||
# Warning level
|
||||
warning_level = self.environment.coredata.get_builtin_option('warning_level')
|
||||
ET.SubElement(type_config, 'WarningLevel').text = 'Level' + warning_level
|
||||
# End configuration
|
||||
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
|
||||
generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands(target, root)
|
||||
(gen_src, gen_hdrs, gen_objs, gen_langs) = self.split_sources(generated_files)
|
||||
|
@ -467,6 +593,7 @@ class Vs2010Backend(backends.Backend):
|
|||
gen_src += custom_src
|
||||
gen_hdrs += custom_hdrs
|
||||
gen_langs += custom_langs
|
||||
# Project information
|
||||
direlem = ET.SubElement(root, 'PropertyGroup')
|
||||
fver = ET.SubElement(direlem, '_ProjectFileVersion')
|
||||
fver.text = self.project_file_version
|
||||
|
@ -474,15 +601,13 @@ class Vs2010Backend(backends.Backend):
|
|||
outdir.text = '.\\'
|
||||
intdir = ET.SubElement(direlem, 'IntDir')
|
||||
intdir.text = target.get_id() + '\\'
|
||||
tname = ET.SubElement(direlem, 'TargetName')
|
||||
tname.text = target_name
|
||||
inclinc = ET.SubElement(direlem, 'LinkIncremental')
|
||||
inclinc.text = 'true'
|
||||
tfilename = os.path.splitext(target.get_filename())
|
||||
ET.SubElement(direlem, 'TargetName').text = tfilename[0]
|
||||
ET.SubElement(direlem, 'TargetExt').text = tfilename[1]
|
||||
|
||||
# Build information
|
||||
compiles = ET.SubElement(root, 'ItemDefinitionGroup')
|
||||
clconf = ET.SubElement(compiles, 'ClCompile')
|
||||
opt = ET.SubElement(clconf, 'Optimization')
|
||||
opt.text = 'disabled'
|
||||
inc_dirs = ['.', self.relpath(self.get_target_private_dir(target), self.get_target_dir(target)),
|
||||
proj_to_src_dir] + generated_files_include_dirs
|
||||
|
||||
|
@ -496,18 +621,24 @@ class Vs2010Backend(backends.Backend):
|
|||
for l, args in target.extra_args.items():
|
||||
if l in extra_args:
|
||||
extra_args[l] += compiler.unix_compile_flags_to_native(args)
|
||||
general_args = compiler.get_buildtype_args(self.buildtype).copy()
|
||||
# FIXME all the internal flags of VS (optimization etc) are represented
|
||||
# by their own XML elements. In theory we should split all flags to those
|
||||
# that have an XML element and those that don't and serialise them
|
||||
# properly. This is a crapton of work for no real gain, so just dump them
|
||||
# here.
|
||||
general_args += compiler.get_option_compile_args(self.environment.coredata.compiler_options)
|
||||
general_args = compiler.get_option_compile_args(self.environment.coredata.compiler_options)
|
||||
for d in target.get_external_deps():
|
||||
try:
|
||||
general_args += d.compile_args
|
||||
except AttributeError:
|
||||
pass
|
||||
# Cflags required by external deps might have UNIX-specific flags,
|
||||
# so filter them out if needed
|
||||
d_compile_args = compiler.unix_compile_flags_to_native(d.get_compile_args())
|
||||
for arg in d_compile_args:
|
||||
if arg.startswith('-I'):
|
||||
inc_dir = arg[2:]
|
||||
# De-dup
|
||||
if inc_dir not in inc_dirs:
|
||||
inc_dirs.append(inc_dir)
|
||||
else:
|
||||
general_args.append(arg)
|
||||
|
||||
for l, args in extra_args.items():
|
||||
extra_args[l] = [Vs2010Backend.quote_define_cmdline(x) for x in args]
|
||||
|
@ -540,8 +671,6 @@ class Vs2010Backend(backends.Backend):
|
|||
preproc = ET.SubElement(clconf, 'PreprocessorDefinitions')
|
||||
rebuild = ET.SubElement(clconf, 'MinimalRebuild')
|
||||
rebuild.text = 'true'
|
||||
rtlib = ET.SubElement(clconf, 'RuntimeLibrary')
|
||||
rtlib.text = 'MultiThreadedDebugDLL'
|
||||
funclink = ET.SubElement(clconf, 'FunctionLevelLinking')
|
||||
funclink.text = 'true'
|
||||
pch_node = ET.SubElement(clconf, 'PrecompiledHeader')
|
||||
|
@ -564,28 +693,39 @@ class Vs2010Backend(backends.Backend):
|
|||
pch_out = ET.SubElement(clconf, 'PrecompiledHeaderOutputFile')
|
||||
pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % pch_source[2]
|
||||
|
||||
warnings = ET.SubElement(clconf, 'WarningLevel')
|
||||
warnings.text = 'Level3'
|
||||
debinfo = ET.SubElement(clconf, 'DebugInformationFormat')
|
||||
debinfo.text = 'EditAndContinue'
|
||||
resourcecompile = ET.SubElement(compiles, 'ResourceCompile')
|
||||
ET.SubElement(resourcecompile, 'PreprocessorDefinitions')
|
||||
link = ET.SubElement(compiles, 'Link')
|
||||
# Put all language args here, too.
|
||||
extra_link_args = compiler.get_option_link_args(self.environment.coredata.compiler_options)
|
||||
# FIXME: Can these buildtype linker args be added as tags in the
|
||||
# vcxproj file (similar to buildtype compiler args) instead of in
|
||||
# AdditionalOptions?
|
||||
extra_link_args += compiler.get_buildtype_linker_args(self.buildtype)
|
||||
for l in self.environment.coredata.external_link_args.values():
|
||||
extra_link_args += compiler.unix_link_flags_to_native(l)
|
||||
extra_link_args += compiler.unix_link_flags_to_native(target.link_args)
|
||||
extra_link_args += l
|
||||
if not isinstance(target, build.StaticLibrary):
|
||||
extra_link_args += target.link_args
|
||||
# External deps must be last because target link libraries may depend on them.
|
||||
for dep in target.get_external_deps():
|
||||
extra_link_args += dep.get_link_args()
|
||||
for d in target.get_dependencies():
|
||||
if isinstance(d, build.StaticLibrary):
|
||||
for dep in d.get_external_deps():
|
||||
extra_link_args += dep.get_link_args()
|
||||
extra_link_args = compiler.unix_link_flags_to_native(extra_link_args)
|
||||
(additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args)
|
||||
if len(extra_link_args) > 0:
|
||||
extra_link_args.append('%(AdditionalOptions)')
|
||||
ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_link_args)
|
||||
if len(additional_libpaths) > 0:
|
||||
additional_libpaths.insert(0, '%(AdditionalLibraryDirectories)')
|
||||
ET.SubElement(link, 'AdditionalLibraryDirectories').text = ';'.join(additional_libpaths)
|
||||
|
||||
additional_links = []
|
||||
# Add more libraries to be linked if needed
|
||||
for t in target.get_dependencies():
|
||||
lobj = self.build.targets[t.get_id()]
|
||||
rel_path = self.relpath(lobj.subdir, target.subdir)
|
||||
linkname = os.path.join(rel_path, lobj.get_import_filename())
|
||||
linkname = os.path.join(down, self.get_target_filename_for_linking(lobj))
|
||||
additional_links.append(linkname)
|
||||
for lib in self.get_custom_target_provided_libraries(target):
|
||||
additional_links.append(self.relpath(lib, self.get_target_dir(target)))
|
||||
|
@ -600,26 +740,37 @@ class Vs2010Backend(backends.Backend):
|
|||
ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links)
|
||||
ofile = ET.SubElement(link, 'OutputFile')
|
||||
ofile.text = '$(OutDir)%s' % target.get_filename()
|
||||
addlibdir = ET.SubElement(link, 'AdditionalLibraryDirectories')
|
||||
addlibdir.text = '%(AdditionalLibraryDirectories)'
|
||||
subsys = ET.SubElement(link, 'SubSystem')
|
||||
subsys.text = subsystem
|
||||
gendeb = ET.SubElement(link, 'GenerateDebugInformation')
|
||||
gendeb.text = 'true'
|
||||
if isinstance(target, build.SharedLibrary):
|
||||
# DLLs built with MSVC always have an import library except when
|
||||
# they're data-only DLLs, but we don't support those yet.
|
||||
ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename()
|
||||
pdb = ET.SubElement(link, 'ProgramDataBaseFileName')
|
||||
pdb.text = '$(OutDir}%s.pdb' % target_name
|
||||
# Add module definitions file, if provided
|
||||
if target.vs_module_defs:
|
||||
relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src))
|
||||
ET.SubElement(link, 'ModuleDefinitionFile').text = relpath
|
||||
if '/ZI' in buildtype_args or '/Zi' in buildtype_args:
|
||||
pdb = ET.SubElement(link, 'ProgramDataBaseFileName')
|
||||
pdb.text = '$(OutDir}%s.pdb' % target_name
|
||||
if isinstance(target, build.Executable):
|
||||
ET.SubElement(link, 'EntryPointSymbol').text = entrypoint
|
||||
targetmachine = ET.SubElement(link, 'TargetMachine')
|
||||
targetmachine.text = 'MachineX86'
|
||||
targetplatform = self.platform.lower()
|
||||
if targetplatform == 'win32':
|
||||
targetmachine.text = 'MachineX86'
|
||||
elif targetplatform == 'x64':
|
||||
targetmachine.text = 'MachineX64'
|
||||
elif targetplatform == 'arm':
|
||||
targetmachine.text = 'MachineARM'
|
||||
else:
|
||||
raise MesonException('Unsupported Visual Studio target machine: ' + targetmachine)
|
||||
|
||||
extra_files = target.extra_files
|
||||
if len(headers) + len(gen_hdrs) + len(extra_files) > 0:
|
||||
inc_hdrs = ET.SubElement(root, 'ItemGroup')
|
||||
for h in headers:
|
||||
relpath = h.rel_to_builddir(proj_to_src_root)
|
||||
relpath = os.path.join(down, h.rel_to_builddir(self.build_to_src))
|
||||
ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath)
|
||||
for h in gen_hdrs:
|
||||
ET.SubElement(inc_hdrs, 'CLInclude', Include=h)
|
||||
|
@ -630,7 +781,7 @@ class Vs2010Backend(backends.Backend):
|
|||
if len(sources) + len(gen_src) + len(pch_sources) > 0:
|
||||
inc_src = ET.SubElement(root, 'ItemGroup')
|
||||
for s in sources:
|
||||
relpath = s.rel_to_builddir(proj_to_src_root)
|
||||
relpath = os.path.join(down, s.rel_to_builddir(self.build_to_src))
|
||||
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
|
||||
self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s)
|
||||
self.add_additional_options(s, inc_cl, extra_args, additional_options_set)
|
||||
|
@ -658,7 +809,7 @@ class Vs2010Backend(backends.Backend):
|
|||
if self.has_objects(objects, additional_objects, gen_objs):
|
||||
inc_objs = ET.SubElement(root, 'ItemGroup')
|
||||
for s in objects:
|
||||
relpath = s.rel_to_builddir(proj_to_src_root)
|
||||
relpath = os.path.join(down, s.rel_to_builddir(self.build_to_src))
|
||||
ET.SubElement(inc_objs, 'Object', Include=relpath)
|
||||
for s in additional_objects:
|
||||
ET.SubElement(inc_objs, 'Object', Include=s)
|
||||
|
|
|
@ -292,12 +292,10 @@ class XCodeBackend(backends.Backend):
|
|||
reftype = 0
|
||||
if isinstance(t, build.Executable):
|
||||
typestr = 'compiled.mach-o.executable'
|
||||
path = t.get_filename()
|
||||
path = fname
|
||||
elif isinstance(t, build.SharedLibrary):
|
||||
# OSX has a completely different shared library
|
||||
# naming scheme so do this manually.
|
||||
typestr = self.get_xcodetype('dummy.dylib')
|
||||
path = t.get_osx_filename()
|
||||
path = fname
|
||||
else:
|
||||
typestr = self.get_xcodetype(fname)
|
||||
path = '"%s"' % t.get_filename()
|
||||
|
@ -626,7 +624,7 @@ class XCodeBackend(backends.Backend):
|
|||
headerdirs.append(os.path.join(self.environment.get_build_dir(), cd))
|
||||
for l in target.link_targets:
|
||||
abs_path = os.path.join(self.environment.get_build_dir(),
|
||||
l.subdir, buildtype, l.get_osx_filename())
|
||||
l.subdir, buildtype, l.get_filename())
|
||||
dep_libs.append("'%s'" % abs_path)
|
||||
if isinstance(l, build.SharedLibrary):
|
||||
links_dylib = True
|
||||
|
|
|
@ -16,8 +16,9 @@ from . import coredata
|
|||
from . import environment
|
||||
from . import dependencies
|
||||
from . import mlog
|
||||
import copy, os
|
||||
import copy, os, re
|
||||
from .mesonlib import File, flatten, MesonException
|
||||
from .environment import for_windows, for_darwin
|
||||
|
||||
known_basic_kwargs = {'install' : True,
|
||||
'c_pch' : True,
|
||||
|
@ -71,6 +72,38 @@ We are fully aware that these are not really usable or pleasant ways to do
|
|||
this but it's the best we can do given the way shell quoting works.
|
||||
'''
|
||||
|
||||
def sources_are_suffix(sources, suffix):
|
||||
for source in sources:
|
||||
if source.endswith('.' + suffix):
|
||||
return True
|
||||
return False
|
||||
|
||||
def compiler_is_msvc(sources, is_cross, env):
|
||||
"""
|
||||
Since each target does not currently have the compiler information attached
|
||||
to it, we must do this detection manually here.
|
||||
|
||||
This detection is purposely incomplete and will cause bugs if other code is
|
||||
extended and this piece of code is forgotten.
|
||||
"""
|
||||
compiler = None
|
||||
if sources_are_suffix(sources, 'c'):
|
||||
try:
|
||||
compiler = env.detect_c_compiler(is_cross)
|
||||
except MesonException:
|
||||
return False
|
||||
elif sources_are_suffix(sources, 'cxx') or \
|
||||
sources_are_suffix(sources, 'cpp') or \
|
||||
sources_are_suffix(sources, 'cc'):
|
||||
try:
|
||||
compiler = env.detect_cpp_compiler(is_cross)
|
||||
except MesonException:
|
||||
return False
|
||||
if compiler and compiler.get_id() == 'msvc':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class InvalidArguments(MesonException):
|
||||
pass
|
||||
|
||||
|
@ -209,6 +242,10 @@ class BuildTarget():
|
|||
raise InvalidArguments('Build target %s has no sources.' % name)
|
||||
self.validate_sources()
|
||||
|
||||
def __repr__(self):
|
||||
repr_str = "<{0} {1}: {2}>"
|
||||
return repr_str.format(self.__class__.__name__, self.get_id(), self.filename)
|
||||
|
||||
def get_id(self):
|
||||
# This ID must also be a valid file name on all OSs.
|
||||
# It should also avoid shell metacharacters for obvious
|
||||
|
@ -593,6 +630,10 @@ class Generator():
|
|||
self.exe = exe
|
||||
self.process_kwargs(kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
repr_str = "<{0}: {1}>"
|
||||
return repr_str.format(self.__class__.__name__, self.exe)
|
||||
|
||||
def get_exe(self):
|
||||
return self.exe
|
||||
|
||||
|
@ -670,15 +711,19 @@ class GeneratedList():
|
|||
class Executable(BuildTarget):
|
||||
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
|
||||
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
|
||||
self.prefix = ''
|
||||
self.suffix = environment.get_exe_suffix()
|
||||
suffix = environment.get_exe_suffix()
|
||||
if len(self.sources) > 0 and self.sources[0].endswith('.cs'):
|
||||
suffix = 'exe'
|
||||
if suffix != '':
|
||||
self.filename = self.name + '.' + suffix
|
||||
else:
|
||||
self.filename = self.name
|
||||
# Unless overriden, executables have no suffix or prefix. Except on
|
||||
# Windows and with C#/Mono executables where the suffix is 'exe'
|
||||
if not hasattr(self, 'prefix'):
|
||||
self.prefix = ''
|
||||
if not hasattr(self, 'suffix'):
|
||||
# Executable for Windows or C#/Mono
|
||||
if for_windows(is_cross, environment) or sources_are_suffix(self.sources, 'cs'):
|
||||
self.suffix = 'exe'
|
||||
else:
|
||||
self.suffix = ''
|
||||
self.filename = self.name
|
||||
if self.suffix:
|
||||
self.filename += '.' + self.suffix
|
||||
|
||||
def type_suffix(self):
|
||||
return "@exe"
|
||||
|
@ -686,52 +731,161 @@ class Executable(BuildTarget):
|
|||
class StaticLibrary(BuildTarget):
|
||||
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
|
||||
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
|
||||
if len(self.sources) > 0 and self.sources[0].endswith('.cs'):
|
||||
if sources_are_suffix(self.sources, 'cs'):
|
||||
raise InvalidArguments('Static libraries not supported for C#.')
|
||||
# By default a static library is named libfoo.a even on Windows because
|
||||
# MSVC does not have a consistent convention for what static libraries
|
||||
# are called. The MSVC CRT uses libfoo.lib syntax but nothing else uses
|
||||
# it and GCC only looks for static libraries called foo.lib and
|
||||
# libfoo.a. However, we cannot use foo.lib because that's the same as
|
||||
# the import library. Using libfoo.a is ok because people using MSVC
|
||||
# always pass the library filename while linking anyway.
|
||||
if not hasattr(self, 'prefix'):
|
||||
self.prefix = environment.get_static_lib_prefix()
|
||||
self.suffix = environment.get_static_lib_suffix()
|
||||
if len(self.sources) > 0 and self.sources[0].endswith('.rs'):
|
||||
self.suffix = 'rlib'
|
||||
self.prefix = 'lib'
|
||||
if not hasattr(self, 'suffix'):
|
||||
# Rust static library crates have .rlib suffix
|
||||
if sources_are_suffix(self.sources, 'rs'):
|
||||
self.suffix = 'rlib'
|
||||
else:
|
||||
self.suffix = 'a'
|
||||
self.filename = self.prefix + self.name + '.' + self.suffix
|
||||
|
||||
def get_import_filename(self):
|
||||
return self.filename
|
||||
|
||||
def get_osx_filename(self):
|
||||
return self.get_filename()
|
||||
|
||||
def type_suffix(self):
|
||||
return "@sta"
|
||||
|
||||
class SharedLibrary(BuildTarget):
|
||||
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
|
||||
self.version = None
|
||||
self.soversion = None
|
||||
self.ltversion = None
|
||||
self.vs_module_defs = None
|
||||
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs);
|
||||
if len(self.sources) > 0 and self.sources[0].endswith('.cs'):
|
||||
prefix = 'lib'
|
||||
suffix = 'dll'
|
||||
else:
|
||||
prefix = environment.get_shared_lib_prefix()
|
||||
suffix = environment.get_shared_lib_suffix()
|
||||
# The import library this target will generate
|
||||
self.import_filename = None
|
||||
# The import library that Visual Studio would generate (and accept)
|
||||
self.vs_import_filename = None
|
||||
# The import library that GCC would generate (and prefer)
|
||||
self.gcc_import_filename = None
|
||||
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
|
||||
if not hasattr(self, 'prefix'):
|
||||
self.prefix = prefix
|
||||
self.prefix = None
|
||||
if not hasattr(self, 'suffix'):
|
||||
if len(self.sources) > 0 and self.sources[0].endswith('.rs'):
|
||||
self.suffix = 'rlib'
|
||||
self.suffix = None
|
||||
self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
|
||||
self.determine_filenames(is_cross, environment)
|
||||
|
||||
def determine_filenames(self, is_cross, env):
|
||||
"""
|
||||
See https://github.com/mesonbuild/meson/pull/417 for details.
|
||||
|
||||
First we determine the filename template (self.filename_tpl), then we
|
||||
set the output filename (self.filename).
|
||||
|
||||
The template is needed while creating aliases (self.get_aliaslist),
|
||||
which are needed while generating .so shared libraries for Linux.
|
||||
|
||||
Besides this, there's also the import library name, which is only used
|
||||
on Windows since on that platform the linker uses a separate library
|
||||
called the "import library" during linking instead of the shared
|
||||
library (DLL). The toolchain will output an import library in one of
|
||||
two formats: GCC or Visual Studio.
|
||||
|
||||
When we're building with Visual Studio, the import library that will be
|
||||
generated by the toolchain is self.vs_import_filename, and with
|
||||
MinGW/GCC, it's self.gcc_import_filename. self.import_filename will
|
||||
always contain the import library name this target will generate.
|
||||
"""
|
||||
prefix = ''
|
||||
suffix = ''
|
||||
self.filename_tpl = self.basic_filename_tpl
|
||||
# If the user already provided the prefix and suffix to us, we don't
|
||||
# need to do any filename suffix/prefix detection.
|
||||
# NOTE: manual prefix/suffix override is currently only tested for C/C++
|
||||
if self.prefix != None and self.suffix != None:
|
||||
pass
|
||||
# C# and Mono
|
||||
elif sources_are_suffix(self.sources, 'cs'):
|
||||
prefix = ''
|
||||
suffix = 'dll'
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
|
||||
# Rust
|
||||
elif sources_are_suffix(self.sources, 'rs'):
|
||||
# Currently, we always build --crate-type=rlib
|
||||
prefix = 'lib'
|
||||
suffix = 'rlib'
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
|
||||
# C, C++, Swift, Vala
|
||||
# Only Windows uses a separate import library for linking
|
||||
# For all other targets/platforms import_filename stays None
|
||||
elif for_windows(is_cross, env):
|
||||
suffix = 'dll'
|
||||
self.vs_import_filename = '{0}.lib'.format(self.name)
|
||||
self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name)
|
||||
if compiler_is_msvc(self.sources, is_cross, env):
|
||||
# Shared library is of the form foo.dll
|
||||
prefix = ''
|
||||
# Import library is called foo.lib
|
||||
self.import_filename = self.vs_import_filename
|
||||
# Assume GCC-compatible naming
|
||||
else:
|
||||
self.suffix = suffix
|
||||
self.importsuffix = environment.get_import_lib_suffix()
|
||||
self.filename = self.prefix + self.name + '.' + self.suffix
|
||||
# Shared library is of the form libfoo.dll
|
||||
prefix = 'lib'
|
||||
# Import library is called libfoo.dll.a
|
||||
self.import_filename = self.gcc_import_filename
|
||||
# Shared library has the soversion if it is defined
|
||||
if self.soversion:
|
||||
self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}'
|
||||
else:
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
|
||||
elif for_darwin(is_cross, env):
|
||||
prefix = 'lib'
|
||||
suffix = 'dylib'
|
||||
if self.soversion:
|
||||
# libfoo.X.dylib
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.soversion}.{0.suffix}'
|
||||
else:
|
||||
# libfoo.dylib
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
|
||||
else:
|
||||
prefix = 'lib'
|
||||
suffix = 'so'
|
||||
if self.ltversion:
|
||||
# libfoo.so.X[.Y[.Z]] (.Y and .Z are optional)
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.ltversion}'
|
||||
elif self.soversion:
|
||||
# libfoo.so.X
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.soversion}'
|
||||
else:
|
||||
# No versioning, libfoo.so
|
||||
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
|
||||
if self.prefix == None:
|
||||
self.prefix = prefix
|
||||
if self.suffix == None:
|
||||
self.suffix = suffix
|
||||
self.filename = self.filename_tpl.format(self)
|
||||
|
||||
def process_kwargs(self, kwargs, environment):
|
||||
super().process_kwargs(kwargs, environment)
|
||||
# Shared library version
|
||||
if 'version' in kwargs:
|
||||
self.set_version(kwargs['version'])
|
||||
self.ltversion = kwargs['version']
|
||||
if not isinstance(self.ltversion, str):
|
||||
raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__)
|
||||
if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion):
|
||||
raise InvalidArguments('Invalid Shared library version "{0}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.'.format(self.ltversion))
|
||||
# Try to extract/deduce the soversion
|
||||
if 'soversion' in kwargs:
|
||||
self.set_soversion(kwargs['soversion'])
|
||||
self.soversion = kwargs['soversion']
|
||||
if isinstance(self.soversion, int):
|
||||
self.soversion = str(self.soversion)
|
||||
if not isinstance(self.soversion, str):
|
||||
raise InvalidArguments('Shared library soversion is not a string or integer.')
|
||||
try:
|
||||
int(self.soversion)
|
||||
except ValueError:
|
||||
raise InvalidArguments('Shared library soversion must be a valid integer')
|
||||
elif self.ltversion:
|
||||
# library version is defined, get the soversion from that
|
||||
self.soversion = self.ltversion.split('.')[0]
|
||||
# Visual Studio module-definitions file
|
||||
if 'vs_module_defs' in kwargs:
|
||||
path = kwargs['vs_module_defs']
|
||||
if (os.path.isabs(path)):
|
||||
|
@ -742,46 +896,41 @@ class SharedLibrary(BuildTarget):
|
|||
def check_unknown_kwargs(self, kwargs):
|
||||
self.check_unknown_kwargs_int(kwargs, known_shlib_kwargs)
|
||||
|
||||
def get_shbase(self):
|
||||
return self.prefix + self.name + '.' + self.suffix
|
||||
|
||||
def get_import_filename(self):
|
||||
return self.prefix + self.name + '.' + self.importsuffix
|
||||
"""
|
||||
The name of the import library that will be outputted by the compiler
|
||||
|
||||
Returns None if there is no import library required for this platform
|
||||
"""
|
||||
return self.import_filename
|
||||
|
||||
def get_import_filenameslist(self):
|
||||
if self.import_filename:
|
||||
return [self.vs_import_filename, self.gcc_import_filename]
|
||||
return []
|
||||
|
||||
def get_all_link_deps(self):
|
||||
return [self] + self.get_transitive_link_deps()
|
||||
|
||||
def get_filename(self):
|
||||
'''Works on all platforms except OSX, which does its own thing.'''
|
||||
fname = self.get_shbase()
|
||||
if self.version is None:
|
||||
return fname
|
||||
else:
|
||||
return fname + '.' + self.version
|
||||
|
||||
def get_osx_filename(self):
|
||||
if self.version is None:
|
||||
return self.get_shbase()
|
||||
return self.prefix + self.name + '.' + self.version + '.' + self.suffix
|
||||
|
||||
def set_version(self, version):
|
||||
if not isinstance(version, str):
|
||||
raise InvalidArguments('Shared library version is not a string.')
|
||||
self.version = version
|
||||
|
||||
def set_soversion(self, version):
|
||||
if isinstance(version, int):
|
||||
version = str(version)
|
||||
if not isinstance(version, str):
|
||||
raise InvalidArguments('Shared library soversion is not a string or integer.')
|
||||
self.soversion = version
|
||||
|
||||
def get_aliaslist(self):
|
||||
aliases = []
|
||||
if self.soversion is not None:
|
||||
aliases.append(self.get_shbase() + '.' + self.soversion)
|
||||
if self.version is not None:
|
||||
aliases.append(self.get_shbase())
|
||||
"""
|
||||
If the versioned library name is libfoo.so.0.100.0, aliases are:
|
||||
* libfoo.so.0 (soversion)
|
||||
* libfoo.so (unversioned; for linking)
|
||||
"""
|
||||
# Aliases are only useful with .so libraries. Also if the .so library
|
||||
# ends with .so (no versioning), we don't need aliases.
|
||||
if self.suffix != 'so' or self.filename.endswith('.so'):
|
||||
return []
|
||||
# Unversioned alias: libfoo.so
|
||||
aliases = [self.basic_filename_tpl.format(self)]
|
||||
# If ltversion != soversion we create an soversion alias: libfoo.so.X
|
||||
if self.ltversion and self.ltversion != self.soversion:
|
||||
if not self.soversion:
|
||||
# This is done in self.process_kwargs()
|
||||
raise AssertionError('BUG: If library version is defined, soversion must have been defined')
|
||||
alias_tpl = self.filename_tpl.replace('ltversion', 'soversion')
|
||||
aliases.append(alias_tpl.format(self))
|
||||
return aliases
|
||||
|
||||
def type_suffix(self):
|
||||
|
@ -815,6 +964,10 @@ class CustomTarget:
|
|||
mlog.log(mlog.bold('Warning:'), 'Unknown keyword arguments in target %s: %s' %
|
||||
(self.name, ', '.join(unknowns)))
|
||||
|
||||
def __repr__(self):
|
||||
repr_str = "<{0} {1}: {2}>"
|
||||
return repr_str.format(self.__class__.__name__, self.get_id(), self.command)
|
||||
|
||||
def get_id(self):
|
||||
return self.name + self.type_suffix()
|
||||
|
||||
|
@ -851,7 +1004,7 @@ class CustomTarget:
|
|||
for i, c in enumerate(cmd):
|
||||
if hasattr(c, 'held_object'):
|
||||
c = c.held_object
|
||||
if isinstance(c, str):
|
||||
if isinstance(c, str) or isinstance(c, File):
|
||||
final_cmd.append(c)
|
||||
elif isinstance(c, dependencies.ExternalProgram):
|
||||
if not c.found():
|
||||
|
@ -867,8 +1020,6 @@ class CustomTarget:
|
|||
if not isinstance(s, str):
|
||||
raise InvalidArguments('Array as argument %d contains a non-string.' % i)
|
||||
final_cmd.append(s)
|
||||
elif isinstance(c, File):
|
||||
final_cmd.append(os.path.join(c.subdir, c.fname))
|
||||
else:
|
||||
raise InvalidArguments('Argument %s in "command" is invalid.' % i)
|
||||
self.command = final_cmd
|
||||
|
@ -944,6 +1095,10 @@ class RunTarget:
|
|||
self.dependencies = dependencies
|
||||
self.subdir = subdir
|
||||
|
||||
def __repr__(self):
|
||||
repr_str = "<{0} {1}: {2}>"
|
||||
return repr_str.format(self.__class__.__name__, self.get_id(), self.command)
|
||||
|
||||
def get_id(self):
|
||||
return self.name + self.type_suffix()
|
||||
|
||||
|
@ -994,6 +1149,12 @@ class ConfigureFile():
|
|||
self.targetname = targetname
|
||||
self.configuration_data = configuration_data
|
||||
|
||||
def __repr__(self):
|
||||
repr_str = "<{0}: {1} -> {2}>"
|
||||
src = os.path.join(self.subdir, self.sourcename)
|
||||
dst = os.path.join(self.subdir, self.targetname)
|
||||
return repr_str.format(self.__class__.__name__, src, dst)
|
||||
|
||||
def get_configuration_data(self):
|
||||
return self.configuration_data
|
||||
|
||||
|
@ -1011,6 +1172,9 @@ class ConfigurationData():
|
|||
super().__init__()
|
||||
self.values = {}
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.values)
|
||||
|
||||
def get(self, name):
|
||||
return self.values[name]
|
||||
|
||||
|
|
|
@ -274,6 +274,13 @@ class Compiler():
|
|||
def get_linker_always_args(self):
|
||||
return []
|
||||
|
||||
def gen_import_library_args(self, implibname):
|
||||
"""
|
||||
Used only on Windows for libraries that need an import library.
|
||||
This currently means C, C++, Fortran.
|
||||
"""
|
||||
return []
|
||||
|
||||
def get_options(self):
|
||||
return {} # build afresh every time
|
||||
|
||||
|
@ -473,6 +480,14 @@ class CCompiler(Compiler):
|
|||
def get_linker_search_args(self, dirname):
|
||||
return ['-L'+dirname]
|
||||
|
||||
def gen_import_library_args(self, implibname):
|
||||
"""
|
||||
The name of the outputted import library
|
||||
|
||||
This implementation is used only on Windows by compilers that use GNU ld
|
||||
"""
|
||||
return ['-Wl,--out-implib=' + implibname]
|
||||
|
||||
def sanity_check_impl(self, work_dir, environment, sname, code):
|
||||
mlog.debug('Sanity testing ' + self.language + ' compiler:', ' '.join(self.exelist))
|
||||
mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
|
||||
|
@ -1499,6 +1514,10 @@ class VisualStudioCCompiler(CCompiler):
|
|||
objname = os.path.splitext(pchname)[0] + '.obj'
|
||||
return (objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname ])
|
||||
|
||||
def gen_import_library_args(self, implibname):
|
||||
"The name of the outputted import library"
|
||||
return ['/IMPLIB:' + implibname]
|
||||
|
||||
def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
|
||||
return []
|
||||
|
||||
|
@ -2057,6 +2076,14 @@ class GnuFortranCompiler(FortranCompiler):
|
|||
def get_always_args(self):
|
||||
return ['-pipe']
|
||||
|
||||
def gen_import_library_args(self, implibname):
|
||||
"""
|
||||
The name of the outputted import library
|
||||
|
||||
Used only on Windows
|
||||
"""
|
||||
return ['-Wl,--out-implib=' + implibname]
|
||||
|
||||
class G95FortranCompiler(FortranCompiler):
|
||||
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
|
||||
super().__init__(exelist, version, is_cross, exe_wrapper=None)
|
||||
|
@ -2068,6 +2095,14 @@ class G95FortranCompiler(FortranCompiler):
|
|||
def get_always_args(self):
|
||||
return ['-pipe']
|
||||
|
||||
def gen_import_library_args(self, implibname):
|
||||
"""
|
||||
The name of the outputted import library
|
||||
|
||||
Used only on Windows
|
||||
"""
|
||||
return ['-Wl,--out-implib=' + implibname]
|
||||
|
||||
class SunFortranCompiler(FortranCompiler):
|
||||
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
|
||||
super().__init__(exelist, version, is_cross, exe_wrapper=None)
|
||||
|
|
|
@ -80,11 +80,37 @@ def detect_system():
|
|||
return platform.system().lower()
|
||||
|
||||
|
||||
def for_windows(is_cross, env):
|
||||
"""
|
||||
Host machine is windows?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return mesonlib.is_windows()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'windows'
|
||||
return False
|
||||
|
||||
def for_darwin(is_cross, env):
|
||||
"""
|
||||
Host machine is Darwin (iOS/OS X)?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return mesonlib.is_osx()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'darwin'
|
||||
return False
|
||||
|
||||
|
||||
class Environment():
|
||||
private_dir = 'meson-private'
|
||||
log_dir = 'meson-logs'
|
||||
coredata_file = os.path.join(private_dir, 'coredata.dat')
|
||||
version_regex = '\d+(\.\d+)+(-[a-zA-Z0-9]+)?'
|
||||
|
||||
def __init__(self, source_dir, build_dir, main_script_file, options, original_cmd_line_args):
|
||||
assert(os.path.isabs(main_script_file))
|
||||
assert(not os.path.islink(main_script_file))
|
||||
|
@ -122,33 +148,22 @@ class Environment():
|
|||
self.default_static_linker = 'ar'
|
||||
self.vs_static_linker = 'lib'
|
||||
|
||||
# Various prefixes and suffixes for import libraries, shared libraries,
|
||||
# static libraries, and executables.
|
||||
# Versioning is added to these names in the backends as-needed.
|
||||
cross = self.is_cross_build()
|
||||
if (not cross and mesonlib.is_windows()) \
|
||||
or (cross and self.cross_info.has_host() and self.cross_info.config['host_machine']['system'] == 'windows'):
|
||||
self.exe_suffix = 'exe'
|
||||
if self.detect_c_compiler(cross).get_id() == 'msvc':
|
||||
self.import_lib_suffix = 'lib'
|
||||
else:
|
||||
# MinGW-GCC doesn't generate and can't link with a .lib
|
||||
# It uses the DLL file as the import library
|
||||
self.import_lib_suffix = 'dll'
|
||||
self.shared_lib_suffix = 'dll'
|
||||
self.shared_lib_prefix = ''
|
||||
self.static_lib_suffix = 'lib'
|
||||
self.static_lib_prefix = ''
|
||||
self.object_suffix = 'obj'
|
||||
self.shared_lib_dir = self.get_bindir()
|
||||
else:
|
||||
self.exe_suffix = ''
|
||||
if (not cross and mesonlib.is_osx()) or \
|
||||
(cross and self.cross_info.has_host() and self.cross_info.config['host_machine']['system'] == 'darwin'):
|
||||
self.shared_lib_suffix = 'dylib'
|
||||
else:
|
||||
self.shared_lib_suffix = 'so'
|
||||
self.shared_lib_prefix = 'lib'
|
||||
self.static_lib_suffix = 'a'
|
||||
self.static_lib_prefix = 'lib'
|
||||
self.object_suffix = 'o'
|
||||
self.import_lib_suffix = self.shared_lib_suffix
|
||||
self.shared_lib_dir = self.get_libdir()
|
||||
# Common to all platforms
|
||||
self.import_lib_dir = self.get_libdir()
|
||||
self.static_lib_dir = self.get_libdir()
|
||||
|
||||
def is_cross_build(self):
|
||||
return self.cross_info is not None
|
||||
|
@ -641,22 +656,17 @@ class Environment():
|
|||
def get_exe_suffix(self):
|
||||
return self.exe_suffix
|
||||
|
||||
# On Windows (MSVC) the library has suffix dll
|
||||
# but you link against a file that has suffix lib.
|
||||
def get_import_lib_suffix(self):
|
||||
return self.import_lib_suffix
|
||||
def get_import_lib_dir(self):
|
||||
"Install dir for the import library (library used for linking)"
|
||||
return self.import_lib_dir
|
||||
|
||||
def get_shared_lib_prefix(self):
|
||||
return self.shared_lib_prefix
|
||||
def get_shared_lib_dir(self):
|
||||
"Install dir for the shared library"
|
||||
return self.shared_lib_dir
|
||||
|
||||
def get_shared_lib_suffix(self):
|
||||
return self.shared_lib_suffix
|
||||
|
||||
def get_static_lib_prefix(self):
|
||||
return self.static_lib_prefix
|
||||
|
||||
def get_static_lib_suffix(self):
|
||||
return self.static_lib_suffix
|
||||
def get_static_lib_dir(self):
|
||||
"Install dir for the static library"
|
||||
return self.static_lib_dir
|
||||
|
||||
def get_object_suffix(self):
|
||||
return self.object_suffix
|
||||
|
@ -682,17 +692,6 @@ class Environment():
|
|||
def get_datadir(self):
|
||||
return self.coredata.get_builtin_option('datadir')
|
||||
|
||||
def find_library(self, libname, dirs):
|
||||
if dirs is None:
|
||||
dirs = mesonlib.get_library_dirs()
|
||||
suffixes = [self.get_shared_lib_suffix(), self.get_static_lib_suffix()]
|
||||
prefix = self.get_shared_lib_prefix()
|
||||
for d in dirs:
|
||||
for suffix in suffixes:
|
||||
trial = os.path.join(d, prefix + libname + '.' + suffix)
|
||||
if os.path.isfile(trial):
|
||||
return trial
|
||||
|
||||
|
||||
def get_args_from_envvars(lang):
|
||||
if lang == 'c':
|
||||
|
|
|
@ -28,6 +28,16 @@ class File:
|
|||
self.subdir = subdir
|
||||
self.fname = fname
|
||||
|
||||
def __str__(self):
|
||||
return os.path.join(self.subdir, self.fname)
|
||||
|
||||
def __repr__(self):
|
||||
ret = '<File: {0}'
|
||||
if not self.is_built:
|
||||
ret += ' (not built)'
|
||||
ret += '>'
|
||||
return ret.format(os.path.join(self.subdir, self.fname))
|
||||
|
||||
@staticmethod
|
||||
def from_source_file(source_root, subdir, fname):
|
||||
if not os.path.isfile(os.path.join(source_root, subdir, fname)):
|
||||
|
|
|
@ -52,7 +52,7 @@ def do_install(datafilename):
|
|||
|
||||
def install_subdirs(data):
|
||||
for (src_dir, inst_dir, dst_dir) in data.install_subdirs:
|
||||
if src_dir.endswith('/'):
|
||||
if src_dir.endswith('/') or src_dir.endswith('\\'):
|
||||
src_dir = src_dir[:-1]
|
||||
src_prefix = os.path.join(src_dir, inst_dir)
|
||||
print('Installing subdir %s to %s.' % (src_prefix, dst_dir))
|
||||
|
|
70
run_tests.py
70
run_tests.py
|
@ -124,44 +124,52 @@ def setup_commands(backend):
|
|||
test_commands = [ninja_command, 'test', 'benchmark']
|
||||
install_commands = [ninja_command, 'install']
|
||||
|
||||
def platform_fix_filename(fname):
|
||||
if mesonlib.is_osx():
|
||||
if fname.endswith('.so'):
|
||||
return fname[:-2] + 'dylib'
|
||||
return fname.replace('.so.', '.dylib.')
|
||||
elif mesonlib.is_windows():
|
||||
if fname.endswith('.so'):
|
||||
(p, f) = os.path.split(fname)
|
||||
f = f[3:-2] + 'dll'
|
||||
return os.path.join(p, f)
|
||||
if fname.endswith('.a'):
|
||||
return fname[:-1] + 'lib'
|
||||
def get_relative_files_list_from_dir(fromdir):
|
||||
paths = []
|
||||
for (root, _, files) in os.walk(fromdir):
|
||||
reldir = os.path.relpath(root, start=fromdir)
|
||||
for f in files:
|
||||
path = os.path.join(reldir, f).replace('\\', '/')
|
||||
if path.startswith('./'):
|
||||
path = path[2:]
|
||||
paths.append(path)
|
||||
return paths
|
||||
|
||||
def platform_fix_exe_name(fname):
|
||||
if not fname.endswith('?exe'):
|
||||
return fname
|
||||
fname = fname[:-4]
|
||||
if mesonlib.is_windows():
|
||||
return fname + '.exe'
|
||||
return fname
|
||||
|
||||
def validate_install(srcdir, installdir):
|
||||
if mesonlib.is_windows():
|
||||
# Don't really know how Windows installs should work
|
||||
# so skip.
|
||||
return ''
|
||||
# List of installed files
|
||||
info_file = os.path.join(srcdir, 'installed_files.txt')
|
||||
# If this exists, the test does not install any other files
|
||||
noinst_file = 'usr/no-installed-files'
|
||||
expected = {}
|
||||
found = {}
|
||||
if os.path.exists(info_file):
|
||||
ret_msg = ''
|
||||
# Generate list of expected files
|
||||
if os.path.exists(os.path.join(installdir, noinst_file)):
|
||||
expected[noinst_file] = False
|
||||
elif os.path.exists(info_file):
|
||||
for line in open(info_file):
|
||||
expected[platform_fix_filename(line.strip())] = True
|
||||
for root, _, files in os.walk(installdir):
|
||||
for fname in files:
|
||||
found_name = os.path.join(root, fname)[len(installdir)+1:]
|
||||
found[found_name] = True
|
||||
expected = set(expected)
|
||||
found = set(found)
|
||||
missing = expected - found
|
||||
for fname in missing:
|
||||
return 'Expected file %s missing.' % fname
|
||||
extra = found - expected
|
||||
for fname in extra:
|
||||
return 'Found extra file %s.' % fname
|
||||
return ''
|
||||
expected[platform_fix_exe_name(line.strip())] = False
|
||||
# Check if expected files were found
|
||||
for fname in expected:
|
||||
if os.path.exists(os.path.join(installdir, fname)):
|
||||
expected[fname] = True
|
||||
for (fname, found) in expected.items():
|
||||
if not found:
|
||||
ret_msg += 'Expected file {0} missing.\n'.format(fname)
|
||||
# Check if there are any unexpected files
|
||||
found = get_relative_files_list_from_dir(installdir)
|
||||
for fname in found:
|
||||
if fname not in expected:
|
||||
ret_msg += 'Extra file {0} found.\n'.format(fname)
|
||||
return ret_msg
|
||||
|
||||
def log_text_file(logfile, testdir, stdo, stde):
|
||||
global stop, executor, futures
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
usr/lib/libsomelib.so
|
||||
usr/lib/libsomelib.so.0
|
||||
usr/lib/libsomelib.so.1.2.3
|
||||
usr/lib/prefixsomelib.suffix
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
project('library versions', 'c')
|
||||
|
||||
lib = shared_library('somelib', 'lib.c', \
|
||||
version : '1.2.3', \
|
||||
soversion : '0', \
|
||||
install : true)
|
||||
shared_library('somelib', 'lib.c',
|
||||
name_prefix : 'prefix',
|
||||
name_suffix : 'suffix',
|
||||
install_dir : 'lib',
|
||||
install : true)
|
||||
|
||||
subdir('subdir')
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# Test that using files generated with configure_file as sources works.
|
||||
# We do this inside a subdir so that the path isn't accidentally correct
|
||||
# because there is no structure in the build dir.
|
||||
genlib = configure_file(input : '../lib.c',
|
||||
output : 'genlib.c',
|
||||
configuration : configuration_data())
|
||||
shared_library('genlib', genlib,
|
||||
install : false)
|
|
@ -1,4 +1 @@
|
|||
usr/bin/prog
|
||||
usr/lib/liblib1.so
|
||||
usr/lib/liblib2.so
|
||||
usr/lib/liblib3.so
|
||||
usr/bin/prog?exe
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
subdir('subdir2')
|
||||
subdir('subdir3')
|
||||
|
||||
lib1 = shared_library('lib1', 'lib1.c', install : true, link_with : [lib2, lib3])
|
||||
lib1 = shared_library('lib1', 'lib1.c', install : false, link_with : [lib2, lib3])
|
||||
|
|
|
@ -1 +1 @@
|
|||
lib2 = shared_library('lib2', 'lib2.c', install : true)
|
||||
lib2 = shared_library('lib2', 'lib2.c', install : false)
|
||||
|
|
|
@ -1 +1 @@
|
|||
lib3 = shared_library('lib3', 'lib3.c', install : true)
|
||||
lib3 = shared_library('lib3', 'lib3.c', install : false)
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
usr/bin/user
|
||||
usr/lib/libsublib.so
|
||||
usr/bin/user?exe
|
||||
usr/share/sublib/sublib.depmf
|
||||
|
|
|
@ -13,7 +13,7 @@ if meson.project_version() != '1.0.0'
|
|||
endif
|
||||
|
||||
i = include_directories('include')
|
||||
l = shared_library('sublib', 'sublib.c', include_directories : i, install : true,
|
||||
l = shared_library('sublib', 'sublib.c', include_directories : i, install : false,
|
||||
c_args : '-DBUILDING_SUB=2')
|
||||
t = executable('simpletest', 'simpletest.c', include_directories : i, link_with : l)
|
||||
test('plain', t)
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
usr/include/simple.h
|
||||
usr/lib/libsimple.so
|
||||
usr/lib/pkgconfig/simple.pc
|
||||
|
|
|
@ -2,7 +2,7 @@ project('pkgconfig-gen', 'c')
|
|||
|
||||
pkgg = import('pkgconfig')
|
||||
|
||||
lib = shared_library('simple', 'simple.c', install : true)
|
||||
lib = shared_library('simple', 'simple.c')
|
||||
libver = '1.0'
|
||||
h = install_headers('simple.h')
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
usr/dib/dab/dub/prog
|
||||
usr/dib/dab/dub/prog?exe
|
||||
usr/some/dir/sample.h
|
||||
usr/woman/prog.1.gz
|
||||
usr/meow/datafile.cat
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
usr/bin/prog
|
||||
usr/lib/libmylib.so
|
||||
usr/bin/prog?exe
|
||||
|
|
|
@ -2,7 +2,7 @@ project('shared library linking test', 'c', 'cpp')
|
|||
|
||||
lib = shared_library('mylib',
|
||||
'libfile.c' # Split to different lines before and after the comma to test parser.
|
||||
, install : true)
|
||||
, install : false) # Don't install libraries in common tests; the path is platform-specific
|
||||
exe = executable('prog', 'main.c', link_with : lib, install : true)
|
||||
|
||||
test('runtest', exe)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
usr/bin/prog
|
||||
usr/bin/prog?exe
|
||||
usr/diiba/daaba/file.dat
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
project('custom install script', 'c')
|
||||
|
||||
if meson.get_compiler('c').get_id() == 'msvc'
|
||||
meson.add_install_script('myinstall.bat')
|
||||
install_data('no-installed-files', install_dir : '')
|
||||
else
|
||||
meson.add_install_script('myinstall.sh')
|
||||
executable('prog', 'prog.c', install : true)
|
||||
endif
|
||||
executable('prog', 'prog.c', install : true)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
@ECHO OFF
|
||||
|
||||
echo At this point we could do something.
|
|
@ -4,9 +4,7 @@ set -eu
|
|||
|
||||
echo Starting custom installation step
|
||||
|
||||
# These commands fail on Windows, but we don't really care.
|
||||
|
||||
mkdir -p "${DESTDIR}${MESON_INSTALL_PREFIX}/diiba/daaba"
|
||||
touch "${DESTDIR}${MESON_INSTALL_PREFIX}/diiba/daaba/file.dat"
|
||||
|
||||
echo Finishing custom install step
|
||||
echo Finished custom install step
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
usr/bin/prog1
|
||||
usr/bin/prog2
|
||||
usr/bin/prog3
|
||||
usr/bin/prog1?exe
|
||||
usr/bin/prog2?exe
|
||||
usr/bin/prog3?exe
|
||||
|
|
|
@ -2,3 +2,19 @@ custom_target('thing',
|
|||
output : 'final.dat',
|
||||
input : cfile,
|
||||
command : [find_program('mycompiler.py'), '@INPUT@', '@OUTPUT@'])
|
||||
|
||||
# Test usage of a `configure_file` as part of the command list
|
||||
py3 = find_program('python3', required : false)
|
||||
if not py3.found()
|
||||
# Maybe 'python' is Python 3
|
||||
py3 = find_program('python')
|
||||
endif
|
||||
|
||||
compiler = configure_file(input : 'mycompiler.py',
|
||||
output : 'mycompiler2.py',
|
||||
configuration : configuration_data())
|
||||
|
||||
custom_target('thing2',
|
||||
output : 'final2.dat',
|
||||
input : cfile,
|
||||
command : [py3, compiler, '@INPUT@', '@OUTPUT@'])
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
usr/bin/prog
|
||||
usr/lib/libshar.so
|
||||
usr/bin/prog?exe
|
||||
usr/lib/libstat.a
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
project('install test', 'c')
|
||||
|
||||
stlib = static_library('stat', 'stat.c', install : true)
|
||||
shlib = shared_library('shar', 'shar.c', install : true)
|
||||
exe = executable('prog', 'prog.c', install : true)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
int func() { return 15; }
|
|
@ -1,2 +1,2 @@
|
|||
usr/bin/prog.exe
|
||||
usr/lib/libhelper.dll
|
||||
usr/lib/helper.dll
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
usr/lib/libsome.so
|
||||
usr/lib/libsome.so.0
|
||||
usr/lib/libsome.so.1.2.3
|
||||
usr/lib/libnoversion.so
|
||||
usr/lib/libonlyversion.so
|
||||
usr/lib/libonlyversion.so.1
|
||||
usr/lib/libonlyversion.so.1.4.5
|
||||
usr/lib/libonlysoversion.so
|
||||
usr/lib/libonlysoversion.so.5
|
|
@ -0,0 +1,3 @@
|
|||
int myFunc() {
|
||||
return 55;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
project('library versions', 'c')
|
||||
|
||||
shared_library('some', 'lib.c',
|
||||
version : '1.2.3',
|
||||
soversion : '0',
|
||||
install : true)
|
||||
|
||||
shared_library('noversion', 'lib.c',
|
||||
install : true)
|
||||
|
||||
shared_library('onlyversion', 'lib.c',
|
||||
version : '1.4.5',
|
||||
install : true)
|
||||
|
||||
shared_library('onlysoversion', 'lib.c',
|
||||
# Also test that int soversion is acceptable
|
||||
soversion : 5,
|
||||
install : true)
|
|
@ -0,0 +1,3 @@
|
|||
usr/lib/libsublib.so
|
||||
usr/lib/libsublib.so.5
|
||||
usr/lib/libsublib.so.2.1.0
|
|
@ -0,0 +1,6 @@
|
|||
project('subproj lib install', 'c',
|
||||
version : '2.3.4',
|
||||
license : 'mylicense')
|
||||
|
||||
# Test that the subproject library gets installed
|
||||
subproject('sublib', version : '1.0.0')
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef SUBDEFS_H_
|
||||
#define SUBDEFS_H_
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#if defined BUILDING_SUB
|
||||
#define DLL_PUBLIC __declspec(dllexport)
|
||||
#else
|
||||
#define DLL_PUBLIC __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if defined __GNUC__
|
||||
#define DLL_PUBLIC __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#pragma message ("Compiler does not support symbol visibility.")
|
||||
#define DLL_PUBLIC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int DLL_PUBLIC subfunc();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,10 @@
|
|||
project('subproject', 'c',
|
||||
version : '1.0.0',
|
||||
license : ['sublicense1', 'sublicense2'])
|
||||
|
||||
i = include_directories('include')
|
||||
shared_library('sublib', 'sublib.c',
|
||||
version : '2.1.0',
|
||||
soversion : 5,
|
||||
include_directories : i, install : true,
|
||||
c_args : '-DBUILDING_SUB=2')
|
|
@ -0,0 +1,5 @@
|
|||
#include<subdefs.h>
|
||||
|
||||
int DLL_PUBLIC subfunc() {
|
||||
return 42;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
usr/lib/libsome.0.dylib
|
||||
usr/lib/libnoversion.dylib
|
||||
usr/lib/libonlyversion.1.dylib
|
||||
usr/lib/libonlysoversion.5.dylib
|
|
@ -0,0 +1,3 @@
|
|||
int myFunc() {
|
||||
return 55;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
project('library versions', 'c')
|
||||
|
||||
shared_library('some', 'lib.c',
|
||||
version : '1.2.3',
|
||||
soversion : '0',
|
||||
install : true)
|
||||
|
||||
shared_library('noversion', 'lib.c',
|
||||
install : true)
|
||||
|
||||
shared_library('onlyversion', 'lib.c',
|
||||
version : '1.4.5',
|
||||
install : true)
|
||||
|
||||
shared_library('onlysoversion', 'lib.c',
|
||||
# Also test that int soversion is acceptable
|
||||
soversion : 5,
|
||||
install : true)
|
|
@ -1 +1 @@
|
|||
usr/bin/prog
|
||||
usr/bin/prog?exe
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
usr/bin/prog
|
||||
usr/bin/prog?exe
|
||||
usr/lib/libstuff.rlib
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
usr/bin/prog
|
||||
usr/bin/prog?exe
|
||||
usr/lib/libstuff.rlib
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
usr/bin/libsome-0.dll
|
||||
usr/lib/libsome.dll.a
|
||||
usr/bin/libnoversion.dll
|
||||
usr/lib/libnoversion.dll.a
|
|
@ -0,0 +1,6 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int myFunc() {
|
||||
return 55;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
project('mingw dll versioning', 'c')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
# Test that MinGW/GCC creates correctly-named dll files and dll.a files,
|
||||
# and also installs them in the right place
|
||||
if cc.get_id() != 'msvc'
|
||||
shared_library('some', 'lib.c',
|
||||
version : '1.2.3',
|
||||
soversion : '0',
|
||||
install : true)
|
||||
|
||||
shared_library('noversion', 'lib.c',
|
||||
install : true)
|
||||
else
|
||||
install_data('no-installed-files', install_dir : '')
|
||||
endif
|
|
@ -0,0 +1,4 @@
|
|||
usr/bin/some-0.dll
|
||||
usr/lib/some.lib
|
||||
usr/bin/noversion.dll
|
||||
usr/lib/noversion.lib
|
|
@ -0,0 +1,6 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int myFunc() {
|
||||
return 55;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
project('msvc dll versioning', 'c')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
# Test that MSVC creates foo-0.dll and bar.dll
|
||||
if cc.get_id() == 'msvc'
|
||||
shared_library('some', 'lib.c',
|
||||
version : '1.2.3',
|
||||
soversion : '0',
|
||||
install : true)
|
||||
|
||||
shared_library('noversion', 'lib.c',
|
||||
install : true)
|
||||
else
|
||||
install_data('no-installed-files', install_dir : '')
|
||||
endif
|
Loading…
Reference in New Issue