diff --git a/atdna/CMakeLists.txt b/atdna/CMakeLists.txt index 1388281..e3b4397 100644 --- a/atdna/CMakeLists.txt +++ b/atdna/CMakeLists.txt @@ -152,10 +152,16 @@ endif() # Super handy macro for adding atdna target macro(atdna out) + # Ninja wants invocations in root binary dir for DEPFILE application + file(RELATIVE_PATH out_rel ${CMAKE_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/${out}") + # Make input files source-relative set(ins "") + set(ins_impdeps "") foreach(arg ${ARGN}) list(APPEND ins ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) + list(APPEND ins_impdeps CXX) + list(APPEND ins_impdeps ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) endforeach() # Get local include directories for atdna @@ -194,8 +200,22 @@ macro(atdna out) endif() # Make target - add_custom_command(OUTPUT ${out} COMMAND $ - ARGS ${extraargs} -o ${out} ${cdefcli} ${inccli} "-I${ATHENA_INCLUDE_DIR}" - -isystem "${CLANG_INCLUDE_DIR}" ${ins} - DEPENDS ${ins} COMMENT "Generating DNA ${out}") + if(${CMAKE_GENERATOR} STREQUAL "Ninja") + # Use Ninja's DEPFILE parser in cooperation with atdna + add_custom_command(OUTPUT ${out} COMMAND $ + ARGS ${extraargs} -o ${out_rel} -MD -MT ${out_rel} -MF ${out_rel}.d ${cdefcli} ${inccli} + "-I${ATHENA_INCLUDE_DIR}" -isystem "${CLANG_INCLUDE_DIR}" ${ins} + DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} + DEPFILE "${CMAKE_CURRENT_BINARY_DIR}/${out}.d" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating DNA ${out_rel}") + else() + # Use CMake's built-in dependency scanner for makefile targets + add_custom_command(OUTPUT ${out} COMMAND $ + ARGS ${extraargs} -o ${out_rel} ${cdefcli} ${inccli} + "-I${ATHENA_INCLUDE_DIR}" -isystem "${CLANG_INCLUDE_DIR}" ${ins} + DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating DNA ${out_rel}") + endif() endmacro() diff --git a/atdna/atdnaConfig.cmake.in b/atdna/atdnaConfig.cmake.in index d73e53c..5ffad07 100644 --- a/atdna/atdnaConfig.cmake.in +++ b/atdna/atdnaConfig.cmake.in @@ -13,10 +13,16 @@ find_package(Athena REQUIRED) # Super handy macro for adding atdna target macro(atdna out) + # Ninja wants invocations in root binary dir for DEPFILE application + file(RELATIVE_PATH out_rel ${CMAKE_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/${out}") + # Make input files source-relative set(ins "") + set(ins_impdeps "") foreach(arg ${ARGN}) list(APPEND ins ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) + list(APPEND ins_impdeps CXX) + list(APPEND ins_impdeps ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) endforeach() # Get local include directories for atdna @@ -50,9 +56,23 @@ macro(atdna out) endif() # Make target - add_custom_command(OUTPUT ${out} COMMAND $ - ARGS ${extraargs} -o ${out} ${cdefcli} ${inccli} "-I${ATHENA_INCLUDE_DIR}" - -isystem "@CONF_CLANG_INCLUDE_DIR@" ${ins} - DEPENDS ${ins} COMMENT "Generating DNA ${out}") + if(${CMAKE_GENERATOR} STREQUAL "Ninja") + # Use Ninja's DEPFILE parser in cooperation with atdna + add_custom_command(OUTPUT ${out} COMMAND $ + ARGS ${extraargs} -o ${out_rel} -MD -MT ${out_rel} -MF ${out_rel}.d ${cdefcli} ${inccli} + "-I${ATHENA_INCLUDE_DIR}" -isystem "${CLANG_INCLUDE_DIR}" ${ins} + DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} + DEPFILE "${CMAKE_CURRENT_BINARY_DIR}/${out}.d" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating DNA ${out_rel}") + else() + # Use CMake's built-in dependency scanner for makefile targets + add_custom_command(OUTPUT ${out} COMMAND $ + ARGS ${extraargs} -o ${out_rel} ${cdefcli} ${inccli} + "-I${ATHENA_INCLUDE_DIR}" -isystem "${CLANG_INCLUDE_DIR}" ${ins} + DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating DNA ${out_rel}") + endif() endmacro() diff --git a/atdna/main.cpp b/atdna/main.cpp index 820bf6b..41b66e9 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -4,6 +4,7 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/Utils.h" #include "clang/Tooling/Tooling.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" @@ -61,6 +62,14 @@ static llvm::cl::list SystemIncludeSearchPaths("isystem", static llvm::cl::opt StandardCXXLib("stdlib", llvm::cl::desc("Standard C++ library")); +static llvm::cl::opt DepFile("MD", llvm::cl::desc("Make Dependency file")); + +static llvm::cl::opt DepFileOut("MF", + llvm::cl::desc("Dependency file out path")); + +static llvm::cl::list DepFileTargets("MT", + llvm::cl::desc("Dependency file targets")); + static llvm::cl::list SystemIncRoot("isysroot", llvm::cl::desc("System include root")); @@ -2372,11 +2381,20 @@ class ATDNAAction : public clang::ASTFrontendAction return {}; } + std::unique_ptr TheDependencyFileGenerator; + public: - explicit ATDNAAction() {} + explicit ATDNAAction() = default; std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef /*filename*/) { + clang::DependencyOutputOptions DepOpts; + DepOpts.OutputFile = DepFileOut; + DepOpts.Targets = DepFileTargets; + if (!DepOpts.OutputFile.empty()) + TheDependencyFileGenerator.reset( + clang::DependencyFileGenerator::CreateAndAttachToPreprocessor(compiler.getPreprocessor(), DepOpts)); + std::unique_ptr fileout; StreamOut* fileoutOld; if (OutputFilename.size()) @@ -2406,7 +2424,8 @@ int main(int argc, const char** argv) args.push_back(argv[a]); llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); - clang::tooling::ToolInvocation TI(args, new ATDNAAction, fman.get()); + ATDNAAction* action = new ATDNAAction(); + clang::tooling::ToolInvocation TI(args, action, fman.get()); if (!TI.run()) return 1;