विषय पर बढ़ें

अंतिम अद्यतन:2026-10-12

Meson से C++ प्रोजेक्ट बिल्ड करना

हाल ही में कुछ open source projects उपयोग करते समय पाया कि उन सभी ने meson+ninja के build तरीके को अपनाया है और CMake, Makefile के तरीके को छोड़ दिया है, इस लेख में हम Meson का परिचय कराएँगे, इंस्टॉलेशन से लेकर एक पूरे meson प्रोजेक्ट के लेखन तक।

आइए, अब मुख्य विषय में आते हैं।

1. Meson इंस्टॉल करना

https://github.com/mesonbuild/meson

Meson को PyPi से प्राप्त किया जा सकता है, इसलिए pip3 install meson से इंस्टॉल किया जा सकता है। अलग-अलग systems में सही pip command का उपयोग सुनिश्चित करें, और Python 3 version वाला pip ही ज़रूर उपयोग करें।

अगर चाहें, तो standard Python command से locally भी इंस्टॉल किया जा सकता है:

python3 -m pip install meson

Ninja से build करने की स्थिति में, Ninja को सीधे उसके GitHub release page से या PyPi के ज़रिए download किया जा सकता है:

python3 -m pip install ninja

Meson build के इंस्टॉलेशन के बारे में अधिक जानकारी के लिए, नीचे दी गई Meson की official website पढ़ें।

https://mesonbuild.com/Getting-meson.html

2. Meson Vs Cmake

जब सभी CMake उपयोग करते हैं, तो Meson क्यों उपयोग करें, इन दोनों के अपने-अपने फ़ायदे और नुकसान क्या हैं?

Performance की दृष्टि से, Meson अपनी तेज़ build speed के लिए जाना जाता है। Meson का design build speed को optimize करने के लिए किया गया है, और incremental builds में यह विशेष रूप से उत्कृष्ट प्रदर्शन करता है। Meson, Ninja build system को डिफ़ॉल्ट backend के रूप में उपयोग करता है, और Ninja खुद भी तेज़ और efficient होने के लिए जाना जाता है।

इसकी तुलना में, CMake की build speed project के size से प्रभावित हो सकती है, खासकर बड़े projects में। CMake विभिन्न generators (जैसे Makefile) उपयोग करता है, और अलग-अलग generators की performance भी भिन्न हो सकती है।

बेशक compilation speed बढ़ाने के लिए CMake + Ninja का उपयोग भी किया जा सकता है।

Open source project के नज़रिए से देखें तो Meson के उपयोग के दृश्य भी बहुत हैं, उदाहरण के लिए: PostgreSQL, QEMU, GNOME Software, GTK+, आदि

https://mesonbuild.com/Users.html

2.1 Meson के फ़ायदे और नुकसान

1.फ़ायदे

  • Python आधारित, उपयोग में सरल
  • cross compilation का समर्थन
  • सभी objects strongly typed हैं: objects 'dependency', 'include directory' जैसी entities हैं, इसलिए string replacement की गलतियाँ होना बहुत मुश्किल है।
  • थर्ड-पार्टी लाइब्रेरीज़ reference करना बहुत सुविधाजनक
  • बहुत बहुत तेज़, खासकर incremental build के समय।
  • documentation, cmake से n गुना बेहतर।

http://mesonbuild.com

2.नुकसान

  • शायद CMake जितना mature नहीं
  • Python3 + Ninja की dependency
  • project generators, IDE समर्थन में Meson, CMake जितना नहीं
  • vscode समर्थन
  • https://github.com/mesonbuild/vscode-meson
  • उपलब्ध modules सीमित
  • non-meson projects को खुद wrapdb पर submit करना पड़ता है
  • https://mesonbuild.com/Wrapdb-projects.html

2.2 CMake के फ़ायदे और नुकसान

1.फ़ायदे

  • IDE समर्थन friendly, team collaboration के लिए काफी अच्छा
  • mature, लगभग C++ projects का standard बन चुका है

2.कमियाँ

  • cross compilation कठिन
  • compilation speed तुलनात्मक रूप से धीमी

3. Meson WrapDB

चूंकि googletest एक meson project नहीं है, तो meson से इसे dependency के रूप में कैसे उपयोग करें?

इसी तरह, grpc, abseil-cpp के उपयोग का तरीका भी समान है।

