Skip to content

Commit

Permalink
cmake: generate the complete .config at configuration time.
Browse files Browse the repository at this point in the history
Add cmake -DINIT_CONFIG= option that can point at any initial file.

"make clean" does not delete .config any more.

Note reconfiguration does NOT causes recompilation because -imacros
hides the generated .h from CMake's dependency scan. This is not a
regression, that problems exists since -imacros was introduced. At least
it's now possible to "make clean" and rebuild without losing the .config
file.

Fix for thesofproject#3617

Signed-off-by: Marc Herbert <[email protected]>
  • Loading branch information
marc-hb authored and lgirdwood committed Mar 3, 2021
1 parent 453c686 commit 288e228
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 64 deletions.
41 changes: 18 additions & 23 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ if(NOT (${CMAKE_VERSION} VERSION_LESS "3.13.0"))
cmake_policy(SET CMP0079 OLD)
endif()

if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
# FindPythonInterp is bugged and may sometimes be unable to find
# Python 3 when both Python 2 & 3 are in PATH,
# so it's always better to use CMake 3.12+
find_package(PythonInterp 3.0)
set(PYTHON3 "${PYTHON_EXECUTABLE}")
else()
find_package(Python3 COMPONENTS Interpreter)
set(PYTHON3 "${Python3_EXECUTABLE}")
endif()

option(BUILD_UNIT_TESTS "Build unit tests" OFF)
option(BUILD_CLANG_SCAN "Build for clang's scan-build" OFF)

Expand Down Expand Up @@ -95,30 +106,14 @@ include(scripts/cmake/version.cmake)

include(scripts/cmake/dist.cmake)

# cmake itself cannot depend on files that don't exist
# so to make it regenerate when .config file is created,
# we make it depend on containing directory
# NOTE: some filesystems may be unable to watch directory change,
# in that case cmake may need to be regenerated from CLI
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${GENERATED_DIRECTORY} ${DOT_CONFIG_PATH})

if(EXISTS ${DOT_CONFIG_PATH})
read_kconfig_config(${DOT_CONFIG_PATH})
endif()

if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
# FindPythonInterp is bugged and may sometimes be unable to find
# Python 3 when both Python 2 & 3 are in PATH,
# so it's always better to use CMake 3.12+
find_package(PythonInterp 3.0)
set(PYTHON3 "${PYTHON_EXECUTABLE}")
else()
find_package(Python3 COMPONENTS Interpreter)
set(PYTHON3 "${Python3_EXECUTABLE}")
endif()

include(scripts/cmake/kconfig.cmake)
read_kconfig_config(${DOT_CONFIG_PATH})

# FIXME: this successful triggers CMake to re-run, however -imacros
# hides the generated .h dependency from CMake and most sources are NOT
# recompiled.
set_property(DIRECTORY APPEND
PROPERTY CMAKE_CONFIGURE_DEPENDS ${DOT_CONFIG_PATH})

add_dependencies(sof_public_headers genconfig check_version_h)
target_include_directories(sof_public_headers INTERFACE ${GENERATED_DIRECTORY}/include)
Expand Down
2 changes: 1 addition & 1 deletion scripts/cmake/defconfigs.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: BSD-3-Clause

# Looks for defconfig files in arch directory
# Looks for defconfig files in arch directories where kconfig.cmake looks too.
set(DEFCONFIGS_DIRECTORY "${PROJECT_SOURCE_DIR}/src/arch/${ARCH}/configs")
file(GLOB DEFCONFIG_PATHS "${DEFCONFIGS_DIRECTORY}/*_defconfig")

Expand Down
119 changes: 100 additions & 19 deletions scripts/cmake/kconfig.cmake
Original file line number Diff line number Diff line change
@@ -1,9 +1,105 @@
# SPDX-License-Identifier: BSD-3-Clause

# Kconfig targets

include(${CMAKE_CURRENT_LIST_DIR}/defconfigs.cmake)


### configure-time .config ###


if(NOT INIT_CONFIG_found)
# Brand new build directory, search for initial configuration

# Default value when no -DINIT_CONFIG on the command line
set(INIT_CONFIG "initial.config" CACHE STRING "Initial .config file")

