1# SPDX-License-Identifier: BSD-3-Clause
2
3cmake_minimum_required(VERSION 3.10)
4
5if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
6	message(FATAL_ERROR
7		" In-source builds are not supported.\n"
8		" Please remove CMakeCache.txt and the CMakeFiles directory.\n"
9		" Then specify a build directory. Example: cmake -Bbuild ..."
10	)
11endif()
12
13if(NOT (${CMAKE_VERSION} VERSION_LESS "3.13.0"))
14	# CMake 3.13+ has less restrictive rules for target_link_libraries()
15	# Until we make 3.13 as required minimum version we want to
16	# use old behaviour for compatibility
17	cmake_policy(SET CMP0079 OLD)
18endif()
19
20if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
21	# FindPythonInterp is bugged and may sometimes be unable to find
22	# Python 3 when both Python 2 & 3 are in PATH,
23	# so it's always better to use CMake 3.12+
24	find_package(PythonInterp 3.0)
25	set(PYTHON3 "${PYTHON_EXECUTABLE}")
26else()
27	find_package(Python3 COMPONENTS Interpreter)
28	set(PYTHON3 "${Python3_EXECUTABLE}")
29endif()
30
31option(BUILD_UNIT_TESTS "Build unit tests" OFF)
32option(BUILD_UNIT_TESTS_HOST "Build unit tests for host" OFF)
33option(BUILD_UNIT_TESTS_XTENSA_GCC "Build xtensa unit test using GCC" OFF)
34option(BUILD_CLANG_SCAN "Build for clang's scan-build" OFF)
35option(BUILD_COUNTERS "Enable build counter(s), timestamps and any other
36non-deterministic build features" OFF)
37
38if(CONFIG_LIBRARY OR BUILD_UNIT_TESTS_HOST)
39	set(ARCH host)
40else()
41	# firmware build supports only xtensa arch for now
42	set(ARCH xtensa)
43endif()
44
45# let user override built-in toolchains
46if(DEFINED CMAKE_TOOLCHAIN_FILE)
47	set(TOOLCHAIN "${CMAKE_TOOLCHAIN_FILE}")
48else()
49	include(scripts/cmake/${ARCH}-toolchain.cmake OPTIONAL)
50endif()
51
52include(scripts/cmake/misc.cmake)
53
54project(SOF C ASM)
55
56# intended to be used where PROJECT_* variables are not set
57# for example in standalone scripts like version.cmake
58set(SOF_ROOT_SOURCE_DIRECTORY "${PROJECT_SOURCE_DIR}")
59set(SOF_ROOT_BINARY_DIRECTORY "${PROJECT_BINARY_DIR}")
60
61# check git hooks
62include(scripts/cmake/git-hooks.cmake)
63
64# checkout submodules
65include(scripts/cmake/git-submodules.cmake)
66
67# most of other options are set on per-arch and per-target basis
68set(CMAKE_ASM_FLAGS -DASSEMBLY)
69
70# interface library that is used only as container for sof public header files
71# that may be exported / installed
72add_library(sof_public_headers INTERFACE)
73
74target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/src/include)
75target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/rimage/src/include)
76
77# interface library that is used only as container for sof binary options
78# other targets can use it to build with the same options
79add_library(sof_options INTERFACE)
80
81target_link_libraries(sof_options INTERFACE sof_public_headers)
82
83if(BUILD_COUNTERS)
84target_compile_definitions(sof_options INTERFACE BLD_COUNTERS=1)
85else()
86target_compile_definitions(sof_options INTERFACE BLD_COUNTERS=0)
87endif()
88
89# interface library that is used only as container for sof statically
90# linked libraries
91add_library(sof_static_libraries INTERFACE)
92
93# get compiler name and version
94execute_process(
95	COMMAND ${CMAKE_C_COMPILER} --version
96	OUTPUT_VARIABLE cc_version_output
97	OUTPUT_STRIP_TRAILING_WHITESPACE
98	ERROR_QUIET
99)
100
101string(REGEX MATCH "^[^\r\n]+" CC_VERSION_TEXT "${cc_version_output}")
102if(NOT CC_VERSION_TEXT)
103	message(WARNING "Couldn't get compiler version")
104	set(CC_VERSION_TEXT 0)
105endif()
106
107set(GENERATED_DIRECTORY ${PROJECT_BINARY_DIR}/generated)
108file(MAKE_DIRECTORY ${GENERATED_DIRECTORY}/include)
109
110set(DOT_CONFIG_PATH ${GENERATED_DIRECTORY}/.config)
111set(CONFIG_H_PATH ${GENERATED_DIRECTORY}/include/autoconfig.h CACHE
112  PATH "Path to kconfig's .h output file")
113set(VERSION_H_PATH ${GENERATED_DIRECTORY}/include/version.h)
114
115include(scripts/cmake/version.cmake)
116
117include(scripts/cmake/dist.cmake)
118
119include(scripts/cmake/kconfig.cmake)
120read_kconfig_config(${DOT_CONFIG_PATH})
121
122# FIXME: this successful triggers CMake to re-run, however -imacros
123# hides the generated .h dependency from CMake and most sources are NOT
124# recompiled.
125set_property(DIRECTORY APPEND
126	PROPERTY CMAKE_CONFIGURE_DEPENDS ${DOT_CONFIG_PATH})
127
128add_dependencies(sof_public_headers genconfig check_version_h)
129target_include_directories(sof_public_headers INTERFACE ${GENERATED_DIRECTORY}/include)
130
131if(CONFIG_LIBRARY)
132	if (CONFIG_LIBRARY_STATIC)
133		add_library(sof STATIC "")
134	else()
135		add_library(sof SHARED "")
136	endif()
137	target_link_libraries(sof PRIVATE sof_options)
138	target_link_libraries(sof PRIVATE sof_static_libraries)
139	install(TARGETS sof DESTINATION lib)
140
141	add_subdirectory(src)
142
143	sof_append_relative_path_definitions(sof)
144
145	get_target_property(incdirs sof_public_headers INTERFACE_INCLUDE_DIRECTORIES)
146
147	# we append slash at the end to make CMake copy contents of directories
148	# instead of directories
149	set(incdirs_for_install "")
150
151	foreach(d ${incdirs})
152		list(APPEND incdirs_for_install "${d}/")
153	endforeach()
154
155	install(DIRECTORY ${incdirs_for_install}
156		DESTINATION include
157		PATTERN "*.h"
158	)
159
160	# rest of this file is not needed for host build
161	return()
162endif()
163
164if(BUILD_UNIT_TESTS)
165	enable_testing()
166	add_subdirectory(src/arch/${ARCH})
167	add_subdirectory(test)
168	# rest of this file is not needed for unit tests
169	return()
170endif()
171
172# for FW just install api folders
173install(
174	DIRECTORY
175		${PROJECT_SOURCE_DIR}/src/include/ipc
176		${PROJECT_SOURCE_DIR}/src/include/kernel
177		${PROJECT_SOURCE_DIR}/src/include/user
178		${PROJECT_SOURCE_DIR}/rimage/src/include/sof/kernel
179		${PROJECT_SOURCE_DIR}/rimage/src/include/sof/user
180	DESTINATION include/sof
181	PATTERN "*.h"
182)
183
184add_library(sof_ld_flags INTERFACE)
185add_library(sof_ld_scripts INTERFACE)
186
187target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/third_party_include)
188link_directories(${PROJECT_SOURCE_DIR}/third_party_libraries)
189
190# declare target with no sources to let cmake know about it
191add_executable(sof "")
192target_link_libraries(sof PRIVATE sof_options)
193target_link_libraries(sof PRIVATE sof_ld_scripts)
194target_link_libraries(sof PRIVATE sof_ld_flags)
195target_link_libraries(sof PRIVATE sof_static_libraries)
196
197if (BUILD_COUNTERS)
198sof_add_build_counter_rule()
199endif()
200
201add_subdirectory(src)
202
203sof_append_relative_path_definitions(sof)
204