2011-06-30 2 views
2

Мне нужно определить количество байтов в произвольном файле с помощью сценария CMake, но переносимым образом.Что такое переносной способ в CMake для определения размера файла?

Этот файл может быть большим, поэтому чтение его с помощью команды файла (READ ...) и подсчета длины строки не является оптимальным.

Если мне нужно было работать только на MacOS и/или Linux, я бы просто использовал wc -c, что дает мне именно то, что я хочу. Но сценарий должен быть совместимым с Windows, предполагая только программную цепочку Windows. (Я не очень хорошо разбираюсь в разработке Windows.)

Я ожидал, что это будет обычная операция, но я не нахожу ничего похожего в источнике CMake Modules (вероятно, искал неправильную вещь), и это не по-видимому, поддерживаются командами cmake -E.

Так что я ищу либо какой-нибудь умный способ получить эту информацию с помощью одной команды, либо рекомендацию о том, какие команды я могу использовать в Windows и обернуть вокруг if(WIN32) условный.

+1

Мне любопытно, почему вы думаете, что это обычная операция , – RobertJMaynard

+0

В инструменте, предназначенном для создания и проверки файлов различных типов, размер файла является фундаментальным свойством. Решение sakara также включает подкоманду 'TIMESTAMP', еще одно фундаментальное свойство. – metasim

ответ

2

Существует модуль CMake под названием FileInformation, который позволяет получить размер файла портативным способом. Это добавляет новый подраздел команды CMake встроенный file команды:

file (SIZE filename variable) 
+0

Отлично! Спасибо, что поделились этим модулем. Действительно должен быть частью официального дистрибутива. – metasim

+0

Мне любопытно узнать, является ли 'макро (файл)' переопределением и использованием '_file()' общий шаблон, который можно использовать со всеми командами CMake, или если это возможно только потому, что базовая реализация 'file (...) 'предоставляет эту возможность?Я не могу найти документацию по этому поводу. Это очень мощный механизм. – metasim

+1

Это общий шаблон, упомянутый в списке рассылки CMake. См. [Здесь] (http://www.cmake.org/pipermail/cmake/2009-October/032725.html). – sakra

2

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

cmake_minimum_required(VERSION 2.8) 
project(test) 

try_run(RUN_RESULT COMPILE_RESULT ${CMAKE_CURRENT_BINARY_DIR}/bin 
    ${CMAKE_CURRENT_SOURCE_DIR}/filesize.c 
    RUN_OUTPUT_VARIABLE FILE_SIZE 
    ARGS ${CMAKE_CURRENT_SOURCE_DIR}/bigfile) 

if (NOT COMPILE_RESULT) 
    message(FATAL_ERROR "Filesize failed to compile") 
endif() 

if (RUN_RESULT EQUAL 0) 
    message(STATUS "Filesize ${FILE_SIZE}") 
else() 
    message(WARNING "Filesize failed") 
endif() 

И в filesize.c:

#include <stdio.h> 
int main(int argc, const char *argv[]) 
{ 
     FILE *fp = fopen(argv[1], "rb"); 
     if (fp != NULL) { 
       fseek(fp, 0, SEEK_END); 
       printf("%d", ftell(fp)); 
       fclose(fp); 
       return 0; 
     } 
     return 1; 
} 

COMPILE_RESULT ИСТИНА или ЛОЖЬ. И если файл не найден, try_run возвращает ошибку (в RUN_RESULT). В противном случае cmake запускает программу, которая ищет конец файла и печатает размер в байтах. Результат фиксируется в переменной FILE_SIZE.

Единственная проблема заключается в том, что он не будет работать для кросс-компиляции, так как try_run ничего не запускает в этом случае.

+0

Благодарим за подробный подход и напоминание о том, что CMake неплохо занимается созданием утилит. Я принял ответ @ sakra, потому что он так хорошо сочетается с существующей командой 'file()' и хорошо дополняется модулем. Это отличный и полезный ответ. – metasim

+0

Истинное решение плюс sakra будет работать для кросс-скомпилированного кода, поскольку он не полагается на скомпилированный код, вместо этого использует скрипты, специфичные для платформы (хотя скрипты на платформе очень скользкие, чтобы спуститься!). – richq

1

Ну, для коротких файлов вы можете сделать:

function(get_file_size var filename) 
    file(READ "${filename}" content HEX) 
    string(LENGTH "${content}" content_length) 
    math(EXPR content_length "${content_length}/2") 
    set(${var} ${content_length} PARENT_SCOPE) 
endfunction() 

get_file_size(len "main.c") 
message(STATUS "len(main.c)=${len}") 
+1

Вам нужно некоторое дополнительное цитирование, например. 'string (LENGTH" $ {content} "content_length)' в случае, если файл содержит точки с запятой. Да, цитирование CMake является странным. – Timmmm

Смежные вопросы