# - ".' is the top source directory.
# - "src/arch/${arch}/configs" is for convenience and compatibility with
# defconfigs.cmake.
# - First found wins.
# - If two archs ever use the same platform_defconfig name then a full
# path must be used, e.g.: -DINIT_CONFIG=src/arch/myarch/collision_defconfig

set(init_config_search_list ".")
foreach(arch "xtensa" "host")
list(APPEND init_config_search_list "src/arch/${arch}/configs")
endforeach()

find_file(INIT_CONFIG_found
NAMES ${INIT_CONFIG}
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH
PATHS ${init_config_search_list}
)

else() # old build directory

if (INIT_CONFIG)
message(WARNING
"IGNORING '-DINIT_CONFIG=${INIT_CONFIG}!!' "
"Using up-to-date ${INIT_CONFIG_found} instead."
)
endif()

endif() # new/old build directory


if(NOT INIT_CONFIG_found)
message(FATAL_ERROR
"Initial configuration missing, no ${INIT_CONFIG} found. "
"Provide a ${PROJECT_SOURCE_DIR}/initial.config file or specify some "
"other -DINIT_CONFIG=location relative to '${PROJECT_SOURCE_DIR}/' or "
"'${PROJECT_SOURCE_DIR}/src/arch/*/configs/'"
)
endif()

# Did someone or something remove our generated/.config?
if(NOT EXISTS ${INIT_CONFIG_found})
message(FATAL_ERROR "The file ${INIT_CONFIG_found} vanished!")
endif()

# Don't confuse this configure-time, .config generation with
# the build-time, autoconfig.h genconfig target below
message(STATUS
"(Re-)generating ${DOT_CONFIG_PATH}\n"
" and ${CONFIG_H_PATH}\n"
" from ${INIT_CONFIG_found}"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E env
KCONFIG_CONFIG=${INIT_CONFIG_found}
srctree=${PROJECT_SOURCE_DIR}
CC_VERSION_TEXT=${CC_VERSION_TEXT}
ARCH=${ARCH}
${PYTHON3} ${PROJECT_SOURCE_DIR}/scripts/kconfig/genconfig.py
--config-out=${DOT_CONFIG_PATH}
--header-path ${CONFIG_H_PATH}
${PROJECT_SOURCE_DIR}/Kconfig
WORKING_DIRECTORY ${GENERATED_DIRECTORY}
# Available only from CMake 3.18. Amazingly not the default.
# COMMAND_ERROR_IS_FATAL ANY
RESULT_VARIABLE _genret
)
if(${_genret})
message(FATAL_ERROR
"genconfig.py from ${INIT_CONFIG_found} to ${DOT_CONFIG_PATH} failed")
endif()

if(NOT ${INIT_CONFIG_found} STREQUAL ${DOT_CONFIG_PATH})
# Brand new build directory and config.
message(STATUS
"Done, future changes to ${INIT_CONFIG_found}\n"
" will be IGNORED by this build directory! The primary .config\n"
" file is now 'generated/.config' in the build directory."
)
endif()
# Now force CMake to forget about the initial config and to re-use our
# own private ${DOT_CONFIG_PATH} when it decides it must re-run itself.
unset(INIT_CONFIG CACHE)
set(INIT_CONFIG_found ${DOT_CONFIG_PATH} CACHE FILEPATH "active .config" FORCE)


### build-time Kconfig targets ###

