How to setup a meson build system for a complicated project

33 Views Asked by At

I have a project I am trying to port from makefiles to meson... and am just trying to figure out how to set it up so that everything builds correctly.

Where Foo A is made by combining Platform/A/* and Foo/A/* together and compiling everything... Bar A is made by combining Platform/A/* and Bar/A/* etc... And Foo/A, Foo/B, Foo/C are used together to make Foo.

Basically Platform contains device specific functionality... and Foo/Bar contain use specific functionality, that can change (via headers) some of the device specific values. such that platform/A cannot be compiled without Foo/A.

With a makefile this is doable, but ugly, and it is a pain to setup the dev environment... I am trying to figure out a more elegant way to do this.

rootdir
 - Common
 - Platform
   - A
     - inc/*
     - src/*
   - B
     - inc/*
     - src/*
 - Foo
   - A
     - inc
     - src
   - B
     - inc
     - src
# Seperate build, but has same build philosphy and relies on platform/*
 - Bar
   - A
     - inc/*
     - src/*
   - B
     - inc/*
     - src/*


1

There are 1 best solutions below

0
mitch_ On

So in a perfect world, your Platform would not require external configuration headers to be provided in order for it to compile. If this were the case, then you could simply have this:

# meson.build
project(...)
subdir('Platform')
subdir('Foo')
subdir('Bar')

# Platform/meson.build
platform_lib = library('platform', platform..., include_directories: 'inc')
platform_dep = declare_dependency(link_with: platform_lib, include_directories: 'inc')

# Foo/meson.build
foo_lib = library('foo', foo..., include_directories: ['A/inc', 'B/inc'], dependencies: platform_dep)

# Bar/meson.build
bar_lib = library('bar', bar..., include_directories: ['A/inc', 'B/inc'], dependencies: platform_dep)

You could even omit the subdir(...) calls and inline all of the config in the top-level meson.build. A key benefit here is that Platform is compiled exactly once, and re-used in the building of Foo and Bar.

Assuming you can't rework Platform, then you can actually still use this template, with one small tweak:

# Platform/meson.build
# NOTE: No platform_lib anymore
platform_dep = declare_dependency(sources: platform..., include_directories: 'inc')

dependency objects can be thought of as a way to 'mix in' compilation and linkage information to a build target. So, when meson interprets foo_lib = library(..., dependencies: platform_dep), it will add in all of the platform... sources to this target. The result is that your Platform gets compiled as part of the Foo build target.

However, this is also true of your Bar target. So, with this solution, you end up compiling Platform twice. If you have more than two targets, and Platform isn't particularly small, this can end up eating a lot of your build time. The first example I gave does not have this problem, as we will compile Platform once, and then simply link it with Foo and Bar.

There are some other solutions involving subprojects but I won't get into those unless this solution doesn't fit your needs.