build: Add meson build

Change-Id: Id01834cf0b6580b7e6f6fa195b4a547fd03222ce
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/.gitignore b/.gitignore
index 6e54fa7..a0d5bae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,3 +60,6 @@
 __pycache__/
 *.py[cod]
 *$py.class
+
+/build*/
+/subprojects/*/
diff --git a/gen/meson.build b/gen/meson.build
new file mode 100644
index 0000000..af850f2
--- /dev/null
+++ b/gen/meson.build
@@ -0,0 +1,14 @@
+# Generated file; do not modify.
+sdbuspp_gen_meson_ver = run_command(
+    sdbuspp_gen_meson_prog,
+    '--version',
+).stdout().strip().split('\n')[0]
+
+if sdbuspp_gen_meson_ver != 'sdbus++-gen-meson version 2'
+    warning('Generated meson files from wrong version of sdbus++-gen-meson.')
+    warning(
+        'Expected "sdbus++-gen-meson version 2", got:',
+        sdbuspp_gen_meson_ver
+    )
+endif
+
diff --git a/gen/regenerate-meson b/gen/regenerate-meson
new file mode 100755
index 0000000..5b4fc06
--- /dev/null
+++ b/gen/regenerate-meson
@@ -0,0 +1,4 @@
+#!/bin/bash
+cd "$(dirname "$0")" || exit
+export PATH="$PWD/../subprojects/sdbusplus/tools:$PATH"
+exec sdbus++-gen-meson --command meson --directory .. --output .
diff --git a/gen/run-ci b/gen/run-ci
new file mode 100755
index 0000000..d38927a
--- /dev/null
+++ b/gen/run-ci
@@ -0,0 +1,15 @@
+#!/bin/bash
+cd "$(dirname "$0")" || exit
+./regenerate-meson || exit
+rc=0
+git --no-pager diff --exit-code -- . || rc=$?
+untracked="$(git ls-files --others --exclude-standard -- .)" || rc=$?
+if [ -n "$untracked" ]; then
+  echo "Untracked files:" >&2
+  echo "$untracked" >&2
+  rc=1
+fi
+if (( rc != 0 )); then
+  echo "Generated meson files differ from expected values" >&2
+  exit 1
+fi
diff --git a/gen/xyz/meson.build b/gen/xyz/meson.build
new file mode 100644
index 0000000..e4991ad
--- /dev/null
+++ b/gen/xyz/meson.build
@@ -0,0 +1,2 @@
+# Generated file; do not modify.
+subdir('openbmc_project')
diff --git a/gen/xyz/openbmc_project/Network/IP/Create/meson.build b/gen/xyz/openbmc_project/Network/IP/Create/meson.build
new file mode 100644
index 0000000..1c11aeb
--- /dev/null
+++ b/gen/xyz/openbmc_project/Network/IP/Create/meson.build
@@ -0,0 +1,14 @@
+# Generated file; do not modify.
+generated_sources += custom_target(
+    'xyz/openbmc_project/Network/IP/Create__cpp'.underscorify(),
+    input: [ meson.project_source_root() / 'xyz/openbmc_project/Network/IP/Create.interface.yaml',  ],
+    output: [ 'server.cpp', 'server.hpp', 'client.hpp',  ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'cpp',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.project_source_root(),
+        'xyz/openbmc_project/Network/IP/Create',
+    ],
+)
+
diff --git a/gen/xyz/openbmc_project/Network/IP/meson.build b/gen/xyz/openbmc_project/Network/IP/meson.build
new file mode 100644
index 0000000..9949e2a
--- /dev/null
+++ b/gen/xyz/openbmc_project/Network/IP/meson.build
@@ -0,0 +1,16 @@
+# Generated file; do not modify.
+subdir('Create')
+generated_others += custom_target(
+    'xyz/openbmc_project/Network/IP/Create__markdown'.underscorify(),
+    input: [ meson.project_source_root() / 'xyz/openbmc_project/Network/IP/Create.interface.yaml',  ],
+    output: [ 'Create.md' ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'markdown',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.project_source_root(),
+        'xyz/openbmc_project/Network/IP/Create',
+    ],
+    build_by_default: true,
+)
+
diff --git a/gen/xyz/openbmc_project/Network/Neighbor/CreateStatic/meson.build b/gen/xyz/openbmc_project/Network/Neighbor/CreateStatic/meson.build
new file mode 100644
index 0000000..947a393
--- /dev/null
+++ b/gen/xyz/openbmc_project/Network/Neighbor/CreateStatic/meson.build
@@ -0,0 +1,14 @@
+# Generated file; do not modify.
+generated_sources += custom_target(
+    'xyz/openbmc_project/Network/Neighbor/CreateStatic__cpp'.underscorify(),
+    input: [ meson.project_source_root() / 'xyz/openbmc_project/Network/Neighbor/CreateStatic.interface.yaml',  ],
+    output: [ 'server.cpp', 'server.hpp', 'client.hpp',  ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'cpp',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.project_source_root(),
+        'xyz/openbmc_project/Network/Neighbor/CreateStatic',
+    ],
+)
+
diff --git a/gen/xyz/openbmc_project/Network/Neighbor/meson.build b/gen/xyz/openbmc_project/Network/Neighbor/meson.build
new file mode 100644
index 0000000..c4d2e8d
--- /dev/null
+++ b/gen/xyz/openbmc_project/Network/Neighbor/meson.build
@@ -0,0 +1,16 @@
+# Generated file; do not modify.
+subdir('CreateStatic')
+generated_others += custom_target(
+    'xyz/openbmc_project/Network/Neighbor/CreateStatic__markdown'.underscorify(),
+    input: [ meson.project_source_root() / 'xyz/openbmc_project/Network/Neighbor/CreateStatic.interface.yaml',  ],
+    output: [ 'CreateStatic.md' ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'markdown',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.project_source_root(),
+        'xyz/openbmc_project/Network/Neighbor/CreateStatic',
+    ],
+    build_by_default: true,
+)
+
diff --git a/gen/xyz/openbmc_project/Network/VLAN/Create/meson.build b/gen/xyz/openbmc_project/Network/VLAN/Create/meson.build
new file mode 100644
index 0000000..e9d59f0
--- /dev/null
+++ b/gen/xyz/openbmc_project/Network/VLAN/Create/meson.build
@@ -0,0 +1,14 @@
+# Generated file; do not modify.
+generated_sources += custom_target(
+    'xyz/openbmc_project/Network/VLAN/Create__cpp'.underscorify(),
+    input: [ meson.project_source_root() / 'xyz/openbmc_project/Network/VLAN/Create.interface.yaml',  ],
+    output: [ 'server.cpp', 'server.hpp', 'client.hpp',  ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'cpp',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.project_source_root(),
+        'xyz/openbmc_project/Network/VLAN/Create',
+    ],
+)
+
diff --git a/gen/xyz/openbmc_project/Network/VLAN/meson.build b/gen/xyz/openbmc_project/Network/VLAN/meson.build
new file mode 100644
index 0000000..569f436
--- /dev/null
+++ b/gen/xyz/openbmc_project/Network/VLAN/meson.build
@@ -0,0 +1,16 @@
+# Generated file; do not modify.
+subdir('Create')
+generated_others += custom_target(
+    'xyz/openbmc_project/Network/VLAN/Create__markdown'.underscorify(),
+    input: [ meson.project_source_root() / 'xyz/openbmc_project/Network/VLAN/Create.interface.yaml',  ],
+    output: [ 'Create.md' ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'markdown',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.project_source_root(),
+        'xyz/openbmc_project/Network/VLAN/Create',
+    ],
+    build_by_default: true,
+)
+
diff --git a/gen/xyz/openbmc_project/Network/meson.build b/gen/xyz/openbmc_project/Network/meson.build
new file mode 100644
index 0000000..3151cc9
--- /dev/null
+++ b/gen/xyz/openbmc_project/Network/meson.build
@@ -0,0 +1,4 @@
+# Generated file; do not modify.
+subdir('IP')
+subdir('Neighbor')
+subdir('VLAN')
diff --git a/gen/xyz/openbmc_project/meson.build b/gen/xyz/openbmc_project/meson.build
new file mode 100644
index 0000000..3974f16
--- /dev/null
+++ b/gen/xyz/openbmc_project/meson.build
@@ -0,0 +1,2 @@
+# Generated file; do not modify.
+subdir('Network')
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..fa989c3
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,143 @@
+project(
+  'phosphor-networkd',
+  'cpp',
+  version: '0.1',
+  meson_version: '>=0.57.0',
+  default_options: [
+    'warning_level=3',
+    'cpp_std=c++20',
+  ])
+
+conf_data = configuration_data()
+conf_data.set_quoted('DEFAULT_BUSNAME', 'xyz.openbmc_project.Network')
+conf_data.set_quoted('SYSTEMD_TARGET', 'multi-user.target')
+conf_data.set('HAVE_UBOOT_ENV', get_option('uboot-env'))
+conf_data.set(
+  'LINK_LOCAL_AUTOCONFIGURATION',
+  get_option('default-link-local-autoconf'))
+conf_data.set(
+  'ENABLE_IPV6_ACCEPT_RA',
+  get_option('default-ipv6-accept-ra'))
+conf_data.set('NIC_SUPPORTS_ETHTOOL', get_option('nic-ethtool'))
+conf_data.set('SYNC_MAC_FROM_INVENTORY', get_option('sync-mac'))
+conf_header = configure_file(
+  output: 'config.h',
+  configuration: conf_data)
+
+sdbusplus_dep = dependency('sdbusplus', required: false)
+if sdbusplus_dep.found()
+  sdbusplusplus_prog = find_program('sdbus++', native: true)
+  sdbuspp_gen_meson_prog = find_program('sdbus++-gen-meson', native: true)
+else
+  sdbusplus_proj = subproject('sdbusplus', required: true)
+  sdbusplus_dep = sdbusplus_proj.get_variable('sdbusplus_dep')
+  sdbusplusplus_prog = sdbusplus_proj.get_variable('sdbusplusplus_prog')
+  sdbuspp_gen_meson_prog = sdbusplus_proj.get_variable('sdbuspp_gen_meson_prog')
+endif
+
+phosphor_dbus_interfaces_dep = dependency('phosphor-dbus-interfaces')
+phosphor_logging_dep = dependency('phosphor-logging')
+
+generated_sources = [ conf_header ]
+generated_others = []
+yaml_sources = []
+subdir('gen')
+subdir('gen/xyz')
+
+networkd_headers = include_directories('.', 'gen')
+
+executable(
+  'ncsi-netlink',
+  'argument.cpp',
+  'ncsi_netlink_main.cpp',
+  'ncsi_util.cpp',
+  implicit_include_directories: false,
+  include_directories: networkd_headers,
+  dependencies: [
+    dependency('libnl-3.0'),
+    dependency('libnl-genl-3.0'),
+    phosphor_dbus_interfaces_dep,
+    phosphor_logging_dep,
+  ],
+  install: true,
+  install_dir: get_option('bindir'))
+
+json_dep = declare_dependency()
+if get_option('sync-mac')
+  # nlohmann_json might not have a pkg-config. It is header only so just make
+  # sure we can access the needed symbols from the header.
+  has_json = meson.get_compiler('cpp').has_header_symbol(
+    'nlohmann/json.hpp',
+    'nlohmann::json::string_t',
+    required: false)
+  if not has_json
+    json_dep = dependency(
+      'nlohmann_json',
+      fallback: ['nlohmann_json', 'nlohmann_json_dep'],
+      required: true)
+  endif
+endif
+
+networkd_deps = [
+  json_dep,
+  phosphor_dbus_interfaces_dep,
+  phosphor_logging_dep,
+  sdbusplus_dep,
+  dependency('sdeventplus', fallback: ['sdeventplus', 'sdeventplus_dep']),
+  dependency('stdplus', fallback: ['stdplus', 'stdplus_dep']),
+]
+
+networkd_lib = static_library(
+  'networkd',
+  generated_sources,
+  'ethernet_interface.cpp',
+  'neighbor.cpp',
+  'ipaddress.cpp',
+  'netlink.cpp',
+  'network_config.cpp',
+  'network_manager.cpp',
+  'system_configuration.cpp',
+  'util.cpp',
+  'routing_table.cpp',
+  'config_parser.cpp',
+  'dhcp_configuration.cpp',
+  'vlan_interface.cpp',
+  'rtnetlink_server.cpp',
+  'dns_updater.cpp',
+  'watch.cpp',
+  implicit_include_directories: false,
+  include_directories: networkd_headers,
+  dependencies: networkd_deps)
+
+networkd_dep = declare_dependency(
+  sources: generated_sources,
+  dependencies: networkd_deps,
+  include_directories: networkd_headers,
+  link_with: networkd_lib)
+
+executable(
+  'phosphor-network-manager',
+  'network_manager_main.cpp',
+  implicit_include_directories: false,
+  dependencies: networkd_dep,
+  install: true,
+  install_dir: get_option('bindir'))
+
+configure_file(
+  input: 'xyz.openbmc_project.Network.service.in',
+  output: 'xyz.openbmc_project.Network.service',
+  configuration: conf_data,
+  install: true,
+  install_dir: dependency('systemd').get_variable(
+    pkgconfig: 'systemdsystemunitdir'))
+
+configure_file(
+  input: 'xyz.openbmc_project.Network.conf.in',
+  output: 'xyz.openbmc_project.Network.conf',
+  configuration: conf_data,
+  install: true,
+  install_dir: get_option('datadir') / 'dbus-1' / 'system.d')
+
+if not get_option('tests').disabled()
+  subdir('test')
+endif
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..d351fea
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,12 @@
+option('tests', type: 'feature', description: 'Build tests')
+
+option('uboot-env', type: 'boolean',
+       description: 'Update u-boot env for MAC changes')
+option('default-link-local-autoconf', type: 'boolean',
+       description: 'Enable link local autoconfiguration by default')
+option('default-ipv6-accept-ra', type: 'boolean',
+       description: 'Accept router advertisements by default')
+option('nic-ethtool', type: 'boolean',
+       description: 'Enable ethtool information lookup')
+option('sync-mac', type: 'boolean',
+       description: 'Sync mac address with phosphor-inventory-manager')
diff --git a/subprojects/googletest.wrap b/subprojects/googletest.wrap
new file mode 100644
index 0000000..56da9ef
--- /dev/null
+++ b/subprojects/googletest.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/google/googletest
+revision = HEAD
diff --git a/subprojects/sdbusplus.wrap b/subprojects/sdbusplus.wrap
new file mode 100644
index 0000000..7f736e7
--- /dev/null
+++ b/subprojects/sdbusplus.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/openbmc/sdbusplus
+revision = HEAD
diff --git a/subprojects/sdeventplus.wrap b/subprojects/sdeventplus.wrap
new file mode 100644
index 0000000..7503664
--- /dev/null
+++ b/subprojects/sdeventplus.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/openbmc/sdeventplus
+revision = HEAD
diff --git a/subprojects/stdplus.wrap b/subprojects/stdplus.wrap
new file mode 100644
index 0000000..00dae65
--- /dev/null
+++ b/subprojects/stdplus.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/openbmc/stdplus
+revision = HEAD
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 0000000..552fb01
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,64 @@
+gtest = dependency('gtest', main: true, disabler: true, required: false)
+gmock = dependency('gmock', disabler: true, required: false)
+if not gtest.found() or not gmock.found()
+  gtest_opts = import('cmake').subproject_options()
+  gtest_opts.add_cmake_defines({'CMAKE_CXX_FLAGS': '-Wno-pedantic'})
+  gtest_proj = import('cmake').subproject(
+    'googletest',
+    options: gtest_opts,
+    required: false)
+  if gtest_proj.found()
+    gtest = declare_dependency(
+      dependencies: [
+        dependency('threads'),
+        gtest_proj.dependency('gtest'),
+        gtest_proj.dependency('gtest_main'),
+      ])
+    gmock = gtest_proj.dependency('gmock')
+  else
+    assert(not build_tests.enabled(), 'Googletest is required')
+  endif
+endif
+
+test_headers = include_directories('.')
+
+test_deps = [
+  meson.get_compiler('cpp').find_library('dl'),
+  networkd_dep,
+  gtest,
+  gmock,
+]
+
+test_lib = static_library(
+  'networkd-test',
+  'mock_syscall.cpp',
+  'global_network_objects.cpp',
+  implicit_include_directories: false,
+  include_directories: test_headers,
+  dependencies: test_deps)
+
+test_dep = declare_dependency(
+  dependencies: test_deps,
+  include_directories: test_headers,
+  link_with: test_lib)
+
+tests = [
+  'config_parser',
+  'ethernet_interface',
+  'neighbor',
+  'netlink',
+  'network_manager',
+  #'rtnetlink',
+  'util',
+  'vlan_interface',
+]
+
+foreach t : tests
+  test(
+    t,
+    executable(
+      t.underscorify(),
+      'test_' + t + '.cpp',
+      implicit_include_directories: false,
+      dependencies: test_dep))
+endforeach
diff --git a/xyz.openbmc_project.Network.conf.in b/xyz.openbmc_project.Network.conf.in
index b34fe6c..6d10a3c 100644
--- a/xyz.openbmc_project.Network.conf.in
+++ b/xyz.openbmc_project.Network.conf.in
@@ -2,7 +2,7 @@
         "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 <busconfig>
         <policy user="root">
-                <allow own="@DEFAULT_BUSNAME@"/>
-                <allow send_destination="@DEFAULT_BUSNAME@"/>
+                <allow own=@DEFAULT_BUSNAME@/>
+                <allow send_destination=@DEFAULT_BUSNAME@/>
         </policy>
 </busconfig>
diff --git a/xyz.openbmc_project.Network.service.in b/xyz.openbmc_project.Network.service.in
index a478462..20e1631 100644
--- a/xyz.openbmc_project.Network.service.in
+++ b/xyz.openbmc_project.Network.service.in
@@ -8,9 +8,9 @@
 Restart=always
 Type=dbus
 BusName=@DEFAULT_BUSNAME@
-RuntimeDirectory = network
-RuntimeDirectoryPreserve = yes
-StateDirectory = network
+RuntimeDirectory=network
+RuntimeDirectoryPreserve=yes
+StateDirectory=network
 
 [Install]
 WantedBy=@SYSTEMD_TARGET@