Какой команде cmake соответствует vpath в GNU make? - PullRequest
2 голосов
/ 26 февраля 2012

Я переписываю скрипт сборки cmake из существующего файла сборки GNU. Это первый скрипт cmake, который я пытался написать.

GNU make предоставляет команду vpaths, но я не могу найти соответствующую команду.

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

У вас есть какое-нибудь решение для этого?


Это занимает некоторое время при многих источниках и режиссерах.

макрос (vpath resultSource NumOfSource NumOfDir sourceList DirList) математика (EXPR startDirIndex "3 + $ {NumOfSource}") математика (EXPR endIndex "2 + $ {NumOfSource} + $ {NumOfDir}")

message(STATUS "startDirIndex: ${startDirIndex}")
message(STATUS "endIndex: ${endIndex}")

set( __SRC_LIST__ )
set( __SRC_DIR__ )

set( pos 0 )
foreach(item ${ARGV})
    if( ${pos} EQUAL ${startDirIndex} 
        OR ${pos} GREATER ${startDirIndex} )

        list( APPEND __SRC_DIR__ ${item} )
        #message(STATUS "DIR:${item}")

    elseif( ${pos} GREATER 2 )

        list( APPEND __SRC_LIST__ ${item} )
        #message(STATUS "SRC:${item}")

    endif( ${pos} EQUAL ${startDirIndex} 
        OR ${pos} GREATER ${startDirIndex} )

    math(EXPR pos "${pos}+1")
endforeach(item ${ARGV})

#message(STATUS "__SRC_LIST__: ${__SRC_LIST__}")
#message(STATUS "__SRC_DIR__: ${__SRC_DIR__}")

#set( SOURCE_EXTENTION cpp c C CPP)
set( SOURCE_EXTENTION cpp )
#list( APPEND SOURCE_EXTENTION ${CMAKE_CXX_SOURCE_FILE_EXTENSIONS} ${CMAKE_C_SOURCE_FILE_EXTENSIONS} )

#message(STATUS "SOURCE_EXTENTION: ${SOURCE_EXTENTION}")

set( temp_list "" )

foreach( dir ${__SRC_DIR__} )
    foreach( src ${__SRC_LIST__} )
        set( cand_src )
        foreach( postfix ${SOURCE_EXTENTION})
            set( cand_src "${dir}/${src}.${postfix}" )
            file(GLOB result ${cand_src} )
            if( NOT ${result} STREQUAL "" )
                list( APPEND temp_list ${result} )                    
            endif( NOT ${result} STREQUAL "" )                            
        endforeach( postfix ${SOURCE_EXTENTION})
    endforeach( src ${__SRC_LIST__} )
endforeach( dir ${__SRC_DIR__} )

set( ${resultSource} ${temp_list} )

#message(STATUS "temp_list: ${temp_list}")

endmacro (vpath resultSource NumOfSource NumOfDir sourceList DirList)

1 Ответ

3 голосов
/ 27 февраля 2012

Это то, что я думаю. Полный отказ от ответственности: я на самом деле не гуру cmake, и этот ответ основан исключительно на моих исследованиях после прочтения вопроса. У меня нет проекта, чтобы проверить это, и я никогда не использовал vpath в Makefile, который я написал.

Кроме того, этот вопрос не публикует пример Makefile и не публикует макрос, используемый OP, что заставляет меня сомневаться в том, чтобы дать ответ «используй это», но здесь идет речь.

Во-первых: почему мы используем vpath в нашем Makefile? Поскольку я не знал, что такое vpath, я посмотрел его. Из GNU Make Manual , раздел 4.5:

Функции поиска по каталогам make облегчают это, автоматически выполняя поиск по нескольким каталогам, чтобы найти необходимое условие ... Аналогично переменной VPATH, но более избирательной является директива vpath (обратите внимание на нижний регистр), которая позволяет указывать путь поиска для определенного класса имен файлов: тех, которые соответствуют определенному шаблону. Таким образом, вы можете предоставить определенные каталоги поиска для одного класса имен файлов и другие каталоги (или ни одного) для других имен файлов.

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

Я нашел несколько примеров vpath, которые кажутся показательными для его использования - этот вопрос StackOverflow , этот и, наконец, Управление проектами с помощью GNU make, третий Редакция раздел 2.3.

Так вот , почему вы бы использовали vpath. Итак, двигаясь дальше:

Во-вторых, как добиться того же, используя cmake. И здесь полезен дальнейший вклад со стороны ОП.

Если у вас есть несколько целей , которые вы строите из структуры каталогов, подобной этой:

|- library1/
|-- {C++ Source}
|- Tool/
|-- {C++ Source}
|- Project/
|-- src/
|---- {C++ Source}

Вы должны использовать несколько CMakeLists.txt, по одному в каждом из подкаталогов. В library1 вы создадите библиотеку (ADD_LIBRARY( libNAME src1.cxx src2.cxx src3.cxx )), в Tool вы добавите исполняемый файл (ADD_EXECUTABLE( theTOOL src1.cxx src2.cxx )). Наконец, в Project/src/ вы создадите исполняемый файл вашего проекта с ADD_EXECUTABLE, связав его с libNAME, который вы встроили в library1.

В этом сценарии вам не нужно искать , потому что ваш источник явно помещен в CMakeLists.txt.

Если вы не делаете что-то подобное выше, и ваш источник просто распределен по многим многим каталогам, примерно так:

|-Project/
|--src/
|----maths/
|------ { SOURCE FILES }
|----sound/
|------ { SOURCE FILES }
|----imagegeneration/
|------ { SOURCE FILES }

В этом случае вы создаете только одну вещь и просто распространяете свой источник для простоты использования. В этом случае есть несколько вариантов для вас.

  1. Вы можете использовать ответ, отправленный здесь , чтобы автоматически добавлять все файлы типа к цели. Это НЕ должно быть сделано! Из cmake --help-command file (выделено мной):

    GLOB сгенерирует список всех файлов, которые соответствуют выражениям globbing, и сохранит его в переменной ... Мы не рекомендуем использовать GLOB для сбора списка источников файлы из вашего исходного дерева .
    [См. ниже причину, по которой это так]
  2. Вы можете использовать директиву add_subdirectory, чтобы добавить несколько подкаталогов, по одному для каждого вашего исходного подкаталога. Это тоже не идеально. (Некоторая подтверждающая документация: ссылка , в которой обсуждается использование add_subdirectory таким образом)

  3. Вы можете использовать aux_source_directory для сбора исходных файлов из указанного каталога и сохранения в переменной. (Прочтите cmake --help-command aux_source_directory, если вам это интересно). Однако, это тоже , а не рекомендуется.

Итак почему не следует использовать (1), (2) или (3)? cmake не является заменой для make или Makefiles. Скорее, cmake генерирует a build system, который вы затем используете для создания своего проекта. Это различие стоит отметить. Хотя вы можете легко добавить несколько источников к вашему CMakeLists.txt автоматически, вы вызовете неоднозначность для cmake: cmake не сможет создать систему сборки, которая знает исходные файлы, чтобы определить, что изменилось!

Это проблема всех трех методов, упомянутых выше. От cmake --help-command aux_source_directory:

Хотя это, кажется, работает, CMake не может сгенерировать систему сборки, которая знает, когда новый исходный файл был добавлен. Обычно сгенерированная система сборки знает, когда нужно перезапустить CMake, потому что файл CMakeLists.txt изменен, чтобы добавить новый источник. Когда источник только что добавлен в каталог без изменения этого файла, придется вручную Перезапустите CMake, чтобы сгенерировать систему сборки, включающую новый файл.

Суммирование: как добавить исходные файлы в cmake?

При использовании cmake вы должны явно добавлять исходные файлы к каждому из ваших CMakeLists.txt. Если вы используете несколько каталогов для разделения логических фрагментов кода, это должно быть явно указано в CMakeLists.txt, что-то похожее на следующее:

set ( MyApplication_SRC_FILES
    maths/a.cpp
    maths/b.cpp
    sound/c.cpp
    sound/d.cpp
    imagegeneration/e.cpp
    imagegeneration/f.cpp
)
ADD_EXECUTABLE ( MyApplication ${MyApplication_SRC_FILES} )

Это позволяет cmake создать систему сборки, которая может собрать ваш код. Существуют подходящие методы для добавления многочисленных файлов в каталогах в систему сборки, описанные в (1), (2) и (3) выше; но к ним следует относиться с осторожностью, а не использовать их только потому, что «так я и поступил со своим Makefile». Вы не пишете саму систему сборки; это шаг назад от Makefile, и поэтому к нему следует относиться немного по-другому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...