Skip to content

Commit f06abbb

Browse files
llvm-beanzabrachet
authored andcommitted
LLVM Driver Multicall tool
This patch adds an llvm-driver multicall tool that can combine multiple LLVM-based tools. The build infrastructure is enabled for a tool by adding the GENERATE_DRIVER option to the add_llvm_executable CMake call, and changing the tool's main function to a canonicalized tool_name_main format (i.e. llvm_ar_main, clang_main, etc...). As currently implemented llvm-driver contains dsymutil, llvm-ar, llvm-cxxfilt, llvm-objcopy, and clang (if clang is included in the build). llvm-driver can be enabled from builds by setting LLVM_TOOL_LLVM_DRIVER_BUILD=On. There are several limitations in the current implementation, which can be addressed in subsequent patches: (1) the multicall binary cannot currently properly handle multi-dispatch tools. This means symlinking llvm-ranlib to llvm-driver will not properly result in llvm-ar's main being called. (2) the multicall binary cannot be comprised of tools containing conflicting cl::opt options as the global cl::opt option list cannot contain duplicates. These limitations can be addressed in subsequent patches. Differential revision: https://reviews.llvm.org/D109977
1 parent c2d27c8 commit f06abbb

File tree

28 files changed

+275
-14
lines changed

28 files changed

+275
-14
lines changed

clang/cmake/modules/AddClang.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,5 +184,8 @@ function(clang_target_link_libraries target type)
184184
else()
185185
target_link_libraries(${target} ${type} ${ARGN})
186186
endif()
187+
if (TARGET obj.${target})
188+
target_link_libraries(obj.${target} ${ARGN})
189+
endif()
187190

188191
endfunction()

clang/tools/driver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ add_clang_tool(clang
3131
DEPENDS
3232
intrinsics_gen
3333
${support_plugins}
34+
GENERATE_DRIVER
3435
)
3536

3637
clang_target_link_libraries(clang

clang/tools/driver/driver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV) {
327327
return 1;
328328
}
329329

