cmake: support object libraries

pull/4969/head
Daniel Mensinger 6 years ago
parent f73b36c2f3
commit 1041c71eb0
No known key found for this signature in database
GPG Key ID: 54DD94C131E277D4
  1. 43
      mesonbuild/cmake/interpreter.py
  2. 11
      mesonbuild/interpreter.py
  3. 9
      test cases/cmake/4 object library/main.cpp
  4. 14
      test cases/cmake/4 object library/meson.build
  5. 10
      test cases/cmake/4 object library/subprojects/cmObjLib/CMakeLists.txt
  6. 5
      test cases/cmake/4 object library/subprojects/cmObjLib/libA.cpp
  7. 5
      test cases/cmake/4 object library/subprojects/cmObjLib/libA.hpp
  8. 6
      test cases/cmake/4 object library/subprojects/cmObjLib/libB.cpp
  9. 5
      test cases/cmake/4 object library/subprojects/cmObjLib/libB.hpp

@ -20,11 +20,11 @@ from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCo
from .. import mlog
from ..build import Build
from ..environment import Environment
from ..mparser import Token, BaseNode, CodeBlockNode, FunctionNode, ArrayNode, ArgumentNode, AssignmentNode, BooleanNode, StringNode, IdNode
from ..mparser import Token, BaseNode, CodeBlockNode, FunctionNode, ArrayNode, ArgumentNode, AssignmentNode, BooleanNode, StringNode, IdNode, MethodNode
from ..backend.backends import Backend
from ..dependencies.base import CMakeDependency, ExternalProgram
from subprocess import Popen, PIPE, STDOUT
from typing import Dict
from typing import Dict, List
import os, re
CMAKE_BACKEND_GENERATOR_MAP = {
@ -50,6 +50,7 @@ CMAKE_TGT_TYPE_MAP = {
'MODULE_LIBRARY': 'shared_module',
'SHARED_LIBRARY': 'shared_library',
'EXECUTABLE': 'executable',
'OBJECT_LIBRARY': 'static_library',
}
class ConverterTarget:
@ -75,6 +76,7 @@ class ConverterTarget:
self.generated = []
self.includes = []
self.link_with = []
self.object_libs = []
self.compile_opts = {}
self.pie = False
@ -160,6 +162,17 @@ class ConverterTarget:
if os.path.commonpath([self.install_dir, install_prefix]) == install_prefix:
self.install_dir = os.path.relpath(self.install_dir, install_prefix)
def process_object_libs(self, obj_target_list: List['ConverterTarget']):
# Try to detect the object library(s) from the generated input sources
temp = [os.path.basename(x) for x in self.generated if x.endswith('.o')]
self.generated = [x for x in self.generated if not x.endswith('.o')]
for i in obj_target_list:
out_objects = [os.path.basename(x + '.o') for x in i.sources + i.generated]
for j in out_objects:
if j in temp:
self.object_libs += [i]
break
def meson_func(self) -> str:
return CMAKE_TGT_TYPE_MAP.get(self.type.upper())
@ -171,6 +184,7 @@ class ConverterTarget:
mlog.log(' -- install_dir: ', mlog.bold(self.install_dir))
mlog.log(' -- link_libraries: ', mlog.bold(str(self.link_libraries)))
mlog.log(' -- link_with: ', mlog.bold(str(self.link_with)))
mlog.log(' -- object_libs: ', mlog.bold(str(self.object_libs)))
mlog.log(' -- link_flags: ', mlog.bold(str(self.link_flags)))
mlog.log(' -- languages: ', mlog.bold(str(self.languages)))
mlog.log(' -- includes: ', mlog.bold(str(self.includes)))
@ -297,11 +311,19 @@ class CMakeInterpreter:
self.targets += [ConverterTarget(k)]
output_target_map = {x.full_name: x for x in self.targets}
object_libs = []
# First pass: Basic target cleanup
for i in self.targets:
i.postprocess(output_target_map, self.src_dir, self.install_prefix)
if i.type == 'OBJECT_LIBRARY':
object_libs += [i]
self.languages += [x for x in i.languages if x not in self.languages]
# Second pass: Detect object library dependencies
for i in self.targets:
i.process_object_libs(object_libs)
mlog.log('CMake project', mlog.bold(self.project_name), 'has', mlog.bold(str(len(self.targets))), 'build targets.')
def pretend_to_be_meson(self) -> CodeBlockNode:
@ -342,6 +364,14 @@ class CMakeInterpreter:
func_n = FunctionNode(self.subdir, 0, 0, name, args_n)
return func_n
def method(obj: BaseNode, name: str, args=[], kwargs={}) -> MethodNode:
args_n = ArgumentNode(token())
if not isinstance(args, list):
args = [args]
args_n.arguments = [nodeify(x) for x in args]
args_n.kwargs = {k: nodeify(v) for k, v in kwargs.items()}
return MethodNode(self.subdir, 0, 0, obj, name, args_n)
def assign(var_name: str, value: BaseNode) -> AssignmentNode:
return AssignmentNode(self.subdir, 0, 0, var_name, value)
@ -351,13 +381,19 @@ class CMakeInterpreter:
processed = {}
def process_target(tgt: ConverterTarget):
# First handle inter dependencies
# First handle inter target dependencies
link_with = []
objec_libs = []
for i in tgt.link_with:
assert(isinstance(i, ConverterTarget))
if i.name not in processed:
process_target(i)
link_with += [id(processed[i.name]['tgt'])]
for i in tgt.object_libs:
assert(isinstance(i, ConverterTarget))
if i.name not in processed:
process_target(i)
objec_libs += [processed[i.name]['tgt']]
# Determine the meson function to use for the build target
tgt_func = tgt.meson_func()
@ -379,6 +415,7 @@ class CMakeInterpreter:
'install': tgt.install,
'install_dir': tgt.install_dir,
'override_options': tgt.override_options,
'objects': [method(id(x), 'extract_all_objects') for x in objec_libs],
}
# Handle compiler args

