ldgen: pass component libraries directly

This commit is contained in:
Renz Christian Bagaporo 2019-04-26 13:42:10 +08:00
parent ca6cff7637
commit b1ecd75d83
5 changed files with 66 additions and 76 deletions

View file

@ -1,7 +1,6 @@
# Makefile to support the linker script generation mechanism # Makefile to support the linker script generation mechanism
LDGEN_SECTIONS_INFO_FILES = $(foreach lib, $(COMPONENT_LIBRARIES), $(BUILD_DIR_BASE)/$(lib)/lib$(lib).a.sections_info)
LDGEN_FRAGMENT_FILES = $(COMPONENT_LDFRAGMENTS) LDGEN_FRAGMENT_FILES = $(COMPONENT_LDFRAGMENTS)
LDGEN_LIBRARIES=$(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(libcomp)/lib$(libcomp).a)
ON_WINDOWS:=n ON_WINDOWS:=n
@ -15,54 +14,45 @@ endif
# the components # the components
ifeq ($(ON_WINDOWS),y) ifeq ($(ON_WINDOWS),y)
define ldgen_process_template define ldgen_process_template
$(BUILD_DIR_BASE)/ldgen.section_infos: $(LDGEN_SECTIONS_INFO_FILES) $(IDF_PATH)/make/ldgen.mk $(BUILD_DIR_BASE)/ldgen.section_infos: $(LDGEN_LIBRARIES) $(IDF_PATH)/make/ldgen.mk
printf "$(foreach info,$(LDGEN_SECTIONS_INFO_FILES),$(subst \,/,$(shell cygpath -w $(info)))\n)" > $(BUILD_DIR_BASE)/ldgen.section_infos printf "$(foreach info,$(LDGEN_LIBRARIES),$(subst \,/,$(shell cygpath -w $(info)))\n)" > $(BUILD_DIR_BASE)/ldgen_libraries
$(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(BUILD_DIR_BASE)/ldgen.section_infos $(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(BUILD_DIR_BASE)/ldgen_libraries
@echo 'Generating $(notdir $(2))' @echo 'Generating $(notdir $(2))'
$(PYTHON) $(IDF_PATH)/tools/ldgen/ldgen.py \ $(PYTHON) $(IDF_PATH)/tools/ldgen/ldgen.py \
--input $(1) \ --input $(1) \
--config $(SDKCONFIG) \ --config $(SDKCONFIG) \
--fragments $(LDGEN_FRAGMENT_FILES) \ --fragments $(LDGEN_FRAGMENT_FILES) \
--libraries-file $(BUILD_DIR_BASE)/ldgen_libraries \
--output $(2) \ --output $(2) \
--sections $(BUILD_DIR_BASE)/ldgen.section_infos \
--kconfig $(IDF_PATH)/Kconfig \ --kconfig $(IDF_PATH)/Kconfig \
--env "COMPONENT_KCONFIGS=$(foreach k, $(COMPONENT_KCONFIGS), $(shell cygpath -w $(k)))" \ --env "COMPONENT_KCONFIGS=$(foreach k, $(COMPONENT_KCONFIGS), $(shell cygpath -w $(k)))" \
--env "COMPONENT_KCONFIGS_PROJBUILD=$(foreach k, $(COMPONENT_KCONFIGS_PROJBUILD), $(shell cygpath -w $(k)))" \ --env "COMPONENT_KCONFIGS_PROJBUILD=$(foreach k, $(COMPONENT_KCONFIGS_PROJBUILD), $(shell cygpath -w $(k)))" \
--env "IDF_CMAKE=n" --env "IDF_CMAKE=n" \
--objdump $(OBJDUMP)
endef endef
else # ON_WINDOWS else # ON_WINDOWS
define ldgen_process_template define ldgen_process_template
$(BUILD_DIR_BASE)/ldgen.section_infos: $(LDGEN_SECTIONS_INFO_FILES) $(IDF_PATH)/make/ldgen.mk $(BUILD_DIR_BASE)/ldgen_libraries: $(LDGEN_LIBRARIES) $(IDF_PATH)/make/ldgen.mk
printf "$(foreach info,$(LDGEN_SECTIONS_INFO_FILES),$(info)\n)" > $(BUILD_DIR_BASE)/ldgen.section_infos printf "$(foreach library,$(LDGEN_LIBRARIES),$(library)\n)" > $(BUILD_DIR_BASE)/ldgen_libraries
$(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(BUILD_DIR_BASE)/ldgen.section_infos $(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(BUILD_DIR_BASE)/ldgen_libraries
@echo 'Generating $(notdir $(2))' @echo 'Generating $(notdir $(2))'
$(PYTHON) $(IDF_PATH)/tools/ldgen/ldgen.py \ $(PYTHON) $(IDF_PATH)/tools/ldgen/ldgen.py \
--input $(1) \ --input $(1) \
--config $(SDKCONFIG) \ --config $(SDKCONFIG) \
--fragments $(LDGEN_FRAGMENT_FILES) \ --fragments $(LDGEN_FRAGMENT_FILES) \
--libraries-file $(BUILD_DIR_BASE)/ldgen_libraries \
--output $(2) \ --output $(2) \
--sections $(BUILD_DIR_BASE)/ldgen.section_infos \
--kconfig $(IDF_PATH)/Kconfig \ --kconfig $(IDF_PATH)/Kconfig \
--env "COMPONENT_KCONFIGS=$(COMPONENT_KCONFIGS)" \ --env "COMPONENT_KCONFIGS=$(COMPONENT_KCONFIGS)" \
--env "COMPONENT_KCONFIGS_PROJBUILD=$(COMPONENT_KCONFIGS_PROJBUILD)" \ --env "COMPONENT_KCONFIGS_PROJBUILD=$(COMPONENT_KCONFIGS_PROJBUILD)" \
--env "IDF_CMAKE=n" --env "IDF_CMAKE=n" \
--objdump $(OBJDUMP)
endef endef
endif # ON_WINDOWS endif # ON_WINDOWS
define ldgen_create_commands define ldgen_create_commands
$(foreach lib, $(COMPONENT_LIBRARIES), \
$(eval $(call ldgen_generate_target_sections_info, $(BUILD_DIR_BASE)/$(lib)/lib$(lib).a)))
ldgen-clean: ldgen-clean:
rm -f $(LDGEN_SECTIONS_INFO_FILES) rm -f $(BUILD_DIR_BASE)/ldgen_libraries
rm -f $(BUILD_DIR_BASE)/ldgen.section_infos
endef
# Target to generate sections info file from objdump of component archive
define ldgen_generate_target_sections_info
$(1).sections_info: $(1)
@echo 'Generating $(notdir $(1).sections_info)'
$(OBJDUMP) -h $(1) > $(1).sections_info
endef endef

View file

@ -64,7 +64,7 @@ function(register_component)
set_property(TARGET ${COMPONENT_TARGET} PROPERTY OUTPUT_NAME ${COMPONENT_NAME}) set_property(TARGET ${COMPONENT_TARGET} PROPERTY OUTPUT_NAME ${COMPONENT_NAME})
ldgen_generate_sections_info(${COMPONENT_TARGET}) ldgen_component_add(${COMPONENT_TARGET})
else() else()
add_library(${COMPONENT_TARGET} INTERFACE) # header-only component add_library(${COMPONENT_TARGET} INTERFACE) # header-only component
set(include_type INTERFACE) set(include_type INTERFACE)

View file

@ -1,45 +1,34 @@
# Utilities for supporting linker script generation in the build system # Utilities for supporting linker script generation in the build system
# ldgen_create_target # ldgen_set_variables
# #
# Create the custom target to attach the fragment files and template files # Create the custom target to attach the fragment files and template files
# for the build to. # for the build to.
function(ldgen_set_variables) function(ldgen_set_variables)
add_custom_target(ldgen_section_infos) add_custom_target(ldgen)
add_custom_target(ldgen DEPENDS ldgen_section_infos)
endfunction() endfunction()
# ldgen_add_fragment_file # ldgen_add_fragment_files
# #
# Add one or more linker fragment files, and append it to the list of fragment # Add one or more linker fragment files, and append it to the list of fragment
# files found so far. # files found so far.
function(ldgen_add_fragment_files target fragment_files) function(ldgen_add_fragment_files component fragment_files)
spaces2list(fragment_files) spaces2list(fragment_files)
foreach(fragment_file ${fragment_files}) foreach(fragment_file ${fragment_files})
get_filename_component(fragment_file_abs_dir ${fragment_file} ABSOLUTE BASE_DIR ${component_dir}) get_filename_component(_fragment_file ${fragment_file} ABSOLUTE)
list(APPEND fragment_files_full_path ${fragment_file_abs_dir}) list(APPEND _fragment_files ${_fragment_file})
endforeach() endforeach()
set_property(TARGET ldgen APPEND PROPERTY FRAGMENT_FILES ${fragment_files_full_path}) set_property(TARGET ldgen APPEND PROPERTY FRAGMENT_FILES ${_fragment_files})
endfunction() endfunction()
# ldgen_generate_sections_info # ldgen_component_add
# #
# Generate sections info for specified target to be used in linker script generation # Add component to known libraries for linker script generation
function(ldgen_generate_sections_info target) function(ldgen_component_add component_lib)
get_filename_component(target_sections_info ${CMAKE_CURRENT_BINARY_DIR}/${target}.sections_info ABSOLUTE) set_property(TARGET ldgen APPEND PROPERTY OUTPUT_LIBRARIES "$<TARGET_FILE:${component_lib}>")
set_property(TARGET ldgen APPEND PROPERTY LIBRARIES ${component_lib})
add_custom_command(
OUTPUT ${target_sections_info}
COMMAND ${CMAKE_OBJDUMP} $<TARGET_FILE:${target}> -h > ${target_sections_info}
DEPENDS ${target}
)
add_custom_target(${target}_sections_info DEPENDS ${target_sections_info})
add_dependencies(ldgen_section_infos ${target}_sections_info)
set_property(TARGET ldgen_section_infos APPEND PROPERTY SECTIONS_INFO_FILES ${target_sections_info})
endfunction() endfunction()
# ldgen_process_template # ldgen_process_template
@ -47,10 +36,17 @@ endfunction()
# Passes a linker script template to the linker script generation tool for # Passes a linker script template to the linker script generation tool for
# processing # processing
function(ldgen_process_template template output) function(ldgen_process_template template output)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/ldgen.section_infos get_property(output_libraries TARGET ldgen PROPERTY OUTPUT_LIBRARIES)
CONTENT "$<JOIN:$<TARGET_PROPERTY:ldgen_section_infos,SECTIONS_INFO_FILES>,\n>") file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/ldgen_libraries.in CONTENT "$<JOIN:${output_libraries},\n>")
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/ldgen_libraries INPUT ${CMAKE_BINARY_DIR}/ldgen_libraries.in)
get_filename_component(filename "${template}" NAME_WE)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${CMAKE_BINARY_DIR}/ldgen_libraries.in"
"${CMAKE_BINARY_DIR}/ldgen_libraries")
# Create command to invoke the linker script generator tool.
add_custom_command( add_custom_command(
OUTPUT ${output} OUTPUT ${output}
COMMAND ${PYTHON} ${IDF_PATH}/tools/ldgen/ldgen.py COMMAND ${PYTHON} ${IDF_PATH}/tools/ldgen/ldgen.py
@ -58,15 +54,16 @@ function(ldgen_process_template template output)
--fragments "$<JOIN:$<TARGET_PROPERTY:ldgen,FRAGMENT_FILES>,\t>" --fragments "$<JOIN:$<TARGET_PROPERTY:ldgen,FRAGMENT_FILES>,\t>"
--input ${template} --input ${template}
--output ${output} --output ${output}
--sections ${CMAKE_BINARY_DIR}/ldgen.section_infos --kconfig ${ROOT_KCONFIG}
--kconfig ${IDF_PATH}/Kconfig
--env "COMPONENT_KCONFIGS=${COMPONENT_KCONFIGS}" --env "COMPONENT_KCONFIGS=${COMPONENT_KCONFIGS}"
--env "COMPONENT_KCONFIGS_PROJBUILD=${COMPONENT_KCONFIGS_PROJBUILD}" --env "COMPONENT_KCONFIGS_PROJBUILD=${COMPONENT_KCONFIGS_PROJBUILD}"
--env "IDF_CMAKE=y" --env "IDF_CMAKE=y"
--env "IDF_PATH=${IDF_PATH}" --env "IDF_PATH=${IDF_PATH}"
--env "IDF_TARGET=${IDF_TARGET}" --env "IDF_TARGET=${IDF_TARGET}"
DEPENDS ${template} $<TARGET_PROPERTY:ldgen,FRAGMENT_FILES> ${SDKCONFIG} --libraries-file ${CMAKE_BINARY_DIR}/ldgen_libraries
ldgen_section_infos --objdump ${CMAKE_OBJDUMP}
DEPENDS ${template} $<TARGET_PROPERTY:ldgen,FRAGMENT_FILES>
$<TARGET_PROPERTY:ldgen,LIBRARIES> ${SDKCONFIG}
) )
get_filename_component(output_name ${output} NAME) get_filename_component(output_name ${output} NAME)
@ -74,9 +71,9 @@ function(ldgen_process_template template output)
add_dependencies(ldgen ldgen_${output_name}_script) add_dependencies(ldgen ldgen_${output_name}_script)
endfunction() endfunction()
# ldgen_create_commands # ldgen_add_dependencies
# #
# Create the command to generate the output scripts from templates presented. # Add dependency of project executable to ldgen custom target.
function(ldgen_add_dependencies) function(ldgen_add_dependencies)
if(IDF_PROJECT_EXECUTABLE) if(IDF_PROJECT_EXECUTABLE)
add_dependencies(${IDF_PROJECT_EXECUTABLE} ldgen) add_dependencies(${IDF_PROJECT_EXECUTABLE} ldgen)

