Всем снова привет. После предыдущих трех сообщений о основных исполняемых файлах, базовом управлении зависимостями и установке ваших двоичных файлов в Meson, сегодня я хочу сосредоточиться на двух вещах, которые до сих пор просто игнорировались: базовый синтаксис языка и команда Meson. линия. Что касается части командной строки, я также покажу, как использовать инструмент тестирования, и кратко расскажу о модульных тестах.

Синтаксис языка

У меня есть сильная тенденция сравнивать язык Meson с языком CMake. Почему? Ну, в основном потому, что, если я сейчас использую Meson, одно из моих самых больших разочарований, безусловно, было из-за языка CMake.

Приход в Meson, убегающий от бесконечных экспериментов с управлением пространством, интерполяцией переменных и совершенно безумными условными операторами, - это находка и одна из главных причин, почему я решил остановиться на Meson.

Итак, как выглядит синтаксис Meson? Что ж, для тех, кто привык к любому «обычному» (как в популярному) языку программирования, Meson не представляет никаких трудностей.

В Meson переменные могут содержать любой тип, но этот тип является сильным. Это означает, что Meson может легко обнаруживать ошибки во время настройки. Самое приблизительное, что вы можете придумать, - это сильный динамический язык программирования, такой как Python.

Вот тизер основных типов данных:

  • числа
  • булевы
  • струны
  • массивы
  • настраиваемые объекты, возвращаемые Meson
  • функции
  • методы
  • поток управления
  • зацикливание
  • логические операции
  • тернарный оператор
  • Комментарии

Я постараюсь быть как можно короче, чтобы объяснить все это с помощью фрагмента кода:

# Comments start with # and last for the rest of the line
my_number = 7 # This is a number
my_string = 'hello' # This is a string
# Ternary operator and booleans
cond = true
result = cond ? true : false
# An array. Can hold any kind of objects
arr = ['hello', 1, false]
# Add more elements
arr += ['bye', true]
# You can add a single item without enclosing in array
arr += 'world' # add to array
# Looping
foreach a : arr
  message(a) # Function call
endforecach

cpp_compiler = meson.get_compiler('cpp')
mylib = cpp_compiler.find_library('somelib', required : false)
mylib2 = cpp_compiler.find_library('anotherlib', required : false)
# Control flow with logical operation and (or also supported)
if mylib.found() and mylib2.found() # Method from object called
   message('Lib found')
endif
# Nested arrays and indexing
some_data = [['somelib', 'dir1'], ['someotherlib', 'dir2']]
foreach sd : some_data
   cpp_compiler.find_library(sd[0], dirs : sd[1])
endforeach

Думаю, это легко понять любому среднему программисту. Я упомяну только несколько вещей, которые могут быть немного другими или более неожиданными. Условные выражения и циклы заканчиваются на endif и endforeach соответственно. Массивы неизменяемы (при использовании + = концептуально создается новый массив со всем содержимым). Это означает, что этот код

arr1 = [3]
arr2 = arr1
arr2 += 5

возвращает arr1 со значением [3] и arr2 со значением [3, 5], а именно, arr1 не добавляет элемент arr2.

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

Командная строка Meson

Основная командная строка в Meson гибкая и не слишком отличается от командной строки CMake и Autotools.

Meson, как CMake, является генератором системы сборки: он генерирует файлы внутренней системы сборки. Генерация по умолчанию использует ниндзя в качестве бэкэнда, но можно использовать и другие. Остерегайтесь, поскольку, насколько мне известно, текущая поддержка: ninja лучше всего поддерживается, Visual Studio должна работать довольно хорошо, а XCode на самом деле не готов к производству. На данный момент я постоянно использую себя ниндзя и планирую проверить поддержку Visual Studio, но я не могу утверждать, насколько хорошо это работает на практике со сложным проектом с run_commands, run_targets и пользовательскими скриптами. Бэкэнд ниндзя работает отлично, по крайней мере, могу сказать :)

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

mkdir build
cd build
meson .. # Here you are mentioning the source dir

Вышеупомянутые команды определят каталог .. как исходный каталог и поместят все содержимое в build directory. Часть вывода этого вызова для моего проекта выглядит так:

The Meson build system
Version: 0.47.0.dev1
Source dir: /Users/germandiago/Desktop/tpii
Build dir: /Users/germandiago/Desktop/tpii/build
Build type: native build
Project name: tpii
Native C++ compiler: ccache c++ (clang 9.0.0 "Apple LLVM version 9.0.0 (clang-900.0.39.2)")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Configuring tpi-service-config.hpp using configuration
Program git found: YES (/usr/bin/git)
Program cmake found: YES (/usr/local/bin/cmake)
Program make found: YES (/usr/local/bin/make)
Dependency Boost (filesystem, regex, iostreams, system) found: YES 1.66, /usr/local/Cellar/boost/1.66.0/
Dependency Boost () found: YES 1.66, /usr/local/Cellar/boost/1.66.0/
Message: Initializating git submodules and compiling needed libraries. This can take a while...
Using json from cache.
Using json-2.1.1-1-wrap.zip from cache.