add_custom_target(
menuconfig
COMMAND ${CMAKE_COMMAND} -E env
Expand Down Expand Up @@ -33,24 +129,9 @@ add_custom_target(

file(GLOB_RECURSE KCONFIG_FILES "${SOF_ROOT_SOURCE_DIRECTORY}/Kconfig")

if(EXISTS ${DOT_CONFIG_PATH})
# Update with olddefconfig only if config was previously generated
add_custom_command(
OUTPUT ${DOT_CONFIG_PATH}
COMMAND ${CMAKE_COMMAND} -E env
srctree=${PROJECT_SOURCE_DIR}
CC_VERSION_TEXT=${CC_VERSION_TEXT}
ARCH=${ARCH}
${PYTHON3} ${PROJECT_SOURCE_DIR}/scripts/kconfig/olddefconfig.py
${PROJECT_SOURCE_DIR}/Kconfig
DEPENDS ${KCONFIG_FILES}
WORKING_DIRECTORY ${GENERATED_DIRECTORY}
COMMENT "Regenerating .config with olddefconfig"
VERBATIM
USES_TERMINAL
)
endif()

# Don't confuse this build-time, .h target with the
# configure-time, .config genconfig above.
add_custom_command(
OUTPUT ${CONFIG_H_PATH}
COMMAND ${CMAKE_COMMAND} -E env
Expand Down
8 changes: 8 additions & 0 deletions scripts/cmake/misc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ function(get_optimization_flag OUT_VAR)
set(${OUT_VAR} "Og" PARENT_SCOPE)
elseif(CONFIG_OPTIMIZE_FOR_NONE)
set(${OUT_VAR} "O0" PARENT_SCOPE)
else()
message(FATAL_ERROR "no CONFIG_OPTIMIZE_ found")
endif()
endfunction()

Expand All @@ -54,6 +56,12 @@ function(add_local_sources target)
endif()

target_sources(${target} PRIVATE ${path})
# -imacros${CONFIG_H_PATH} escapes regular .h dep scanning
# add_dependencies(${target} genconfig) # has no effect?
set_source_files_properties(${path}
PROPERTIES
OBJECT_DEPENDS ${CONFIG_H_PATH}
)
endforeach()
endfunction()

Expand Down
3 changes: 1 addition & 2 deletions scripts/xtensa-build-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,8 @@ do
-DMEU_OPENSSL="${MEU_OPENSSL}" \
"${MEU_PATH_OPTION}" \
"${PRIVATE_KEY_OPTION}" \
-DINIT_CONFIG=${PLATFORM}${DEFCONFIG_PATCH}_defconfig \
"$SOF_TOP"

cmake --build . -- ${PLATFORM}${DEFCONFIG_PATCH}_defconfig
)

if [ -n "$OVERRIDE_CONFIG" ]
Expand Down
3 changes: 0 additions & 3 deletions src/arch/xtensa/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,6 @@ endif()
# linker scripts

function(sof_add_ld_script binary_name script_name)
if(NOT EXISTS ${DOT_CONFIG_PATH})
return()
endif()

set(lds_in ${PROJECT_SOURCE_DIR}/src/platform/${platform_folder}/${script_name}.in)
set(lds_out ${PROJECT_BINARY_DIR}/${script_name})
Expand Down
9 changes: 1 addition & 8 deletions tools/oss-fuzz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,11 @@ ExternalProject_Add(sof_ep
-DCMAKE_INSTALL_PREFIX=${sof_install_directory}
-DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE}
-DCONFIG_H_PATH=${config_h}
-DINIT_CONFIG=library_defconfig
BUILD_ALWAYS 1
BUILD_BYPRODUCTS "${sof_install_directory}/lib/libsof.so"
)

ExternalProject_Add_Step(
sof_ep defconfig
COMMAND ${CMAKE_COMMAND} --build . --target library_defconfig
DEPENDEES configure
DEPENDERS build
WORKING_DIRECTORY "${sof_binary_directory}"
)

add_library(sof_library STATIC IMPORTED)
set_target_properties(sof_library PROPERTIES IMPORTED_LOCATION "${sof_install_directory}/lib/libsof.a")
add_dependencies(sof_library sof_ep)
Expand Down
9 changes: 1 addition & 8 deletions tools/testbench/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,12 @@ ExternalProject_Add(sof_ep
CMAKE_ARGS -DCONFIG_LIBRARY=ON
-DCMAKE_INSTALL_PREFIX=${sof_install_directory}
-DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE}
-DINIT_CONFIG=library_defconfig
-DCONFIG_H_PATH=${config_h}
BUILD_ALWAYS 1
BUILD_BYPRODUCTS "${sof_install_directory}/lib/libsof.so"
)

ExternalProject_Add_Step(
sof_ep defconfig
COMMAND ${CMAKE_COMMAND} --build . --target library_defconfig
DEPENDEES configure
DEPENDERS build
WORKING_DIRECTORY "${sof_binary_directory}"
)

add_library(sof_library SHARED IMPORTED)
set_target_properties(sof_library PROPERTIES IMPORTED_LOCATION "${sof_install_directory}/lib/libsof.so")
add_dependencies(sof_library sof_ep)
Expand Down

0 comments on commit 288e228

Please sign in to comment.