View file

@ -573,8 +573,8 @@ class SectionsInfo(dict):
def __init__(self): def __init__(self):
self.sections = dict() self.sections = dict()
def add_sections_info(self, sections_info_file): def add_sections_info(self, sections_info_dump):
first_line = sections_info_file.readline() first_line = sections_info_dump.readline()
archive_path = (Literal("In archive").suppress() + archive_path = (Literal("In archive").suppress() +
# trim the last character from archive_path, : # trim the last character from archive_path, :
@ -587,10 +587,10 @@ class SectionsInfo(dict):
try: try:
results = parser.parseString(first_line) results = parser.parseString(first_line)
except ParseException as p: except ParseException as p:
raise ParseException("File " + sections_info_file.name + " is not a valid sections info file. " + p.message) raise ParseException("Parsing sections info for library " + sections_info_dump.name + " failed. " + p.message)
archive = os.path.basename(results.archive_path) archive = os.path.basename(results.archive_path)
self.sections[archive] = SectionsInfo.__info(sections_info_file.name, sections_info_file.read()) self.sections[archive] = SectionsInfo.__info(sections_info_dump.name, sections_info_dump.read())
def _get_infos_from_file(self, info): def _get_infos_from_file(self, info):
# Object file line: '{object}: file format elf32-xtensa-le' # Object file line: '{object}: file format elf32-xtensa-le'

View file

@ -18,12 +18,14 @@
import argparse import argparse
import sys import sys
import tempfile import tempfile
import subprocess
from fragments import FragmentFile from fragments import FragmentFile
from sdkconfig import SDKConfig from sdkconfig import SDKConfig
from generation import GenerationModel, TemplateModel, SectionsInfo from generation import GenerationModel, TemplateModel, SectionsInfo
from ldgen_common import LdGenFailure from ldgen_common import LdGenFailure
from pyparsing import ParseException, ParseFatalException from pyparsing import ParseException, ParseFatalException
from io import StringIO
def main(): def main():
@ -42,9 +44,9 @@ def main():
nargs="+") nargs="+")
argparser.add_argument( argparser.add_argument(
"--sections", "-s", "--libraries-file",
type=argparse.FileType("r"), type=argparse.FileType("r"),
help="Library sections info") help="File that contains the list of libraries in the build")
argparser.add_argument( argparser.add_argument(
"--output", "-o", "--output", "-o",
@ -64,27 +66,28 @@ def main():
action='append', default=[], action='append', default=[],
help='Environment to set when evaluating the config file', metavar='NAME=VAL') help='Environment to set when evaluating the config file', metavar='NAME=VAL')
argparser.add_argument(
"--objdump",
help="Path to toolchain objdump")
args = argparser.parse_args() args = argparser.parse_args()
input_file = args.input input_file = args.input
fragment_files = [] if not args.fragments else args.fragments fragment_files = [] if not args.fragments else args.fragments
libraries_file = args.libraries_file
config_file = args.config config_file = args.config
output_path = args.output output_path = args.output
kconfig_file = args.kconfig kconfig_file = args.kconfig
sections = args.sections objdump = args.objdump
try: try:
sections_infos = SectionsInfo() sections_infos = SectionsInfo()
for library in libraries_file:
if sections: library = library.strip()
section_info_contents = [s.strip() for s in sections.read().split("\n")] if library:
section_info_contents = [s for s in section_info_contents if s] dump = StringIO(subprocess.check_output([objdump, "-h", library]).decode())
else: dump.name = library
section_info_contents = [] sections_infos.add_sections_info(dump)
for sections_info_file in section_info_contents:
with open(sections_info_file) as sections_info_file_obj:
sections_infos.add_sections_info(sections_info_file_obj)
generation_model = GenerationModel() generation_model = GenerationModel()