Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate Meson as optional build system #262

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,45 @@ jobs:
cmake .
msbuild FlatCC.sln /m /property:Configuration=Release
ctest -VV

meson-build:
name: Meson (${{matrix.os}})
runs-on: ${{matrix.os}}
continue-on-error: true
strategy:
matrix:
os: [ ubuntu-22.04, macos-12, windows-2022 ]
steps:
- uses: actions/checkout@v3

- uses: microsoft/setup-msbuild@v1.1
if: runner.os == 'windows'
- uses: actions/setup-python@v2
if: runner.os == 'windows'
- name: Prepare MSVC
uses: bus1/cabuild/action/msdevshell@v1
with:
architecture: x64
if: runner.os == 'windows'
- name: Install dependencies (windows)
if: runner.os == 'windows'
run: |
pip install meson

- name: Install dependencies (ubuntu)
if: runner.os == 'linux'
run: |
sudo apt update -y
sudo apt install ninja-build meson

- name: Install dependencies (macos)
if: runner.os == 'macos'
run: |
brew install meson ninja

- name: Build and run tests
run: |
meson setup build --buildtype release
meson compile -C build
meson test -C build --verbose
meson test -C build --benchmark --verbose
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ C given a FlatBuffer schema file. This introduction also creates a separate test
project with the traditional monster example, here in a C version.

