@@ -918,6 +918,7 @@ static void readConfigs(opt::InputArgList &args) {
918
918
config->optimizeBBJumps =
919
919
args.hasFlag (OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false );
920
920
config->demangle = args.hasFlag (OPT_demangle, OPT_no_demangle, true );
921
+ config->dependencyFile = args.getLastArgValue (OPT_dependency_file);
921
922
config->dependentLibraries = args.hasFlag (OPT_dependent_libraries, OPT_no_dependent_libraries, true );
922
923
config->disableVerify = args.hasArg (OPT_disable_verify);
923
924
config->discard = getDiscard (args);
@@ -1564,6 +1565,75 @@ static void handleLibcall(StringRef name) {
1564
1565
sym->fetch ();
1565
1566
}
1566
1567
1568
+ // Handle --dependency-file=<path>. If that option is given, lld creates a
1569
+ // file at a given path with the following contents:
1570
+ //
1571
+ // <output-file>: <input-file> ...
1572
+ //
1573
+ // <input-file>:
1574
+ //
1575
+ // where <output-file> is a pathname of an output file and <input-file>
1576
+ // ... is a list of pathnames of all input files. `make` command can read a
1577
+ // file in the above format and interpret it as a dependency info. We write
1578
+ // phony targets for every <input-file> to avoid an error when that file is
1579
+ // removed.
1580
+ //
1581
+ // This option is useful if you want to make your final executable to depend
1582
+ // on all input files including system libraries. Here is why.
1583
+ //
1584
+ // When you write a Makefile, you usually write it so that the final
1585
+ // executable depends on all user-generated object files. Normally, you
1586
+ // don't make your executable to depend on system libraries (such as libc)
1587
+ // because you don't know the exact paths of libraries, even though system
1588
+ // libraries that are linked to your executable statically are technically a
1589
+ // part of your program. By using --dependency-file option, you can make
1590
+ // lld to dump dependency info so that you can maintain exact dependencies
1591
+ // easily.
1592
+ static void writeDependencyFile () {
1593
+ std::error_code ec;
1594
+ raw_fd_ostream os (config->dependencyFile , ec, sys::fs::F_None);
1595
+ if (ec) {
1596
+ error (" cannot open " + config->dependencyFile + " : " + ec.message ());
1597
+ return ;
1598
+ }
1599
+
1600
+ // We use the same escape rules as Clang/GCC which are accepted by Make/Ninja:
1601
+ // * A space is escaped by a backslash which itself must be escaped.
1602
+ // * A hash sign is escaped by a single backslash.
1603
+ // * $ is escapes as $$.
1604
+ auto printFilename = [](raw_fd_ostream &os, StringRef filename) {
1605
+ llvm::SmallString<256 > nativePath;
1606
+ llvm::sys::path::native (filename.str (), nativePath);
1607
+ llvm::sys::path::remove_dots (nativePath, /* remove_dot_dot=*/ true );
1608
+ for (unsigned i = 0 , e = nativePath.size (); i != e; ++i) {
1609
+ if (nativePath[i] == ' #' ) {
1610
+ os << ' \\ ' ;
1611
+ } else if (nativePath[i] == ' ' ) {
1612
+ os << ' \\ ' ;
1613
+ unsigned j = i;
1614
+ while (j > 0 && nativePath[--j] == ' \\ ' )
1615
+ os << ' \\ ' ;
1616
+ } else if (nativePath[i] == ' $' ) {
1617
+ os << ' $' ;
1618
+ }
1619
+ os << nativePath[i];
1620
+ }
1621
+ };
1622
+
1623
+ os << config->outputFile << " :" ;
1624
+ for (StringRef path : config->dependencyFiles ) {
1625
+ os << " \\\n " ;
1626
+ printFilename (os, path);
1627
+ }
1628
+ os << " \n " ;
1629
+
1630
+ for (StringRef path : config->dependencyFiles ) {
1631
+ os << " \n " ;
1632
+ printFilename (os, path);
1633
+ os << " :\n " ;
1634
+ }
1635
+ }
1636
+
1567
1637
// Replaces common symbols with defined symbols reside in .bss sections.
1568
1638
// This function is called after all symbol names are resolved. As a
1569
1639
// result, the passes after the symbol resolution won't see any
@@ -2064,6 +2134,11 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
2064
2134
return false ;
2065
2135
});
2066
2136
2137
+ // Since we now have a complete set of input files, we can create
2138
+ // a .d file to record build dependencies.
2139
+ if (!config->dependencyFile .empty ())
2140
+ writeDependencyFile ();
2141
+
2067
2142
// Now that the number of partitions is fixed, save a pointer to the main
2068
2143
// partition.
2069
2144
mainPart = &partitions[0 ];
0 commit comments