यहाँ पहले WrapDB का परिचय देना ज़रूरी है, Meson WrapDB, Meson build system का एक component है, जो थर्ड-पार्टी projects की build description files को manage और provide करता है, जिन्हें आमतौर पर "wrap" files कहा जाता है। इन wrap files में थर्ड-पार्टी project को configure और build करने के लिए ज़रूरी जानकारी होती है, ताकि उन्हें Meson build system उपयोग करने वाले अन्य projects में आसानी से integrate किया जा सके।

search command या नीचे दी गई website से थर्ड-पार्टी लाइब्रेरीज़ की खोज की जा सकती है।

https://mesonbuild.com/Wrapdb-projects.html#meson-wrapdb-packages

हम gtest के उपयोग का उदाहरण लेते हैं:

  • gtest search करें
meson wrap search gtest

अगर यह command wrap किए गए project का नाम return करती है, तो अगला step लिया जा सकता है:

  • अपने project में subprojects directory बनाएँ, install से gtest इंस्टॉल करें
mkdir -p subprojects
meson wrap install gtest

इस समय आपके project की सभी dependencies subprojects directory में इंस्टॉल हो चुकी हैं।

➜  gtest_div tree -L 1 subprojects
subprojects
├── gtest.wrap

इससे gtest.wrap generate होगा, इसकी सामग्री में निम्नलिखित शामिल होगा।

ध्यान दें: यह फ़ाइल ऊपर install के बाद बनी फ़ाइल है, इसे बदलने की सलाह नहीं दी जाती।

[wrap-file]
directory = googletest-1.14.0
source_url = https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
source_filename = gtest-1.14.0.tar.gz
source_hash = 8ad598c73ad796e0d8280b082cebd82a630d73e73cd3c70057938a6501bba5d7
patch_filename = gtest_1.14.0-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/gtest_1.14.0-1/get_patch
patch_hash = 2e693c7d3f9370a7aa6dac802bada0874d3198ad4cfdf75647b818f691182b50
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/gtest_1.14.0-1/gtest-1.14.0.tar.gz
wrapdb_version = 1.14.0-1

[provide]
gtest = gtest_dep
gtest_main = gtest_main_dep
gmock = gmock_dep
gmock_main = gmock_main_dep

4. एक meson प्रोजेक्ट कैसे लिखें?

आगे बढ़ते हुए practice के चरण में आते हैं, एक meson project कैसे लिखें?

नीचे a/b division test का उदाहरण है, gtest से unit testing करने वाला एक छोटा project।

4.1 कोड लिखना

double divide(double a, double b);

.h और .cc को src directory में रखें:

src
├── division.cc
└── division.h

इसके बाद same level पर test directory बनाएँ।

test
└── division_test.cc

4.2 meson प्रोजेक्ट प्रबंधन

project के root path पर meson.build फ़ाइल जोड़ें, इसकी सामग्री इस प्रकार है:

project('gtest_div', 'cpp')
gtest_proj = subproject('gtest')
gtest_dep = gtest_proj.get_variable('gtest_main_dep') 
div_src = files('src/division.cc')
tests_src = files('test/division_test.cc')
e = executable(
    'division_test',
    tests_src + div_src, 
    dependencies : [ gtest_dep],
    override_options : ['cpp_std=c++14']
)
# https://mesonbuild.com/Unit-tests.html#testing-tool
test('this is a division test', e)

देखा जा सकता है कि यह सामग्री python के syntax से लगभग एक समान है, python से परिचित लोगों के लिए यह code समझना बहुत आसान है, यहाँ ऊपर दिए गए कुछ ज़रूरी हिस्सों पर ध्यान से बात करेंगे।

  • थर्ड-पार्टी लाइब्रेरी import करना

उदाहरण के लिए: आपके import किए गए थर्ड-पार्टी लाइब्रेरी वाले project का नाम gtest है, जैसे:

project('gtest', 'cpp',
  version : '1.14.0',
  default_options : ['cpp_std=c++14'],
  license : 'bsd')

तब subproject से इस project को प्राप्त किया जा सकता है, और फिर gtest_proj.get_variable से gtest की dependency जानकारी प्राप्त की जा सकती है, उदाहरण के लिए: googletest में इसे इस तरह declare किया गया है:

gtest_main_dep = declare_dependency(
    include_directories : gtest_incdir,
    sources : [gtest_libsources, gtest_mainsources],
    dependencies : dependency('threads')
)
  • executable