For now assume a Unix like system although that is not a general requirement -
see also [Building](#building). You will need git, cmake, bash, a C compiler,
and either the ninja build system, or make.
see also [Building](#building). You will need git, either cmake or meson, bash,
a C compiler, and either the ninja build system, or make.

git clone https://github.com/dvidelabs/flatcc.git
cd flatcc
Expand All @@ -117,7 +117,7 @@ and either the ninja build system, or make.
ls generated

`scripts/initbuild.sh` is optional and chooses the build backend, which defaults
to ninja.
to ninja via CMake.

The setup script builds flatcc using CMake, then creates a test project
directory with the monster example, and a build script which is just a small
Expand Down Expand Up @@ -2218,16 +2218,17 @@ To initialize and run the build (see required build tools below):
The `bin` and `lib` folders will be created with debug and release
build products.

The build depends on `CMake`. By default the `Ninja` build tool is also required,
but alternatively `make` can be used.
The build depends on either `CMake` or `Meson`. By default the `Ninja` build tool
is also required, but alternatively `make` can be used.

Optionally switch to a different build tool by choosing one of:

scripts/initbuild.sh cmake
scripts/initbuild.sh meson
scripts/initbuild.sh make
scripts/initbuild.sh make-concurrent
scripts/initbuild.sh ninja

where `ninja` is the default and `make-concurrent` is `make` with the `-j` flag.
where `cmake` is the default and `make-concurrent` is `make` with the `-j` flag.

To enforce a 32-bit build on a 64-bit machine the following configuration
can be used:
Expand Down Expand Up @@ -2367,7 +2368,7 @@ a different assert behaviour is desirable, it is possible to override
the default behaviour in runtime part of flatcc library via logic defined
in [flatcc_assert.h](include/flatcc/flatcc_assert.h).

By default Posix `assert` is beeing used. It can be changed by preprocessor definition:
By default Posix `assert` is being used. It can be changed by preprocessor definition:

-DFLATCC_ASSERT=own_assert

Expand Down
216 changes: 216 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# NOTE: This build system is maintained by the community.
project('flatcc',
'c', 'cpp',
version : '0.6.1',
license : 'Apache-2.0',
default_options : ['c_std=c11', 'cpp_std=c++11', 'default_library=static'],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to add default_library=static here; the user can configure how they want to do this via a command line option, or Meson will intelligently handle this for you away (i.e. if used as a subproject, Meson will build this as static anyway)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found some time to work on this. So the reason I added default_library=static originally is to make Windows build correctly on the CI. Ultimately without this, Meson's library() generates a DLL. Given that flatcc currently does not explicitly export any symbols from this DLL by setting __declspec(dllexport) on any symbols, MSVC does not create any import lib flatcc.lib causing subsequent links to this library to fail, notably the flatcc cli tool. By forcing the generation of a static library, the link problems are avoided.

I've been trying various ways to get around this including both_libraries(), but nothing seems to produce a linkable library on Windows. I think that the best path forward is to leave this as it is default_library=static specified in the toplevel Meson script, and if users want to specify --default-library=shared on the command-line then they are free to, but with the knowledge that this will cause Windows link failures. This mirrors CMake's -DBUILD_SHARED_LIBS=on option, which when activated with flatcc also causes Windows link failures due to missing import libs.

I have a local patch with explicitly adds __declspec(dllexport) to flatcc's public API, which seems to resolve the issue for both Meson and CMake, but if such a patch is ever considered for submission to flatcc, I think it would be best to do it separately from this PR. It touches lots of files.

TL;DR: On Windows, neither Meson nor CMake is currently capable of building and linking a shared version of flatcc, so default to static under Meson as is already the case under CMake.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK that makes sense. I ran into a similar issue with nanoarrow last month - the advice I received from upstream was to do something like:

if is_windows
    libtype = 'static_library'
else
    libtype = 'library'
endif

build_target(
    ....,
    target_type: libtype,
)

mesonbuild/wrapdb#1536 (comment)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course could also try to properly export symbols and simulate the issues by setting -fvisibility=hidden for gcc, but that would require changes to the flatcc code itself

meson_version : '>=0.56.0'
)

buildtype = get_option('buildtype')
ignore_const_cond = get_option('ignore_const_cond')
allow_werror = get_option('allow_werror')
gnu_posix_memalign = get_option('gnu_posix_memalign')
has_c99_var_decl = get_option('c_std') != 'c89'

cc = meson.get_compiler('c')
cc_id = cc.get_id()
cc_version = cc.version()

cxx = meson.get_compiler('cpp')

c_args = []

if get_option('flatcc_portable') or cc_id == 'msvc'
c_args += '-DFLATCC_PORTABLE'
endif

if get_option('flatcc_debug_verify')
c_args += '-DFLATCC_DEBUG_VERIFY=1'
endif

if get_option('flatcc_fast_double')
c_args += '-DGRISU3_PARSE_ALLOW_ERROR'
c_args += '-DFLATCC_USE_GRISU3=1'
endif

if buildtype == 'release' or buildtype == 'minsize'
c_args += '-DNDEBUG'
endif

if cc_id == 'mvsc'

has_c99_var_decl = cc_version.version_compare('>=18')
c_args += '-W3'

elif cc_id == 'clang'

c_args += [
'-Wstrict-prototypes',
'-Wsign-conversion',
'-Wconversion',
'-pedantic',
'-Wextra'
]

if ignore_const_cond
c_args += '-Wno-tautological-constant-out-of-range-compare'
endif

if cc_version.version_compare('< 6')
c_args += '-Wno-missing-field-initializers'
endif

elif cc_id == 'gcc'

c_args += [
'-Wall',
'-Wextra',
]

if ignore_const_cond
c_args += '-Wno-type-limits'
endif

if cc_version.version_compare('>4.8')
c_args += '-Wsign-compare'
endif

if cc_version.version_compare('>8')
c_args += [ '-Wno-stringop-truncation', '-Wno-format-overflow' ]
endif

if cc_version.version_compare('>=11')
c_args += '-Wno-misleading-indentation'
endif

if gnu_posix_memalign
c_args += '-DPORTABLE_POSIX_MEMALIGN=1'
endif

endif

if build_machine.system() == 'windows'
c_args += '-D_CRT_SECURE_NO_WARNINGS'
endif

if allow_werror
c_args += '-Werror'
endif

# Reflection must be disabled temporarily when making breaking changes.
if get_option('flatcc_reflection')
c_args += '-DFLATCC_REFLECTION=1'
else
c_args += '-DFLATCC_REFLECTION=0'
endif

add_project_arguments(cc.get_supported_arguments(c_args), language: 'c')
add_project_arguments(cxx.get_supported_arguments(c_args), language: 'cpp')

inc_dir = include_directories('include', 'config', 'external')

if not meson.is_subproject()
install_subdir('include/flatcc', install_dir: 'include')
endif

flatccrt_src = [
'src/runtime/builder.c',
'src/runtime/emitter.c',
'src/runtime/refmap.c',
'src/runtime/json_parser.c',
'src/runtime/json_printer.c',
'src/runtime/verifier.c'
]

flatcc_src = [
'src/compiler/codegen_c.c',
'src/compiler/codegen_c_builder.c',
'src/compiler/codegen_c_json_parser.c',
'src/compiler/codegen_c_json_printer.c',
'src/compiler/codegen_c_reader.c',
'src/compiler/codegen_c_sort.c',
'src/compiler/codegen_c_sorter.c',
'src/compiler/codegen_c_verifier.c',
'src/compiler/codegen_schema.c',
'src/compiler/coerce.c',
'src/compiler/fileio.c',
'src/compiler/flatcc.c',
'src/compiler/parser.c',
'src/compiler/semantics.c',
'src/compiler/hash_tables/name_table.c',
'src/compiler/hash_tables/schema_table.c',
'src/compiler/hash_tables/scope_table.c',
'src/compiler/hash_tables/symbol_table.c',
'src/compiler/hash_tables/value_set.c',
'external/hash/cmetrohash64.c',
'external/hash/ptr_set.c',
'external/hash/str_set.c',
flatccrt_src
]

flatccrt_name = 'flatccrt'
flatcc_name = 'flatcc'

if buildtype == 'debug' and build_machine.system() != 'windows'
flatccrt_name = 'flatccrt_d'
flatcc_name = 'flatcc_d'
endif

libflatccrt = library(flatccrt_name,
sources: flatccrt_src,
include_directories: inc_dir,
install: not meson.is_subproject()
)

libflatcc = library(flatcc_name,
sources: flatcc_src,
include_directories: inc_dir,
install: not meson.is_subproject()
)

flatcc = executable(flatcc_name,
sources: ['src/cli/flatcc_cli.c'],
link_with: libflatcc,
include_directories: inc_dir,
install: not meson.is_subproject()
)

if not meson.is_subproject() and build_machine.system() != 'windows'

mkdir_command = find_program('mkdir')
cp_command = find_program('cp')

copy_targets = {
'flatcc-copy' : [flatcc, meson.project_source_root() / 'bin'],
'libflatccrt-copy' : [libflatccrt, meson.project_source_root() / 'lib'],
'libflatcc-copy' : [libflatcc, meson.project_source_root() / 'lib']
}

foreach target_name, target_details : copy_targets
target = target_details[0]
destination = target_details[1]
custom_target(target_name,
command: [ mkdir_command, '-p', destination, '&&', cp_command, target, destination ],
output: 'fake-@0@'.format(target_name),
build_by_default: true,
build_always_stale: false
)
endforeach
endif

meson.override_find_program('flatcc', flatcc)

subdir('rules')

if not get_option('flatcc_disable_tests') and not meson.is_subproject()
# For end user programs, samples, and test.
subdir('samples')
subdir('test')
endif

flatcc_dep = declare_dependency(
link_with: libflatcc,
include_directories: inc_dir
)

78 changes: 78 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Use this for some compilers that doesn't C11 standard.
# It is not needed for some non-compliant compilers such as
# recent gcc and clang.

option('flatcc_portable', type : 'boolean', value : false)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although common in CMake you don't need to prefix the options with flatcc; if needed in Meson you can add the library name as a prefix to things anyway, so -Dflatcc:portable would look for the flatcc library and set the portable flag.

Of course if you are just compiling from flatcc you don't need to specify this, and could just go with the shorter -Dportable= command line argument

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I've removed the flatcc_ prefix for all the options as you suggested. I'll push up a new version of this PR in the near future once I have implemented as much of the feedback as possible.


# Use this option to trigger assertions on flatcc errors. Useful to
# learn more about why api is used incorrectly or where a binary
# flatbuffer fails a verify test.

option('flatcc_debug_verify', type : 'boolean', value : false)

# Controls the flatcc compilers ability to handle binary schema (bfbs).
# Can be used to trim down flatcc and libflatcc size, but is primarily
# for internal development because flatcc won't otherwise compile while
# there are breaking changes in generated code.

option('flatcc_reflection', type : 'boolean', value : true)

# This option controls a special case in grisu3 but does not enable or
# disable grisu3 floating point parsing, which is enabled without
# special configuration elsewhere:
#
# Fast grisu3 string/floating point conversion still depends on strtod
# for about 1-2% of the conversions in order to produce an exact result.
# By allowing a minor difference in the least significant bits, this
# dependeny can be avoided, and speed improved. Some strtod
# implementations call strlen which is really slow on large JSON
# buffers, and catastrophic on buffers that are not zero-terminated -
# regardless of size. Most platforms have a decent strtod these days.

option('flatcc_fast_double', type : 'boolean', value : false)

# Only build libraries, not samples, tests, or benchmarks.
# This option is implied true when building as a subproject
# regardless of this setting.

option('flatcc_disable_tests', type : 'boolean', value : false)

option('ignore_const_cond', type: 'boolean', value: false)
option('allow_werror', type: 'boolean', value: true)
option('gnu_posix_memalign', type: 'boolean', value: true)

# --
# -- For more detailed control, see also config/config.h compiler flags.
# --


#####################################################################
#
# EXPERIMENTAL SETTINGS
#
# Subject to change without notice.
#
#####################################################################


# dealing with missing support for proper multi output dependencies in
# both ninja build and in flatcc. For now the myschema_reader.h is used
# to drive the depencies.

option('xflatcc_multi_dep_targets', type : 'boolean', value : false)

# Removes all tests, except the important `monster_test`.
# Useful for smaller test suite on new build targets
# and for testing dependency rules without noise.

option('xflatcc_monster_test_only', type : 'boolean', value : false)

# Currently (meson 0.34) it is not possible to generate .bfbs. files
# because there must be a registered compiler that handles .bfbs
# extension, but it is possible to use a custom target that does.

option('xflatcc_reflection_test_custom', type : 'boolean', value : true)

# Experimental support for automatically generating latest tag
# and revision from source control.
option('xflatcc_gen_version', type : 'boolean', value : false)
Loading