@ -2560,15 +2560,18 @@ external dependencies (including libraries) must go to "dependencies".''')
with mlog.nested():
mlog.log('Processing generated meson AST')
mlog.log()
mlog.log('=== BEGIN meson.build ===')
# Debug print the generated meson file
mlog.debug('=== BEGIN meson.build ===')
from .ast import AstIndentationGenerator, AstPrinter
printer = AstPrinter()
ast.accept(AstIndentationGenerator())
ast.accept(printer)
printer.post_process()
mlog.log(printer.result)
mlog.log('=== END meson.build ===')
mlog.log()
mlog.debug(printer.result)
mlog.debug('=== END meson.build ===')
mlog.debug()
result = self.do_subproject_meson(dirname, subdir, default_options, required, kwargs, ast, cm_int.bs_files)
mlog.log()

@ -0,0 +1,9 @@
#include <iostream>
#include "libA.hpp"
#include "libB.hpp"
using namespace std;
int main() {
cout << getLibStr() << " -- " << getZlibVers() << endl;
}

@ -0,0 +1,14 @@
project('cmake_object_lib_test', ['cpp'])
sub_pro = subproject('cmObjLib')
sub_sha = sub_pro.get_variable('lib_sha_dep')
sub_sta = sub_pro.get_variable('lib_sta_dep')
# Required for the static library
zlib_dep = dependency('zlib')
exe_sha = executable('shared', ['main.cpp'], dependencies: [sub_sha])
exe_sta = executable('static', ['main.cpp'], dependencies: [sub_sta, zlib_dep])
test('test1', exe_sha)
test('test1', exe_sta)

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.7)
find_package(ZLIB REQUIRED)
add_library(lib_obj OBJECT libA.cpp libB.cpp)
add_library(lib_sha SHARED $<TARGET_OBJECTS:lib_obj>)
add_library(lib_sta STATIC $<TARGET_OBJECTS:lib_obj>)
target_link_libraries(lib_sha ZLIB::ZLIB)
target_link_libraries(lib_sta ZLIB::ZLIB)

@ -0,0 +1,5 @@
#include "libA.hpp"
std::string getLibStr() {
return "Hello World";
}

@ -0,0 +1,5 @@
#pragma once
#include <string>
std::string getLibStr();

@ -0,0 +1,6 @@
#include "libB.hpp"
#include <zlib.h>
std::string getZlibVers() {
return zlibVersion();
}

@ -0,0 +1,5 @@
#pragma once
#include <string>
std::string getZlibVers();
Loading…
Cancel
Save