330-
int main(int Argc, const char **Argv) {
330+
int clang_main(int Argc, char **Argv) {
331331
noteBottomOfStack();
332332
llvm::InitLLVM X(Argc, Argv);
333333
llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL

llvm/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ include(VersionFromVCS)
269269
option(LLVM_APPEND_VC_REV
270270
"Embed the version control system revision in LLVM" ON)
271271

272+
option(LLVM_TOOL_LLVM_DRIVER_BUILD "Enables building the llvm multicall tool" OFF)
273+
272274
set(PACKAGE_NAME LLVM)
273275
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
274276
set(PACKAGE_BUGREPORT "https://github.com/llvm/llvm-project/issues/")

llvm/cmake/driver-template.cpp.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//===-- driver-template.cpp -----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
int @TOOL_NAME@_main(int argc, char **argv);
10+
11+
int main(int argc, char **argv) { return @TOOL_NAME@_main(argc, argv); }

llvm/cmake/modules/AddLLVM.cmake

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ endmacro(add_llvm_library name)
859859

860860
macro(add_llvm_executable name)
861861
cmake_parse_arguments(ARG
862-
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS"
862+
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS;GENERATE_DRIVER"
863863
"ENTITLEMENTS;BUNDLE_PATH"
864864
"DEPENDS"
865865
${ARGN})
@@ -869,7 +869,7 @@ macro(add_llvm_executable name)
869869
list(APPEND LLVM_COMMON_DEPENDS ${ARG_DEPENDS})
870870

871871
# Generate objlib
872-
if(LLVM_ENABLE_OBJLIB)
872+
if(LLVM_ENABLE_OBJLIB OR ARG_GENERATE_DRIVER)
873873
# Generate an obj library for both targets.
874874
set(obj_name "obj.${name}")
875875
add_library(${obj_name} OBJECT EXCLUDE_FROM_ALL
@@ -884,6 +884,23 @@ macro(add_llvm_executable name)
884884
set_target_properties(${obj_name} PROPERTIES FOLDER "Object Libraries")
885885
endif()
886886

887+
if (ARG_GENERATE_DRIVER)
888+
string(REPLACE "-" "_" TOOL_NAME ${name})
889+
configure_file(
890+
${LLVM_MAIN_SRC_DIR}/cmake/driver-template.cpp.in
891+
${CMAKE_CURRENT_BINARY_DIR}/${name}-driver.cpp)
892+
893+
list(APPEND ALL_FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-driver.cpp)
894+
895+
set_property(GLOBAL APPEND PROPERTY LLVM_DRIVER_COMPONENTS ${LLVM_LINK_COMPONENTS})
896+
set_property(GLOBAL APPEND PROPERTY LLVM_DRIVER_DEPS ${ARG_DEPENDS} ${LLVM_COMMON_DEPENDS})
897+
set_property(GLOBAL APPEND PROPERTY LLVM_DRIVER_OBJLIBS "${obj_name}")
898+
899+
set_property(GLOBAL APPEND PROPERTY LLVM_DRIVER_TOOLS ${name})
900+
target_link_libraries(${obj_name} ${LLVM_PTHREAD_LIB})
901+
llvm_config(${obj_name} ${USE_SHARED} ${LLVM_LINK_COMPONENTS} )
902+
endif()
903+
887904
add_windows_version_resource_file(ALL_FILES ${ALL_FILES})
888905

889906
if(XCODE)
@@ -1449,6 +1466,12 @@ function(llvm_add_implicit_projects project)
14491466
foreach(dir ${sub-dirs})
14501467
if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt")
14511468
canonicalize_tool_name(${dir} name)
1469+
# I don't like special casing things by order, but the llvm-driver ends up
1470+
# linking the object libraries from all the tools that opt-in, so adding
1471+
# it separately at the end is probably the simplest case.
1472+
if("${name}" STREQUAL "LLVM_DRIVER")
1473+
continue()
1474+
endif()
14521475
if (${project}_TOOL_${name}_BUILD)
14531476
get_filename_component(fn "${dir}" NAME)
14541477
list(APPEND list_of_implicit_subdirs "${fn}")
@@ -1998,6 +2021,16 @@ endfunction()
19982021

19992022
function(add_llvm_tool_symlink link_name target)
20002023
cmake_parse_arguments(ARG "ALWAYS_GENERATE" "OUTPUT_DIR" "" ${ARGN})
2024+
2025+
get_property(LLVM_DRIVER_TOOLS GLOBAL PROPERTY LLVM_DRIVER_TOOLS)
2026+
2027+
if (${target} IN_LIST LLVM_DRIVER_TOOLS)
2028+
string(REPLACE "-" "_" tool_entry ${target})
2029+
string(REPLACE "-" "_" key ${link_name})
2030+
string(REPLACE "llvm-" "" tool_name ${link_name})
2031+
set_property(GLOBAL APPEND_STRING PROPERTY
2032+
LLVM_EXTRA_DRIVER_ENTRIES "LLVM_DRIVER_TOOL(\"${tool_name}\", ${tool_entry})\n")
2033+
endif()
20012034
set(dest_binary "$<TARGET_FILE:${target}>")
20022035

20032036
# This got a bit gross... For multi-configuration generators the target

llvm/lib/Support/Path.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,9 +1202,18 @@ Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl<char> &Buffer,
12021202
#include "Windows/Path.inc"
12031203
#endif
12041204

1205+
bool IsLLVMDriver = false;
1206+
12051207
namespace llvm {
12061208
namespace sys {
12071209
namespace fs {
1210+
1211+
std::string getMainExecutable(const char *Argv0, void *MainAddr) {
1212+
if (IsLLVMDriver)
1213+
return sys::path::stem(Argv0).str();
1214+
return getMainExecutableImpl(Argv0, MainAddr);
1215+
}
1216+
12081217
TempFile::TempFile(StringRef Name, int FD)
12091218
: TmpName(std::string(Name)), FD(FD) {}
12101219
TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }

llvm/lib/Support/Unix/Path.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ getprogpath(char ret[PATH_MAX], const char *bin)
194194

195195
/// GetMainExecutable - Return the path to the main executable, given the
196196
/// value of argv[0] from program startup.
197-
std::string getMainExecutable(const char *argv0, void *MainAddr) {
197+
std::string getMainExecutableImpl(const char *argv0, void *MainAddr) {
198198
#if defined(__APPLE__)
199199
// On OS X the executable path is saved to the stack by dyld. Reading it
200200
// from there is much faster than calling dladdr, especially for large

llvm/lib/Support/Windows/Path.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ namespace fs {
130130

131131
const file_t kInvalidFile = INVALID_HANDLE_VALUE;
132132

133-
std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
133+
std::string getMainExecutableImpl(const char *argv0, void *MainExecAddr) {
134134
SmallVector<wchar_t, MAX_PATH> PathName;
135135
PathName.resize_for_overwrite(PathName.capacity());
136136
DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.size());

llvm/test/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ llvm_canonicalize_cmake_booleans(
2121
LLVM_RAEVICT_MODEL_AUTOGENERATED
2222
LLVM_ENABLE_EXPENSIVE_CHECKS
2323
LLVM_INCLUDE_DXIL_TESTS
24+
LLVM_TOOL_LLVM_DRIVER_BUILD
2425
)
2526

2627
configure_lit_site_cfg(
@@ -144,6 +145,10 @@ if(TARGET llvm-lto)
144145
set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} llvm-lto)
145146
endif()
146147

148+
if(TARGET llvm-driver)
149+
set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} llvm-driver)
150+
endif()
151+
147152
# If Intel JIT events are supported, depend on a tool that tests the listener.
148153
if( LLVM_USE_INTEL_JITEVENTS )
149154
set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} llvm-jitlistener)

0 commit comments

Comments
 (0)