Add meson build

This commit is to add meson build.
and later, we will remove Autotools and replace it with meson build.

Tested: built openpower-occ-control successfully and Unit test passes.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I7f5fbc7150194a78f9b36bb256613fc70b834130
diff --git a/gen/README b/gen/README
new file mode 100644
index 0000000..71182b5
--- /dev/null
+++ b/gen/README
@@ -0,0 +1,2 @@
+This directory contains generated meson.build files from sdbus++-gen-meson.
+Do not edit them by hand.
diff --git a/gen/meson.build b/gen/meson.build
new file mode 100644
index 0000000..56193c7
--- /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 3'
+    warning('Generated meson files from wrong version of sdbus++-gen-meson.')
+    warning(
+        'Expected "sdbus++-gen-meson version 3", got:',
+        sdbuspp_gen_meson_ver
+    )
+endif
+
diff --git a/gen/org/meson.build b/gen/org/meson.build
new file mode 100644
index 0000000..6488f22
--- /dev/null
+++ b/gen/org/meson.build
@@ -0,0 +1,2 @@
+# Generated file; do not modify.
+subdir('open_power')
diff --git a/gen/org/open_power/OCC/Device/meson.build b/gen/org/open_power/OCC/Device/meson.build
new file mode 100644
index 0000000..0f287ad
--- /dev/null
+++ b/gen/org/open_power/OCC/Device/meson.build
@@ -0,0 +1,14 @@
+# Generated file; do not modify.
+generated_sources += custom_target(
+    'org/open_power/OCC/Device__cpp'.underscorify(),
+    input: [ '../../../../../org/open_power/OCC/Device.errors.yaml',  ],
+    output: [ 'error.cpp', 'error.hpp',  ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'cpp',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.current_source_dir() / '../../../../..',
+        'org/open_power/OCC/Device',
+    ],
+)
+
diff --git a/gen/org/open_power/OCC/meson.build b/gen/org/open_power/OCC/meson.build
new file mode 100644
index 0000000..7433b15
--- /dev/null
+++ b/gen/org/open_power/OCC/meson.build
@@ -0,0 +1,15 @@
+# Generated file; do not modify.
+subdir('Device')
+generated_others += custom_target(
+    'org/open_power/OCC/Device__markdown'.underscorify(),
+    input: [ '../../../../org/open_power/OCC/Device.errors.yaml',  ],
+    output: [ 'Device.md' ],
+    command: [
+        sdbuspp_gen_meson_prog, '--command', 'markdown',
+        '--output', meson.current_build_dir(),
+        '--tool', sdbusplusplus_prog,
+        '--directory', meson.current_source_dir() / '../../../..',
+        'org/open_power/OCC/Device',
+    ],
+)
+
diff --git a/gen/org/open_power/meson.build b/gen/org/open_power/meson.build
new file mode 100644
index 0000000..8eed05c
--- /dev/null
+++ b/gen/org/open_power/meson.build
@@ -0,0 +1,2 @@
+# Generated file; do not modify.
+subdir('OCC')
diff --git a/gen/regenerate-meson b/gen/regenerate-meson
new file mode 100755
index 0000000..56bc2c6
--- /dev/null
+++ b/gen/regenerate-meson
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+REPO_ROOT=$(git rev-parse --show-toplevel)
+
+# Find sdbus++-gen-meson
+#   1. Check $SDBUSPP_GEN_MESON
+#   2. Check in $PATH
+#   3. Check in subprojects/sdbusplus
+if [ ! -x "$SDBUSPP_GEN_MESON" ]; then
+    SDBUSPP_GEN_MESON="$(which sdbus++-gen-meson 2> /dev/null)"
+fi
+if [ ! -x "$SDBUSPP_GEN_MESON" ]; then
+    SDBUSPP_GEN_MESON="$REPO_ROOT/subprojects/sdbusplus/tools/sdbus++-gen-meson"
+fi
+if [ ! -x "$SDBUSPP_GEN_MESON" ]; then
+    echo "Cannot find sdbus++-gen-meson ($SDBUSPP_GEN_MESON)."
+    exit 1
+fi
+
+$SDBUSPP_GEN_MESON \
+    --command meson \
+    --directory "$REPO_ROOT" \
+    --output "$REPO_ROOT/gen"
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/meson.build b/meson.build
new file mode 100644
index 0000000..453fef2
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,166 @@
+project(
+    'openpower-occ-control', 'cpp',
+    version : '1.0.0',
+    meson_version: '>=0.57.0',
+    default_options: [
+        'warning_level=3',
+        'werror=true',
+        'cpp_std=c++20',
+        'buildtype=debugoptimized'
+    ]
+)
+
+conf_data = configuration_data()
+conf_data.set_quoted('OCC_CONTROL_BUSNAME', 'org.open_power.OCC.Control')
+conf_data.set_quoted('OCC_CONTROL_ROOT', '/org/open_power/control')
+conf_data.set_quoted('OCC_SENSORS_ROOT', '/xyz/openbmc_project/sensors')
+conf_data.set_quoted('CPU_NAME', 'cpu')
+conf_data.set_quoted('OCC_NAME', 'occ')
+conf_data.set_quoted('OCC_MASTER_NAME', 'occ-hwmon.1')
+conf_data.set_quoted('OCC_DEV_PATH', '/dev/occ')
+conf_data.set_quoted('CPU_SUBPATH', '/xyz/openbmc_project/inventory/system/chassis/motherboard')
+
+conf_data.set('MAX_CPUS', get_option('max-cpus'))
+conf_data.set('OCC_CPU_TEMP_SENSOR_TYPE', 0xC0)
+conf_data.set('OCC_DIMM_TEMP_SENSOR_TYPE', 0xD0)
+conf_data.set('PS_DERATING_FACTOR', 90)
+
+if get_option('i2c-occ').enabled()
+    conf_data.set_quoted('OCC_HWMON_PATH', '/sys/bus/i2c/drivers/occ-hwmon/')
+    conf_data.set_quoted('DEV_PATH', '/sys/bus/i2c/devices')
+    conf_data.set_quoted('I2C_OCC_DEVICE_NAME', 'p8-occ-hwmon')
+else
+    conf_data.set_quoted('OCC_HWMON_PATH', '/sys/bus/platform/drivers/occ-hwmon/')
+    conf_data.set_quoted('DEV_PATH', '/sys/bus/platform/devices/')
+endif
+
+if get_option('install-error-yaml').disabled()
+    conf_data.set('I2C_OCC', get_option('i2c-occ').enabled())
+    conf_data.set('READ_OCC_SENSORS', get_option('read-occ-sensors').enabled())
+    conf_data.set('PLDM', get_option('with-host-communication-protocol')=='pldm')
+    conf_data.set('POWER10', get_option('power10-support').enabled())
+endif
+
+configure_file(output: 'config.h',
+    configuration: conf_data
+)
+
+sdbusplusplus_prog = find_program('sdbus++')
+sdbuspp_gen_meson_prog = find_program('sdbus++-gen-meson')
+python_prog = find_program('python3', required: true)
+realpath_prog = find_program('realpath')
+
+selected_subdirs = []
+selected_subdirs += 'org/open_power/OCC'
+
+generated_root = meson.current_build_dir() / 'gen'
+generated_others = []
+generated_sources = []
+
+# Source the generated meson files.
+subdir('gen')
+foreach d : selected_subdirs
+  subdir('gen' / d)
+endforeach
+
+# Parse through the list from sdbus++-gendir and put into sets.
+generated_headers = []
+generated_cpp = []
+generated_others_files = []
+
+foreach g : generated_sources generated_others
+    foreach f : g.to_list()
+        rel_path = run_command(
+            realpath_prog,
+            '--relative-to', generated_root,
+            f.full_path(),
+        ).stdout().strip().split('\n')[-1]
+
+        if rel_path.endswith('.hpp')
+            generated_headers += rel_path
+        elif rel_path.endswith('.cpp')
+            generated_cpp += rel_path
+        else
+            generated_others_files += rel_path
+        endif
+    endforeach
+endforeach
+
+deps = []
+sources = []
+if get_option('install-error-yaml').disabled()
+    sdbusplus_dep = dependency('sdbusplus')
+    sdeventplus_dep = dependency('sdeventplus')
+    phosphor_logging_dep = dependency('phosphor-logging')
+    phosphor_dbus_interfaces_dep = dependency('phosphor-dbus-interfaces')
+
+    deps += [
+        sdbusplus_dep,
+        sdeventplus_dep,
+        phosphor_logging_dep,
+        phosphor_dbus_interfaces_dep,
+    ]
+
+    sources += [
+        'app.cpp',
+        'occ_pass_through.cpp',
+        'occ_manager.cpp',
+        'occ_status.cpp',
+        'occ_device.cpp',
+        'occ_errors.cpp',
+        'occ_presence.cpp',
+        'occ_command.cpp',
+        'occ_dbus.cpp',
+        'powercap.cpp',
+        'i2c_occ.cpp',
+        'utils.cpp',
+    ]
+
+    if get_option('with-host-communication-protocol')=='pldm'
+        libpldm_dep = dependency('libpldm')
+        deps += [
+            libpldm_dep,
+        ]
+        sources += [
+            'pldm.cpp',
+        ]
+    endif
+
+    if get_option('power10-support').enabled()
+        sources += [
+            'powermode.cpp',
+        ]
+    endif
+
+    yamldir = get_option('yamldir')
+    if yamldir == ''
+        yamldir = meson.project_source_root() / 'example/occ_sensor.yaml'
+    endif
+
+    # Generate occ-sensor.hpp.
+    occ_sensor_hpp = custom_target(
+        'occ-sensor.hpp',
+        command : [
+            python_prog,
+            meson.project_source_root() + '/sensor_gen.py',
+            '-f', meson.project_source_root() / yamldir,
+            '-i', meson.current_build_dir(),
+        ],
+        output : 'occ-sensor.hpp')
+    sources += [occ_sensor_hpp]
+
+    executable(
+        'openpower-occ-control',
+        sources,
+        generated_sources,
+        include_directories: ['.', 'gen'],
+        implicit_include_directories: true,
+        dependencies: deps,
+        install: true,
+        install_dir: get_option('bindir')
+    )
+endif
+
+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..a948e46
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,53 @@
+option(
+    'tests',
+    type : 'feature',
+    description : 'Build tests'
+)
+
+option(
+    'install-error-yaml',
+    type : 'feature',
+    description : 'Enable installing error yaml file',
+    value: 'disabled'
+)
+
+option(
+    'i2c-occ',
+    type : 'feature',
+    description : 'Enable I2C OCC support',
+    value: 'disabled'
+)
+
+option(
+    'read-occ-sensors',
+    type : 'feature',
+    description : 'Enable read occ sensors support',
+    value: 'disabled'
+)
+
+option(
+    'max-cpus',
+    type : 'integer',
+    min:0, max:255,
+    description : 'Maximum number of CPUs',
+    value: 2
+)
+
+option(
+    'with-host-communication-protocol',
+    type : 'string',
+    description : 'To specify the host communication protocol'
+)
+
+option(
+    'power10-support',
+    type : 'feature',
+    description : 'Enable Power10 support',
+    value: 'disabled'
+)
+
+option(
+    'yamldir',
+    type : 'string',
+    description : 'The path to the yaml config files'
+)
\ No newline at end of file
diff --git a/occ_errors.hpp b/occ_errors.hpp
index 3b00e94..6fe0983 100644
--- a/occ_errors.hpp
+++ b/occ_errors.hpp
@@ -41,7 +41,7 @@
         // Nothing to do here.
     }
 
