forked from ARM-software/LLVM-embedded-toolchain-for-Arm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
1505 lines (1407 loc) · 51.7 KB
/
CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#
# Copyright (c) 2022, Arm Limited and affiliates.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# How to use this file
#
# This file is used to build LLVM Embedded Toolchain for Arm.
# Recent versions of the following tools are pre-requisites:
# * A toolchain such as gcc & binutils
# * cmake
# * meson
# * ninja
# * python3
# * make and qemu to run tests
#
# Commands to build:
# mkdir build
# cd build
# cmake .. -GNinja -DFETCHCONTENT_QUIET=OFF
# ninja
# ninja check-llvm-toolchain
#
# To make it easy to get started, the above command checks out
# llvm-project & picolibc Git repos automatically.
#
# If the repos are checked out automatically then cmake will fetch the
# latest changes and check them out every time it runs. To disable this
# behaviour run:
# cmake . -DFETCHCONTENT_FULLY_DISCONNECTED=ON
#
# If you prefer you can check out and patch the repos manually and use those:
# mkdir repos
# git -C repos clone https://github.com/llvm/llvm-project.git
# git -C repos/llvm-project apply ../../patches/llvm-project.patch
# git -C repos clone https://github.com/picolibc/picolibc.git
# git -C repos/picolibc apply ../../patches/picolibc.patch
# mkdir build
# cd build
# cmake .. -GNinja -DFETCHCONTENT_SOURCE_DIR_LLVMPROJECT=../repos/llvm-project -DFETCHCONTENT_SOURCE_DIR_PICOLIBC=../repos/picolibc
# ninja
# ninja check-llvm-toolchain
#
# To install the toolchain run:
# cmake . --install-prefix /absolute/path/to/install/directory
# ninja install-llvm-toolchain
#
#
# This file is designed to be used in a way that will be familiar to
# LLVM developers. Targets like clang and check-all can be built as usual.
# In addition there are targets to build picolibc & runtimes variants.
#
#
# Cross-building from Linux to Windows MinGW is supported.
# Note that a build created this way includes GCC & MinGW DLLs which
# come under a different license. See building-from-source.md for
# details.
#
# To enable cross-building run:
# cmake . -DLLVM_TOOLCHAIN_CROSS_BUILD_MINGW=ON -DCMAKE_INSTALL_PREFIX=$(pwd)/install-mingw
#
# If cross-building, there will be two toolchains built:
# 1. The "build" toolchain. This is used to build the libraries.
# 2. The "host" toolchain. This is the toolchain that will be packaged
# up into "LLVM Embedded Toolchain for Arm".
# For "native" builds the "build" toolchain is also used as the "host"
# toolchain.
#
# The terminology can be pretty confusing when you've got
# toolchains building toolchains. There's a good explanation at
# https://docs.conan.io/en/latest/systems_cross_building/cross_building.html
#
# To build the "build" toolchain we add the llvm source as a
# subdirectory. This means you can build all its targets such
# as check-llvm directly.
# If cross-building, a "host" toolchain is built. It is built as a
# separate project.
#
# When libraries are built, they are always copied into the "build"
# toolchain. The primary reason for this is to minimise the number of
# if/else statements in the CMake code, but it has the nice side-effect
# that a cross-build is almost a superset of a native build.
# It is only at install time that one of either the "build" or "host"
# toolchain is copied to the install location.
# This makes it easy to switch back and forth between native and cross
# builds with:
# cmake . -DLLVM_TOOLCHAIN_CROSS_BUILD_MINGW=<ON or OFF> --install-prefix=...
#
#
# When building the toolchain repeatedly, the most time-consuming part
# can be building the libraries since each one is configured separately.
# To work around this, the variants that get built can be limited using
# the LLVM_TOOLCHAIN_LIBRARY_VARIANTS option e.g.:
# cmake . '-DLLVM_TOOLCHAIN_LIBRARY_VARIANTS=aarch64;armv6m_soft_nofp'
# CONFIGURE_HANDLED_BY_BUILD was introduced in CMake 3.20 and it
# greatly speeds up incremental builds.
cmake_minimum_required(VERSION 3.20)
option(
LLVM_TOOLCHAIN_CROSS_BUILD_MINGW
"Cross-build for Windows. Using this option implies that you accept the GCC & MinGW licenses."
)
option(
PREBUILT_TARGET_LIBRARIES
"Target libraries are prebuilt so no need to build them"
)
set(TARGET_LIBRARIES_DIR
"lib/clang-runtimes" CACHE STRING
"Directory containing the target libraries."
)
set(LLVM_TOOLCHAIN_LIBRARY_VARIANTS
"" CACHE STRING
"Build only the specified library variants. If not specified then build all variants."
)
set(BUG_REPORT_URL "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/issues" CACHE STRING "")
set(LLVM_DISTRIBUTION_COMPONENTS
clang-format
clang-resource-headers
clang
dsymutil
lld
llvm-ar
llvm-config
llvm-cov
llvm-cxxfilt
llvm-dwarfdump
llvm-nm
llvm-objcopy
llvm-objdump
llvm-profdata
llvm-ranlib
llvm-readelf
llvm-readobj
llvm-size
llvm-strip
llvm-symbolizer
llvm-link
llc
opt
LTO
CACHE STRING ""
)
set(LLVM_TOOLCHAIN_DISTRIBUTION_COMPONENTS
llvm-toolchain-config-files
llvm-toolchain-docs
llvm-toolchain-libs
llvm-toolchain-samples
llvm-toolchain-third-party-licenses
CACHE STRING "Components defined by this CMakeLists that should be
installed by the install-llvm-toolchain target"
)
set(LLVM_ENABLE_PROJECTS clang;lld CACHE STRING "")
set(LLVM_TARGETS_TO_BUILD ARM CACHE STRING "")
set(LLVM_DEFAULT_TARGET_TRIPLE arm-none-eabi CACHE STRING "")
set(LLVM_APPEND_VC_REV OFF CACHE BOOL "")
set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "")
set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
# Default to a release build
# (CMAKE_BUILD_TYPE is a special CMake variable so if you want to set
# it then you have to FORCE it).
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE BOOL "" FORCE)
endif()
find_package(Python3 REQUIRED COMPONENTS Interpreter)
if(NOT CMAKE_C_COMPILER_LAUNCHER AND NOT CMAKE_CXX_COMPILER_LAUNCHER)
# If ccache is available then use it by default.
find_program(CCACHE_EXECUTABLE ccache)
if(CCACHE_EXECUTABLE)
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE FILEPATH "" FORCE)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE FILEPATH "" FORCE)
endif()
endif()
# If lld is available then use it by default.
find_program(LLD_EXECUTABLE lld)
if(LLD_EXECUTABLE)
set(LLVM_USE_LINKER lld CACHE STRING "")
endif()
# A lot of files get installed which makes the install messages too
# noisy to be useful so default to disabling them.
set(CMAKE_INSTALL_MESSAGE NEVER CACHE STRING "")
include(ExternalProject)
include(FetchContent)
# Check out and patch llvm-project and picolibc.
#
# If you'd rather check out and patch manually then run cmake with
# -DFETCHCONTENT_SOURCE_DIR_LLVMPROJECT=/path/to/llvm-project
# -DFETCHCONTENT_SOURCE_DIR_PICOLIBC=/path/to/picolibc
#
# By default check out will be silent but this can be changed by running
# cmake with -DFETCHCONTENT_QUIET=OFF
#
# If you want to stop cmake updating the repos then run
# cmake . -DFETCHCONTENT_FULLY_DISCONNECTED=ON
# Read which revisions of the repos to use.
file(READ versions.json VERSIONS_JSON)
function(read_repo_version output_variable_prefix repo)
string(JSON tag GET ${VERSIONS_JSON} "repos" "${repo}" "tag")
string(JSON tagType GET ${VERSIONS_JSON} "repos" "${repo}" "tagType")
if(tagType STREQUAL "commithash")
# GIT_SHALLOW doesn't work with commit hashes.
set(shallow OFF)
elseif(tagType STREQUAL "branch")
set(shallow ON)
# CMake docs recommend that "branch names and tags should
# generally be specified as remote names"
set(tag "origin/${tag}")
elseif(tagType STREQUAL "tag")
set(shallow ON)
else()
message(FATAL_ERROR "Unrecognised tagType ${tagType}")
endif()
set(${output_variable_prefix}_TAG "${tag}" PARENT_SCOPE)
set(${output_variable_prefix}_SHALLOW "${shallow}" PARENT_SCOPE)
endfunction()
read_repo_version(llvmproject llvm-project)
read_repo_version(picolibc picolibc)
FetchContent_Declare(llvmproject
GIT_REPOSITORY https://github.com/llvm/llvm-project.git
GIT_TAG "${llvmproject_TAG}"
GIT_SHALLOW "${llvmproject_SHALLOW}"
GIT_PROGRESS TRUE
PATCH_COMMAND git reset --quiet --hard && git clean --quiet --force -dx && git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project.patch
# Add the llvm subdirectory later to ensure that
# LLVMEmbeddedToolchainForArm is the first project declared.
# Otherwise CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
# can't be used.
SOURCE_SUBDIR do_not_add_llvm_subdir_yet
)
FetchContent_Declare(picolibc
GIT_REPOSITORY https://github.com/picolibc/picolibc.git
GIT_TAG "${picolibc_TAG}"
GIT_SHALLOW "${picolibc_SHALLOW}"
GIT_PROGRESS TRUE
PATCH_COMMAND git reset --quiet --hard && git clean --quiet --force -dx && git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/picolibc.patch
# We only want to download the content, not configure it at this
# stage. picolibc will be built in many configurations using
# ExternalProject_Add using the sources that are checked out here.
SOURCE_SUBDIR do_not_add_picolibc_subdir
)
FetchContent_MakeAvailable(llvmproject)
FetchContent_MakeAvailable(picolibc)
function(get_llvm_version_numbers llvmproject_SOURCE_DIR)
# Grab the version out of LLVM sources
file(
STRINGS ${llvmproject_SOURCE_DIR}/llvm/CMakeLists.txt version_strings
REGEX [[set\(LLVM_VERSION_[A-Z]+ [0-9]+\)]]
)
string(REGEX MATCH [[MAJOR ([0-9]+)]] unused "${version_strings}")
set(LLVM_VERSION_MAJOR ${CMAKE_MATCH_1} PARENT_SCOPE)
string(REGEX MATCH [[MINOR ([0-9]+)]] unused "${version_strings}")
set(LLVM_VERSION_MINOR ${CMAKE_MATCH_1} PARENT_SCOPE)
string(REGEX MATCH [[PATCH ([0-9]+)]] unused "${version_strings}")
set(LLVM_VERSION_PATCH ${CMAKE_MATCH_1} PARENT_SCOPE)
endfunction()
get_llvm_version_numbers(${llvmproject_SOURCE_DIR})
project(
LLVMEmbeddedToolchainForArm
VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}
DESCRIPTION "LLVM Embedded Toolchain for Arm"
HOMEPAGE_URL "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm"
)
# We generally want to install to a local directory to see what the
# output will look like rather than install into the system, so change
# the default accordingly.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
# Note that this code only works after the first call to project so it
# can't be moved after the add_subdirectory command below.
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX
"${CMAKE_BINARY_DIR}/install"
CACHE PATH "" FORCE
)
endif()
# These must be set before include(CPack) which the llvm CMakeLists.txt does.
# Restrict which LLVM components are installed.
if(LLVM_TOOLCHAIN_CROSS_BUILD_MINGW)
set(CPACK_COMPONENTS_ALL ${LLVM_TOOLCHAIN_DISTRIBUTION_COMPONENTS} llvm-toolchain-mingw)
else()
set(CPACK_COMPONENTS_ALL ${LLVM_TOOLCHAIN_DISTRIBUTION_COMPONENTS} ${LLVM_DISTRIBUTION_COMPONENTS})
endif()
# Enable limiting the installed components in TGZ and ZIP packages.
set(CPACK_ARCHIVE_COMPONENT_INSTALL TRUE)
# Don't create a separate archive for each component.
set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)
# When extracting the files put them in an ArmCompiler-.../ directory.
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY TRUE)
# Compress package in parallel.
set(CPACK_THREADS 0 CACHE STRING "")
if(CMAKE_OSX_ARCHITECTURES)
# For universal binaries don't include architecture in the package name.
set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}")
else()
string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} processor_name)
string(REGEX MATCH "amd64|x64|x86" x86_match ${processor_name})
if(x86_match)
set(processor_name "x86_64")
else()
set(processor_name "AArch64")
endif()
if(LLVM_TOOLCHAIN_CROSS_BUILD_MINGW)
set(CPACK_SYSTEM_NAME "Windows-${processor_name}")
else()
set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${processor_name}")
endif()
endif()
add_subdirectory(
${llvmproject_SOURCE_DIR}/llvm llvm
)
# Including CPack again after llvm CMakeLists.txt included it
# resets CPACK_PACKAGE_VERSION to the default MAJOR.MINOR.PATCH format.
include(CPack)
# Ensure LLVM tool symlinks are installed.
list(APPEND CMAKE_MODULE_PATH ${llvmproject_SOURCE_DIR}/llvm/cmake/modules)
llvm_install_symlink(LLVM llvm-ranlib llvm-ar ALWAYS_GENERATE)
llvm_install_symlink(LLVM llvm-readelf llvm-readobj ALWAYS_GENERATE)
llvm_install_symlink(LLVM llvm-strip llvm-objcopy ALWAYS_GENERATE)
# For building picolibc use Meson.
# Although picolibc has support for building with CMake, the Meson code
# is more mature and works better with LLVM.
find_program(MESON_EXECUTABLE meson REQUIRED)
include(cmake/to_meson_list.cmake)
# Generate VERSION.txt
# Use add_custom_target instead of add_custom_command so that the target
# is always considered out-of-date, ensuring that VERSION.txt will be
# updated when the git revision changes.
add_custom_target(
version_txt
COMMAND
"${CMAKE_COMMAND}"
-DLLVMEmbeddedToolchainForArm_VERSION=${LLVMEmbeddedToolchainForArm_VERSION}
-DLLVMEmbeddedToolchainForArm_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-Dllvmproject_SOURCE_DIR=${llvmproject_SOURCE_DIR}
-Dpicolibc_SOURCE_DIR=${picolibc_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate_version_txt.cmake
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/VERSION.txt
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/VERSION.txt
DESTINATION .
COMPONENT llvm-toolchain-docs
)
# Groups all the targets that comprise the toolchain.
add_custom_target(llvm-toolchain ALL)
# Groups all the runtime targets
add_custom_target(llvm-toolchain-runtimes)
# Groups all C++ runtime libraries tests
add_custom_target(check-llvm-toolchain-runtimes)
add_custom_target(check-compiler-rt)
add_custom_target(check-cxxabi)
add_custom_target(check-unwind)
add_custom_target(check-cxx)
add_dependencies(
check-llvm-toolchain-runtimes
check-compiler-rt
check-cxxabi
check-unwind
check-cxx
)
if(NOT LLVM_TOOLCHAIN_CROSS_BUILD_MINGW)
add_dependencies(
llvm-toolchain
${LLVM_DISTRIBUTION_COMPONENTS}
)
endif()
add_dependencies(
llvm-toolchain
llvm-toolchain-runtimes
version_txt
)
foreach(variant ${LLVM_TOOLCHAIN_LIBRARY_VARIANTS})
set(enable_${variant} TRUE)
endforeach()
set(picolibc_specific_runtimes_options
-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF
-DLIBCXXABI_ENABLE_THREADS=OFF
-DLIBCXX_TEST_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/test-support/llvm-libc++-picolibc.cfg.in
-DLIBCXX_ENABLE_EXCEPTIONS=OFF
-DLIBCXXABI_TEST_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/test-support/llvm-libc++abi-picolibc.cfg.in
-DLIBCXX_ENABLE_MONOTONIC_CLOCK=OFF
-DLIBCXX_ENABLE_RANDOM_DEVICE=OFF
-DLIBCXX_ENABLE_RTTI=OFF
-DLIBCXX_ENABLE_THREADS=OFF
-DLIBCXX_ENABLE_WIDE_CHARACTERS=OFF
-DLIBUNWIND_ENABLE_THREADS=OFF
-DLIBUNWIND_TEST_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/test-support/llvm-libunwind-picolibc.cfg.in
)
add_custom_target(check-picolibc)
# Set LLVM_DEFAULT_EXTERNAL_LIT to the directory of clang
# which was build in previous step. This path is not exported
# by add_subdirectory of llvm project
set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_BINARY_DIR}/bin/llvm-lit")
function(get_test_executor_params target_triple qemu_machine qemu_cpu qemu_params)
if(target_triple MATCHES "^aarch64")
set(qemu_command "qemu-system-aarch64")
else()
set(qemu_command "qemu-system-arm")
endif()
# Use colon as a separator because comma and semicolon are used for
# other purposes in CMake.
string(REPLACE " " ":" qemu_params_list "${qemu_params}")
set(
test_executor_params
--qemu-command ${qemu_command}
--qemu-machine ${qemu_machine})
if(qemu_cpu)
list(APPEND test_executor_params --qemu-cpu ${qemu_cpu})
endif()
if(qemu_params_list)
list(APPEND test_executor_params "--qemu-params=${qemu_params_list}")
endif()
set(test_executor_params "${test_executor_params}" PARENT_SCOPE)
endfunction()
function(
add_picolibc
directory
variant
target_triple
flags
test_executor_params
default_boot_flash_addr
default_boot_flash_size
default_flash_addr
default_flash_size
default_ram_addr
default_ram_size
default_stack_size
)
if(CMAKE_INSTALL_MESSAGE STREQUAL NEVER)
set(MESON_INSTALL_QUIET "--quiet")
endif()
if(target_triple MATCHES "^aarch64")
set(cpu_family aarch64)
else()
set(cpu_family arm)
endif()
ExternalProject_Add(
picolibc_${variant}
SOURCE_DIR ${picolibc_SOURCE_DIR}
INSTALL_DIR "${LLVM_BINARY_DIR}/${directory}"
PREFIX picolibc/${variant}
DEPENDS clang lld llvm-ar llvm-config llvm-nm llvm-ranlib llvm-strip
CONFIGURE_COMMAND
${MESON_EXECUTABLE}
setup
-Dincludedir=include
-Dlibdir=lib
-Dspecsdir=none
-Dmultilib=false
-Dtests-enable-stack-protector=false
--prefix <INSTALL_DIR>
--cross-file <BINARY_DIR>/meson-cross-build.txt
<SOURCE_DIR>
BUILD_COMMAND ${MESON_EXECUTABLE} configure -Dtests=false
COMMAND ${MESON_EXECUTABLE} compile
INSTALL_COMMAND ${MESON_EXECUTABLE} install ${MESON_INSTALL_QUIET}
TEST_COMMAND ${MESON_EXECUTABLE} configure -Dtests=true
# meson<0.64.0 does not properly apply new configuration after
# "meson configure -Dtests=false"
# use "meson setup --reconfigure" as a workaround
COMMAND ${MESON_EXECUTABLE} setup . <SOURCE_DIR> -Dtests=true --reconfigure
COMMAND ${MESON_EXECUTABLE} test
COMMAND ${MESON_EXECUTABLE} configure -Dtests=false
USES_TERMINAL_CONFIGURE FALSE
USES_TERMINAL_BUILD TRUE
USES_TERMINAL_TEST TRUE
LIST_SEPARATOR ,
# Always run the build command so that incremental builds are correct.
BUILD_ALWAYS TRUE
CONFIGURE_HANDLED_BY_BUILD TRUE
TEST_EXCLUDE_FROM_MAIN TRUE
STEP_TARGETS install test
)
# Set meson_c_args to a comma-separated list of the clang path
# and flags e.g. 'path/to/clang', '--target=armv6m-none-eabi',
# '-march=armv6m'
separate_arguments(flags)
list(PREPEND flags "${LLVM_BINARY_DIR}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}")
list(APPEND flags --sysroot "${LLVM_BINARY_DIR}/${directory}")
to_meson_list("${flags}" meson_c_args)
set(test_executor_bin ${CMAKE_CURRENT_SOURCE_DIR}/test-support/picolibc-test-wrapper.py)
to_meson_list("${test_executor_params}" test_executor_params)
ExternalProject_Get_Property(picolibc_${variant} BINARY_DIR)
configure_file(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/cmake/meson-cross-build.txt.in ${BINARY_DIR}/meson-cross-build.txt @ONLY)
# Building picolibc tests requires compiler_rt to be installed.
# Building compiler_rt tests requires picolibc to be installed.
# To solve this compiler_rt relies on picolibc to be just installed, not on
# the full target, which would include tests. Picolibc tests, are enabled
# only in tests step, otherwise, they would be built before install.
ExternalProject_Add_StepDependencies(picolibc_${variant} test compiler_rt_${variant}-install)
add_dependencies(check-picolibc picolibc_${variant}-test)
add_dependencies(
llvm-toolchain-runtimes
picolibc_${variant}
)
endfunction()
function(get_runtimes_flags directory flags)
set(runtimes_flags "${flags} -ffunction-sections -fdata-sections -fno-ident --sysroot ${LLVM_BINARY_DIR}/${directory}" PARENT_SCOPE)
endfunction()
function(
add_compiler_rt
directory
variant
target_triple
flags
test_executor
libc_target
)
# We can't always put the exact target
# architecture in the triple, because compiler-rt's cmake
# system doesn't recognize every possible Arm architecture
# version. So mostly we just say 'arm' and control the arch
# version via -march=armv7m (or whatever).
# Exceptions are architectures pre-armv7, which compiler-rt expects to
# see in the triple because that's where it looks to decide whether to
# use specific assembly sources.
if(NOT target_triple MATCHES "^(aarch64-none-elf|arm-none-eabi|armv[4-6])")
message(FATAL_ERROR "\
Target triple name \"${target_triple}\" not compatible with compiler-rt.
Use -march to specify the architecture.")
endif()
# Also, compiler-rt looks in the ABI component of the
# triple to decide whether to use the hard float ABI.
if(flags MATCHES "-mfloat-abi=hard" AND NOT target_triple MATCHES "-eabihf$")
message(FATAL_ERROR "\
Hard-float library with target triple \"${target_triple}\" must end \"-eabihf\"")
endif()
get_runtimes_flags("${directory}" "${flags}")
set(compiler_rt_test_flags "${runtimes_flags} -fno-exceptions -fno-rtti -lcrt0-semihost -lsemihost -T picolibcpp.ld")
if(variant STREQUAL "armv6m_soft_nofp")
set(compiler_rt_test_flags "${compiler_rt_test_flags} -fomit-frame-pointer")
endif()
ExternalProject_Add(
compiler_rt_${variant}
SOURCE_DIR ${llvmproject_SOURCE_DIR}/compiler-rt
PREFIX compiler-rt/${variant}
INSTALL_DIR compiler-rt/${variant}/install
DEPENDS clang lld llvm-ar llvm-config llvm-nm llvm-ranlib ${libc_target}
CMAKE_ARGS
-DCMAKE_AR=${LLVM_BINARY_DIR}/bin/llvm-ar${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_COMPILER_TARGET=${target_triple}
-DCMAKE_ASM_FLAGS=${runtimes_flags}
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_CXX_COMPILER=${LLVM_BINARY_DIR}/bin/clang++${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER_TARGET=${target_triple}
-DCMAKE_CXX_FLAGS=${runtimes_flags}
-DCMAKE_C_COMPILER=${LLVM_BINARY_DIR}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_C_COMPILER_TARGET=${target_triple}
-DCMAKE_C_FLAGS=${runtimes_flags}
-DCMAKE_INSTALL_MESSAGE=${CMAKE_INSTALL_MESSAGE}
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_NM=${LLVM_BINARY_DIR}/bin/llvm-nm${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_RANLIB=${LLVM_BINARY_DIR}/bin/llvm-ranlib${CMAKE_EXECUTABLE_SUFFIX}
# Let CMake know we're cross-compiling
-DCMAKE_SYSTEM_NAME=Generic
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
-DCOMPILER_RT_BAREMETAL_BUILD=ON
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF
-DCOMPILER_RT_BUILD_PROFILE=OFF
-DCOMPILER_RT_BUILD_SANITIZERS=OFF
-DCOMPILER_RT_BUILD_XRAY=OFF
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON
-DCOMPILER_RT_INCLUDE_TESTS=ON
-DCOMPILER_RT_EMULATOR=${test_executor}
-DCOMPILER_RT_TEST_COMPILER=${LLVM_BINARY_DIR}/bin/clang
-DCOMPILER_RT_TEST_COMPILER_CFLAGS=${compiler_rt_test_flags}
-DLLVM_LIT_ARGS=${LLVM_LIT_ARGS}
-DLLVM_CMAKE_DIR=${LLVM_BINARY_DIR}/lib/cmake/llvm
-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON
STEP_TARGETS build install
USES_TERMINAL_CONFIGURE FALSE
USES_TERMINAL_BUILD TRUE
USES_TERMINAL_INSTALL TRUE
USES_TERMINAL_TEST TRUE
LIST_SEPARATOR ,
# Always run the build command so that incremental builds are correct.
BUILD_ALWAYS TRUE
CONFIGURE_HANDLED_BY_BUILD TRUE
INSTALL_COMMAND ${CMAKE_COMMAND} --install .
# Copy compiler-rt lib directory, moving libraries out of their
# target-specific subdirectory.
COMMAND
${CMAKE_COMMAND}
-E copy_directory
<INSTALL_DIR>/lib/${target_triple}
"${LLVM_BINARY_DIR}/${directory}/lib"
)
add_dependencies(
llvm-toolchain-runtimes
compiler_rt_${variant}
)
endfunction()
function(
add_libcxx_libcxxabi_libunwind
directory
variant
target_triple
flags
test_executor
libc_target
extra_cmake_options
)
get_runtimes_flags("${directory}" "${flags}")
ExternalProject_Add(
libcxx_libcxxabi_libunwind_${variant}
SOURCE_DIR ${llvmproject_SOURCE_DIR}/runtimes
INSTALL_DIR "${LLVM_BINARY_DIR}/${directory}"
PREFIX libcxx_libcxxabi_libunwind/${variant}
DEPENDS clang compiler_rt_${variant} lld llvm-ar llvm-config llvm-nm llvm-ranlib ${libc_target}
CMAKE_ARGS
-DCMAKE_AR=${LLVM_BINARY_DIR}/bin/llvm-ar${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_FLAGS=${runtimes_flags}
-DCMAKE_BUILD_TYPE=MinSizeRel
-DCMAKE_CXX_COMPILER=${LLVM_BINARY_DIR}/bin/clang++${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER_TARGET=${target_triple}
-DCMAKE_CXX_FLAGS=${runtimes_flags}
-DCMAKE_C_COMPILER=${LLVM_BINARY_DIR}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_C_COMPILER_TARGET=${target_triple}
-DCMAKE_C_FLAGS=${runtimes_flags}
-DCMAKE_INSTALL_MESSAGE=${CMAKE_INSTALL_MESSAGE}
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_NM=${LLVM_BINARY_DIR}/bin/llvm-nm${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_RANLIB=${LLVM_BINARY_DIR}/bin/llvm-ranlib${CMAKE_EXECUTABLE_SUFFIX}
# Let CMake know we're cross-compiling
-DCMAKE_SYSTEM_NAME=Generic
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
-DLIBC_LINKER_SCRIPT=picolibcpp.ld
-DLIBCXXABI_BAREMETAL=ON
-DLIBCXXABI_ENABLE_ASSERTIONS=OFF
-DLIBCXXABI_ENABLE_SHARED=OFF
-DLIBCXXABI_ENABLE_STATIC=ON
-DLIBCXXABI_LIBCXX_INCLUDES="${LLVM_BINARY_DIR}/${directory}/include/c++/v1"
-DLIBCXXABI_USE_COMPILER_RT=ON
-DLIBCXXABI_USE_LLVM_UNWINDER=ON
-DLIBCXXABI_EXECUTOR=${test_executor}
-DLIBCXX_CXX_ABI=libcxxabi
-DLIBCXX_ENABLE_FILESYSTEM=OFF
-DLIBCXX_ENABLE_SHARED=OFF
-DLIBCXX_ENABLE_STATIC=ON
-DLIBCXX_INCLUDE_BENCHMARKS=OFF
-DLIBCXX_EXECUTOR=${test_executor}
-DLIBUNWIND_ENABLE_SHARED=OFF
-DLIBUNWIND_ENABLE_STATIC=ON
-DLIBUNWIND_IS_BAREMETAL=ON
-DLIBUNWIND_REMEMBER_HEAP_ALLOC=ON
-DLIBUNWIND_USE_COMPILER_RT=ON
-DLIBUNWIND_EXECUTOR=${test_executor}
-DLLVM_LIT_ARGS=${LLVM_LIT_ARGS}
-DLLVM_ENABLE_RUNTIMES=libcxxabi,libcxx,libunwind
-DRUNTIME_TEST_ARCH_FLAGS=${flags}
-DRUNTIME_VARIANT_NAME=${variant}
${extra_cmake_options}
STEP_TARGETS build
USES_TERMINAL_CONFIGURE FALSE
USES_TERMINAL_BUILD TRUE
USES_TERMINAL_INSTALL TRUE
USES_TERMINAL_TEST TRUE
LIST_SEPARATOR ,
# Always run the build command so that incremental builds are correct.
BUILD_ALWAYS TRUE
CONFIGURE_HANDLED_BY_BUILD TRUE
)
add_dependencies(
llvm-toolchain-runtimes
libcxx_libcxxabi_libunwind_${variant}
)
endfunction()
function(add_compiler_rt_tests variant)
ExternalProject_Add_Step(
compiler_rt_${variant}
check-compiler-rt
COMMAND "${CMAKE_COMMAND}" --build <BINARY_DIR> --target check-compiler-rt
USES_TERMINAL TRUE
EXCLUDE_FROM_MAIN TRUE
ALWAYS TRUE
)
ExternalProject_Add_StepTargets(compiler_rt_${variant} check-compiler-rt)
ExternalProject_Add_StepDependencies(
compiler_rt_${variant}
check-compiler-rt
compiler_rt_${variant}-build
)
add_custom_target(check-compiler-rt-${variant})
add_dependencies(check-compiler-rt-${variant} compiler_rt_${variant}-check-compiler-rt)
add_dependencies(check-compiler-rt check-compiler-rt-${variant})
add_dependencies(check-llvm-toolchain-runtimes-${variant} check-compiler-rt-${variant})
endfunction()
function(add_libcxx_libcxxabi_libunwind_tests variant)
foreach(check_target check-cxxabi check-unwind check-cxx)
ExternalProject_Add_Step(
libcxx_libcxxabi_libunwind_${variant}
${check_target}
COMMAND "${CMAKE_COMMAND}" --build <BINARY_DIR> --target ${check_target}
USES_TERMINAL TRUE
EXCLUDE_FROM_MAIN TRUE
ALWAYS TRUE
)
ExternalProject_Add_StepTargets(libcxx_libcxxabi_libunwind_${variant} ${check_target})
ExternalProject_Add_StepDependencies(
libcxx_libcxxabi_libunwind_${variant}
${check_target}
libcxx_libcxxabi_libunwind_${variant}-build
)
add_custom_target(${check_target}-${variant})
add_dependencies(${check_target}-${variant} libcxx_libcxxabi_libunwind_${variant}-${check_target})
add_dependencies(${check_target} libcxx_libcxxabi_libunwind_${variant}-${check_target})
add_dependencies(check-llvm-toolchain-runtimes-${variant} ${check_target}-${variant})
endforeach()
endfunction()
include(contrib/contrib.cmake)
function(make_config_cfg directory variant flags)
# Create clang configuration files
# https://clang.llvm.org/docs/UsersManual.html#configuration-files
set(crt0 "-lcrt0")
set(extra_args "")
configure_file(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/cmake/config.cfg.in ${LLVM_BINARY_DIR}/bin/${variant}.cfg)
set(crt0 "-lcrt0-semihost")
set(extra_args "\n-lsemihost")
configure_file(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/cmake/config.cfg.in ${LLVM_BINARY_DIR}/bin/${variant}_semihost.cfg)
install(FILES
${LLVM_BINARY_DIR}/bin/${variant}.cfg
${LLVM_BINARY_DIR}/bin/${variant}_semihost.cfg
DESTINATION bin
COMPONENT llvm-toolchain-config-files
)
endfunction()
function(get_compiler_rt_target_triple target_arch flags)
if(target_arch STREQUAL "aarch64")
set(target_triple "aarch64-none-elf")
else()
# Choose the target triple so that compiler-rt will do the
# right thing. We can't always put the exact target
# architecture in the triple, because compiler-rt's cmake
# system doesn't recognize every possible Arm architecture
# version. So mostly we just say 'arm' and control the arch
# version via -march=armv7m (or whatever).
# Exceptions are architectures pre-armv7, which compiler-rt expects to
# see in the triple because that's where it looks to decide whether to
# use specific assembly sources.
if(target_arch MATCHES "^armv[4-6]")
set(target_triple "${target_arch}-none-eabi")
else()
set(target_triple "arm-none-eabi")
endif()
if(flags MATCHES "-mfloat-abi=hard")
# Also, compiler-rt looks in the ABI component of the
# triple to decide whether to use the hard float ABI.
set(target_triple "${target_triple}hf")
endif()
endif()
set(target_triple "${target_triple}" PARENT_SCOPE)
endfunction()
function(add_library_variant target_arch)
set(
one_value_args
SUFFIX
COMPILE_FLAGS
MULTILIB_FLAGS
QEMU_MACHINE
QEMU_CPU
QEMU_PARAMS
BOOT_FLASH_ADDRESS
BOOT_FLASH_SIZE
FLASH_ADDRESS
FLASH_SIZE
RAM_ADDRESS
RAM_SIZE
STACK_SIZE
)
cmake_parse_arguments(VARIANT "" "${one_value_args}" "" ${ARGN})
if(VARIANT_SUFFIX)
set(variant "${target_arch}_${VARIANT_SUFFIX}")
else()
set(variant "${target_arch}")
endif()
if(LLVM_TOOLCHAIN_LIBRARY_VARIANTS)
if(NOT enable_${variant})
message("Disabling library variant ${variant}")
return()
else()
message("Enabling library variant ${variant}")
endif()
endif()
if(target_arch STREQUAL "aarch64")
set(parent_dir_name aarch64-none-elf)
else()
set(parent_dir_name arm-none-eabi)
endif()
get_compiler_rt_target_triple("${target_arch}" "${VARIANT_COMPILE_FLAGS}")
set(directory "${TARGET_LIBRARIES_DIR}/${parent_dir_name}/${variant}")
set(VARIANT_COMPILE_FLAGS "--target=${target_triple} ${VARIANT_COMPILE_FLAGS}")
make_config_cfg("${directory}" "${variant}" "${VARIANT_COMPILE_FLAGS}")
get_test_executor_params(
"${target_triple}"
"${VARIANT_QEMU_MACHINE}"
"${VARIANT_QEMU_CPU}"
"${VARIANT_QEMU_PARAMS}"
)
set(
lit_test_executor
${CMAKE_CURRENT_SOURCE_DIR}/test-support/lit-exec-qemu.py
${test_executor_params}
)
list(JOIN lit_test_executor " " lit_test_executor)
if(NOT PREBUILT_TARGET_LIBRARIES)
add_picolibc(
"${directory}"
"${variant}"
"${target_triple}"
"${VARIANT_COMPILE_FLAGS}"
"${test_executor_params}"
"${VARIANT_BOOT_FLASH_ADDRESS}"
"${VARIANT_BOOT_FLASH_SIZE}"
"${VARIANT_FLASH_ADDRESS}"
"${VARIANT_FLASH_SIZE}"
"${VARIANT_RAM_ADDRESS}"
"${VARIANT_RAM_SIZE}"
"${VARIANT_STACK_SIZE}"
)
add_compiler_rt(
"${directory}"
"${variant}"
"${target_triple}"
"${VARIANT_COMPILE_FLAGS}"
"${lit_test_executor}"
"picolibc_${variant}-install"
)
add_libcxx_libcxxabi_libunwind(
"${directory}"
"${variant}"
"${target_triple}"
"${VARIANT_COMPILE_FLAGS}"
"${lit_test_executor}"
"picolibc_${variant}-install"
"${picolibc_specific_runtimes_options}"
)
if(VARIANT_COMPILE_FLAGS MATCHES "-march=armv8")
message("C++ runtime libraries tests disabled for ${variant}")
else()
add_custom_target(check-llvm-toolchain-runtimes-${variant})
add_dependencies(check-llvm-toolchain-runtimes check-llvm-toolchain-runtimes-${variant})
add_compiler_rt_tests("${variant}")
add_libcxx_libcxxabi_libunwind_tests("${variant}")
endif()
add_contrib_libs(
"${directory}"
"${variant}"
"${target_triple}"
"${VARIANT_COMPILE_FLAGS}"
"${lit_test_executor}"
"picolibc_${variant}-install"
)
endif()
string(APPEND multilib_yaml_content "- Dir: ${parent_dir_name}/${variant}\n")
string(APPEND multilib_yaml_content " Flags:\n")
string(REPLACE " " ";" multilib_flags_list ${VARIANT_MULTILIB_FLAGS})
foreach(flag ${multilib_flags_list})
string(APPEND multilib_yaml_content " - ${flag}\n")
endforeach()
install(
DIRECTORY "${LLVM_BINARY_DIR}/${directory}/"
DESTINATION "${directory}"
COMPONENT llvm-toolchain-libs
)
set(multilib_yaml_content "${multilib_yaml_content}" PARENT_SCOPE)
endfunction()
set(multilib_yaml_content "")
# Define which library variants to build and which flags to use.
# The order is <arch> <name suffix> <compile flags> <multilib selection flags> <qemu params>
add_library_variant(
aarch64
COMPILE_FLAGS "-march=armv8-a"
MULTILIB_FLAGS "--target=aarch64-none-unknown-elf"
QEMU_MACHINE "virt"
QEMU_CPU "cortex-a57"
BOOT_FLASH_ADDRESS 0x40000000
BOOT_FLASH_SIZE 0x1000
FLASH_ADDRESS 0x40001000
FLASH_SIZE 0x3ff000
RAM_ADDRESS 0x40400000
RAM_SIZE 2M
STACK_SIZE 8K
)
add_library_variant(
armv4t
COMPILE_FLAGS "-march=armv4t"
MULTILIB_FLAGS "--target=armv4t-none-unknown-eabi -mfpu=none"
QEMU_MACHINE "none"
QEMU_CPU "ti925t"
QEMU_PARAMS "-m 1G"
BOOT_FLASH_ADDRESS 0x00000000
BOOT_FLASH_SIZE 0x1000
FLASH_ADDRESS 0x00001000
FLASH_SIZE 0x3ff000
RAM_ADDRESS 0x20000000
RAM_SIZE 2M
STACK_SIZE 4K
)
add_library_variant(
armv5te
COMPILE_FLAGS "-march=armv5te"
MULTILIB_FLAGS "--target=armv5e-none-unknown-eabi -mfpu=none"
QEMU_MACHINE "none"
QEMU_CPU "arm926"
QEMU_PARAMS "-m 1G"
BOOT_FLASH_ADDRESS 0x00000000
BOOT_FLASH_SIZE 0x1000
FLASH_ADDRESS 0x00001000
FLASH_SIZE 0x3ff000
RAM_ADDRESS 0x20000000
RAM_SIZE 2M
STACK_SIZE 4K
)