Add "-M" dependency generation to Slang.
Change-Id: I26d1daf1005de7b3ad297fba5ad0d85a1aab1e45
diff --git a/Android.mk b/Android.mk
index fd7b60f..7c2b9ff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -104,6 +104,7 @@
libclangLex \
libclangCodeGen \
libclangBasic \
+ libclangFrontend \
libLLVMSupport \
libLLVMSystem
diff --git a/slang.cpp b/slang.cpp
index 725b7c1..2744b05 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -14,6 +14,10 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
@@ -277,11 +281,12 @@
bool Slang::setOutput(const char *OutputFile) {
std::string Error;
- _mkdir_given_a_file(OutputFile);
switch (mOT) {
+ case OT_Dependency:
case OT_Assembly:
case OT_LLVMAssembly: {
+ _mkdir_given_a_file(OutputFile);
mOS.reset(new llvm::raw_fd_ostream(OutputFile, Error, 0));
break;
}
@@ -290,13 +295,16 @@
break;
}
case OT_Object:
- case OT_Bitcode:
- default: {
+ case OT_Bitcode: {
+ _mkdir_given_a_file(OutputFile);
mOS.reset(new llvm::raw_fd_ostream(OutputFile,
Error,
llvm::raw_fd_ostream::F_Binary));
break;
}
+ default:
+ llvm_unreachable("Unknown compiler output type");
+ break;
}
if (!Error.empty()) {
@@ -311,7 +319,48 @@
return true;
}
+bool Slang::setDepTargetBC(const char *targetBCFile) {
+ mDepTargetBCFileName = targetBCFile;
+
+ return true;
+}
+
+int Slang::generateDepFile() {
+ if((mDiagnostics->getNumErrors() > 0) || (mOS.get() == NULL))
+ return mDiagnostics->getNumErrors();
+
+ /* Initialize options for generating dependency file */
+ clang::DependencyOutputOptions DepOpts;
+ DepOpts.IncludeSystemHeaders = 1;
+ DepOpts.OutputFile = mOutputFileName;
+ DepOpts.Targets.push_back(mDepTargetBCFileName);
+
+ /* Per-compilation needed initialization */
+ createPreprocessor();
+ AttachDependencyFileGen(*mPP.get(), DepOpts);
+
+ /* Inform the diagnostic client we are processing a source file */
+ mDiagClient->BeginSourceFile(LangOpts, mPP.get());
+
+ /* Go through the source file (no operations necessary) */
+ clang::Token Tok;
+ mPP->EnterMainSourceFile();
+ do {
+ mPP->Lex(Tok);
+ } while (Tok.isNot(clang::tok::eof));
+
+ mPP->EndSourceFile();
+
+ /* Clean up after compilation */
+ mPP.reset();
+
+ return mDiagnostics->getNumErrors();
+}
+
int Slang::compile() {
+ if (mOT == OT_Dependency)
+ return generateDepFile();
+
if ((mDiagnostics->getNumErrors() > 0) || (mOS.get() == NULL))
return mDiagnostics->getNumErrors();
diff --git a/slang.h b/slang.h
index 84b94d3..a528a6c 100644
--- a/slang.h
+++ b/slang.h
@@ -46,6 +46,7 @@
public:
typedef enum {
+ OT_Dependency,
OT_Assembly,
OT_LLVMAssembly,
OT_Bitcode,
@@ -92,6 +93,7 @@
// Input file name
std::string mInputFileName;
std::string mOutputFileName;
+ std::string mDepTargetBCFileName;
OutputType mOT;
@@ -147,6 +149,9 @@
return mOutputFileName;
}
+ bool setDepTargetBC(const char *targetBCFile);
+
+ int generateDepFile();
int compile();
inline const char *getErrorMessage() { return mDiagClient->str().c_str(); }
diff --git a/slang_driver.cpp b/slang_driver.cpp
index a3cbdba..34426fa 100644
--- a/slang_driver.cpp
+++ b/slang_driver.cpp
@@ -189,6 +189,7 @@
static std::string* InputFileNames;
static std::string* OutputFileNames;
+static std::string* DepTargetBCFileNames;
// Where to store the bc file.
// possible values:
@@ -213,6 +214,7 @@
{ "emit-llvm", no_argument, (int*) &OutputFileType, Slang::OT_LLVMAssembly },
{ "emit-bc", no_argument, (int*) &OutputFileType, Slang::OT_Bitcode },
{ "emit-asm", no_argument, NULL, 'S' },
+ { "emit-dep", no_argument, (int*) &OutputFileType, Slang::OT_Dependency },
{ "emit-obj", no_argument, NULL, 'c' },
{ "emit-nothing", no_argument, (int*) &OutputFileType, Slang::OT_Nothing },
@@ -271,8 +273,11 @@
extern int opterr;
static int FileCount;
-static int AddOutputFileSuffix(std::string &pathFile) {
- switch (OutputFileType) {
+static int AddFileSuffix(std::string &pathFile, Slang::OutputType type) {
+ switch (type) {
+ case Slang::OT_Dependency:
+ pathFile += ".d";
+ break;
case Slang::OT_Assembly:
pathFile += ".S";
break;
@@ -311,6 +316,7 @@
InputFileNames = NULL;
OutputFileNames = NULL;
+ DepTargetBCFileNames = NULL;
Verbose = false;
FeatureEnabledList[0] = NULL;
@@ -328,8 +334,12 @@
/* Turn off the error message output by getopt_long */
opterr = 0;
- while((ch = getopt_long(Argc, Argv, "Schvo:u:t:j:p:I:s:", SlangOpts, NULL)) != -1) {
+ while((ch = getopt_long(Argc, Argv, "MSchvo:u:t:j:p:I:s:", SlangOpts, NULL)) != -1) {
switch(ch) {
+ case 'M':
+ OutputFileType = Slang::OT_Dependency;
+ break;
+
case 'S':
OutputFileType = Slang::OT_Assembly;
break;
@@ -479,12 +489,14 @@
FileCount = Argc;
InputFileNames = new std::string[FileCount];
OutputFileNames = new std::string[FileCount];
+ DepTargetBCFileNames = new std::string[FileCount];
int count;
for (count = 0; count < FileCount; count++) {
InputFileNames[count].assign(Argv[optind + count]);
if ( OutputPathName && !strcmp(OutputPathName, "-") ) {
OutputFileNames[count].assign("stdout");
+ DepTargetBCFileNames[count].assign("stdout");
continue;
}
@@ -497,14 +509,23 @@
}
_outF += slang::RSSlangReflectUtils::BCFileNameFromRSFileName(
InputFileNames[count].c_str());
+ std::string _outD(_outF);
- int status = AddOutputFileSuffix(_outF);
+ int status = AddFileSuffix(_outF, OutputFileType);
+
if (status < 0) {
return false;
} else if (!status) {
OutputFileNames[count].assign("/dev/null");
+ DepTargetBCFileNames[count].assign("/dev/null");
} else {
OutputFileNames[count].assign(_outF);
+ if (OutputFileType == Slang::OT_Dependency) {
+ if (AddFileSuffix(_outD, Slang::OT_Bitcode) <= 0) {
+ return false;
+ }
+ DepTargetBCFileNames[count].assign(_outD);
+ }
}
}
@@ -532,6 +553,7 @@
cout << "Output to: " << ((strcmp(OutputPathName, "-")) ? OutputPathName : "(standard output)") << ", type: ";
switch(OutputFileType) {
+ case Slang::OT_Dependency: cout << "Dependencies"; break;
case Slang::OT_Assembly: cout << "Target Assembly"; break;
case Slang::OT_LLVMAssembly: cout << "LLVM Assembly"; break;
case Slang::OT_Bitcode: cout << "Bitcode"; break;
@@ -710,6 +732,7 @@
std::string beforeLink;
if (NoLink) {
SLANG_CALL_AND_CHECK( slang->setOutput(OutputFileNames[count].c_str()) );
+ SLANG_CALL_AND_CHECK( slang->setDepTargetBC(DepTargetBCFileNames[count].c_str()) );
} else {
std::string stem = slang::RSSlangReflectUtils::BCFileNameFromRSFileName(
InputFileNames[count].c_str());
@@ -725,6 +748,7 @@
beforeLink.assign(tmpFileName);
SLANG_CALL_AND_CHECK( slang->setOutput(beforeLink.c_str()) );
+ SLANG_CALL_AND_CHECK( slang->setDepTargetBC(beforeLink.c_str()) );
}
SLANG_CALL_AND_CHECK( slang->compile() <= 0 );
@@ -733,11 +757,14 @@
if(slang->getErrorMessage())
cout << slang->getErrorMessage();
- SLANG_CALL_AND_CHECK( slang->reflectToJavaPath(JavaReflectionPathName) );
-
char realPackageName[0x100];
- SLANG_CALL_AND_CHECK( slang->reflectToJava(JavaReflectionPackageName,
- realPackageName, sizeof(realPackageName)));
+
+ if (OutputFileType != Slang::OT_Dependency) {
+ SLANG_CALL_AND_CHECK( slang->reflectToJavaPath(JavaReflectionPathName) );
+
+ SLANG_CALL_AND_CHECK( slang->reflectToJava(JavaReflectionPackageName,
+ realPackageName, sizeof(realPackageName)));
+ }
if (NoLink) {
goto generate_bitcode_accessor;
@@ -839,7 +866,7 @@
OUTPUT_OPTION("-o", "--output-obj-path=<PATH>", "Write compilation output at this path ('-' means stdout)");
OUTPUT_OPTION("-j", "--output-java-reflection-class=<PACKAGE NAME>", "Output reflection of exportables in the native domain into Java");
OUTPUT_OPTION("-p", "--output-java-reflection-path=<PATH>", "Write reflection output at this path");
- OUTPUT_OPTION("-I", "--include-path=<PATH>", "Add a hearder search path");
+ OUTPUT_OPTION("-I", "--include-path=<PATH>", "Add a header search path");
OUTPUT_OPTION("-s", "--bitcode-storage=<VALUE>", "Where to store the bc file. 'ar' means apk resource, 'jc' means Java code.");
cout << endl;
@@ -849,6 +876,7 @@
OUTPUT_OPTION(NULL, "--emit-llvm", "Set output type to LLVM assembly (.ll)");
OUTPUT_OPTION(NULL, "--emit-bc", "Set output type to Bitcode (.bc) (Default)");
OUTPUT_OPTION("-S", "--emit-asm", "Set output type to target assmbly code (.S)");
+ OUTPUT_OPTION("-M", "--emit-dep", "Set output type to Make dependency (.d)");
OUTPUT_OPTION("-c", "--emit-obj", "Set output type to target object file (.o)");
OUTPUT_OPTION(NULL, "--emit-nothing", "Output nothing");