cmake: Do not compile explicit header files

0.54
Daniel Mensinger 5 years ago committed by Nirbheek Chauhan
parent bd8d079473
commit 79d13ce783
  1. 34
      mesonbuild/cmake/data/preload.cmake
  2. 2
      mesonbuild/cmake/interpreter.py
  3. 61
      mesonbuild/cmake/traceparser.py
  4. 10
      test cases/cmake/18 skip include files/main.cpp
  5. 9
      test cases/cmake/18 skip include files/meson.build
  6. 15
      test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt
  7. 10
      test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp
  8. 16
      test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp
  9. 30
      test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt
  10. 7
      test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp
  11. 7
      test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp
  12. 7
      test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp
  13. 7
      test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp

@ -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()

@ -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()

@ -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)

@ -0,0 +1,10 @@
#include <iostream>
#include <cmMod.hpp>
using namespace std;
int main(void) {
cmModClass obj("Hello");
cout << obj.getStr() << endl;
return 0;
}

@ -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)

@ -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)

@ -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

@ -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;
};

@ -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++)

@ -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";
}

@ -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();
}

@ -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();
}

@ -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;
}
Loading…
Cancel
Save