Да, я использую CMake для создания другого проекта, поэтому вы его видите здесь :) После завершения настройки вы можете просто сделать ninjaи весело смотреть, как строится ваш проект.

Вы также можете из корня вашего проекта:

mkdir build
meson build # Here you are mentioning the build dir 
ninja -C build

То есть вы можете просто создать каталог сборки и вызвать мезон из корня. Параметр -C в команде ninja указывает Ninja на сборку из каталога сборки, как это может делать GNU Make.

Теперь перейдем к самой командной строке: ваш терминал и введите meson --help. Вы увидите нечто похожее на это (вывод обрезан для соответствующего обсуждения):

optional arguments:
-h, --help            show this help message and exit
  --buildtype {plain,debug,debugoptimized,release,minsize}
                        Build type to use (default: debug).
  --strip               Strip targets on install.
  --unity {on,off,subprojects}
                        Unity build (default: off).
  
  --werror              Treat warnings as errors.
  --warnlevel {1,2,3}   Compiler warning level to use (default: 1).
  --layout {mirror,flat}
                        Build directory layout (default: mirror).
  --default-library {shared,static,both}
                        Default library type (default: shared).
  --backend {ninja,vs,vs2010,vs2015,vs2017,xcode}
                        Backend to use (default: ninja).
  --stdsplit            Split stdout and stderr in test logs.
  --errorlogs           Whether to print the logs from failing tests.
  --install-umask INSTALL_UMASK
                        Default umask to apply on permissions of installed
                        files (default: 022).
  -D option             Set the value of an option, can be used several times
                        to set multiple options.
  --cross-file CROSS_FILE
                        File describing cross compilation environment.
  -v, --version         show program's version number and exit
  --wrap-mode {WrapMode.default,WrapMode.nofallback,WrapMode.nodownload,WrapMode.forcefallback}
                        Special wrap mode to use
--prefix PREFIX       Installation prefix (default: /usr/local).

Давайте рассмотрим некоторые из наиболее распространенных вариантов:

  • buildtype
  • префикс
  • единство
  • -Doption = ценность

При первом вызове Meson он настроит и кэширует результаты вызова.

Например, вы можете сделать следующее:

meson --buildtype=release --prefix=`pwd`/install -Dmyoption=true --unity=on

Это создаст сборку выпуска, которая будет установлена ​​в вашем установочном каталоге вашего текущего каталога вызова с вашим настраиваемым параметром (определенным в meson_options.txt) и с использованием сборок единства.

Это для первого вызова.

Перенастройка проектов

После того, как проекты настроены, вы можете увидеть текущую конфигурацию с помощью meson configure builddir. Это покажет что-то похожее на это:

Core properties:
  Source dir ...
  Build dir  ...
Core options:
Option          Current Value Possible Values                                  Description
  ------          ------------- ---------------                                  -----------
  buildtype       debug         [plain, debug, debugoptimized, release, minsize] Build type to use.
  warning_level   1             [1, 2, 3]                                        Compiler warning level to use.
  werror          false         [true, false]                                    Treat warnings as errors.
  strip           false         [true, false]                                    Strip targets on install.
  unity           off           [on, off, subprojects]                           Unity build.
  default_library shared        [shared, static, both]                           Default library type.
  install_umask   18                                                             Default umask to apply on permissions of installed files.
  Option            Current Value Description
  ------            ------------- -----------
  backend_max_links 0             Maximum number of linker processes to run or 0 for no limit
Base options:
  Option      Current Value Possible Values                                               Description
  ------      ------------- ---------------                                               -----------
  b_asneeded  true          [true, false]                                                 Use -Wl,--as-needed when linking
  b_colorout  always        [auto, always, never]                                         Use colored output
  b_coverage  false         [true, false]                                                 Enable coverage tracking.
  b_lto       false         [true, false]                                                 Use link time optimization
  b_ndebug    false         [true, false, if-release]                                     Disable asserts
  b_pch       true          [true, false]                                                 Use precompiled headers
  b_pgo       off           [off, generate, use]                                          Use profile guided optimization
  b_sanitize  none          [none, address, thread, undefined, memory, address,undefined] Code sanitizer to use
  b_staticpic true          [true, false]                                                 Build static libraries as position independent
Compiler arguments:
  cpp_args []
Linker args:
  cpp_link_args []
Compiler options:
  Option  Current Value Description
  ------  ------------- -----------
  cpp_std none          C++ language standard to use
Directories:
  Option         Current Value  Description
  ------         -------------  -----------
  prefix         /usr/local     Installation prefix.
  libdir         lib            Library directory.
  libexecdir     libexec        Library executable directory.
  bindir         bin            Executable directory.
  sbindir        sbin           System executable directory.
  includedir     include        Header file directory.
  datadir        share          Data file directory.
  mandir         share/man      Manual page directory.
  infodir        share/info     Info page directory.
  localedir      share/locale   Locale data directory.
  sysconfdir     etc            Sysconf data directory.
  localstatedir  /var/local     Localstate data directory.
  sharedstatedir /var/local/lib Architecture-independent data directory.