executable, cmake के add_executable से बहुत मिलता-जुलता है, यह executable फ़ाइल division_test बनाता है।

  • test

Unit testing का syntax:

e = executable('prog', 'testprog.c')
test('name of test', e)

meson test या ninja test का उपयोग किया जा सकता है, run होने के बाद test log बनता है, जो यहाँ स्थित है:

build/meson-logs/testlog.txt

4.3 Meson प्रोजेक्ट का निर्माण और चलाना

ऊपर के operations से एक meson project तैयार है। आगे, हम इस project को build और run करते हैं।

4.3.1 build directory कॉन्फ़िगर करना

यह cmake के mkdir build && cmake .. के समान है।

meson setup build

run का परिणाम:

➜  gtest_div meson setup build               
The Meson build system
Version: 1.2.3
Source dir: /Users/light/work/practice/gtest_div
Build dir: /Users/light/work/practice/gtest_div/build
Build type: native build
Project name: gtest_div
Project version: undefined
C++ compiler for the host machine: c++ (clang 12.0.5 "Apple clang version 12.0.5 (clang-1205.0.22.11)")
C++ linker for the host machine: c++ ld64 650.9
Host machine cpu family: x86_64
Host machine cpu: x86_64
Downloading gtest source from https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
Download size: 867764
Downloading: ..........
Downloading gtest patch from https://wrapdb.mesonbuild.com/v2/gtest_1.14.0-1/get_patch
Download size: 2440
Downloading: ..........

Executing subproject gtest 

gtest| Project name: gtest
gtest| Project version: 1.14.0
gtest| C++ compiler for the host machine: c++ (clang 12.0.5 "Apple clang version 12.0.5 (clang-1205.0.22.11)")
gtest| C++ linker for the host machine: c++ ld64 650.9
gtest| Run-time dependency threads found: YES
gtest| Dependency threads found: YES unknown (cached)
gtest| Dependency threads found: YES unknown (cached)
gtest| Dependency threads found: YES unknown (cached)
gtest| Build targets in project: 0
gtest| Subproject gtest finished.

Build targets in project: 1

gtest_div undefined

  Subprojects
    gtest: YES

Found ninja-1.11.1 at /usr/local/bin/ninja

इस समय हम subprojects में cached gtest project देख सकते हैं।

subprojects
├── googletest-1.14.0  # here
├── gtest.wrap
└── packagecache # here

4.3.2 संकलन

हम निम्न दो commands उपयोग कर सकते हैं, पहली:

meson compile -C build/

run का log:

➜  gtest_div meson compile -C build/            
INFO: autodetecting backend as ninja
INFO: calculating backend command to run: /usr/local/bin/ninja -C /Users/light/work/practice/gtest_div/build
ninja: Entering directory `/Users/light/work/practice/gtest_div/build'
[5/5] Linking target division_test

दूसरी:

➜  gtest_div ninja -C build
ninja: Entering directory `build'
[5/5] Linking target division_test

ये दोनों commands अनिवार्यतः एक जैसी हैं, दोनों ninja से compile करेंगी, बेशक -C से directory specify न करने पर भी चलेगा, उस स्थिति में cd build && ninja या cd build && meson compile करना होगा।

4.3.3 चलाना और टेस्ट करना

इससे division_test executable program बनेगा, run करने पर:

➜  gtest_div ./build/division_test
Running main() from ../subprojects/googletest-1.14.0/googletest/src/gtest_main.cc
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from DivisionTest
[ RUN      ] DivisionTest.Divide
[       OK ] DivisionTest.Divide (0 ms)
[ RUN      ] DivisionTest.DivideByZero
[       OK ] DivisionTest.DivideByZero (0 ms)
[----------] 2 tests from DivisionTest (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 2 tests.

चूंकि meson.build में unit test test जोड़ा गया है, इसलिए हम उपयोग कर सकते हैं

meson test

या:

ninja test

अगर directory specify करनी हो:

meson test -C build/

or 

ninja test -C build/

run का log:

➜  gtest_div meson test -C build 
ninja: Entering directory `/Users/light/work/practice/gtest_div/build'
ninja: no work to do.
1/1 this is a division test        OK              0.01s

Ok:                 1   
Expected Fail:      0   
Fail:               0   
Unexpected Pass:    0   
Skipped:            0   
Timeout:            0   

Full log written to /Users/light/work/practice/gtest_div/build/meson-logs/testlog.txt

संबंधित विषय

टिप्पणियाँ