Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2024 ChilliBits. All rights reserved. | ||
2 | |||
3 | #include "ExternalLinkerInterface.h" | ||
4 | #include "util/Timer.h" | ||
5 | |||
6 | #include <iostream> | ||
7 | |||
8 | #include <exception/CompilerError.h> | ||
9 | #include <exception/LinkerError.h> | ||
10 | #include <util/FileUtil.h> | ||
11 | |||
12 | namespace spice::compiler { | ||
13 | |||
14 | 178 | void ExternalLinkerInterface::prepare() { | |
15 | // Set target to linker | ||
16 |
2/4✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 178 times.
✗ Branch 5 not taken.
|
178 | addLinkerFlag("--target=" + cliOptions.targetTriple); |
17 | |||
18 | // Static linking | ||
19 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | if (cliOptions.staticLinking) |
20 | ✗ | addLinkerFlag("-static"); | |
21 | |||
22 | // Stripping symbols | ||
23 |
2/2✓ Branch 0 taken 176 times.
✓ Branch 1 taken 2 times.
|
178 | if (!cliOptions.generateDebugInfo) |
24 |
2/4✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 176 times.
✗ Branch 5 not taken.
|
352 | addLinkerFlag("-Wl,-s"); |
25 | |||
26 | // Web Assembly | ||
27 |
3/6✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 178 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 178 times.
|
178 | if (cliOptions.targetArch == TARGET_WASM32 || cliOptions.targetArch == TARGET_WASM64) { |
28 | ✗ | addLinkerFlag("-nostdlib"); | |
29 | ✗ | addLinkerFlag("-Wl,--no-entry"); | |
30 | ✗ | addLinkerFlag("-Wl,--export-all"); | |
31 | } | ||
32 | 178 | } | |
33 | |||
34 | /** | ||
35 | * Start the linking process | ||
36 | */ | ||
37 | 178 | void ExternalLinkerInterface::link() const { | |
38 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 178 times.
|
178 | assert(!outputPath.empty()); |
39 | |||
40 | // Build the linker command | ||
41 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | std::stringstream linkerCommandBuilder; |
42 |
2/4✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 178 times.
✗ Branch 5 not taken.
|
178 | linkerCommandBuilder << FileUtil::findLinkerInvoker(); |
43 |
3/6✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 178 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 178 times.
✗ Branch 8 not taken.
|
178 | linkerCommandBuilder << " -fuse-ld=" << FileUtil::findLinker(); // Select linker |
44 | // Append linker flags | ||
45 |
2/2✓ Branch 5 taken 562 times.
✓ Branch 6 taken 178 times.
|
740 | for (const std::string &linkerFlag : linkerFlags) |
46 |
2/4✓ Branch 1 taken 562 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 562 times.
✗ Branch 5 not taken.
|
562 | linkerCommandBuilder << " " << linkerFlag; |
47 | // Append output path | ||
48 |
3/6✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 178 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 178 times.
✗ Branch 8 not taken.
|
178 | linkerCommandBuilder << " -o " << outputPath.string(); |
49 | // Append object files | ||
50 |
2/2✓ Branch 5 taken 611 times.
✓ Branch 6 taken 178 times.
|
789 | for (const std::string &objectFilePath : objectFilePaths) |
51 |
2/4✓ Branch 1 taken 611 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 611 times.
✗ Branch 5 not taken.
|
611 | linkerCommandBuilder << " " << objectFilePath; |
52 | |||
53 | // Print status message | ||
54 | − | if (cliOptions.printDebugOutput) // GCOV_EXCL_LINE | |
55 | − | std::cout << "\nEmitting executable to path: " << outputPath.string() << "\n"; // GCOV_EXCL_LINE | |
56 | |||
57 | // Call the linker | ||
58 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | Timer timer; |
59 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | timer.start(); |
60 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | const std::string linkerCommand = linkerCommandBuilder.str(); |
61 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | const auto [output, exitCode] = FileUtil::exec(linkerCommand); |
62 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | timer.stop(); |
63 | |||
64 | // Check for linker error | ||
65 | − | if (exitCode != 0) // GCOV_EXCL_LINE | |
66 | − | throw LinkerError(LINKER_ERROR, "Linker exited with non-zero exit code"); // GCOV_EXCL_LINE | |
67 | |||
68 | // Print linker result if appropriate | ||
69 | − | if (cliOptions.printDebugOutput && !output.empty()) // GCOV_EXCL_LINE | |
70 | − | std::cout << "Linking result: " << output << "\n\n"; // GCOV_EXCL_LINE | |
71 | |||
72 | // Print link time | ||
73 | − | if (cliOptions.printDebugOutput) // GCOV_EXCL_LINE | |
74 | − | std::cout << "Total link time: " << timer.getDurationMilliseconds() << " ms\n\n"; // GCOV_EXCL_LINE | |
75 | 178 | } | |
76 | |||
77 | /** | ||
78 | * Add another object file to be linked when calling 'link()' | ||
79 | * | ||
80 | * @param objectFilePath Path to the object file | ||
81 | */ | ||
82 | 642 | void ExternalLinkerInterface::addObjectFilePath(const std::string &objectFilePath) { objectFilePaths.push_back(objectFilePath); } | |
83 | |||
84 | /** | ||
85 | * Add another linker flag for the call to the linker executable | ||
86 | * | ||
87 | * @param flag Linker flag | ||
88 | */ | ||
89 | 563 | void ExternalLinkerInterface::addLinkerFlag(const std::string &flag) { linkerFlags.push_back(flag); } | |
90 | |||
91 | /** | ||
92 | * Add another source file to compile and link in (C or C++) | ||
93 | * | ||
94 | * @param additionalSource Additional source file | ||
95 | */ | ||
96 | 1 | void ExternalLinkerInterface::addAdditionalSourcePath(std::filesystem::path additionalSource) { | |
97 | // Check if the file exists | ||
98 | − | if (!exists(additionalSource)) { // GCOV_EXCL_LINE | |
99 | − | const std::string msg = "The additional source file '" + additionalSource.string() + "' does not exist"; // GCOV_EXCL_LINE | |
100 | − | throw CompilerError(IO_ERROR, msg); // GCOV_EXCL_LINE | |
101 | − | } // GCOV_EXCL_LINE | |
102 | |||
103 | // Add the file to the linker | ||
104 | 1 | additionalSource.make_preferred(); | |
105 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | addObjectFilePath(additionalSource.string()); |
106 | 1 | } | |
107 | |||
108 | } // namespace spice::compiler | ||
109 |