| // UNSUPPORTED: target={{.*}}-aix{{.*}} |
| // |
| // The slash direction in linux and windows are different. |
| // UNSUPPORTED: system-windows |
| // |
| // RUN: rm -fr %t |
| // RUN: mkdir -p %t |
| // RUN: split-file %s %t |
| // |
| // RUN: sed "s|DIR|%/t|g" %t/P1689.json.in > %t/P1689.json |
| // RUN: clang-scan-deps -compilation-database %t/P1689.json -format=p1689 | FileCheck %t/Checks.cpp -DPREFIX=%/t |
| // RUN: clang-scan-deps --mode=preprocess-dependency-directives -compilation-database %t/P1689.json -format=p1689 | FileCheck %t/Checks.cpp -DPREFIX=%/t |
| // |
| // Check the separated dependency format. This is required by CMake for the case |
| // that we have non-exist files in a fresh build and potentially out-of-date after that. |
| // So the build system need to wrtie a compilation database just for scanning purposes, |
| // which is not so good. So here is the per file mode for P1689. |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/M.cppm -o %t/M.o \ |
| // RUN: | FileCheck %t/M.cppm -DPREFIX=%/t |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/Impl.cpp -o %t/Impl.o \ |
| // RUN: | FileCheck %t/Impl.cpp -DPREFIX=%/t |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/impl_part.cppm -o %t/impl_part.o \ |
| // RUN: | FileCheck %t/impl_part.cppm -DPREFIX=%/t |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/interface_part.cppm -o %t/interface_part.o \ |
| // RUN: | FileCheck %t/interface_part.cppm -DPREFIX=%/t |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/User.cpp -o %t/User.o \ |
| // RUN: | FileCheck %t/User.cpp -DPREFIX=%/t |
| // |
| // Check we can generate the make-style dependencies as expected. |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/impl_part.cppm -o %t/impl_part.o \ |
| // RUN: -MT %t/impl_part.o.ddi -MD -MF %t/impl_part.dep |
| // RUN: cat %t/impl_part.dep | FileCheck %t/impl_part.cppm -DPREFIX=%/t --check-prefix=CHECK-MAKE |
| // |
| // Check that we can generate multiple make-style dependency information with compilation database. |
| // RUN: cat %t/P1689.dep | FileCheck %t/Checks.cpp -DPREFIX=%/t --check-prefix=CHECK-MAKE |
| // |
| // Check that we can mix the use of -format=p1689 and -fmodules. |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -c %t/impl_part.cppm -o %t/impl_part.o \ |
| // RUN: | FileCheck %t/impl_part.cppm -DPREFIX=%/t |
| // |
| // Check the path in the make style dependencies are generated in relative path form |
| // RUN: cd %t |
| // RUN: clang-scan-deps -format=p1689 \ |
| // RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t impl_part.cppm -o impl_part.o \ |
| // RUN: -MT impl_part.o.ddi -MD -MF impl_part.dep |
| // RUN: cat impl_part.dep | FileCheck impl_part.cppm -DPREFIX=%/t --check-prefix=CHECK-MAKE-RELATIVE |
| |
| |
| //--- P1689.json.in |
| [ |
| { |
| "directory": "DIR", |
| "command": "clang++ -std=c++20 DIR/M.cppm -c -o DIR/M.o -MT DIR/M.o.ddi -MD -MF DIR/P1689.dep", |
| "file": "DIR/M.cppm", |
| "output": "DIR/M.o" |
| }, |
| { |
| "directory": "DIR", |
| "command": "clang++ -std=c++20 DIR/Impl.cpp -c -o DIR/Impl.o -MT DIR/Impl.o.ddi -MD -MF DIR/P1689.dep", |
| "file": "DIR/Impl.cpp", |
| "output": "DIR/Impl.o" |
| }, |
| { |
| "directory": "DIR", |
| "command": "clang++ -std=c++20 DIR/impl_part.cppm -c -o DIR/impl_part.o -MT DIR/impl_part.o.ddi -MD -MF DIR/P1689.dep", |
| "file": "DIR/impl_part.cppm", |
| "output": "DIR/impl_part.o" |
| }, |
| { |
| "directory": "DIR", |
| "command": "clang++ -std=c++20 DIR/interface_part.cppm -c -o DIR/interface_part.o -MT DIR/interface_part.o.ddi -MD -MF DIR/P1689.dep", |
| "file": "DIR/interface_part.cppm", |
| "output": "DIR/interface_part.o" |
| }, |
| { |
| "directory": "DIR", |
| "command": "clang++ -std=c++20 DIR/User.cpp -c -o DIR/User.o -MT DIR/User.o.ddi -MD -MF DIR/P1689.dep", |
| "file": "DIR/User.cpp", |
| "output": "DIR/User.o" |
| } |
| ] |
| |
| //--- M.cppm |
| export module M; |
| export import :interface_part; |
| import :impl_part; |
| export void Hello(); |
| |
| // CHECK: { |
| // CHECK-NEXT: "revision": 0, |
| // CHECK-NEXT: "rules": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/M.o", |
| // CHECK-NEXT: "provides": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "is-interface": true, |
| // CHECK-NEXT: "logical-name": "M", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/M.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M:interface_part" |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M:impl_part" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "version": 1 |
| // CHECK-NEXT: } |
| |
| //--- Impl.cpp |
| module; |
| #include "header.mock" |
| module M; |
| void Hello() { |
| std::cout << "Hello "; |
| } |
| |
| // CHECK: { |
| // CHECK-NEXT: "revision": 0, |
| // CHECK-NEXT: "rules": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/Impl.o", |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "version": 1 |
| // CHECK-NEXT: } |
| |
| //--- impl_part.cppm |
| module; |
| #include "header.mock" |
| module M:impl_part; |
| import :interface_part; |
| |
| std::string W = "World."; |
| void World() { |
| std::cout << W << std::endl; |
| } |
| |
| // CHECK: { |
| // CHECK-NEXT: "revision": 0, |
| // CHECK-NEXT: "rules": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/impl_part.o", |
| // CHECK-NEXT: "provides": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "is-interface": false, |
| // CHECK-NEXT: "logical-name": "M:impl_part", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/impl_part.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M:interface_part" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "version": 1 |
| // CHECK-NEXT: } |
| |
| // CHECK-MAKE: [[PREFIX]]/impl_part.o.ddi: |
| // CHECK-MAKE: [[PREFIX]]/impl_part.cppm |
| // CHECK-MAKE: [[PREFIX]]/header.mock |
| |
| // CHECK-MAKE-RELATIVE: impl_part.o.ddi: impl_part.cppm header.mock |
| |
| //--- interface_part.cppm |
| export module M:interface_part; |
| export void World(); |
| |
| // CHECK: { |
| // CHECK-NEXT: "revision": 0, |
| // CHECK-NEXT: "rules": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/interface_part.o", |
| // CHECK-NEXT: "provides": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "is-interface": true, |
| // CHECK-NEXT: "logical-name": "M:interface_part", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/interface_part.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "version": 1 |
| // CHECK-NEXT: } |
| |
| //--- User.cpp |
| import M; |
| import third_party_module; |
| int main() { |
| Hello(); |
| World(); |
| return 0; |
| } |
| |
| // CHECK: { |
| // CHECK-NEXT: "revision": 0, |
| // CHECK-NEXT: "rules": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/User.o", |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M" |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "third_party_module" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "version": 1 |
| // CHECK-NEXT: } |
| |
| //--- Checks.cpp |
| // CHECK: { |
| // CHECK-NEXT: "revision": 0, |
| // CHECK-NEXT: "rules": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/Impl.o", |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/M.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/M.o", |
| // CHECK-NEXT: "provides": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "is-interface": true, |
| // CHECK-NEXT: "logical-name": "M", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/M.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M:interface_part", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/interface_part.cppm" |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M:impl_part", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/impl_part.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/User.o", |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/M.cppm" |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "third_party_module" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/impl_part.o", |
| // CHECK-NEXT: "provides": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "is-interface": false, |
| // CHECK-NEXT: "logical-name": "M:impl_part", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/impl_part.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "requires": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "logical-name": "M:interface_part", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/interface_part.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: }, |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "primary-output": "[[PREFIX]]/interface_part.o", |
| // CHECK-NEXT: "provides": [ |
| // CHECK-NEXT: { |
| // CHECK-NEXT: "is-interface": true, |
| // CHECK-NEXT: "logical-name": "M:interface_part", |
| // CHECK-NEXT: "source-path": "[[PREFIX]]/interface_part.cppm" |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ] |
| // CHECK-NEXT: } |
| // CHECK-NEXT: ], |
| // CHECK-NEXT: "version": 1 |
| // CHECK-NEXT: } |
| |
| // CHECK-MAKE-DAG: [[PREFIX]]/impl_part.o.ddi: \ |
| // CHECK-MAKE-DAG-NEXT: [[PREFIX]]/impl_part.cppm \ |
| // CHECK-MAKE-DAG-NEXT: [[PREFIX]]/header.mock |
| // CHECK-MAKE-DAG: [[PREFIX]]/interface_part.o.ddi: \ |
| // CHECK-MAKE-DAG-NEXT: [[PREFIX]]/interface_part.cppm |
| // CHECK-MAKE-DAG: [[PREFIX]]/M.o.ddi: \ |
| // CHECK-MAKE-DAG-NEXT: [[PREFIX]]/M.cppm |
| // CHECK-MAKE-DAG: [[PREFIX]]/User.o.ddi: \ |
| // CHECK-MAKE-DAG-NEXT: [[PREFIX]]/User.cpp |
| // CHECK-MAKE-DAG: [[PREFIX]]/Impl.o.ddi: \ |
| // CHECK-MAKE-DAG-NEXT: [[PREFIX]]/Impl.cpp \ |
| // CHECK-MAKE-DAG-NEXT: [[PREFIX]]/header.mock |
| |
| //--- module.modulemap |
| module Mock { header "header.mock" } |
| |
| //--- header.mock |