-    ~Error()
+    virtual ~Error()
     {
         if (fd >= 0)
         {
diff --git a/occ_status.hpp b/occ_status.hpp
index dce73f8..5856ee9 100644
--- a/occ_status.hpp
+++ b/occ_status.hpp
@@ -1,4 +1,5 @@
 #pragma once
+#include "config.h"
 
 #include "i2c_occ.hpp"
 #include "occ_command.hpp"
diff --git a/powermode.hpp b/powermode.hpp
index 60befce..fd7d466 100644
--- a/powermode.hpp
+++ b/powermode.hpp
@@ -1,8 +1,8 @@
 #pragma once
 
-#ifdef POWER10
 #include "config.h"
 
+#ifdef POWER10
 #include "occ_status.hpp"
 
 #include <sdbusplus/bus.hpp>
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 0000000..4a751c4
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,69 @@
+gtest_dep = dependency('gtest', main: true, disabler: true, required: false)
+gmock_dep = dependency('gmock', disabler: true, required: false)
+if not gtest_dep.found() or not gmock_dep.found()
+    gtest_proj = import('cmake').subproject('googletest', required: false)
+    if gtest_proj.found()
+        gtest_dep = declare_dependency(
+            dependencies: [
+                dependency('threads'),
+                gtest_proj.dependency('gtest'),
+                gtest_proj.dependency('gtest_main'),
+            ]
+        )
+        gmock_dep = gtest_proj.dependency('gmock')
+  else
+        assert(
+            not get_option('tests').enabled(),
+            'Googletest is required if tests are enabled'
+        )
+  endif
+endif
+
+test_sources = [
+  generated_sources,
+  '../occ_pass_through.cpp',
+  '../occ_manager.cpp',
+  '../occ_status.cpp',
+  '../occ_device.cpp',
+  '../occ_errors.cpp',
+  '../occ_presence.cpp',
+  '../occ_command.cpp',
+  '../occ_dbus.cpp',
+  '../powercap.cpp',
+  '../i2c_occ.cpp',
+  '../utils.cpp',
+]
+
+if get_option('with-host-communication-protocol')=='pldm'
+    test_sources += [
+        '../pldm.cpp',
+    ]
+endif
+
+if get_option('power10-support').enabled()
+    test_sources += [
+        '../powermode.cpp',
+    ]
+endif
+
+tests = [
+  'error_files_tests.cpp',
+  'occ_dbus_test.cpp',
+  'TestI2cOcc.cpp',
+  'utest.cpp',
+]
+
+pthread_dep = dependency('threads')
+
+foreach t : tests
+  test(t, executable(t.underscorify(), t,
+                     test_sources,
+                     include_directories: ['..', '../gen'],
+                     dependencies: [
+                         gtest_dep,
+                         gmock_dep,
+                         pthread_dep,
+                         deps
+                         ]),
+       workdir: meson.current_source_dir())
+endforeach
\ No newline at end of file