Создать функцию размера waf

Я создал функцию waf для запуска size во всех файлах сборки, но я не хочу делать это так, как хотел изначально (см. Custom waf задача не запускается и не находит исходники).

Итак, я написал сейчас функцию, которая в целом работает, но снова не находит источники правильно. Я использую @after('apply_link'), поэтому бинарники должны присутствовать...

  • Первый запуск: генерируются все двоичные файлы, но size не имеет входных файлов.
  • Второй запуск: все бинарники есть и функция size запускается корректно. Почему это так?

особенность ваф:

from waflib.TaskGen import extension
from waflib.TaskGen import after

class size(Task.Task):
    color = 'BLUE'
    run_str = '${SIZE} ${SRC} > ${TGT}'

@extension('.o', '.a', '.elf')
@after('apply_link')
def add_size(self, node):
    name = 'size'
    out = node.change_ext('.log')
    task = self.create_task(name, node, out)
    try:
        self.size_tasks.append(task)
    except AttributeError:
        self.size_tasks = [task]
    return task

Использование функции:

    bld(source=bld.path.get_bld().ant_glob('**/*.o **/*.a **/*.elf'),
    features='size')

Дополнительный вопрос: есть ли лучший вариант для регистрации вывода этой задачи как перенаправление вывода с помощью > в выходной файл?


waf
person wafwafwaf    schedule 10.12.2018    source источник


Ответы (1)


Когда вы используете декоратор Taskgen.after, вы просто указываете waf запускать метод add_size после метода apply_link на этапе генерации задачи. Поскольку ваш генератор задач ничего не связывает, у вас нет никакого apply_link метода, он вам не нужен.

Ваша проблема в том, что вы используете ant_glob в каталоге сборки. В первый раз в нем ничего нет, поэтому ant_glob ничего не возвращает, так что ваша задача тут ни при чем :)

Вы должны добавить функцию в генератор задач, которая создает объекты, размер которых вы хотите. Например:

@feature("size") # or feature("*") for every taskgen
@after('apply_link')
def process_sizes(self):

    if getattr(self, "link_task", None) is None:
        return

    objets_to_size = []

    objects_to_size.extend(self.link_task.inputs) # object files
    objects_to_size.extend(self.link_task.outputs) # exe, libs ...

    for node in objects_to_size:
         out = node.change_ext('.log')
         self.create_task("size", node, out)

Использовать:

bld.program(source = "main.c", features = "size", target = "myexe")

Вы получите размер всех файлов процесса ссылки.

@Taskgen.extension используется только Taskgen.process_source, которые обрабатывают атрибут source генератора задач. Он плохо работает с промежуточными объектами, не выраженными в wscript.

person neuro    schedule 10.12.2018
comment
Хм, это не работает на моей машине Cycle detected in the method execution: - process_use after ['propagate_uselib_vars'] - process_source after ['process_use', 'apply_link'] - apply_link after ['process_use', 'update_sources'] - propagate_uselib_vars after [] - update_sources after ['process_source'] - person wafwafwaf; 11.12.2018
comment
@waf3: да, моя ошибка. apply_link идет после process_source. Я отредактирую свой ответ... - person neuro; 11.12.2018
comment
хорошо, замечательно, теперь это работает :) спасибо за редактирование! Но я не могу понять, какие задачи генерируют файлы *.a и *.elf, так как в документации есть только link_task, описанный в документации. - person wafwafwaf; 12.12.2018
comment
статические библиотеки обычно генерируются с помощью ярлыка bld.stlib. Вы можете использовать link_task.outputs. Для .elf не знаю. Возможно, какой-то побочный эффект компиляции/ссылки? - person neuro; 12.12.2018
comment
Например, если у вас есть четкое сопоставление между .o и .elf, вы можете использовать change_ext для достижения того, чего хотите. - person neuro; 12.12.2018
comment
Ваш совет использовать link_task.outputs также был решением. Теперь он работает для всего двоичного вывода! Идеальный ответ, еще раз большое спасибо! - person wafwafwaf; 12.12.2018
comment
есть ли возможность уменьшить уровень логирования функции? - person wafwafwaf; 13.12.2018
comment
Вы можете использовать Logs.debug("myfeature: any log message"). Эти журналы не будут распечатываться на терминале, если вы не используете опцию --zone myfeature. Используйте Logs.info("any log") для журналов, которые вы всегда хотите распечатать. - person neuro; 13.12.2018