build: add meson support

Port the existing autotools build system to meson, add meson wrap files
for all openbmc dependencies, and add appropriate meson rules to
gitignore.

Tested:

Verified executables all build, test cases pass, and executables
install.  Checked configuration files are all installed into the same
locations as a Yocto-built autotools version of the package.  Manually
checked the symlinks for the systemd service files.

```
$ DESTDIR=/tmp/certificate_test ninja install
$ find /tmp/certificate_test/lib /tmp/certificate_test/usr/local/share/phosphor-certificate-manager/
/tmp/certificate_test/lib
/tmp/certificate_test/lib/systemd
/tmp/certificate_test/lib/systemd/system
/tmp/certificate_test/lib/systemd/system/multi-user.target.wants
/tmp/certificate_test/lib/systemd/system/multi-user.target.wants/phosphor-certificate-manager@authority.service
/tmp/certificate_test/lib/systemd/system/multi-user.target.wants/phosphor-certificate-manager@bmcweb.service
/tmp/certificate_test/lib/systemd/system/bmc-vmi-ca-manager.service
/tmp/certificate_test/lib/systemd/system/phosphor-certificate-manager@.service
/tmp/certificate_test/usr/local/share/phosphor-certificate-manager/
/tmp/certificate_test/usr/local/share/phosphor-certificate-manager/authority
/tmp/certificate_test/usr/local/share/phosphor-certificate-manager/bmcweb
$ ls -n /tmp/certificate_test/lib/systemd/system/multi-user.target.wants
total 0
lrwxrwxrwx 1 1000 1000 40 Dec  3 15:37 phosphor-certificate-manager@authority.service -> ../phosphor-certificate-manager@.service
lrwxrwxrwx 1 1000 1000 40 Dec  3 15:37 phosphor-certificate-manager@bmcweb.service -> ../phosphor-certificate-manager@.service
```

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: Ib9700b5a3bb437ccc157a2d060067b8e2b777981
diff --git a/.gitignore b/.gitignore
index 8e37126..f623d4f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+build*/
+subprojects/*
+!subprojects/*.wrap
+
 # Template from:
 # https://github.com/github/gitignore/blob/master/Autotools.gitignore
 
diff --git a/bmc-vmi-ca/meson.build b/bmc-vmi-ca/meson.build
new file mode 100644
index 0000000..93fb90a
--- /dev/null
+++ b/bmc-vmi-ca/meson.build
@@ -0,0 +1,29 @@
+bmc_vmi_ca_deps = [
+    phosphor_dbus_interfaces_dep,
+    phosphor_logging_dep,
+    sdbusplus_dep,
+    sdeventplus_dep,
+]
+
+bmc_vmi_ca_lib = static_library(
+    'bmc_vmi_ca',
+    [
+        'ca_cert_entry.cpp',
+        'ca_certs_manager.cpp',
+    ],
+    include_directories: '..',
+    dependencies: bmc_vmi_ca_deps,
+)
+
+bmc_vmi_ca_dep = declare_dependency(
+    link_with: bmc_vmi_ca_lib,
+    dependencies: bmc_vmi_ca_deps,
+)
+
+executable(
+    'bmc_vmi_ca',
+    'mainapp.cpp',
+    include_directories: '..',
+    dependencies: bmc_vmi_ca_dep,
+    install: true,
+)
diff --git a/config.h.meson b/config.h.meson
new file mode 100644
index 0000000..9b937f6
--- /dev/null
+++ b/config.h.meson
@@ -0,0 +1,19 @@
+#pragma once
+
+/* The DBus busname to own */
+#define BUSNAME "xyz.openbmc_project.Certs.Manager"
+
+/* The certifiicate manager DBus root */
+#define OBJPATH "/xyz/openbmc_project/certs"
+
+/* The CSR file */
+#define CSR_FILE_NAME "domain.csr"
+
+/* The private key file. */
+#define PRIV_KEY_FILE_NAME "privkey.pem"
+
+/* The rsa private key file. */
+#define RSA_PRIV_KEY_FILE_NAME ".rsaprivkey.pem"
+
+/* Authority certificates limit. */
+#define AUTHORITY_CERTIFICATES_LIMIT @authority_limit@
diff --git a/dist/meson.build b/dist/meson.build
new file mode 100644
index 0000000..7ed6046
--- /dev/null
+++ b/dist/meson.build
@@ -0,0 +1,67 @@
+systemd_system_unit_dir = systemd_dep.get_variable(
+    pkgconfig: 'systemdsystemunitdir'
+)
+busconfig_dir = get_option('datadir') / 'dbus-1' / 'system.d'
+cert_manager_dir = get_option('datadir') / 'phosphor-certificate-manager'
+
+certs = []
+busconfig = []
+service_files = [ 'phosphor-certificate-manager@.service' ]
+systemd_alias = []
+
+if not get_option('ca-cert-extension').disabled()
+    busconfig += 'busconfig/bmc-vmi-ca.conf'
+    service_files += 'bmc-vmi-ca-manager.service'
+endif
+
+if not get_option('config-bmcweb').disabled()
+    busconfig += 'busconfig/phosphor-bmcweb-cert-config.conf'
+    certs += 'env/bmcweb'
+    systemd_alias += [[
+        '../phosphor-certificate-manager@.service',
+        'multi-user.target.wants/phosphor-certificate-manager@bmcweb.service'
+    ]]
+endif
+
+if not get_option('config-nslcd').disabled()
+    busconfig += 'busconfig/phosphor-nslcd-authority-cert-config.conf'
+    certs += 'env/authority'
+    systemd_alias += [[
+        '../phosphor-certificate-manager@.service',
+        'multi-user.target.wants/phosphor-certificate-manager@authority.service'
+    ]]
+endif
+
+install_data(
+    service_files,
+    install_dir: systemd_system_unit_dir,
+)
+
+install_data(
+    busconfig,
+    install_dir: busconfig_dir,
+)
+
+install_data(
+    certs,
+    install_dir: cert_manager_dir,
+)
+
+foreach service: systemd_alias
+    # Meson 0.61 will support this:
+    #install_symlink(
+    #      service,
+    #      install_dir: systemd_system_unit_dir,
+    #      pointing_to: link,
+    #  )
+    meson.add_install_script(
+        'sh', '-c',
+        'mkdir -p $(dirname $DESTDIR/@0@/@1@)'.format(systemd_system_unit_dir,
+            service[1]),
+    )
+    meson.add_install_script(
+        'sh', '-c',
+        'ln -s @0@ $DESTDIR/@1@/@2@'.format(service[0], systemd_system_unit_dir,
+            service[1]),
+    )
+endforeach
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..6e8d350
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,94 @@
+project(
+    'phosphor-certificate-manager',
+    'cpp',
+    default_options: [
+        'buildtype=debugoptimized',
+        'cpp_std=c++20',
+        'warning_level=3',
+        'werror=true',
+    ],
+    meson_version: '>=0.57.0',
+)
+
+cpp = meson.get_compiler('cpp')
+
+sdbusplus_dep = dependency(
+    'sdbusplus',
+    fallback: ['sdbusplus', 'sdbusplus_dep'],
+)
+
+sdeventplus_dep = dependency(
+    'sdeventplus',
+    fallback: ['sdeventplus', 'sdeventplus_dep'],
+)
+
+phosphor_dbus_interfaces_dep = dependency(
+    'phosphor-dbus-interfaces',
+    fallback: [
+        'phosphor-dbus-interfaces',
+        'phosphor_dbus_interfaces_dep'
+    ],
+)
+
+phosphor_logging_dep = dependency(
+    'phosphor-logging',
+    fallback: ['phosphor-logging', 'phosphor_logging_dep'],
+)
+
+systemd_dep = dependency('systemd')
+openssl_dep = dependency('openssl')
+
+config_data = configuration_data()
+config_data.set(
+    'authority_limit',
+     get_option('authority-limit')
+)
+
+configure_file(
+    input: 'config.h.meson',
+    output: 'config.h',
+    configuration: config_data
+)
+
+phosphor_certificate_deps = [
+    openssl_dep,
+    phosphor_dbus_interfaces_dep,
+    phosphor_logging_dep,
+    sdbusplus_dep,
+    sdeventplus_dep,
+]
+
+cert_manager_lib = static_library(
+    'phosphor-certificate-manager',
+    [
+        'argument.cpp',
+        'certificate.cpp',
+        'certs_manager.cpp',
+        'csr.cpp',
+        'watch.cpp',
+    ],
+    dependencies: phosphor_certificate_deps,
+)
+
+cert_manager_dep = declare_dependency(
+    link_with: cert_manager_lib,
+    dependencies: phosphor_certificate_deps
+)
+
+executable(
+    'phosphor-certificate-manager',
+    'mainapp.cpp',
+    dependencies: cert_manager_dep,
+    install: true,
+)
+
+if not get_option('ca-cert-extension').disabled()
+  subdir('bmc-vmi-ca')
+endif
+
+subdir('dist')
+
+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..c08b9eb
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,22 @@
+option('tests', type: 'feature', description: 'Build tests')
+
+option('authority-limit',
+    type: 'integer',
+    value: 10,
+    description: 'Authority certificates limit',
+)
+
+option('ca-cert-extension',
+    type: 'feature',
+    description: 'Enable CA certificate manager (IBM specific)'
+)
+
+option('config-bmcweb',
+    type: 'feature',
+    description: 'Install bmcweb cert configs',
+)
+
+option('config-nslcd',
+    type: 'feature',
+    description: 'Install nslcd authority cert configs',
+)
diff --git a/subprojects/phosphor-dbus-interfaces.wrap b/subprojects/phosphor-dbus-interfaces.wrap
new file mode 100644
index 0000000..935a8b2
--- /dev/null
+++ b/subprojects/phosphor-dbus-interfaces.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/openbmc/phosphor-dbus-interfaces.git
+revision = HEAD
diff --git a/subprojects/phosphor-logging.wrap b/subprojects/phosphor-logging.wrap
new file mode 100644
index 0000000..a039fcf
--- /dev/null
+++ b/subprojects/phosphor-logging.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/openbmc/phosphor-logging.git
+revision = HEAD
diff --git a/subprojects/sdbusplus.wrap b/subprojects/sdbusplus.wrap
new file mode 100644
index 0000000..d470130
--- /dev/null
+++ b/subprojects/sdbusplus.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/openbmc/sdbusplus.git
+revision = HEAD
diff --git a/subprojects/sdeventplus.wrap b/subprojects/sdeventplus.wrap
new file mode 100644
index 0000000..085bb5e
--- /dev/null
+++ b/subprojects/sdeventplus.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+url = https://github.com/openbmc/sdeventplus.git
+revision = HEAD
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 0000000..f3996fe
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,51 @@
+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(
+    'test_certs_manager',
+    executable(
+        'test-certs-manager',
+        'certs_manager_test.cpp',
+        include_directories: '..',
+        dependencies: [
+            gtest_dep,
+            gmock_dep,
+            cert_manager_dep,
+        ],
+    ),
+    timeout: 360, # Takes about 1 minute to generate all the certs.  Allow 3x.
+)
+
+if not get_option('ca-cert-extension').disabled()
+    test(
+        'test_ca_certs_manager',
+        executable(
+            'test-ca-certs-manager',
+            'ca_certs_manager_test.cpp',
+            include_directories: '..',
+            dependencies: [
+                gtest_dep,
+                gmock_dep,
+                bmc_vmi_ca_dep,
+            ],
+        ),
+    )
+endif