forked from OSchip/llvm-project
Reapply "[clang][deps] Support inferred modules"
This reapplies commit 95033eb3 that reverted commit 1d9e8e13
.
The tests were failing on Windows due to spaces and backslashes in paths not being handled carefully.
This commit is contained in:
parent
f5b5426433
commit
c98833cdaa
|
@ -33,7 +33,6 @@ makeInvocationForModuleBuildWithoutPaths(const ModuleDeps &Deps,
|
|||
CI.getFrontendOpts().IsSystemModule = Deps.IsSystem;
|
||||
|
||||
CI.getLangOpts()->ImplicitModules = false;
|
||||
CI.getHeaderSearchOpts().ImplicitModuleMaps = false;
|
||||
|
||||
return CI;
|
||||
}
|
||||
|
@ -179,13 +178,22 @@ ModuleID ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
|
|||
const FileEntry *ModuleMap = Instance.getPreprocessor()
|
||||
.getHeaderSearchInfo()
|
||||
.getModuleMap()
|
||||
.getContainingModuleMapFile(M);
|
||||
.getModuleMapFileForUniquing(M);
|
||||
MD.ClangModuleMapFile = std::string(ModuleMap ? ModuleMap->getName() : "");
|
||||
|
||||
serialization::ModuleFile *MF =
|
||||
MDC.Instance.getASTReader()->getModuleManager().lookup(M->getASTFile());
|
||||
MDC.Instance.getASTReader()->visitInputFiles(
|
||||
*MF, true, true, [&](const serialization::InputFile &IF, bool isSystem) {
|
||||
// __inferred_module.map is the result of the way in which an implicit
|
||||
// module build handles inferred modules. It adds an overlay VFS with
|
||||
// this file in the proper directory and relies on the rest of Clang to
|
||||
// handle it like normal. With explicitly built modules we don't need
|
||||
// to play VFS tricks, so replace it with the correct module map.
|
||||
if (IF.getFile()->getName().endswith("__inferred_module.map")) {
|
||||
MD.FileDeps.insert(ModuleMap->getName());
|
||||
return;
|
||||
}
|
||||
MD.FileDeps.insert(IF.getFile()->getName());
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
typedef int inferred;
|
|
@ -0,0 +1 @@
|
|||
enum { bigger_than_int = 0x80000000 };
|
|
@ -0,0 +1,3 @@
|
|||
framework module System [system] {
|
||||
umbrella header "System.h"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
framework module * {}
|
|
@ -0,0 +1,7 @@
|
|||
[
|
||||
{
|
||||
"directory": "DIR",
|
||||
"command": "clang -E DIR/modules_cdb_input.cpp -FFRAMEWORKS -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -pedantic -Werror",
|
||||
"file": "DIR/modules_cdb_input.cpp"
|
||||
}
|
||||
]
|
|
@ -48,7 +48,6 @@
|
|||
// CHECK: "-emit-module"
|
||||
// CHECK-NO-ABS-NOT: "-fmodule-file={{.*}}"
|
||||
// CHECK-ABS: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[CONTEXT_HASH_H1]]/header2-{{[A-Z0-9]+}}.pcm"
|
||||
// CHECK-NOT: "-fimplicit-module-maps"
|
||||
// CHECK: "-fmodule-name=header1"
|
||||
// CHECK: "-fno-implicit-modules"
|
||||
// CHECK: ],
|
||||
|
@ -65,7 +64,6 @@
|
|||
// CHECK-NEXT: "command-line": [
|
||||
// CHECK-NEXT: "-cc1",
|
||||
// CHECK: "-emit-module",
|
||||
// CHECK-NOT: "-fimplicit-module-maps",
|
||||
// CHECK: "-fmodule-name=header1",
|
||||
// CHECK: "-fno-implicit-modules",
|
||||
// CHECK: ],
|
||||
|
@ -82,7 +80,6 @@
|
|||
// CHECK-NEXT: "command-line": [
|
||||
// CHECK-NEXT: "-cc1",
|
||||
// CHECK: "-emit-module",
|
||||
// CHECK-NOT: "-fimplicit-module-maps",
|
||||
// CHECK: "-fmodule-name=header2",
|
||||
// CHECK: "-fno-implicit-modules",
|
||||
// CHECK: ],
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// RUN: rm -rf %t.dir
|
||||
// RUN: rm -rf %t.cdb
|
||||
// RUN: mkdir -p %t.dir
|
||||
// RUN: cp %s %t.dir/modules_cdb_input.cpp
|
||||
// RUN: sed -e "s|DIR|%/t.dir|g" -e "s|FRAMEWORKS|%/S/Inputs/frameworks|g" -e "s|-E|-x objective-c -E|g" \
|
||||
// RUN: %S/Inputs/modules_inferred_cdb.json > %t.cdb
|
||||
//
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -format experimental-full \
|
||||
// RUN: -mode preprocess-minimized-sources > %t.db
|
||||
// RUN: %python %S/../../utils/module-deps-to-rsp.py %t.db --module-name=Inferred > %t.inferred.cc1.rsp
|
||||
// RUN: %python %S/../../utils/module-deps-to-rsp.py %t.db --module-name=System > %t.system.cc1.rsp
|
||||
// RUN: %python %S/../../utils/module-deps-to-rsp.py %t.db --tu-index=0 > %t.tu.rsp
|
||||
// RUN: %clang @%t.inferred.cc1.rsp -pedantic -Werror
|
||||
// RUN: %clang @%t.system.cc1.rsp -pedantic -Werror
|
||||
// RUN: %clang -x objective-c -fsyntax-only %t.dir/modules_cdb_input.cpp \
|
||||
// RUN: -F%S/Inputs/frameworks -fmodules -fimplicit-module-maps \
|
||||
// RUN: -pedantic -Werror @%t.tu.rsp
|
||||
|
||||
#include <Inferred/Inferred.h>
|
||||
#include <System/System.h>
|
||||
|
||||
inferred a = bigger_than_int;
|
|
@ -0,0 +1,61 @@
|
|||
// RUN: rm -rf %t.dir
|
||||
// RUN: rm -rf %t.cdb
|
||||
// RUN: mkdir -p %t.dir
|
||||
// RUN: cp %s %t.dir/modules_cdb_input.cpp
|
||||
// RUN: sed -e "s|DIR|%/t.dir|g" -e "s|FRAMEWORKS|%/S/Inputs/frameworks|g" \
|
||||
// RUN: %/S/Inputs/modules_inferred_cdb.json > %t.cdb
|
||||
//
|
||||
// RUN: echo -%t.dir > %t.result
|
||||
// RUN: echo -%S >> %t.result
|
||||
// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -format experimental-full \
|
||||
// RUN: -generate-modules-path-args -mode preprocess-minimized-sources >> %t.result
|
||||
// RUN: cat %t.result | sed -e 's/\\\\/\//g' -e 's/\\/\//g' | FileCheck --check-prefixes=CHECK %s
|
||||
|
||||
#include <Inferred/Inferred.h>
|
||||
|
||||
inferred a = 0;
|
||||
|
||||
// CHECK: -[[PREFIX:.*]]
|
||||
// CHECK-NEXT: -[[SOURCEDIR:.*]]
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "modules": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "clang-module-deps": [],
|
||||
// CHECK-NEXT: "clang-modulemap-file": "[[SOURCEDIR]]/Inputs/frameworks/module.modulemap",
|
||||
// CHECK-NEXT: "command-line": [
|
||||
// CHECK-NEXT: "-cc1",
|
||||
// CHECK: "-emit-module",
|
||||
// CHECK: "-fmodule-name=Inferred",
|
||||
// CHECK: "-fno-implicit-modules",
|
||||
// CHECK: ],
|
||||
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H1:[A-Z0-9]+]]",
|
||||
// CHECK-NEXT: "file-deps": [
|
||||
// CHECK-NEXT: "[[SOURCEDIR]]/Inputs/frameworks/Inferred.framework/Frameworks/Sub.framework/Headers/Sub.h",
|
||||
// CHECK-NEXT: "[[SOURCEDIR]]/Inputs/frameworks/Inferred.framework/Headers/Inferred.h",
|
||||
// CHECK-NEXT: "[[SOURCEDIR]]/Inputs/frameworks/module.modulemap"
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "name": "Inferred"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "translation-units": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "clang-context-hash": "[[CONTEXT_HASH_H1]]",
|
||||
// CHECK-NEXT: "clang-module-deps": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H1]]",
|
||||
// CHECK-NEXT: "module-name": "Inferred"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "command-line": [
|
||||
// CHECK-NEXT: "-fno-implicit-modules",
|
||||
// CHECK-NEXT: "-fno-implicit-module-maps",
|
||||
// CHECK-NEXT: "-fmodule-file=[[PREFIX]]/module-cache/[[CONTEXT_HASH_H1]]/Inferred-{{[A-Z0-9]+}}.pcm",
|
||||
// CHECK-NEXT: "-fmodule-map-file=[[SOURCEDIR]]/Inputs/frameworks/module.modulemap"
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "file-deps": [
|
||||
// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Converts clang-scan-deps output into response files.
|
||||
# * For modules, arguments in the resulting response file are enough to build a PCM.
|
||||
# * For translation units, the response file needs to be added to the original Clang invocation from compilation
|
||||
# database.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# clang-scan-deps -compilation-database compile_commands.json ... > deps.json
|
||||
# module-deps-to-rsp.py deps.json --module-name=ModuleName > module_name.cc1.rsp
|
||||
# module-deps-to-rsp.py deps.json --tu-index=0 > tu.rsp
|
||||
# clang @module_name.cc1.rsp
|
||||
# clang ... @tu.rsp
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
|
||||
class ModuleNotFoundError(Exception):
|
||||
def __init__(self, module_name):
|
||||
self.module_name = module_name
|
||||
|
||||
class FullDeps:
|
||||
def __init__(self):
|
||||
self.modules = dict()
|
||||
self.translation_units = str()
|
||||
|
||||
def getModulePathArgs(modules, full_deps):
|
||||
cmd = []
|
||||
for md in modules:
|
||||
m = full_deps.modules[md['module-name'] + '-' + md['context-hash']]
|
||||
cmd += [u'-fmodule-map-file=' + m['clang-modulemap-file']]
|
||||
cmd += [u'-fmodule-file=' + md['module-name'] + '-' + md['context-hash'] + '.pcm']
|
||||
return cmd
|
||||
|
||||
def getCommandLineForModule(module_name, full_deps):
|
||||
for m in full_deps.modules.values():
|
||||
if m['name'] == module_name:
|
||||
module = m
|
||||
break
|
||||
else:
|
||||
raise ModuleNotFoundError(module_name)
|
||||
|
||||
cmd = m['command-line']
|
||||
cmd += getModulePathArgs(m['clang-module-deps'], full_deps)
|
||||
cmd += [u'-o', m['name'] + '-' + m['context-hash'] + '.pcm']
|
||||
cmd += [m['clang-modulemap-file']]
|
||||
|
||||
return cmd
|
||||
|
||||
def getCommandLineForTU(tu, full_deps):
|
||||
cmd = tu['command-line']
|
||||
cmd += getModulePathArgs(tu['clang-module-deps'], full_deps)
|
||||
return cmd
|
||||
|
||||
def parseFullDeps(json):
|
||||
ret = FullDeps()
|
||||
for m in json['modules']:
|
||||
ret.modules[m['name'] + '-' + m['context-hash']] = m
|
||||
ret.translation_units = json['translation-units']
|
||||
return ret
|
||||
|
||||
def quote(str):
|
||||
return '"' + str.replace("\\", "\\\\") + '"'
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("full_deps_file", help="Path to the full dependencies json file",
|
||||
type=str)
|
||||
action = parser.add_mutually_exclusive_group(required=True)
|
||||
action.add_argument("--module-name", help="The name of the module to get arguments for",
|
||||
type=str)
|
||||
action.add_argument("--tu-index", help="The index of the translation unit to get arguments for",
|
||||
type=int)
|
||||
args = parser.parse_args()
|
||||
|
||||
full_deps = parseFullDeps(json.load(open(args.full_deps_file, 'r')))
|
||||
|
||||
try:
|
||||
cmd = []
|
||||
|
||||
if args.module_name:
|
||||
cmd = getCommandLineForModule(args.module_name, full_deps)
|
||||
elif args.tu_index != None:
|
||||
cmd = getCommandLineForTU(full_deps.translation_units[args.tu_index], full_deps)
|
||||
|
||||
print(" ".join(map(quote, cmd)))
|
||||
except:
|
||||
print("Unexpected error:", sys.exc_info()[0])
|
||||
raise
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue