blob: 619550b5943a4eae6673b89e77645e5ea18012c6 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001include(ExternalProject)
2
3# llvm_ExternalProject_BuildCmd(out_var target)
4# Utility function for constructing command lines for external project targets
5function(llvm_ExternalProject_BuildCmd out_var target bin_dir)
6 cmake_parse_arguments(ARG "" "CONFIGURATION" "" ${ARGN})
7 if(NOT ARG_CONFIGURATION)
8 set(ARG_CONFIGURATION "$<CONFIGURATION>")
9 endif()
10 if (CMAKE_GENERATOR MATCHES "Make")
11 # Use special command for Makefiles to support parallelism.
12 set(${out_var} "$(MAKE)" "-C" "${bin_dir}" "${target}" PARENT_SCOPE)
13 else()
14 set(${out_var} ${CMAKE_COMMAND} --build ${bin_dir} --target ${target}
15 --config ${ARG_CONFIGURATION} PARENT_SCOPE)
16 endif()
17endfunction()
18
19# llvm_ExternalProject_Add(name source_dir ...
20# USE_TOOLCHAIN
21# Use just-built tools (see TOOLCHAIN_TOOLS)
22# EXCLUDE_FROM_ALL
23# Exclude this project from the all target
24# NO_INSTALL
25# Don't generate install targets for this project
26# ALWAYS_CLEAN
27# Always clean the sub-project before building
28# CMAKE_ARGS arguments...
29# Optional cmake arguments to pass when configuring the project
30# TOOLCHAIN_TOOLS targets...
31# Targets for toolchain tools (defaults to clang;lld)
32# DEPENDS targets...
33# Targets that this project depends on
34# EXTRA_TARGETS targets...
35# Extra targets in the subproject to generate targets for
36# PASSTHROUGH_PREFIXES prefix...
37# Extra variable prefixes (name is always included) to pass down
38# )
39function(llvm_ExternalProject_Add name source_dir)
40 cmake_parse_arguments(ARG
41 "USE_TOOLCHAIN;EXCLUDE_FROM_ALL;NO_INSTALL;ALWAYS_CLEAN"
42 "SOURCE_DIR"
43 "CMAKE_ARGS;TOOLCHAIN_TOOLS;RUNTIME_LIBRARIES;DEPENDS;EXTRA_TARGETS;PASSTHROUGH_PREFIXES"
44 ${ARGN})
45 canonicalize_tool_name(${name} nameCanon)
46 if(NOT ARG_TOOLCHAIN_TOOLS)
47 set(ARG_TOOLCHAIN_TOOLS clang lld)
48 if(NOT APPLE AND NOT WIN32)
49 list(APPEND ARG_TOOLCHAIN_TOOLS llvm-ar llvm-ranlib)
50 endif()
51 endif()
52 foreach(tool ${ARG_TOOLCHAIN_TOOLS})
53 if(TARGET ${tool})
54 list(APPEND TOOLCHAIN_TOOLS ${tool})
55 list(APPEND TOOLCHAIN_BINS $<TARGET_FILE:${tool}>)
56 endif()
57 endforeach()
58
59 if(NOT ARG_RUNTIME_LIBRARIES)
60 set(ARG_RUNTIME_LIBRARIES compiler-rt libcxx)
61 endif()
62 foreach(lib ${ARG_RUNTIME_LIBRARIES})
63 if(TARGET ${lib})
64 list(APPEND RUNTIME_LIBRARIES ${lib})
65 endif()
66 endforeach()
67
68 if(ARG_ALWAYS_CLEAN)
69 set(always_clean clean)
70 endif()
71
72 list(FIND TOOLCHAIN_TOOLS clang FOUND_CLANG)
73 if(FOUND_CLANG GREATER -1)
74 set(CLANG_IN_TOOLCHAIN On)
75 endif()
76
77 if(RUNTIME_LIBRARIES AND CLANG_IN_TOOLCHAIN)
78 list(APPEND TOOLCHAIN_BINS ${RUNTIME_LIBRARIES})
79 endif()
80
81 set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-stamps/)
82 set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-bins/)
83
84 add_custom_target(${name}-clear
85 COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
86 COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
87 COMMENT "Clobbering ${name} build and stamp directories"
88 USES_TERMINAL
89 )
90
91 # Find all variables that start with a prefix and propagate them through
92 get_cmake_property(variableNames VARIABLES)
93
94 list(APPEND ARG_PASSTHROUGH_PREFIXES ${nameCanon})
95 foreach(prefix ${ARG_PASSTHROUGH_PREFIXES})
96 foreach(variableName ${variableNames})
97 if(variableName MATCHES "^${prefix}")
98 string(REPLACE ";" "|" value "${${variableName}}")
99 list(APPEND PASSTHROUGH_VARIABLES
100 -D${variableName}=${value})
101 endif()
102 endforeach()
103 endforeach()
104
105 if(ARG_USE_TOOLCHAIN AND NOT CMAKE_CROSSCOMPILING)
106 if(CLANG_IN_TOOLCHAIN)
107 set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang
108 -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++)
109 endif()
110 if(llvm-ar IN_LIST TOOLCHAIN_TOOLS)
111 list(APPEND compiler_args -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar)
112 endif()
113 if(llvm-ranlib IN_LIST TOOLCHAIN_TOOLS)
114 list(APPEND compiler_args -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib)
115 endif()
116 list(APPEND ARG_DEPENDS ${TOOLCHAIN_TOOLS})
117 endif()
118
119 add_custom_command(
120 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
121 DEPENDS ${ARG_DEPENDS}
122 COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
123 COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
124 COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
125 COMMENT "Clobbering bootstrap build and stamp directories"
126 )
127
128 add_custom_target(${name}-clobber
129 DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
130
131 if(ARG_EXCLUDE_FROM_ALL)
132 set(exclude EXCLUDE_FROM_ALL 1)
133 endif()
134
135 if(CMAKE_SYSROOT)
136 set(sysroot_arg -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
137 endif()
138
139 if(CMAKE_CROSSCOMPILING)
140 set(compiler_args -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
141 -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
142 -DCMAKE_AR=${CMAKE_AR}
143 -DCMAKE_RANLIB=${CMAKE_RANLIB})
144 set(llvm_config_path ${LLVM_CONFIG_PATH})
145 else()
146 set(llvm_config_path "$<TARGET_FILE:llvm-config>")
147 endif()
148
149 ExternalProject_Add(${name}
150 DEPENDS ${ARG_DEPENDS} llvm-config
151 ${name}-clobber
152 PREFIX ${CMAKE_BINARY_DIR}/projects/${name}
153 SOURCE_DIR ${source_dir}
154 STAMP_DIR ${STAMP_DIR}
155 BINARY_DIR ${BINARY_DIR}
156 ${exclude}
157 CMAKE_ARGS ${${nameCanon}_CMAKE_ARGS}
158 ${compiler_args}
159 -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
160 ${sysroot_arg}
161 -DLLVM_BINARY_DIR=${PROJECT_BINARY_DIR}
162 -DLLVM_CONFIG_PATH=${llvm_config_path}
163 -DLLVM_ENABLE_WERROR=${LLVM_ENABLE_WERROR}
164 -DLLVM_HOST_TRIPLE=${LLVM_HOST_TRIPLE}
165 -DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
166 -DPACKAGE_VERSION=${PACKAGE_VERSION}
167 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
168 -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
169 -DCMAKE_EXPORT_COMPILE_COMMANDS=1
170 ${ARG_CMAKE_ARGS}
171 ${PASSTHROUGH_VARIABLES}
172 INSTALL_COMMAND ""
173 STEP_TARGETS configure build
174 BUILD_ALWAYS 1
175 USES_TERMINAL_CONFIGURE 1
176 USES_TERMINAL_BUILD 1
177 USES_TERMINAL_INSTALL 1
178 LIST_SEPARATOR |
179 )
180
181 if(ARG_USE_TOOLCHAIN)
182 set(force_deps DEPENDS ${TOOLCHAIN_BINS})
183 endif()
184
185 llvm_ExternalProject_BuildCmd(run_clean clean ${BINARY_DIR})
186 ExternalProject_Add_Step(${name} clean
187 COMMAND ${run_clean}
188 COMMENT "Cleaning ${name}..."
189 DEPENDEES configure
190 ${force_deps}
191 WORKING_DIRECTORY ${BINARY_DIR}
192 EXCLUDE_FROM_MAIN 1
193 USES_TERMINAL 1
194 )
195 ExternalProject_Add_StepTargets(${name} clean)
196
197 if(ARG_USE_TOOLCHAIN)
198 add_dependencies(${name}-clean ${name}-clobber)
199 set_target_properties(${name}-clean PROPERTIES
200 SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
201 endif()
202
203 if(NOT ARG_NO_INSTALL)
204 install(CODE "execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -P ${BINARY_DIR}/cmake_install.cmake \)"
205 COMPONENT ${name})
206
207 add_llvm_install_targets(install-${name}
208 DEPENDS ${name}
209 COMPONENT ${name})
210 endif()
211
212 # Add top-level targets
213 foreach(target ${ARG_EXTRA_TARGETS})
214 string(REPLACE ":" ";" target_list ${target})
215 list(GET target_list 0 target)
216 list(LENGTH target_list target_list_len)
217 if(${target_list_len} GREATER 1)
218 list(GET target_list 1 target_name)
219 else()
220 set(target_name "${target}")
221 endif()
222 llvm_ExternalProject_BuildCmd(build_runtime_cmd ${target} ${BINARY_DIR})
223 add_custom_target(${target_name}
224 COMMAND ${build_runtime_cmd}
225 DEPENDS ${name}-configure
226 WORKING_DIRECTORY ${BINARY_DIR}
227 VERBATIM
228 USES_TERMINAL)
229 endforeach()
230endfunction()