aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2020-04-15 14:58:14 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2020-04-17 18:28:40 +0300
commitcf4b9e650226892079759bc8f40241f2cec44d09 (patch)
treefb54ca358b3ba7d7607616b731fb6d34b884df9d
parentc0a8abc5809e0ecd72d6180a40acbf05cefbc427 (diff)
downloadmeson-cf4b9e650226892079759bc8f40241f2cec44d09.zip
meson-cf4b9e650226892079759bc8f40241f2cec44d09.tar.gz
meson-cf4b9e650226892079759bc8f40241f2cec44d09.tar.bz2
cmake: Do not compile explicit header files
-rw-r--r--mesonbuild/cmake/data/preload.cmake34
-rw-r--r--mesonbuild/cmake/interpreter.py2
-rw-r--r--mesonbuild/cmake/traceparser.py61
-rw-r--r--test cases/cmake/18 skip include files/main.cpp10
-rw-r--r--test cases/cmake/18 skip include files/meson.build9
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt15
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp10
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp16
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt30
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp7
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp7
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp7
-rw-r--r--test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp7
13 files changed, 200 insertions, 15 deletions
diff --git a/mesonbuild/cmake/data/preload.cmake b/mesonbuild/cmake/data/preload.cmake
index 30178fb..f8caae9 100644
--- a/mesonbuild/cmake/data/preload.cmake
+++ b/mesonbuild/cmake/data/preload.cmake
@@ -31,5 +31,37 @@ macro(add_custom_target)
_add_custom_target(${ARGV})
endmacro()
-set(MESON_PS_DELAYED_CALLS add_custom_command;add_custom_target)
+macro(set_property)
+ meson_ps_inspect_vars()
+ _set_property(${ARGV})
+endmacro()
+
+function(set_source_files_properties)
+ set(FILES)
+ set(I 0)
+ set(PROPERTIES OFF)
+
+ while(I LESS ARGC)
+ if(NOT PROPERTIES)
+ if("${ARGV${I}}" STREQUAL "PROPERTIES")
+ set(PROPERTIES ON)
+ else()
+ list(APPEND FILES "${ARGV${I}}")
+ endif()
+
+ math(EXPR I "${I} + 1")
+ else()
+ set(ID_IDX ${I})
+ math(EXPR PROP_IDX "${ID_IDX} + 1")
+
+ set(ID "${ARGV${ID_IDX}}")
+ set(PROP "${ARGV${PROP_IDX}}")
+
+ set_property(SOURCE ${FILES} PROPERTY "${ID}" "${PROP}")
+ math(EXPR I "${I} + 2")
+ endif()
+ endwhile()
+endfunction()
+
+set(MESON_PS_DELAYED_CALLS add_custom_command;add_custom_target;set_property)
meson_ps_reload_vars()
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index f2f635c..7e9873f 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -411,6 +411,8 @@ class ConverterTarget:
mlog.warning('CMake: path', mlog.bold(x), 'does not exist.')
mlog.warning(' --> Ignoring. This can lead to build errors.')
return None
+ if Path(x) in trace.explicit_headers:
+ return None
if (
os.path.isabs(x)
and os.path.commonpath([x, self.env.get_source_dir()]) == self.env.get_source_dir()
diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py
index d6970f2..432cd21 100644
--- a/mesonbuild/cmake/traceparser.py
+++ b/mesonbuild/cmake/traceparser.py
@@ -25,6 +25,7 @@ from pathlib import Path
import re
import os
import json
+import textwrap
class CMakeTraceLine:
def __init__(self, file, line, func, args):
@@ -76,6 +77,8 @@ class CMakeTraceParser:
self.vars = {} # type: T.Dict[str, T.List[str]]
self.targets = {} # type: T.Dict[str, CMakeTarget]
+ self.explicit_headers = set() # type: T.Set[Path]
+
# T.List of targes that were added with add_custom_command to generate files
self.custom_targets = [] # type: T.List[CMakeGeneratorTarget]
@@ -185,16 +188,18 @@ class CMakeTraceParser:
return None
- def var_to_bool(self, var):
- if var not in self.vars:
- return False
-
- if len(self.vars[var]) < 1:
+ def _str_to_bool(self, expr: T.Union[str, T.List[str]]) -> bool:
+ if not expr:
return False
+ if isinstance(expr, list):
+ expr_str = expr[0]
+ else:
+ expr_str = expr
+ expr_str = expr_str.upper()
+ return expr_str not in ['0', 'OFF', 'NO', 'FALSE', 'N', 'IGNORE'] and not expr_str.endswith('NOTFOUND')
- if self.vars[var][0].upper() in ['1', 'ON', 'TRUE']:
- return True
- return False
+ def var_to_bool(self, var: str) -> bool:
+ return self._str_to_bool(self.vars.get(var, []))
def _gen_exception(self, function: str, error: str, tline: CMakeTraceLine) -> None:
# Generate an exception if the parser is not in permissive mode
@@ -385,9 +390,7 @@ class CMakeTraceParser:
# DOC: https://cmake.org/cmake/help/latest/command/set_property.html
args = list(tline.args)
- # We only care for TARGET properties
- if args.pop(0) != 'TARGET':
- return
+ scope = args.pop(0)
append = False
targets = []
@@ -402,7 +405,7 @@ class CMakeTraceParser:
if curr == 'PROPERTY':
break
- targets.append(curr)
+ targets += curr.split(';')
if not args:
return self._gen_exception('set_property', 'faild to parse argument list', tline)
@@ -412,11 +415,14 @@ class CMakeTraceParser:
return
identifier = args.pop(0)
- value = ' '.join(args).split(';')
+ if self.trace_format == 'human':
+ value = ' '.join(args).split(';')
+ else:
+ value = [y for x in args for y in x.split(';')]
if not value:
return
- for i in targets:
+ def do_target(tgt: str) -> None:
if i not in self.targets:
return self._gen_exception('set_property', 'TARGET {} not found'.format(i), tline)
@@ -428,6 +434,33 @@ class CMakeTraceParser:
else:
self.targets[i].properties[identifier] = value
+ def do_source(src: str) -> None:
+ if identifier != 'HEADER_FILE_ONLY' or not self._str_to_bool(value):
+ return
+
+ current_src_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR')
+ if not current_src_dir:
+ mlog.warning(textwrap.dedent('''\
+ CMake trace: set_property(SOURCE) called before the preload script was loaded.
+ Unable to determine CMAKE_CURRENT_SOURCE_DIR. This can lead to build errors.
+ '''))
+ current_src_dir = '.'
+
+ cur_p = Path(current_src_dir)
+ src_p = Path(src)
+
+ if not src_p.is_absolute():
+ src_p = cur_p / src_p
+ self.explicit_headers.add(src_p)
+
+ if scope == 'TARGET':
+ for i in targets:
+ do_target(i)
+ elif scope == 'SOURCE':
+ files = self._guess_files(targets)
+ for i in files:
+ do_source(i)
+
def _cmake_set_target_properties(self, tline: CMakeTraceLine) -> None:
# DOC: https://cmake.org/cmake/help/latest/command/set_target_properties.html
args = list(tline.args)
diff --git a/test cases/cmake/18 skip include files/main.cpp b/test cases/cmake/18 skip include files/main.cpp
new file mode 100644
index 0000000..9507961
--- /dev/null
+++ b/test cases/cmake/18 skip include files/main.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+#include <cmMod.hpp>
+
+using namespace std;
+
+int main(void) {
+ cmModClass obj("Hello");
+ cout << obj.getStr() << endl;
+ return 0;
+}
diff --git a/test cases/cmake/18 skip include files/meson.build b/test cases/cmake/18 skip include files/meson.build
new file mode 100644
index 0000000..b9a300c
--- /dev/null
+++ b/test cases/cmake/18 skip include files/meson.build
@@ -0,0 +1,9 @@
+project('cmakeSubTest', ['c', 'cpp'])
+
+cm = import('cmake')
+
+sub_pro = cm.subproject('cmMod')
+sub_dep = sub_pro.dependency('cmModLib++')
+
+exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep])
+test('test1', exe1)
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt
new file mode 100644
index 0000000..4db01b3
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmMod)
+set (CMAKE_CXX_STANDARD 14)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+add_definitions("-DDO_NOTHING_JUST_A_FLAG=1")
+
+set(SRCS
+ ${CMAKE_CURRENT_LIST_DIR}/cmMod.hpp
+ ${CMAKE_CURRENT_LIST_DIR}/cmMod.cpp
+)
+
+add_subdirectory(fakeInc)
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp b/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp
new file mode 100644
index 0000000..7551b75
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp
@@ -0,0 +1,10 @@
+#include "cmMod.hpp"
+
+using namespace std;
+
+#define MESON_INCLUDE_IMPL
+#include "fakeInc/cmModInc1.cpp"
+#include "fakeInc/cmModInc2.cpp"
+#include "fakeInc/cmModInc3.cpp"
+#include "fakeInc/cmModInc4.cpp"
+#undef MESON_INCLUDE_IMPL
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp b/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp
new file mode 100644
index 0000000..f7b780f
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "cmmodlib++_export.h"
+#include <string>
+
+class CMMODLIB___EXPORT cmModClass {
+private:
+ std::string str;
+
+ std::string getStr1() const;
+ std::string getStr2() const;
+public:
+ cmModClass(std::string foo);
+
+ std::string getStr() const;
+};
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt
new file mode 100644
index 0000000..39cd080
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt
@@ -0,0 +1,30 @@
+list(APPEND SRCS
+ cmModInc1.cpp
+ cmModInc2.cpp
+ cmModInc3.cpp
+ cmModInc4.cpp
+)
+
+set(SRC_A
+ cmModInc1.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/cmModInc2.cpp
+)
+
+set_property(
+ SOURCE ${SRC_A}
+ PROPERTY
+ HEADER_FILE_ONLY ON
+)
+
+set_source_files_properties(
+ cmModInc3.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/cmModInc4.cpp
+ PROPERTIES
+ LABELS "CMake;Lists;are;fun"
+ HEADER_FILE_ONLY ON
+)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+add_library(cmModLib++ SHARED ${SRCS})
+include(GenerateExportHeader)
+generate_export_header(cmModLib++)
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp
new file mode 100644
index 0000000..b637755
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp
@@ -0,0 +1,7 @@
+#ifndef MESON_INCLUDE_IMPL
+#error "MESON_INCLUDE_IMPL is not defined"
+#endif // !MESON_INCLUDE_IMPL
+
+cmModClass::cmModClass(string foo) {
+ str = foo + " World";
+}
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp
new file mode 100644
index 0000000..8a53567
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp
@@ -0,0 +1,7 @@
+#ifndef MESON_INCLUDE_IMPL
+#error "MESON_INCLUDE_IMPL is not defined"
+#endif // !MESON_INCLUDE_IMPL
+
+string cmModClass::getStr() const {
+ return getStr2();
+}
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp
new file mode 100644
index 0000000..2c8ad12
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp
@@ -0,0 +1,7 @@
+#ifndef MESON_INCLUDE_IMPL
+#error "MESON_INCLUDE_IMPL is not defined"
+#endif // !MESON_INCLUDE_IMPL
+
+string cmModClass::getStr1() const {
+ return getStr2();
+}
diff --git a/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp
new file mode 100644
index 0000000..78a0673
--- /dev/null
+++ b/test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp
@@ -0,0 +1,7 @@
+#ifndef MESON_INCLUDE_IMPL
+#error "MESON_INCLUDE_IMPL is not defined"
+#endif // !MESON_INCLUDE_IMPL
+
+string cmModClass::getStr2() const {
+ return str;
+}