Project options:
  Option                   Current Value  Possible Values Description
  ------                   -------------  --------------- -----------
  build_boost_from_source  false          [true, false]   Download and build boost from sources and use that dependency.
  build_tests              false          [true, false]   Build the test suite
  enable_content_creation  false          [true, false]   Enable custom commands to create website .html contents from .org files
  enable_tpi               false          [true, false]   Build standalone tpi
  enable_tpi_service       true           [true, false]   Build the tpi server
  tpi_service_enable_https false          [true, false]   Wether https is enabled or not. Used for base url
  tpi_service_host         localhost:8085                 Default host or ip address for tpi-service. It can include the port separated by colon
  tpi_service_listen_port  8085                           Default port for tpi-service. It will be used as default when running tpi-service without port argument
Testing options:
  Option    Current Value Possible Values Description
  ------    ------------- --------------- -----------
  stdsplit  true          [true, false]   Split stdout and stderr in test logs.
  errorlogs true          [true, false]   Whether to print the logs from failing tests.

Любую из этих опций, которые вы видите в списке, можно изменить с помощью -Doptionname = value. Вы можете видеть, что возможные значения перечислены в выводе. Это должно упростить задачу. Итак, теперь давайте удалим сборку Unity из проекта и создадим отладочную версию со статическими библиотеками.

meson configure -Ddefault_library=static -Dbuildtype=debug -Dunity=off builddir

Теперь ваш каталог сборки должен быть уже готов к компиляции с новой конфигурацией.

Вы можете настроить любую опцию с обозначением -Doption = value, даже встроенную, начиная с Meson 0.46.0 (например, prefix и default_library).

Подкоманды и тестирование Meson

В Meson есть несколько подкоманд, стиль которых соответствует популярному контролю версий git. Два из них meson introspect(, как следует из названия, для анализа метаданных о целях, таких как файлы сборки и т. Д.) И meson test. Здесь мы увидим только meson test.

В Meson, когда вы добавляете тесты в свой meson.build файл с помощью функции test, и вы можете запускать их в обычном режиме с вызовом серверной части, например ninja test, без использования meson test. Как мы увидим, подкоманда meson предназначена для более продвинутого использования и не всегда требуется.

Вот как вы добавляете тест в Meson:

exe = executable('myexe', sources : ['source.cpp'])
test('mytest', exe, args : ['--somearg'], env : ['ENVVAR=val'])

Как видите, test поддерживает аргументы и переменные среды. Теперь, запустив ninja test, можно запустить этот тест. В Meson параллельно проводятся тесты.

Тесты часто запускаются вместе с -Db_coverage = true, чтобы получить отчеты о покрытии тестами.

Существует также benchmarkфункция, аналогичная тесту, у которой есть соответствующая цель в ниндзя для запуска тестов. Тесты по сути такие же, как тесты, но они не выполняются параллельно.

Теперь давайте посмотрим, как вы можете вызвать инструмент тестирования в некоторых фрагментах:

# Same as ninja test
meson test
# Invoke the test with name 'testname'
meson test testname
# Invoke all tests 10 times (for example because you have randomized tests)
meson test --repeat=10
# Run 'testname' under valgrind
meson test --wrap=valgrind testname
# Looking for a strange, unusual crash? First crash puts you in gdb
meson test --gdb --repeat=10000 testname

Вывод

Я думаю, что на данный момент это все, и вы можете получить представление о том, как работает командная строка, как выглядит синтаксис и как вызывать некоторые тесты при различных потребностях. Это все для серии "Начало работы в Meson"!

В своем следующем посте в блоге я начну серию постов, чтобы рассказать о том, как я сделал небольшой, но достаточно большой реальный проект, исходный код которого скоро будет открыт под лицензией Boost. Этот проект использует веб-интерфейс React, библиотеку, исполняемый файл C ++, а также компилирует и экспортирует некоторое содержимое в режиме .org из Emacs в файлы html, которые позже отображаются после манипулирования DOM с помощью внешнего интерфейса React.

Некоторые из вещей, которые будут включены в проект:

  • компиляция исполняемого файла и библиотек
  • использование meson_options.txt для настройки параметров проекта во время конфигурации
  • создание файла project-config.hpp для использования в проекте
  • использование run_commands для загрузки зависимости и компиляции в CMake перед настройкой
  • запущенные тесты
  • использование подпроектов обертывания
  • установка цели для запуска веб-службы

Эта следующая серия сообщений в блоге не будет сосредоточена только на Meson, но она обязательно покажет, как все было построено, и будет опубликована в качестве примера, на который вы можете взглянуть в своих проектах. Быть в курсе!

Спасибо за чтение!