Browse code

GitHub Actions testing on Ubuntu, Mac, & Windows

Updates to fix issues in the CMake install instructions.

Updates the README.md to indicate that CMake is now preferred

Adds a GitHub Actions badge, Discord badge, and logo to the README.md.

CMake:

- Renamed ENABLE_DOCS to ENABLE_MAN_PAGES.

- Fixed build issue when milter isn't enabled on Linux. Changed the
default to build milter on non-macOS, non-Windows operating systems.

- Fix LD_LIBRARY_PATH for tests including on macOS where LD_LIBRARY_PATH
and DYLD_LIBRARY_PATH must be manually propagated to subprocesses.

- Use UNKNOWN IMPORTED library instead of INTERFACE IMPORTED library for
pdcurses, but still use INTERFACE IMPORTED for ncurses.
UNKNOWN IMPORTED appears to be required so that we can use
$<TARGET_FILE_DIR:Curses::curses> to collected the pdcurses library at
install time on Windows.

- When building with vcpkg on Windows, CMake will automatically install
your app local dependencies (aka the DLL runtime dependencies).
Meanwhile, file(GET_RUNTIME_DEPENDENCIES ...) doesn't appear to work
correctly with vcpkg packages. The solution is to use a custom target
that has CMake perform a local install to the unit_tests directory
when using vcpkg.
This is in fact far easier than using GET_RUNTIME_DEPENDENCIES in the
unit_tests for assembling the test environment but we can't use this
method for the non-vcpkg install because it won't collect
checkDynamic.dll for us because we don't install our tests.
We also can't link with the static check.lib because the static
check.lib has pthreads symbols linked in and will conflict with our
pthread.dll.

TL;DR: We'll continue to use file(GET_RUNTIME_DEPENDENCIES ...) for
assembling the test enviornment on non-vcpkg builds, and use the local
install method for vcpkg builds.

testcase.py: Wrapped a Pathlib.unlink() call in exception handling as
the missing_ok optional parameter requires a Python version too new for
common use.

Remove localtime_r from win32 compat lib.
localtime_r may be present in libcheck when building with vcpkg and
while making it a static function would also solve the issue, using
localtime_s instead like we do everywhere else should work just fine.

check_clamd: Limited the max # of connections for the stress test on Mac
to 850, to address issues found testing on macos-latest on GitHub Actions.

Micah Snyder authored on 2020/11/19 14:19:27
Showing 13 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,173 @@
0
+name: CMake Build
1
+
2
+# Controls when the action will run. Triggers the workflow on push or pull request
3
+# events but only for the master branch
4
+on:
5
+  push:
6
+    branches:
7
+      - rel/*
8
+      - dev/*
9
+      - main
10
+  pull_request:
11
+    branches:
12
+      - rel/*
13
+      - dev/*
14
+      - main
15
+
16
+env:
17
+  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
18
+  BUILD_TYPE: Release
19
+  VCPKG_GIT_REF: 8a9a97315aefb3f8bc5d81bf66ca0025938b9c91
20
+
21
+jobs:
22
+  build-windows:
23
+    runs-on: windows-latest
24
+
25
+    steps:
26
+      - uses: actions/checkout@v1
27
+
28
+      - name: Install Build Tools
29
+        uses: crazy-max/ghaction-chocolatey@v1
30
+        with:
31
+          args: install wixtoolset
32
+
33
+      - uses: lukka/get-cmake@latest
34
+
35
+      # Restore from cache the previously built ports. If cache-miss, download, build vcpkg ports.
36
+      - name: Restore vcpkg ports from cache or install vcpkg
37
+        # Download and build vcpkg, without installing any port. If content is cached already, it is a no-op.
38
+        uses: lukka/run-vcpkg@v5
39
+        id: runvcpkg
40
+        with:
41
+          vcpkgArguments: "curl[openssl] json-c libxml2 pcre2 check pthreads zlib pdcurses bzip2"
42
+          vcpkgGitCommitId: "${{ env.VCPKG_GIT_REF }}"
43
+          vcpkgTriplet: "x64-windows"
44
+
45
+      - name: Print the VCPKG_ROOT & VCPKG_TRIPLET (for debugging)
46
+        shell: bash
47
+        run: echo "'${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_ROOT_OUT }}' '${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_TRIPLET_OUT }}' "
48
+
49
+      - name: dir the VCPKG_ROOT
50
+        run: dir ${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_ROOT_OUT }}
51
+
52
+      - name: Create Build Directory
53
+        shell: bash
54
+        # Some projects don't allow in-source building, so create a separate build directory
55
+        # We'll use this as our working directory for all subsequent commands
56
+        run: cmake -E make_directory ${{runner.workspace}}/build
57
+
58
+      - name: Run CMake+Ninja with triplet (cmd)
59
+        uses: lukka/run-cmake@main
60
+        id: runcmake_cmd
61
+        with:
62
+          cmakeGenerator: "Ninja" # Visual Studio 15 2017
63
+          cmakeListsOrSettingsJson: "CMakeListsTxtBasic"
64
+          cmakeListsTxtPath: "${{runner.workspace}}/clamav-devel/CMakeLists.txt"
65
+          useVcpkgToolchainFile: true
66
+          cmakeAppendedArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" -DENABLE_EXAMPLES=ON -DENABLE_STATIC_LIB=ON -- -v'
67
+          cmakeBuildType: "${{ env.BUILD_TYPE }}"
68
+          vcpkgTriplet: ${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_TRIPLET_OUT }}
69
+          buildDirectory: "${{runner.workspace}}/build"
70
+
71
+      - name: Test
72
+        working-directory: ${{runner.workspace}}/build
73
+        # Execute tests defined by the CMake configuration.
74
+        # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
75
+        run: ctest -C ${{ env.BUILD_TYPE }} -V
76
+
77
+      - name: Create Installer
78
+        working-directory: ${{runner.workspace}}/build
79
+        run: cpack -C ${{ env.BUILD_TYPE }}
80
+
81
+  build-macos:
82
+    runs-on: macos-latest
83
+
84
+    steps:
85
+      - uses: actions/checkout@v1
86
+
87
+      - name: Install Build Tools
88
+        run: brew install bison flex
89
+
90
+      - name: Install Dependencies
91
+        run: brew install bzip2 check curl-openssl json-c libxml2 ncurses openssl@1.1 pcre2 zlib
92
+
93
+      - uses: lukka/get-cmake@latest
94
+
95
+      - name: Create Build Directory
96
+        shell: bash
97
+        # Some projects don't allow in-source building, so create a separate build directory
98
+        # We'll use this as our working directory for all subsequent commands
99
+        run: cmake -E make_directory ${{runner.workspace}}/build
100
+
101
+      - name: Configure CMake
102
+        # Use a bash shell so we can use the same syntax for environment variable
103
+        # access regardless of the host operating system
104
+        working-directory: ${{runner.workspace}}/build
105
+        # Note the current convention is to use the -S and -B options here to specify source
106
+        # and build directories, but this is only available with CMake 3.13 and higher.
107
+        # The CMake binaries on the Github Actions machines are (as of this writing) 3.12
108
+        run:
109
+          cmake ${{runner.workspace}}/clamav-devel -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}
110
+          -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1/
111
+          -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.1.1.dylib
112
+          -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib
113
+          -DENABLE_STATIC_LIB=ON
114
+          -DENABLE_EXAMPLES=ON
115
+
116
+      - name: Build
117
+        shell: bash
118
+        working-directory: ${{runner.workspace}}/build
119
+        # Execute the build.  You can specify a specific target with "--target <NAME>"
120
+        run: cmake --build . --config ${{ env.BUILD_TYPE }}
121
+
122
+      - name: Test
123
+        shell: bash
124
+        working-directory: ${{runner.workspace}}/build
125
+        # Execute tests defined by the CMake configuration.
126
+        # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
127
+        run: ctest -C ${{ env.BUILD_TYPE }} -V
128
+
129
+  build-ubuntu:
130
+    runs-on: ubuntu-latest
131
+
132
+    steps:
133
+      - uses: actions/checkout@v1
134
+
135
+      - name: Install Build Tools
136
+        run: sudo apt-get install -y bison flex valgrind
137
+
138
+      - name: Install Dependencies
139
+        run: sudo apt-get install -y check libbz2-dev libcurl4-openssl-dev libjson-c-dev libmilter-dev libncurses5-dev libpcre3-dev libssl-dev libxml2-dev zlib1g-dev
140
+
141
+      - uses: lukka/get-cmake@latest
142
+
143
+      - name: Create Build Directory
144
+        shell: bash
145
+        # Some projects don't allow in-source building, so create a separate build directory
146
+        # We'll use this as our working directory for all subsequent commands
147
+        run: cmake -E make_directory ${{runner.workspace}}/build
148
+
149
+      - name: Configure CMake
150
+        # Use a bash shell so we can use the same syntax for environment variable
151
+        # access regardless of the host operating system
152
+        working-directory: ${{runner.workspace}}/build
153
+        # Note the current convention is to use the -S and -B options here to specify source
154
+        # and build directories, but this is only available with CMake 3.13 and higher.
155
+        # The CMake binaries on the Github Actions machines are (as of this writing) 3.12
156
+        run:
157
+          cmake ${{runner.workspace}}/clamav-devel -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}
158
+          -DENABLE_STATIC_LIB=ON
159
+          -DENABLE_EXAMPLES=ON
160
+
161
+      - name: Build
162
+        shell: bash
163
+        working-directory: ${{runner.workspace}}/build
164
+        # Execute the build.  You can specify a specific target with "--target <NAME>"
165
+        run: cmake --build . --config ${{ env.BUILD_TYPE }}
166
+
167
+      - name: Test
168
+        shell: bash
169
+        working-directory: ${{runner.workspace}}/build
170
+        # Execute tests defined by the CMake configuration.
171
+        # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
172
+        run: ctest -C ${{ env.BUILD_TYPE }} -V
... ...
@@ -46,6 +46,13 @@ math(EXPR LIBFRESHCLAM_SOVERSION "${LIBFRESHCLAM_CURRENT} - ${LIBFRESHCLAM_AGE}"
46 46
 set(LIBFRESHCLAM_VERSION "${LIBFRESHCLAM_SOVERSION}.${LIBFRESHCLAM_AGE}.${LIBFRESHCLAM_REVISION}")
47 47
 HexVersion(LIBFRESHCLAM_VERSION_NUM ${LIBFRESHCLAM_CURRENT} ${LIBFRESHCLAM_REVISION} ${LIBFRESHCLAM_AGE})
48 48
 
49
+#
50
+# Define C_LINUX because CMake only defines UNIX
51
+#
52
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
53
+    set(C_LINUX 1)
54
+endif()
55
+
49 56
 # Git optionally used to add commit info into build to differentiate in bug reports.
50 57
 find_package(Git)
51 58
 if(Git_FOUND)
... ...
@@ -79,19 +86,27 @@ endif()
79 79
 #
80 80
 
81 81
 # CMake Option default values:
82
-set(ENABLE_APP_DEFAULT          ON)
83
-set(ENABLE_MILTER_DEFAULT       OFF)
84
-set(ENABLE_CLAMONACC_DEFAULT    ON)
85
-set(ENABLE_EXAMPLES_DEFAULT     OFF)
86
-set(ENABLE_TESTS_DEFAULT        ON)
82
+set(ENABLE_APP_DEFAULT              ON)
83
+if(WIN32 OR APPLE)
84
+    set(ENABLE_MILTER_DEFAULT       OFF)
85
+else()
86
+    set(ENABLE_MILTER_DEFAULT       ON)
87
+endif()
88
+if(C_LINUX)
89
+    set(ENABLE_CLAMONACC_DEFAULT    ON)
90
+else()
91
+    set(ENABLE_CLAMONACC_DEFAULT    OFF)
92
+endif()
93
+set(ENABLE_EXAMPLES_DEFAULT         OFF)
94
+set(ENABLE_TESTS_DEFAULT            ON)
87 95
 if(WIN32)
88
-    set(ENABLE_DOCS_DEFAULT     OFF)
96
+    set(ENABLE_MAN_PAGES_DEFAULT    OFF)
89 97
 else()
90
-    set(ENABLE_DOCS_DEFAULT     ON)
98
+    set(ENABLE_MAN_PAGES_DEFAULT    ON)
91 99
 endif()
92
-set(ENABLE_DOXYGEN_DEFAULT      OFF)
93
-set(ENABLE_UNRAR_DEFAULT        ON)
94
-set(ENABLE_SYSTEMD_DEFAULT      ON)
100
+set(ENABLE_DOXYGEN_DEFAULT          OFF)
101
+set(ENABLE_UNRAR_DEFAULT            ON)
102
+set(ENABLE_SYSTEMD_DEFAULT          ON)
95 103
 
96 104
 # See CMakeOptions.cmake for additional options.
97 105
 include(CMakeOptions.cmake)
... ...
@@ -127,8 +142,8 @@ else()
127 127
     set(ENABLE_LIB_ONLY_DISABLED_OTHERS 0)
128 128
 endif()
129 129
 if(ENABLE_LIBCLAMAV_ONLY)
130
-    set(ENABLE_APP              OFF)
131
-    set(ENABLE_EXAMPLES         OFF)
130
+    set(ENABLE_APP                  OFF)
131
+    set(ENABLE_EXAMPLES             OFF)
132 132
 endif()
133 133
 
134 134
 #
... ...
@@ -139,27 +154,15 @@ if(APPLE)
139 139
 endif()
140 140
 set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
141 141
 
142
-#
143
-# Define C_LINUX because CMake only defines UNIX
144
-#
145
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
146
-    set(C_LINUX 1)
147
-
142
+if(C_LINUX)
148 143
     if(CMAKE_COMPILER_IS_GNUCXX)
149
-        # For O_LARGEFILE, O_CLOEXEC, O_DIRECTORY, O_NOFOLLOW, etc flags on older systems
144
+        # Set _GNU_SOURCE for O_LARGEFILE, O_CLOEXEC, O_DIRECTORY, O_NOFOLLOW, etc flags on older systems
150 145
         # (pre POSIX.1-2008: glibc 2.11 and earlier). #4042
151 146
         set(_GNU_SOURCE 1)
152 147
     endif()
153 148
 endif()
154 149
 
155 150
 #
156
-# Set FreeBSD include path to include /usr/local/include
157
-#
158
-if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
159
-    include_directories(/usr/local/include)
160
-endif()
161
-
162
-#
163 151
 # Use the `lib` prefix on Windows, to match previous ClamAV build
164 152
 #
165 153
 if(WIN32)
... ...
@@ -733,7 +736,7 @@ endif()
733 733
 add_subdirectory( libclamunrar_iface )
734 734
 
735 735
 if(NOT ENABLE_EXTERNAL_MSPACK)
736
-    add_subdirectory(libclammspack)
736
+    add_subdirectory( libclammspack )
737 737
 else()
738 738
     find_package(MSPack)
739 739
 endif()
... ...
@@ -761,7 +764,7 @@ if(NOT ENABLE_LIBCLAMAV_ONLY)
761 761
             add_subdirectory( clamonacc )
762 762
         endif()
763 763
 
764
-        if(NOT WIN32 AND ENABLE_MILTER)
764
+        if(ENABLE_MILTER)
765 765
             add_subdirectory( clamav-milter )
766 766
         endif()
767 767
 
... ...
@@ -792,13 +795,11 @@ endif()
792 792
 include(CTest)
793 793
 add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
794 794
 if(ENABLE_TESTS)
795
-    add_subdirectory(test)
796
-    add_subdirectory(unit_tests)
795
+    add_subdirectory( test )
796
+    add_subdirectory( unit_tests )
797 797
 endif()
798 798
 
799
-if(ENABLE_DOCS)
800
-    add_subdirectory( docs )
801
-endif()
799
+add_subdirectory( docs )
802 800
 
803 801
 if(ENABLE_FUZZ)
804 802
     add_subdirectory( fuzz )
... ...
@@ -814,6 +815,7 @@ ${c}    Package Version:        ${e}${PACKAGE_STRING}
814 814
 ${c}    libclamav version:      ${e}${LIBCLAMAV_CURRENT}:${LIBCLAMAV_REVISION}:${LIBCLAMAV_AGE}
815 815
 ${c}    libfreshclam version:   ${e}${LIBFRESHCLAM_CURRENT}:${LIBFRESHCLAM_REVISION}:${LIBFRESHCLAM_AGE}
816 816
 ${c}    Install prefix:         ${e}${CMAKE_INSTALL_PREFIX}
817
+${c}    Host system:            ${e}${CMAKE_HOST_SYSTEM}
817 818
 ${c}    Target system:          ${e}${CMAKE_SYSTEM}
818 819
 ${c}    Compiler:               ${e}
819 820
 ${b}        Build type:         ${e}${CMAKE_BUILD_TYPE}
... ...
@@ -821,7 +823,16 @@ ${b}        C compiler:         ${e}${CMAKE_C_COMPILER}
821 821
 ${b}        C++ compiler:       ${e}${CMAKE_CXX_COMPILER}
822 822
 ${b}        CFLAGS:             ${e}${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
823 823
 ${b}        CXXFLAGS:           ${e}${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
824
-${b}        WARNCFLAGS:         ${e}${WARNCFLAGS}
824
+${b}        WARNCFLAGS:         ${e}${WARNCFLAGS}")
825
+if(VCPKG_TOOLCHAIN)
826
+message("\
827
+${c}    Using vcpkg:            ${e}
828
+${b}        Target Triplet:     ${e}${VCPKG_TARGET_TRIPLET}
829
+${b}        Target Arch:        ${e}${VCPKG_TARGET_ARCHITECTURE}
830
+${b}        Get runtime DLLs:   ${e}${VCPKG_APPLOCAL_DEPS}
831
+${b}        Package root path:  ${e}${VCPKG_CMAKE_FIND_ROOT_PATH}")
832
+endif()
833
+message("\
825 834
 ${c}    Build Options:          ${e}
826 835
 ${b}        Build apps:         ${e}${ENABLE_APP}
827 836
 ${b}        Shared library:     ${e}${ENABLE_SHARED_LIB}
... ...
@@ -829,7 +840,7 @@ ${b}        Static library:     ${e}${ENABLE_STATIC_LIB}
829 829
 ${b}        Enable UnRAR:       ${e}${ENABLE_UNRAR}
830 830
 ${b}        Examples:           ${e}${ENABLE_EXAMPLES}
831 831
 ${b}        Tests:              ${e}${ENABLE_TESTS}
832
-${b}        Build man pages:    ${e}${ENABLE_DOCS}
832
+${b}        Build man pages:    ${e}${ENABLE_MAN_PAGES}
833 833
 ${b}        Build doxygen HTML: ${e}${ENABLE_DOXYGEN}")
834 834
 if(NOT WIN32)
835 835
 message("\
... ...
@@ -1,6 +1,6 @@
1 1
 # Features that can be enabled for cmake (see CMakeLists.txt)
2 2
 
3
-if (WIN32)
3
+if(WIN32)
4 4
     set(APP_CONFIG_DIRECTORY
5 5
         "." CACHE STRING
6 6
         "App Config directory.")
... ...
@@ -77,9 +77,9 @@ option(ENABLE_CLAMONACC
77 77
     "Build clamonacc (Linux-only, requires ENABLE_APP))."
78 78
     ${ENABLE_CLAMONACC_DEFAULT})
79 79
 
80
-option(ENABLE_DOCS
81
-    "Generate documentation."
82
-    ${ENABLE_DOCS_DEFAULT})
80
+option(ENABLE_MAN_PAGES
81
+    "Generate man pages."
82
+    ${ENABLE_MAN_PAGES_DEFAULT})
83 83
 
84 84
 option(ENABLE_DOXYGEN
85 85
     "Generate doxygen HTML documentation for clamav.h, libfreshclam.h."
... ...
@@ -1,16 +1,11 @@
1 1
 # Installation Instructions
2 2
 
3
-**CAUTION**: ClamAV CMake support is experimental in this release and is not
4
-recommended for production systems!!!
5
-
6
-Please help us stabilize it so we can deprecate autotools and Visual Studio.
3
+CMake the preferred build system going forwards. The Windows Visual Studio
4
+solution has been removed, and the Autotools build system will likely be
5
+removed in the near future.
7 6
 
8 7
 _Known Issues / To-do:_
9 8
 
10
-- Support for building unit tests / feature tests and running with CTest
11
-  - A portion of this task will involve converting the shell scripts portions
12
-    to Python unit tests.
13
-- Build fuzz targets.
14 9
 - LLVM bytecode runtime support.
15 10
   - Presently only the bytecode intepreter is supported. LLVM is preferable
16 11
     because it is faster. This task also requires updating to use a modern
... ...
@@ -20,8 +15,12 @@ _Known Issues / To-do:_
20 20
     is updated.
21 21
 - Complete the MAINTAINER_MODE option to generate jsparse files with GPerf.
22 22
 
23
+**Table Of Contents**
24
+
23 25
 - [Installation Instructions](#installation-instructions)
24 26
   - [CMake Basics](#cmake-basics)
27
+    - [Build requirements](#build-requirements)
28
+    - [Optional build requirements (Maintainer-Mode)](#optional-build-requirements-maintainer-mode)
25 29
     - [Basic Release build & system install](#basic-release-build--system-install)
26 30
     - [Basic Debug build](#basic-debug-build)
27 31
     - [Build and install to a specific install location (prefix)](#build-and-install-to-a-specific-install-location-prefix)
... ...
@@ -32,38 +31,45 @@ _Known Issues / To-do:_
32 32
     - [Example Build Commands](#example-build-commands)
33 33
       - [Linux release build, install to system](#linux-release-build-install-to-system)
34 34
       - [macOS debug build, custom OpenSSL path, build examples, local install](#macos-debug-build-custom-openssl-path-build-examples-local-install)
35
-      - [Windows Build](#windows-build)
35
+      - [Windows builds](#windows-builds)
36
+      - [Windows build (with vcpkg)](#windows-build-with-vcpkg)
37
+      - [Windows build (with Mussels)](#windows-build-with-mussels)
38
+      - [Build the Installer](#build-the-installer)
36 39
     - [External Depedencies](#external-depedencies)
37 40
       - [libclamav dependencies](#libclamav-dependencies)
38 41
       - [libfreshclam dependencies](#libfreshclam-dependencies)
39 42
       - [Application dependencies](#application-dependencies)
40 43
       - [Dependency build options](#dependency-build-options)
41
-        - [libcheck](#libcheck)
42
-        - [bzip2](#bzip2)
43
-        - [zlib](#zlib)
44
-        - [libxml2](#libxml2)
45
-        - [libpcre2](#libpcre2)
46
-        - [openssl (libcrypto, libssl)](#openssl-libcrypto-libssl)
47
-        - [libjson-c](#libjson-c)
48
-        - [libmspack](#libmspack)
49
-        - [iconv (POSIX-only)](#iconv-posix-only)
50
-        - [pthreads-win32 (Windows-only)](#pthreads-win32-windows-only)
51
-        - [llvm (optional, _see "Bytecode Runtime" section_)](#llvm-optional-see-bytecode-runtime-section)
52
-        - [libcurl](#libcurl)
53
-        - [ncurses or pdcurses, for clamdtop](#ncurses-or-pdcurses-for-clamdtop)
44
+        - [`libcheck`](#libcheck)
45
+        - [`bzip2`](#bzip2)
46
+        - [`zlib`](#zlib)
47
+        - [`libxml2`](#libxml2)
48
+        - [`libpcre2`](#libpcre2)
49
+        - [`openssl` (`libcrypto`, `libssl`)](#openssl-libcrypto-libssl)
50
+        - [`libjson-c`](#libjson-c)
51
+        - [`libmspack`](#libmspack)
52
+        - [`iconv` (POSIX-only)](#iconv-posix-only)
53
+        - [`pthreads-win32` (Windows-only)](#pthreads-win32-windows-only)
54
+        - [`llvm` (optional, _see "Bytecode Runtime" section_)](#llvm-optional-see-bytecode-runtime-section)
55
+        - [`libcurl`](#libcurl)
56
+        - [`ncurses` or `pdcurses`, for `clamdtop`](#ncurses-or-pdcurses-for-clamdtop)
54 57
         - [Bytecode Runtime](#bytecode-runtime)
55 58
   - [Compilers and Options](#compilers-and-options)
56 59
   - [Compiling For Multiple Architectures](#compiling-for-multiple-architectures)
57 60
 
58 61
 ## CMake Basics
59 62
 
60
-Build requirements:
63
+### Build requirements
64
+
65
+- CMake 3.14+
66
+- A C compiler toolchain such as gcc, clang, or Microsoft Visual Studio.
67
+- Python 3 (to run the test suite)
61 68
 
62
-- CMake 3.13+
63
-- A C-toolchain such as gcc, clang, or Microsoft Visual Studio.
64
-- Flex and Bison. On Windows, `choco install winflexbison`.
69
+### Optional build requirements (Maintainer-Mode)
65 70
 
66
-_Important_: The following instructions assume that you have created a `build`
71
+- GPerf, Flex and Bison. On Windows, `choco install winflexbison`.
72
+
73
+**_Important_**: The following instructions assume that you have created a `build`
67 74
 subdirectory and that subsequent commands are performed from said directory,
68 75
 like so:
69 76
 
... ...
@@ -74,7 +80,7 @@ mkdir build && cd build
74 74
 ### Basic Release build & system install
75 75
 
76 76
 ```sh
77
-cmake .. -DCMAKE_BUILD_TYPE="Release"
77
+cmake .. -D CMAKE_BUILD_TYPE="Release"
78 78
 cmake --build . --config Release
79 79
 sudo cmake --build . --config Release --target install
80 80
 ```
... ...
@@ -84,7 +90,7 @@ sudo cmake --build . --config Release --target install
84 84
 In CMake, "Debug" builds mean that symbols are compiled in.
85 85
 
86 86
 ```sh
87
-cmake .. -DCMAKE_BUILD_TYPE="Debug"
87
+cmake .. -D CMAKE_BUILD_TYPE="Debug"
88 88
 cmake --build . --config Debug
89 89
 ```
90 90
 
... ...
@@ -92,20 +98,31 @@ You will likely also wish to disable compiler/linker optimizations, which you
92 92
 can do like so, using our custom `OPTIMIZE` option:
93 93
 
94 94
 ```sh
95
-cmake .. -DCMAKE_BUILD_TYPE="Debug" -DOPTIMIZE=OFF
95
+cmake .. -D CMAKE_BUILD_TYPE="Debug" -D OPTIMIZE=OFF
96 96
 cmake --build . --config Debug
97 97
 ```
98 98
 
99
-_Tip_: CMake provides four `CMAKE_BUILD_TYPE`s / options for `--config`):
100
-- Debug
101
-- Release
102
-- MinSizeRel
103
-- RelWithDebInfo
99
+_Tip_: CMake provides four build configurations which you can set using the
100
+`CMAKE_BUILD_TYPE` variable or the `--config` (`-C`) command line option.
101
+These are:
102
+- `Debug`
103
+- `Release`
104
+- `MinSizeRel`
105
+- `RelWithDebInfo`
106
+
107
+For multi-config generators, such as "Visual Studio" and "Ninja Multi-Config",
108
+you should not specify the config when you initially configure the project but
109
+you _will_ need to specify the config when you build the project and when
110
+running `ctest` or `cpack`.
111
+
112
+For single-config generators, such as "Make" or "Ninja", you will need to
113
+specify the config when you configure the project, and should _not_ specify the
114
+config when you build the project or run `ctest`.
104 115
 
105 116
 ### Build and install to a specific install location (prefix)
106 117
 
107 118
 ```sh
108
-cmake -DCMAKE_INSTALL_PREFIX:PATH=install ..
119
+cmake -D CMAKE_INSTALL_PREFIX:PATH=install ..
109 120
 cmake --build . --target install --config Release
110 121
 ```
111 122
 
... ...
@@ -121,13 +138,14 @@ cmake --build . --config Release
121 121
 ### Build and run tests
122 122
 
123 123
 The option to build and run tests is enabled by default, which requires that
124
-you provide libcheck `check`, `check-devel`, `check-dev`, etc.
124
+you provide libcheck (i.e. `check`, `check-devel`, `check-dev`, etc).
125 125
 
126 126
 If you're building with `ENABLE_LIBCLAMAV_ONLY=ON` or `ENABLE_APP=OFF`, then
127 127
 libcheck will still be required and you can still run the tests, but it will
128 128
 skip all app tests and only run the libclamav unit tests.
129 129
 
130
-If you wish to disable test support, then configure with `-DENABLE_TESTS=OFF`.
130
+If you wish to disable test support, then configure with `-D ENABLE_TESTS=OFF`.
131
+
131 132
 
132 133
 - `-V`: Verbose
133 134
 
... ...
@@ -145,7 +163,7 @@ ctest -C Release -V
145 145
 The following CMake options can be selected by using `-D`. For example:
146 146
 
147 147
 ```sh
148
-cmake .. -DENABLE_EXAMPLES
148
+cmake .. -D ENABLE_EXAMPLES
149 149
 cmake --build . --config Debug
150 150
 ```
151 151
 
... ...
@@ -201,7 +219,7 @@ cmake --build . --config Debug
201 201
   and requires the following environment variables to be set:
202 202
   - CC = `which clang`
203 203
   - CXX = `which clang++`
204
-  - SANITIZER = address _or_ undefined _or_ memory
204
+  - SANITIZER = "address" _or_ "undefined" _or_ "memory"
205 205
 
206 206
   _Default: `OFF`_
207 207
 
... ...
@@ -233,13 +251,13 @@ cmake --build . --config Debug
233 233
 - `ENABLE_MILTER`: (Posix-only) Build the clamav-milter mail filter daemon.
234 234
   Requires: `ENABLE_APP`
235 235
 
236
-  _Default: `OFF`_
236
+  _Default: `OFF` for Mac & Windows, `ON` for Linux/Unix_
237 237
 
238 238
 - `ENABLE_UNRAR`: Build & install libclamunrar (UnRAR) and libclamunrar_iface.
239 239
 
240 240
   _Default: `ON`_
241 241
 
242
-- `ENABLE_DOCS`: Generate man pages.
242
+- `ENABLE_MAN_PAGES`: Generate man pages.
243 243
 
244 244
   _Default: `OFF`_
245 245
 
... ...
@@ -291,145 +309,226 @@ cmake --build . --config Debug
291 291
 
292 292
 #### Linux release build, install to system
293 293
 
294
-This example sets the build system to Ninja instead of using Make, for speed.
294
+This example sets the build generator to Ninja instead of using Make, for speed.
295 295
 You may need to first use `apt`/`dnf`/`pkg` to install `ninja-build`
296 296
 
297 297
 ```sh
298 298
 cmake .. -G Ninja \
299
-  -DCMAKE_BUILD_TYPE=Release \
300
-  -DENABLE_JSON_SHARED=OFF
299
+  -D CMAKE_BUILD_TYPE=Release \
300
+  -D ENABLE_JSON_SHARED=OFF
301 301
 ninja
302 302
 sudo ninja install
303 303
 ```
304 304
 
305 305
 #### macOS debug build, custom OpenSSL path, build examples, local install
306 306
 
307
-macOS builds use Homebrew to install `flex`, `bison`, and each of the library
308
-dependencies.
307
+For macOS builds, we recommend using Homebrew to install the build tools, such
308
+as `cmake`, `flex`, `bison`, as well as ClamAV's library dependencies.
309 309
 
310 310
 Note that explicit paths for OpenSSL are requires so as to avoid using an older
311 311
 OpenSSL install provided by the operating system.
312 312
 
313 313
 This example also:
314
-
315
-- Build system to Ninja instead of using Make.
314
+- Sets the build generator to Ninja instead of using Make.
316 315
   - You may need to first use `brew` to install `ninja`.
317
-- Sets build type to "Debug" and explicitly disables compiler optimizations.
316
+- Sets build config to "Debug" and explicitly disables compiler optimizations.
318 317
 - Builds static libraries (and also shared libraries, which are on by default).
319 318
 - Builds the example programs, just to test them out.
320
-- Sets the install path (prefix) to ./install
319
+- Sets the install path (prefix) to `./install`.
321 320
 
322 321
 ```sh
323
-cmake .. -G Ninja                                                              \
324
-  -DCMAKE_BUILD_TYPE=Debug                                                     \
325
-  -DOPTIMIZE=OFF                                                               \
326
-  -DENABLE_JSON_SHARED=OFF                                                     \
327
-  -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1/                               \
328
-  -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.1.1.dylib  \
329
-  -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib        \
330
-  -DENABLE_STATIC_LIB=ON                                                       \
331
-  -DENABLE_EXAMPLES=ON                                                         \
332
-  -DCMAKE_INSTALL_PREFIX=install
322
+cmake .. -G Ninja                                                             \
323
+  -D CMAKE_BUILD_TYPE=Debug                                                    \
324
+  -D OPTIMIZE=OFF                                                              \
325
+  -D ENABLE_JSON_SHARED=OFF                                                    \
326
+  -D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1/                              \
327
+  -D OPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.1.1.dylib \
328
+  -D OPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib       \
329
+  -D ENABLE_STATIC_LIB=ON                                                      \
330
+  -D ENABLE_EXAMPLES=ON                                                        \
331
+  -D CMAKE_INSTALL_PREFIX=install
333 332
 ninja
334 333
 ninja install
335 334
 ```
336 335
 
336
+#### Windows builds
337
+
338
+At a minimum you will need Visual Studio 2015 or newer, and CMake.
339
+If you want to build the installer, you'll also need WiX Toolset.
340
+
341
+If you're using Chocolatey, you can install CMake and WiX simply like this:
342
+
343
+```ps1
344
+choco install cmake wixtoolset
345
+```
346
+
347
+Then open a new terminal so that CMake and WiX will be in your `$PATH`.
348
+
337 349
 #### Windows build (with vcpkg)
338 350
 
339
-Building with `vcpkg` is relatively easy, as all of the dependencies are built automatically.
340
-
341
-##### Preprequisites
342
-You'll need CMake, git and vcpkg installed.
343
-
344
-- CMake: Download the installer [here](https://cmake.org/download/#latest) and
345
-  install it.
346
-- Git: Download the installer [here](https://git-scm.com/download/win) and
347
-  install it.
348
-- vcpkg: Get and install [vcpkg](https://github.com/microsoft/vcpkg). Set up
349
-  `vcpkg` as described in their README. Set the variable `$VCPKG_PATH` to the
350
-  location where you installed `vcpkg`. If you want to build for a 64 bit
351
-  system, don't forget to set `vcpkg`'s triple correctly:
352
-  ```ps1
353
-  $env:VCPKG_DEFAULT_TRIPLET="x64-windows"
354
-  $VCPKG_PATH="..." # Path to your vcpkg installation
355
-  ```
356
-
357
-##### Configuring and compiling
358
-Next, install the required packages:
351
+`vcpkg` can be used to build the ClamAV library dependencies automatically.
352
+
353
+`vcpkg` integrates really well with CMake, enabling CMake to find your compiled
354
+libraries automatically, so you don't have to specify the include & library
355
+paths manually as you do when using Mussels (below).
356
+
357
+**Preprequisites:**
358
+
359
+You'll need to install [vcpkg](https://github.com/microsoft/vcpkg).
360
+See the `vcpkg` README for installation instructions.
361
+
362
+Once installed, set the variable `$VCPKG_PATH` to the location where you
363
+installed `vcpkg`:
364
+
365
+```ps1
366
+$VCPKG_PATH="..." # Path to your vcpkg installation
367
+```
368
+
369
+By default, CMake and `vcpkg` build for 32-bit. If you want to build for 64-bit,
370
+set the `VCPKG_DEFAULT_TRIPLET` environment variable:
371
+
372
+```ps1
373
+$env:VCPKG_DEFAULT_TRIPLET="x64-windows"
374
+```
375
+
376
+**Building the libraries and ClamAV:**
377
+
378
+Next, use `vcpkg` to build the required library dependencies:
379
+
359 380
 ```ps1
360 381
 & "$VCPKG_PATH\vcpkg" install 'curl[openssl]' 'json-c' 'libxml2' 'pcre2' 'pthreads' 'zlib' 'pdcurses' 'bzip2'
361 382
 ```
362 383
 
363
-Now check out the ClamAV repository and set your build environment up with
364
-CMake:
384
+Now configure the ClamAV build using the `CMAKE_TOOLCHAIN_FILE` variable which
385
+will enable CMake to automatically find the libraries we built with `vcpkg`.
386
+
365 387
 ```ps1
366
-git clone https://github.com/Cisco-Talos/clamav-devel
367
-cd clamav-devel
368
-mkdir build
369
-cd build
370
-cmake -A x64 `
371
-      -DCMAKE_TOOLCHAIN_FILE="$VCPKG_PATH\scripts\buildsystems\vcpkg.cmake" `
372
-      -DCMAKE_INSTALL_PREFIX='C:\clamav' ..
373
-```
374
-You have to drop the `-A x64` arguments if you're building for 32
375
-bits, and correct the package paths accordingly. Also, if you want to install
376
-via the MSVC project, set up the install path as you like.
377
-
378
-Finally, go ahead and build the project:
388
+cmake .. -A x64 `
389
+  -D CMAKE_TOOLCHAIN_FILE="$VCPKG_PATH\scripts\buildsystems\vcpkg.cmake" `
390
+  -D CMAKE_INSTALL_PREFIX="install"
391
+```
392
+
393
+_Tip_: You have to drop the `-A x64` arguments if you're building for 32-bits,
394
+and correct the package paths accordingly.
395
+
396
+Now, go ahead and build the project:
397
+
379 398
 ```ps1
380 399
 cmake --build . --config Release
381 400
 ```
382 401
 
383
-#### Windows Build (manual or with Mussels)
402
+You can run the test suite with CTest:
403
+
404
+```ps1
405
+ctest -C Release
406
+```
407
+
408
+And you can install to the `install` directory (set above) like this:
409
+
410
+```ps1
411
+cmake --build . --config Release --target install
412
+```
413
+
414
+#### Windows build (with Mussels)
415
+
416
+Much like `vcpkg`, [Mussels](https://github.com/Cisco-Talos/Mussels) can be
417
+used to automatically build the ClamAV library dependencies. Unlike `vcpkg`,
418
+Mussels does not provide a mechanism for CMake to automatically detect the
419
+library paths.
420
+
421
+**Preprequisites:**
422
+
423
+To build the library dependencies with Mussels, use Python's `pip` package
424
+manager to install Mussels:
425
+
426
+```ps1
427
+python3 -m pip install mussels
428
+```
429
+
430
+Update the Mussels cookbooks to get the latest build recipes and set the
431
+`clamav` cookbook to be trusted:
432
+
433
+```ps1
434
+msl update
435
+msl cookbook trust clamav
436
+```
437
+
438
+Use `msl list` if you wish to see the recipes provided by the `clamav` cookbook.
384 439
 
385
-Chocolatey (`choco`) is used to install `winflexbison` and `cmake`.
386
-Visual Studio 2015+ is required, 2017+ recommended.
440
+**Building the libraries and ClamAV:**
387 441
 
388
-These instructions assume that `$env:CLAMAV_DEPENDENCIES` is set to your
389
-[Mussels](https://github.com/Cisco-Talos/Mussels) `install\x64` directory and
390
-that you've used Mussels to build the `clamav_deps` collection which will
391
-provide the required libraries.
442
+Build the `clamav_deps` recipe to compile ClamAV's library dependencies.
443
+By default, Mussels will install them to `~\.mussels\install\<target>`
392 444
 
393
-_Tip_: Instead of building manually, try using Mussels to automate your build!
445
+```ps1
446
+msl build clamav_deps
447
+```
448
+
449
+Next, set `$env:CLAMAV_DEPENDENCIES` to the location where Mussels built your
450
+library dependencies:
394 451
 
395 452
 ```ps1
396 453
 $env:CLAMAV_DEPENDENCIES="$env:userprofile\.mussels\install\x64"
454
+```
455
+
456
+To configure the project, run:
457
+
458
+```ps1
397 459
 cmake ..  -G "Visual Studio 15 2017" -A x64 `
398
-    -DJSONC_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include\json-c"         `
399
-    -DJSONC_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\json-c.lib"             `
400
-    -DENABLE_JSON_SHARED=OFF                                              `
401
-    -DBZIP2_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                `
402
-    -DBZIP2_LIBRARY_RELEASE="$env:CLAMAV_DEPENDENCIES\lib\libbz2.lib"     `
403
-    -DCURL_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                 `
404
-    -DCURL_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libcurl_imp.lib"         `
405
-    -DOPENSSL_ROOT_DIR="$env:CLAMAV_DEPENDENCIES"                         `
406
-    -DOPENSSL_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"              `
407
-    -DOPENSSL_CRYPTO_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libcrypto.lib" `
408
-    -DOPENSSL_SSL_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libssl.lib"       `
409
-    -DZLIB_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libssl.lib"              `
410
-    -DLIBXML2_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"              `
411
-    -DLIBXML2_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libxml2.lib"          `
412
-    -DPCRE2_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                `
413
-    -DPCRE2_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\pcre2-8.lib"            `
414
-    -DCURSES_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"               `
415
-    -DCURSES_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\pdcurses.lib"          `
416
-    -DPThreadW32_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"           `
417
-    -DPThreadW32_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\pthreadVC2.lib"    `
418
-    -DZLIB_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                 `
419
-    -DZLIB_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\zlibstatic.lib"          `
420
-    -DLIBCHECK_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"             `
421
-    -DLIBCHECK_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\checkDynamic.lib"    `
422
-    -DCMAKE_INSTALL_PREFIX="install"
423
-cmake --build . --config Release --target install
424
-copy $env:CLAMAV_DEPENDENCIES\lib\* .\install
460
+  -D JSONC_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include\json-c"         `
461
+  -D JSONC_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\json-c.lib"             `
462
+  -D ENABLE_JSON_SHARED=OFF                                              `
463
+  -D BZIP2_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                `
464
+  -D BZIP2_LIBRARY_RELEASE="$env:CLAMAV_DEPENDENCIES\lib\libbz2.lib"     `
465
+  -D CURL_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                 `
466
+  -D CURL_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libcurl_imp.lib"         `
467
+  -D OPENSSL_ROOT_DIR="$env:CLAMAV_DEPENDENCIES"                         `
468
+  -D OPENSSL_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"              `
469
+  -D OPENSSL_CRYPTO_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libcrypto.lib" `
470
+  -D OPENSSL_SSL_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libssl.lib"       `
471
+  -D ZLIB_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libssl.lib"              `
472
+  -D LIBXML2_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"              `
473
+  -D LIBXML2_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\libxml2.lib"          `
474
+  -D PCRE2_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                `
475
+  -D PCRE2_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\pcre2-8.lib"            `
476
+  -D CURSES_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"               `
477
+  -D CURSES_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\pdcurses.lib"          `
478
+  -D PThreadW32_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"           `
479
+  -D PThreadW32_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\pthreadVC2.lib"    `
480
+  -D ZLIB_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"                 `
481
+  -D ZLIB_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\zlibstatic.lib"          `
482
+  -D LIBCHECK_INCLUDE_DIR="$env:CLAMAV_DEPENDENCIES\include"             `
483
+  -D LIBCHECK_LIBRARY="$env:CLAMAV_DEPENDENCIES\lib\checkDynamic.lib"    `
484
+  -D CMAKE_INSTALL_PREFIX="install"
485
+```
486
+
487
+Now, go ahead and build the project:
488
+
489
+```ps1
490
+cmake --build . --config Release
491
+```
492
+
493
+_Tip_: If you're having include-path issues when building, try building with
494
+detailed verbosity so you can verify that the paths are correct:
495
+
496
+```ps1
497
+cmake --build . --config Release -- /verbosity:detailed
425 498
 ```
426 499
 
427
-_Tip_: If you're having include-path issues, try building with detailed verbosity:
500
+You can run the test suite with CTest:
428 501
 
429 502
 ```ps1
430
-cmake --build . --config Release --target install -- /verbosity:detailed
503
+ctest -C Release
431 504
 ```
432 505
 
506
+And you can install to the `install` (set above) like this:
507
+
508
+```ps1
509
+cmake --build . --config Release --target install
510
+```
511
+
512
+#### Build the Installer
513
+
433 514
 To build the installer, you must have WIX Toolset installed. If you're using
434 515
 Chocolatey, you can install it simply with `choco install wixtoolset` and then
435 516
 open a new terminal so that WIX will be in your PATH.
... ...
@@ -447,150 +546,146 @@ which include C headers. For macOS, Homebrew doesn't separate the headers.
447 447
 
448 448
 #### libclamav dependencies
449 449
 
450
-App developers that only need libclamav can use the `-DENABLE_LIBCLAMAV_ONLY`
450
+App developers that only need libclamav can use the `-D ENABLE_LIBCLAMAV_ONLY`
451 451
 option to bypass ClamAV app dependencies.
452 452
 
453 453
 libclamav requires these library dependencies:
454 454
 
455
-- bzip2
456
-- zlib
457
-- libxml2
458
-- libpcre2
459
-- openssl
460
-- libjson-c
461
-- iconv (POSIX-only, may be provided by system)
462
-- pthreads (or on Windows: pthreads-win32)
463
-- llvm (optional, _see [Bytecode Runtime](#bytecode-runtime))
455
+- `bzip2`
456
+- `zlib`
457
+- `libxml2`
458
+- `libpcre2`
459
+- `openssl`
460
+- `json-c`
461
+- `iconv` (POSIX-only, may be provided by system)
462
+- `pthreads` (Provided by the system on POSIX; Use `pthreads-win32` on Windows)
463
+- `llvm` (optional, _see [Bytecode Runtime](#bytecode-runtime))
464 464
 
465 465
 #### libfreshclam dependencies
466 466
 
467 467
 If you want libclamav _and_ libfreshclam for your app, then use the
468
-`-DENABLE_APP=OFF` option instead.
468
+`-D ENABLE_APP=OFF` option instead.
469 469
 
470 470
 libfreshclam adds these additional library dependencies:
471 471
 
472
-- libcurl
472
+- `libcurl`
473 473
 
474 474
 #### Application dependencies
475 475
 
476 476
 For regular folk who want the ClamAV apps, you'll also need:
477 477
 
478
-- ncurses (or pdcurses), for clamdtop.
479
-- systemd, so clamd, freshclam, clamonacc may run as a systemd service (Linux).
480
-- libsystemd, so clamd will support the clamd.ctl socket (Linux).
478
+- `ncurses` (or `pdcurses`), for `clamdtop`.
479
+- `systemd`, so `clamd`, `freshclam`, `clamonacc` may run as a `systemd`
480
+  service (Linux).
481
+- `libsystemd`, so `clamd` will support the `clamd.ctl` socket (Linux).
481 482
 
482 483
 #### Dependency build options
483 484
 
484 485
 If you have custom install paths for the dependencies on your system or are
485 486
 on Windows, you may need to use the following options...
486 487
 
487
-##### libcheck
488
+##### `libcheck`
488 489
 
489 490
 ```sh
490
-  -DLIBCHECK_ROOT_DIR="_path to libcheck install root_"
491
-  -DLIBCHECK_INCLUDE_DIR="_filepath of libcheck header directory_"
492
-  -DLIBCHECK_LIBRARY="_filepath of libcheck library_"
491
+  -D LIBCHECK_ROOT_DIR="_path to libcheck install root_"
492
+  -D LIBCHECK_INCLUDE_DIR="_filepath of libcheck header directory_"
493
+  -D LIBCHECK_LIBRARY="_filepath of libcheck library_"
493 494
 ```
494 495
 
495
-##### bzip2
496
+##### `bzip2`
496 497
 
497 498
 ```sh
498
-  -DBZIP2_INCLUDE_DIR="_filepath of bzip2 header directory_"
499
-  -DBZIP2_LIBRARIES="_filepath of bzip2 library_"
499
+  -D BZIP2_INCLUDE_DIR="_filepath of bzip2 header directory_"
500
+  -D BZIP2_LIBRARIES="_filepath of bzip2 library_"
500 501
 ```
501 502
 
502
-##### zlib
503
+##### `zlib`
503 504
 
504 505
 ```sh
505
-  -DZLIB_INCLUDE_DIR="_filepath of zlib header directory_"
506
-  -DZLIB_LIBRARY="_filepath of zlib library_"
506
+  -D ZLIB_INCLUDE_DIR="_filepath of zlib header directory_"
507
+  -D ZLIB_LIBRARY="_filepath of zlib library_"
507 508
 ```
508 509
 
509
-##### libxml2
510
+##### `libxml2`
510 511
 
511 512
 ```sh
512
-  -DLIBXML2_INCLUDE_DIR="_filepath of libxml2 header directory_"
513
-  -DLIBXML2_LIBRARY="_filepath of libxml2 library_"
513
+  -D LIBXML2_INCLUDE_DIR="_filepath of libxml2 header directory_"
514
+  -D LIBXML2_LIBRARY="_filepath of libxml2 library_"
514 515
 ```
515 516
 
516
-##### libpcre2
517
+##### `libpcre2`
517 518
 
518 519
 ```sh
519
-  -DPCRE2_INCLUDE_DIR="_filepath of libpcre2 header directory_"
520
-  -DPCRE2_LIBRARY="_filepath of libcpre2 library_"
520
+  -D PCRE2_INCLUDE_DIR="_filepath of libpcre2 header directory_"
521
+  -D PCRE2_LIBRARY="_filepath of libcpre2 library_"
521 522
 ```
522 523
 
523
-##### openssl (libcrypto, libssl)
524
-
525
-Hints to find openssl package:
526
-
527
-```sh
528
-  -DOPENSSL_ROOT_DIR="_path to openssl install root_"
529
-```
524
+##### `openssl` (`libcrypto`, `libssl`)
530 525
 
531 526
 ```sh
532
-  -DOPENSSL_INCLUDE_DIR="_filepath of openssl header directory_"
533
-  -DOPENSSL_CRYPTO_LIBRARY="_filepath of libcrypto library_"
534
-  -DOPENSSL_SSL_LIBRARY="_filepath of libcrypto library_"
527
+  -D OPENSSL_ROOT_DIR="_path to openssl install root_"
528
+  -D OPENSSL_INCLUDE_DIR="_filepath of openssl header directory_"
529
+  -D OPENSSL_CRYPTO_LIBRARY="_filepath of libcrypto library_"
530
+  -D OPENSSL_SSL_LIBRARY="_filepath of libcrypto library_"
535 531
 ```
536 532
 
537
-##### libjson-c
533
+##### `libjson-c`
538 534
 
539
-Tip: You're strongly encouraged to link with the a static json-c library.
535
+_Tip_: You're strongly encouraged to link with the a static json-c library.
540 536
 
541 537
 ```sh
542
-  -DJSONC_INCLUDE_DIR="_path to json-c header directory_"
543
-  -DJSONC_LIBRARY="_filepath of json-c library_"
538
+  -D JSONC_INCLUDE_DIR="_path to json-c header directory_"
539
+  -D JSONC_LIBRARY="_filepath of json-c library_"
544 540
 ```
545 541
 
546
-##### libmspack
542
+##### `libmspack`
547 543
 
548
-These options only apply if you use the `-DENABLE_EXTERNAL_MSPACK=ON` option.
544
+These options only apply if you use the `-D ENABLE_EXTERNAL_MSPACK=ON` option.
549 545
 
550 546
 ```sh
551
-  -DMSPack_INCLUDE_DIR="_path to mspack header directory_"
552
-  -DMSPack_LIBRARY="_filepath of libmspack library_"
547
+  -D MSPack_INCLUDE_DIR="_path to mspack header directory_"
548
+  -D MSPack_LIBRARY="_filepath of libmspack library_"
553 549
 ```
554 550
 
555
-##### iconv (POSIX-only)
551
+##### `iconv` (POSIX-only)
556 552
 
557 553
 On POSIX platforms, iconv might be part of the C library in which case you
558 554
 would not want to specify an external iconv library.
559 555
 
560 556
 ```sh
561
-  -DIconv_INCLUDE_DIR="_path to iconv header directory_"
562
-  -DIconv_LIBRARY="_filepath of iconv library_"
557
+  -D Iconv_INCLUDE_DIR="_path to iconv header directory_"
558
+  -D Iconv_LIBRARY="_filepath of iconv library_"
563 559
 ```
564 560
 
565
-##### pthreads-win32 (Windows-only)
561
+##### `pthreads-win32` (Windows-only)
566 562
 
567 563
 On POSIX platforms, pthread support is detected automatically.  On Windows, you
568 564
 need to specify the following:
569 565
 
570 566
 ```sh
571
-  -DPThreadW32_INCLUDE_DIR="_path to pthread-win32 header directory_"
572
-  -DPThreadW32_LIBRARY="_filepath of pthread-win32 library_"
567
+  -D PThreadW32_INCLUDE_DIR="_path to pthread-win32 header directory_"
568
+  -D PThreadW32_LIBRARY="_filepath of pthread-win32 library_"
573 569
 ```
574 570
 
575
-##### llvm (optional, _see "Bytecode Runtime" section_)
571
+##### `llvm` (optional, _see "Bytecode Runtime" section_)
576 572
 
577 573
 ```sh
578
-  -DBYTECODE_RUNTIME="llvm"
579
-  -DLLVM_ROOT_DIR="_path to llvm install root_" -DLLVM_FIND_VERSION="3.6.0"
574
+  -D BYTECODE_RUNTIME="llvm"
575
+  -D LLVM_ROOT_DIR="_path to llvm install root_" -D LLVM_FIND_VERSION="3.6.0"
580 576
 ```
581 577
 
582
-##### libcurl
578
+##### `libcurl`
583 579
 
584 580
 ```sh
585
-  -DCURL_INCLUDE_DIR="_path to curl header directory_"
586
-  -DCURL_LIBRARY="_filepath of curl library_"
581
+  -D CURL_INCLUDE_DIR="_path to curl header directory_"
582
+  -D CURL_LIBRARY="_filepath of curl library_"
587 583
 ```
588 584
 
589
-##### ncurses or pdcurses, for clamdtop
585
+##### `ncurses` or `pdcurses`, for `clamdtop`
590 586
 
591 587
 ```sh
592
-  -DCURSES_INCLUDE_DIR="_path to curses header directory_"
593
-  -DCURSES_LIBRARY="_filepath of curses library_"
588
+  -D CURSES_INCLUDE_DIR="_path to curses header directory_"
589
+  -D CURSES_LIBRARY="_filepath of curses library_"
594 590
 ```
595 591
 
596 592
 ##### Bytecode Runtime
... ...
@@ -615,22 +710,22 @@ At the moment, the interpreter is the default runtime, while we work out
615 615
 compatibility issues with libLLVM. This default equates to:
616 616
 
617 617
 ```sh
618
-cmake .. -DBYTECODE_RUNTIME="interpreter"
618
+cmake .. -D BYTECODE_RUNTIME="interpreter"
619 619
 ```
620 620
 
621 621
 To build using LLVM instead of the intereter, use:
622 622
 
623 623
 ```sh
624 624
 cmake .. \
625
-  -DBYTECODE_RUNTIME="llvm"       \
626
-  -DLLVM_ROOT_DIR="/opt/llvm/3.6" \
627
-  -DLLVM_FIND_VERSION="3.6.0"
625
+  -D BYTECODE_RUNTIME="llvm"       \
626
+  -D LLVM_ROOT_DIR="/opt/llvm/3.6" \
627
+  -D LLVM_FIND_VERSION="3.6.0"
628 628
 ```
629 629
 
630
-To disable bytecode signature support entire, you may build with this option:
630
+To disable bytecode signature support entirely, you may build with this option:
631 631
 
632 632
 ```sh
633
-cmake .. -DBYTECODE_RUNTIME="none"
633
+cmake .. -D BYTECODE_RUNTIME="none"
634 634
 ```
635 635
 
636 636
 ## Compilers and Options
... ...
@@ -1,7 +1,19 @@
1 1
 # ClamAV
2 2
 
3
-ClamAV® is an open source antivirus engine for detecting trojans, viruses,
4
-malware & other malicious threats.
3
+<p align="center">
4
+  <img width="250" height="250" src="https://raw.githubusercontent.com/Cisco-Talos/clamav-devel/dev/0.104/logo.png" alt='Maeve, the ClamAV mascot'>
5
+</p>
6
+
7
+<p align="center">
8
+  ClamAV® is an open source antivirus engine for detecting trojans, viruses,
9
+  malware & other malicious threats.
10
+</p>
11
+
12
+<p align="center">
13
+  <a href="https://github.com/Cisco-Talos/clamav-devel/actions"><img src="https://github.com/Cisco-Talos/clamav-devel/workflows/CMake%20Build/badge.svg" height="18"></a>
14
+  <a href="https://discord.gg/sGaxA5Q"><img src="https://img.shields.io/discord/636023333074370595.svg?logo=discord" height="18"/></a>
15
+  <a href="https://twitter.com/clamav"><img src="https://abs.twimg.com/favicons/twitter.ico" width="18" height="18"></a>
16
+</p>
5 17
 
6 18
 ## Documentation & FAQ
7 19
 
... ...
@@ -21,36 +33,25 @@ to get started!
21 21
 
22 22
 ## Installation Instructions
23 23
 
24
-### UNIX
25
-
26
-#### Build from Source on Linux/Unix/Mac
27
-
28
-For basic compile and install instructions on Linux/Unix platforms, check out
29
-the [install instructions](INSTALL.autotools.md).
24
+#### Build from Source
30 25
 
31
-For detailed instructions specific to building ClamAV please investigate
32
-our the
33
-[Linux/Unix/Mac Install instructions in the User Manual](https://www.clamav.net/documents/installing-clamav-on-unix-linux-macos-from-source).
26
+For compile and install instructions with CMake, please see
27
+[INSTALL.cmake.md](INSTALL.cmake.md).
28
+For install instructions with the (now deprecated) autotools build system, see
29
+[INSTALL.autotools.md](INSTALL.autotools.md).
34 30
 
35
-For instructions on how to build ClamAV using our new *experimental* CMake
36
-build tooling, see [INSTALL.cmake.md](INSTALL.cmake.md)
31
+For additional instructions specific to building ClamAV please visit our
32
+[online documentation](https://www.clamav.net/documents/clam-antivirus-user-manual).
37 33
 
38
-#### Install from a binary package
34
+#### Install from a binary package distribution
39 35
 
40 36
 For binary package distribution installation instructions, head over to
41 37
 [our website](https://www.clamav.net/documents/installing-clamav).
42 38
 
43
-### Windows
39
+#### Install using an installer (Windows)
44 40
 
45
-#### Build from Source on Windows
46
-
47
-The instructions for building ClamAV from source on Windows is located in the
48
-[Win32 README](win32/README.md).
49
-
50
-#### Using an Install Package
51
-
52
-We provide an installer to install ClamAV on Windows to "C:\\Program Files".
53
-This install method will require you to have Adminstrator priveleges.
41
+We provide installers to install ClamAV on Windows to "C:\\Program Files".
42
+This install method will require you to have Administrator priveleges.
54 43
 
55 44
 We also provide a "Portable Install Package" (i.e. a zip of the required files)
56 45
 for users that may wish to run ClamAV without installing it to a system-owned
... ...
@@ -59,9 +60,6 @@ directory.
59 59
 For details on how to use either option, head over to the
60 60
 [Windows Install instructions in the User Manual](https://www.clamav.net/documents/installing-clamav-on-windows).
61 61
 
62
-For instructions on how to build ClamAV using our new *experimental* CMake
63
-build tooling, see [INSTALL.cmake.md](INSTALL.cmake.md)
64
-
65 62
 ### Upgrading from a previous version
66 63
 
67 64
 Some tips on [how to upgrade](https://www.clamav.net/documents/upgrading-clamav)
... ...
@@ -78,8 +76,8 @@ Catch up on the latest about ClamAV by reading our
78 78
 ## Join the ClamAV Community
79 79
 
80 80
 The best way to get in touch with the ClamAV community is to join our
81
-[our mailing lists](https://www.clamav.net/documents/mailing-lists-faq), and
82
-tune to #clamav on [IRC](irc.freenode.net).
81
+[mailing lists](https://www.clamav.net/documents/mailing-lists-faq) and tune to
82
+#clamav on [IRC](irc.freenode.net) or [Discord](https://discord.gg/sGaxA5Q).
83 83
 
84 84
 ## Want to make a contribution?
85 85
 
... ...
@@ -130,11 +130,11 @@ else()
130 130
       set(CURSES_DEFINITIONS ${PC_PDCurses_CFLAGS_OTHER})
131 131
 
132 132
       if (NOT TARGET Curses::curses)
133
-        add_library(Curses::curses INTERFACE IMPORTED)
133
+        add_library(Curses::curses UNKNOWN IMPORTED)
134 134
         set_target_properties(Curses::curses PROPERTIES
135 135
           INTERFACE_COMPILE_OPTIONS "${PC_PDCurses_CFLAGS_OTHER}"
136 136
           INTERFACE_INCLUDE_DIRECTORIES "${CURSES_INCLUDE_DIR}"
137
-          INTERFACE_LINK_LIBRARIES "${CURSES_LIBRARY}"
137
+          IMPORTED_LOCATION "${CURSES_LIBRARY}"
138 138
         )
139 139
       endif()
140 140
   else()
... ...
@@ -1,79 +1,82 @@
1
+# Generate documentation (man pages, doxygen, etc.)
1 2
 
2
-#
3
-# man pages
4
-#
5
-# .1 files
6
-configure_file(man/clamscan.1.in            man/clamscan.1)
7
-configure_file(man/freshclam.1.in           man/freshclam.1)
8
-configure_file(man/sigtool.1.in             man/sigtool.1)
9
-configure_file(man/clamdscan.1.in           man/clamdscan.1)
10
-configure_file(man/clamconf.1.in            man/clamconf.1)
11
-configure_file(man/clamdtop.1.in            man/clamdtop.1)
12
-configure_file(man/clamsubmit.1.in          man/clamsubmit.1)
13
-configure_file(man/clambc.1.in              man/clambc.1)
14
-# .5 files
15
-configure_file(man/clamd.conf.5.in          man/clamd.conf.5)
16
-configure_file(man/clamav-milter.conf.5.in  man/clamav-milter.conf.5)
17
-configure_file(man/freshclam.conf.5.in      man/freshclam.conf.5)
18
-# .8 files
19
-configure_file(man/clamd.8.in               man/clamd.8)
20
-configure_file(man/clamav-milter.8.in       man/clamav-milter.8)
21
-if(C_LINUX)
22
-    configure_file(man/clamonacc.8.in           man/clamonacc.8)
23
-endif()
3
+if(ENABLE_MAN_PAGES)
4
+    #
5
+    # man pages
6
+    #
7
+    # .1 files
8
+    configure_file(man/clamscan.1.in            man/clamscan.1)
9
+    configure_file(man/freshclam.1.in           man/freshclam.1)
10
+    configure_file(man/sigtool.1.in             man/sigtool.1)
11
+    configure_file(man/clamdscan.1.in           man/clamdscan.1)
12
+    configure_file(man/clamconf.1.in            man/clamconf.1)
13
+    configure_file(man/clamdtop.1.in            man/clamdtop.1)
14
+    configure_file(man/clamsubmit.1.in          man/clamsubmit.1)
15
+    configure_file(man/clambc.1.in              man/clambc.1)
16
+    # .5 files
17
+    configure_file(man/clamd.conf.5.in          man/clamd.conf.5)
18
+    configure_file(man/clamav-milter.conf.5.in  man/clamav-milter.conf.5)
19
+    configure_file(man/freshclam.conf.5.in      man/freshclam.conf.5)
20
+    # .8 files
21
+    configure_file(man/clamd.8.in               man/clamd.8)
22
+    configure_file(man/clamav-milter.8.in       man/clamav-milter.8)
23
+    if(C_LINUX)
24
+        configure_file(man/clamonacc.8.in           man/clamonacc.8)
25
+    endif()
24 26
 
25
-set(MAN1_FILES
26
-    man/clamscan.1
27
-    man/freshclam.1
28
-    man/sigtool.1
29
-    man/clamdscan.1
30
-    man/clamconf.1
31
-    man/clamdtop.1
32
-    man/clamsubmit.1
33
-    man/clambc.1)
34
-foreach(m IN LISTS MAN1_FILES)
35
-    install(
36
-        FILES
37
-            ${CMAKE_CURRENT_BINARY_DIR}/${m}
38
-        DESTINATION
39
-            ${CMAKE_INSTALL_PREFIX}/share/man/man1)
40
-endforeach()
27
+    set(MAN1_FILES
28
+        man/clamscan.1
29
+        man/freshclam.1
30
+        man/sigtool.1
31
+        man/clamdscan.1
32
+        man/clamconf.1
33
+        man/clamdtop.1
34
+        man/clamsubmit.1
35
+        man/clambc.1)
36
+    foreach(m IN LISTS MAN1_FILES)
37
+        install(
38
+            FILES
39
+                ${CMAKE_CURRENT_BINARY_DIR}/${m}
40
+            DESTINATION
41
+                ${CMAKE_INSTALL_PREFIX}/share/man/man1)
42
+    endforeach()
41 43
 
42
-set(MAN5_FILES
43
-    man/clamd.conf.5
44
-    man/clamav-milter.conf.5
45
-    man/freshclam.conf.5)
46
-foreach(m IN LISTS MAN5_FILES)
47
-    install(
48
-        FILES
49
-            ${CMAKE_CURRENT_BINARY_DIR}/${m}
50
-        DESTINATION
51
-            ${CMAKE_INSTALL_PREFIX}/share/man/man5)
52
-endforeach()
44
+    set(MAN5_FILES
45
+        man/clamd.conf.5
46
+        man/clamav-milter.conf.5
47
+        man/freshclam.conf.5)
48
+    foreach(m IN LISTS MAN5_FILES)
49
+        install(
50
+            FILES
51
+                ${CMAKE_CURRENT_BINARY_DIR}/${m}
52
+            DESTINATION
53
+                ${CMAKE_INSTALL_PREFIX}/share/man/man5)
54
+    endforeach()
53 55
 
54
-set(MAN8_FILES
55
-    man/clamd.8
56
-    man/clamav-milter.8)
57
-foreach(m IN LISTS MAN8_FILES)
58
-    install(
59
-        FILES
60
-            ${CMAKE_CURRENT_BINARY_DIR}/${m}
61
-        DESTINATION
62
-            ${CMAKE_INSTALL_PREFIX}/share/man/man8)
63
-endforeach()
56
+    set(MAN8_FILES
57
+        man/clamd.8
58
+        man/clamav-milter.8)
59
+    foreach(m IN LISTS MAN8_FILES)
60
+        install(
61
+            FILES
62
+                ${CMAKE_CURRENT_BINARY_DIR}/${m}
63
+            DESTINATION
64
+                ${CMAKE_INSTALL_PREFIX}/share/man/man8)
65
+    endforeach()
64 66
 
65
-if(C_LINUX)
66
-    # Also install Linux-only manpage
67
-    install(
68
-        FILES
69
-            ${CMAKE_CURRENT_BINARY_DIR}/man/clamonacc.8
70
-        DESTINATION
71
-            ${CMAKE_INSTALL_PREFIX}/share/man/man8)
67
+    if(C_LINUX)
68
+        # Also install Linux-only manpage
69
+        install(
70
+            FILES
71
+                ${CMAKE_CURRENT_BINARY_DIR}/man/clamonacc.8
72
+            DESTINATION
73
+                ${CMAKE_INSTALL_PREFIX}/share/man/man8)
74
+    endif()
72 75
 endif()
73 76
 
74 77
 if(ENABLE_DOXYGEN)
75 78
     #
76
-    # clamav.h doxygen docs
79
+    # clamav.h and libfreshclam.h doxygen docs
77 80
     #
78 81
     find_package(Doxygen REQUIRED)
79 82
 
... ...
@@ -91,8 +94,7 @@ if(ENABLE_DOXYGEN)
91 91
     doxygen_add_docs(doxygen
92 92
         ${CMAKE_SOURCE_DIR}/libclamav/clamav.h
93 93
         ${CMAKE_SOURCE_DIR}/libfreshclam/libfreshclam.h
94
-        COMMENT "Generate html documentation"
95
-    )
94
+        COMMENT "Generate html documentation")
96 95
 
97 96
     install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
98 97
         DESTINATION ${CMAKE_INSTALL_DOCDIR}
99 98
new file mode 100644
100 99
Binary files /dev/null and b/logo.png differ
... ...
@@ -182,10 +182,10 @@ if(WIN32)
182 182
     file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}                                     BUILD)
183 183
     file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}                             TMP)
184 184
 
185
-    file(TO_NATIVE_PATH $<TARGET_FILE_DIR:check_clamav>/check_clamav.exe        CHECK_CLAMAV)
185
+    file(TO_NATIVE_PATH $<TARGET_FILE:check_clamav>                             CHECK_CLAMAV)
186 186
     if(ENABLE_APP)
187
-        file(TO_NATIVE_PATH $<TARGET_FILE_DIR:check_clamav>/check_clamd.exe         CHECK_CLAMD)
188
-        file(TO_NATIVE_PATH $<TARGET_FILE_DIR:check_clamav>/check_fpu_endian.exe    CHECK_FPU_ENDIAN)
187
+        file(TO_NATIVE_PATH $<TARGET_FILE:check_clamd>                              CHECK_CLAMD)
188
+        file(TO_NATIVE_PATH $<TARGET_FILE:check_fpu_endian>                         CHECK_FPU_ENDIAN)
189 189
 
190 190
         file(TO_NATIVE_PATH $<TARGET_FILE_DIR:check_clamav>/clambc.exe              CLAMBC)
191 191
         file(TO_NATIVE_PATH $<TARGET_FILE_DIR:check_clamav>/clamd.exe               CLAMD)
... ...
@@ -198,7 +198,7 @@ if(WIN32)
198 198
         file(TO_NATIVE_PATH $<TARGET_FILE_DIR:check_clamav>/sigtool.exe             SIGTOOL)
199 199
     endif()
200 200
 else()
201
-    set(LD_LIBRARY_PATH     $<TARGET_FILE_DIR:ClamAV::libclamav>:$<TARGET_FILE_DIR:ClamAV::libmspack:$<TARGET_FILE_DIR:ClamAV::libunrar_iface>:$<TARGET_FILE_DIR:ClamAV::libunrar:$ENV{LD_LIBRARY_PATH})
201
+    set(LD_LIBRARY_PATH     $<TARGET_FILE_DIR:ClamAV::libclamav>:$<TARGET_FILE_DIR:ClamAV::libmspack>:$<TARGET_FILE_DIR:ClamAV::libunrar_iface>:$<TARGET_FILE_DIR:ClamAV::libunrar>:$ENV{LD_LIBRARY_PATH})
202 202
     if(NOT ENABLE_LIBCLAMAV_ONLY)
203 203
         set(LD_LIBRARY_PATH $<TARGET_FILE_DIR:ClamAV::libfreshclam>:${LD_LIBRARY_PATH})
204 204
     endif()
... ...
@@ -221,9 +221,12 @@ else()
221 221
         set(CLAMCONF           $<TARGET_FILE:clamconf>)
222 222
         set(FRESHCLAM          $<TARGET_FILE:freshclam-bin>)
223 223
         set(SIGTOOL            $<TARGET_FILE:sigtool>)
224
-
225
-        set(CLAMAV_MILTER      $<TARGET_FILE:clamav-milter>)
226
-        set(CLAMONACC          $<TARGET_FILE:clamonacc>)
224
+        if(ENABLE_MILTER)
225
+            set(CLAMAV_MILTER      $<TARGET_FILE:clamav-milter>)
226
+        endif()
227
+        if(ENABLE_CLAMONACC)
228
+            set(CLAMONACC          $<TARGET_FILE:clamonacc>)
229
+        endif()
227 230
     endif()
228 231
 endif()
229 232
 
... ...
@@ -312,106 +315,136 @@ endif()
312 312
 if(WIN32)
313 313
     #
314 314
     # Prepare a test install, with all our DLL dependencies co-located with our EXEs and DLLs
315
-    # Generate GetLibs-$<CONFIG>.ctest which will collect all required DLL and EXE dependencies when `ctest` is run.
316 315
     #
317
-    if(ENABLE_APP)
318
-        set(GEN_SCRIPT [[
319
-            # Collect runtime DLL dependencies for our libs and apps
320
-            file(GET_RUNTIME_DEPENDENCIES
321
-                LIBRARIES
322
-                    $<TARGET_FILE:ClamAV::libclamav>
323
-                    $<TARGET_FILE:ClamAV::libfreshclam>
324
-                EXECUTABLES
325
-                    $<TARGET_FILE:check_clamav>
326
-                    $<TARGET_FILE:check_fpu_endian>
327
-                    $<TARGET_FILE:check_clamd>
328
-                    $<TARGET_FILE:clambc>
329
-                    $<TARGET_FILE:clamd>
330
-                    $<TARGET_FILE:clamdscan>
331
-                    $<TARGET_FILE:clamdtop>
332
-                    $<TARGET_FILE:clamscan>
333
-                    $<TARGET_FILE:clamsubmit>
334
-                    $<TARGET_FILE:clamconf>
335
-                    $<TARGET_FILE:freshclam-bin>
336
-                    $<TARGET_FILE:sigtool>
337
-                RESOLVED_DEPENDENCIES_VAR _r_deps
338
-                UNRESOLVED_DEPENDENCIES_VAR _u_deps
339
-                DIRECTORIES
340
-                    $<TARGET_FILE_DIR:OpenSSL::SSL>
341
-                    $<TARGET_FILE_DIR:OpenSSL::Crypto>
342
-                    $<TARGET_FILE_DIR:ZLIB::ZLIB>
343
-                    $<TARGET_FILE_DIR:BZip2::BZip2>
344
-                    $<TARGET_FILE_DIR:PCRE2::pcre2>
345
-                    $<TARGET_FILE_DIR:LibXml2::LibXml2>
346
-                    $<TARGET_FILE_DIR:CURL::libcurl>
347
-                    $<TARGET_FILE_DIR:JSONC::jsonc>
348
-                CONFLICTING_DEPENDENCIES_PREFIX CTEST_CONFLICTING_DEPENDENCIES
316
+    if(VCPKG_APPLOCAL_DEPS)
317
+        #
318
+        # Have CMake invoke itself to performa a local install for our test suite.
319
+        #
320
+        if(ENABLE_APP)
321
+            add_custom_target(test_install
322
+                ALL
323
+                "${CMAKE_COMMAND}"
324
+                -D CMAKE_INSTALL_PREFIX:string=$<TARGET_FILE_DIR:check_clamav>
325
+                -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
326
+                DEPENDS
327
+                    check_clamav check_clamd check_fpu_endian
328
+                    ClamAV::libclamav ClamAV::libfreshclam ClamAV::libunrar ClamAV::libunrar_iface ClamAV::libmspack
329
+                    clambc clamd clamdscan clamdtop clamscan clamsubmit clamconf freshclam-bin sigtool
349 330
             )
350
-            foreach(_file ${_r_deps})
351
-                string(TOLOWER ${_file} _file_lower)
352
-                if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*")
353
-                    message("Collecting DLL dependency: ${_file}")
354
-                    file(COPY ${_file} DESTINATION $<TARGET_FILE_DIR:check_clamav>)
355
-                endif()
356
-            endforeach()
331
+        else()
332
+            add_custom_target(test_install
333
+                ALL
334
+                "${CMAKE_COMMAND}"
335
+                -D CMAKE_INSTALL_PREFIX:string=$<TARGET_FILE_DIR:check_clamav>
336
+                -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
337
+                DEPENDS
338
+                    check_clamav
339
+                    ClamAV::libclamav ClamAV::libfreshclam ClamAV::libunrar ClamAV::libunrar_iface ClamAV::libmspack
340
+            )
341
+        endif()
342
+    else()
343
+        #
344
+        # Generate GetLibs-$<CONFIG>.ctest which will collect all required DLL and EXE dependencies when `ctest` is run.
345
+        #
346
+        if(ENABLE_APP)
347
+            set(GEN_SCRIPT [[
348
+                # Collect runtime DLL dependencies for our libs and apps
349
+                file(GET_RUNTIME_DEPENDENCIES
350
+                    LIBRARIES
351
+                        $<TARGET_FILE:ClamAV::libclamav>
352
+                        $<TARGET_FILE:ClamAV::libfreshclam>
353
+                    EXECUTABLES
354
+                        $<TARGET_FILE:check_clamav>
355
+                        $<TARGET_FILE:check_fpu_endian>
356
+                        $<TARGET_FILE:check_clamd>
357
+                        $<TARGET_FILE:clambc>
358
+                        $<TARGET_FILE:clamd>
359
+                        $<TARGET_FILE:clamdscan>
360
+                        $<TARGET_FILE:clamdtop>
361
+                        $<TARGET_FILE:clamscan>
362
+                        $<TARGET_FILE:clamsubmit>
363
+                        $<TARGET_FILE:clamconf>
364
+                        $<TARGET_FILE:freshclam-bin>
365
+                        $<TARGET_FILE:sigtool>
366
+                    RESOLVED_DEPENDENCIES_VAR _r_deps
367
+                    UNRESOLVED_DEPENDENCIES_VAR _u_deps
368
+                    DIRECTORIES
369
+                        $<TARGET_FILE_DIR:OpenSSL::SSL>
370
+                        $<TARGET_FILE_DIR:OpenSSL::Crypto>
371
+                        $<TARGET_FILE_DIR:ZLIB::ZLIB>
372
+                        $<TARGET_FILE_DIR:BZip2::BZip2>
373
+                        $<TARGET_FILE_DIR:PCRE2::pcre2>
374
+                        $<TARGET_FILE_DIR:LibXml2::LibXml2>
375
+                        $<TARGET_FILE_DIR:CURL::libcurl>
376
+                        $<TARGET_FILE_DIR:JSONC::jsonc>
377
+                    CONFLICTING_DEPENDENCIES_PREFIX CTEST_CONFLICTING_DEPENDENCIES
378
+                )
379
+                foreach(_file ${_r_deps})
380
+                    string(TOLOWER ${_file} _file_lower)
381
+                    if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*")
382
+                        message("Collecting DLL dependency: ${_file}")
383
+                        file(COPY ${_file} DESTINATION $<TARGET_FILE_DIR:check_clamav>)
384
+                    endif()
385
+                endforeach()
357 386
 
358
-            # Collect our libs
359
-            file(COPY $<TARGET_FILE:ClamAV::libclamav> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
360
-            file(COPY $<TARGET_FILE:ClamAV::libmspack> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
361
-            file(COPY $<TARGET_FILE:ClamAV::libfreshclam> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
362
-            file(COPY $<TARGET_FILE:ClamAV::libunrar> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
363
-            file(COPY $<TARGET_FILE:ClamAV::libunrar_iface> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
387
+                # Collect our libs
388
+                file(COPY $<TARGET_FILE:ClamAV::libclamav> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
389
+                file(COPY $<TARGET_FILE:ClamAV::libmspack> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
390
+                file(COPY $<TARGET_FILE:ClamAV::libfreshclam> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
391
+                file(COPY $<TARGET_FILE:ClamAV::libunrar> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
392
+                file(COPY $<TARGET_FILE:ClamAV::libunrar_iface> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
364 393
 
365
-            # Collect our apps
366
-            file(COPY $<TARGET_FILE:check_fpu_endian> DESTINATION $<TARGET_FILE_DIR:check_fpu_endian>)
367
-            file(COPY $<TARGET_FILE:check_clamd> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
368
-            file(COPY $<TARGET_FILE:clambc> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
369
-            file(COPY $<TARGET_FILE:clamd> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
370
-            file(COPY $<TARGET_FILE:clamdscan> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
371
-            file(COPY $<TARGET_FILE:clamdtop> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
372
-            file(COPY $<TARGET_FILE:clamscan> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
373
-            file(COPY $<TARGET_FILE:clamsubmit> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
374
-            file(COPY $<TARGET_FILE:clamconf> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
375
-            file(COPY $<TARGET_FILE:freshclam-bin> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
376
-            file(COPY $<TARGET_FILE:sigtool> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
377
-        ]])
378
-    else()
379
-        # We don't have libfreshclam unit tests, so no need to check if ENABLE_LIBCLAMAV_ONLY is enabled.
380
-        set(GEN_SCRIPT [[
381
-            # Collect runtime DLL dependencies for our libs
382
-            file(GET_RUNTIME_DEPENDENCIES
383
-                LIBRARIES
384
-                    $<TARGET_FILE:ClamAV::libclamav>
385
-                EXECUTABLES
386
-                    $<TARGET_FILE:check_clamav>
387
-                RESOLVED_DEPENDENCIES_VAR _r_deps
388
-                UNRESOLVED_DEPENDENCIES_VAR _u_deps
389
-                DIRECTORIES
390
-                    $<TARGET_FILE_DIR:OpenSSL::SSL>
391
-                    $<TARGET_FILE_DIR:OpenSSL::Crypto>
392
-                    $<TARGET_FILE_DIR:ZLIB::ZLIB>
393
-                    $<TARGET_FILE_DIR:BZip2::BZip2>
394
-                    $<TARGET_FILE_DIR:PCRE2::pcre2>
395
-                    $<TARGET_FILE_DIR:LibXml2::LibXml2>
396
-                    $<TARGET_FILE_DIR:JSONC::jsonc>
397
-                CONFLICTING_DEPENDENCIES_PREFIX CTEST_CONFLICTING_DEPENDENCIES
398
-            )
399
-            foreach(_file ${_r_deps})
400
-                string(TOLOWER ${_file} _file_lower)
401
-                if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*")
402
-                    message("DEPENDENCY: ${_file}")
403
-                    file(COPY ${_file} DESTINATION $<TARGET_FILE_DIR:check_clamav>)
404
-                endif()
405
-            endforeach()
394
+                # Collect our apps
395
+                file(COPY $<TARGET_FILE:check_fpu_endian> DESTINATION $<TARGET_FILE_DIR:check_fpu_endian>)
396
+                file(COPY $<TARGET_FILE:check_clamd> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
397
+                file(COPY $<TARGET_FILE:clambc> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
398
+                file(COPY $<TARGET_FILE:clamd> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
399
+                file(COPY $<TARGET_FILE:clamdscan> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
400
+                file(COPY $<TARGET_FILE:clamdtop> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
401
+                file(COPY $<TARGET_FILE:clamscan> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
402
+                file(COPY $<TARGET_FILE:clamsubmit> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
403
+                file(COPY $<TARGET_FILE:clamconf> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
404
+                file(COPY $<TARGET_FILE:freshclam-bin> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
405
+                file(COPY $<TARGET_FILE:sigtool> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
406
+            ]])
407
+        else()
408
+            # We don't have libfreshclam unit tests, so no need to check if ENABLE_LIBCLAMAV_ONLY is enabled.
409
+            set(GEN_SCRIPT [[
410
+                # Collect runtime DLL dependencies for our libs
411
+                file(GET_RUNTIME_DEPENDENCIES
412
+                    LIBRARIES
413
+                        $<TARGET_FILE:ClamAV::libclamav>
414
+                    EXECUTABLES
415
+                        $<TARGET_FILE:check_clamav>
416
+                    RESOLVED_DEPENDENCIES_VAR _r_deps
417
+                    UNRESOLVED_DEPENDENCIES_VAR _u_deps
418
+                    DIRECTORIES
419
+                        $<TARGET_FILE_DIR:OpenSSL::SSL>
420
+                        $<TARGET_FILE_DIR:OpenSSL::Crypto>
421
+                        $<TARGET_FILE_DIR:ZLIB::ZLIB>
422
+                        $<TARGET_FILE_DIR:BZip2::BZip2>
423
+                        $<TARGET_FILE_DIR:PCRE2::pcre2>
424
+                        $<TARGET_FILE_DIR:LibXml2::LibXml2>
425
+                        $<TARGET_FILE_DIR:JSONC::jsonc>
426
+                    CONFLICTING_DEPENDENCIES_PREFIX CTEST_CONFLICTING_DEPENDENCIES
427
+                )
428
+                foreach(_file ${_r_deps})
429
+                    string(TOLOWER ${_file} _file_lower)
430
+                    if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*")
431
+                        message("DEPENDENCY: ${_file}")
432
+                        file(COPY ${_file} DESTINATION $<TARGET_FILE_DIR:check_clamav>)
433
+                    endif()
434
+                endforeach()
406 435
 
407
-            # Collect our libs
408
-            file(COPY $<TARGET_FILE:ClamAV::libclamav> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
409
-            file(COPY $<TARGET_FILE:ClamAV::libmspack> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
410
-            file(COPY $<TARGET_FILE:ClamAV::libunrar> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
411
-            file(COPY $<TARGET_FILE:ClamAV::libunrar_iface> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
412
-        ]])
413
-    endif()
436
+                # Collect our libs
437
+                file(COPY $<TARGET_FILE:ClamAV::libclamav> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
438
+                file(COPY $<TARGET_FILE:ClamAV::libmspack> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
439
+                file(COPY $<TARGET_FILE:ClamAV::libunrar> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
440
+                file(COPY $<TARGET_FILE:ClamAV::libunrar_iface> DESTINATION $<TARGET_FILE_DIR:check_clamav>)
441
+            ]])
442
+        endif()
414 443
 
415
-    file(GENERATE OUTPUT GetLibs-$<CONFIG>.ctest CONTENT ${GEN_SCRIPT})
416
-    set_directory_properties(PROPERTIES TEST_INCLUDE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Run-GetLibs.ctest)
444
+        file(GENERATE OUTPUT GetLibs-$<CONFIG>.ctest CONTENT ${GEN_SCRIPT})
445
+        set_directory_properties(PROPERTIES TEST_INCLUDE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Run-GetLibs.ctest)
446
+    endif()
417 447
 endif()
418 448
\ No newline at end of file
... ...
@@ -97,6 +97,11 @@ static void conn_setup_mayfail(int may)
97 97
     ck_assert_msg(sockd != -1, "Unable to create socket: %s\n", strerror(errno));
98 98
 
99 99
     rc = connect(sockd, (struct sockaddr *)&nixsock, (socklen_t)sizeof(nixsock));
100
+    if (rc == -1 && (may && (errno == ECONNREFUSED))) {
101
+        close(sockd);
102
+        sockd = -1;
103
+        return;
104
+    }
100 105
     ck_assert_msg(rc != -1, "Unable to connect(): %s\n", strerror(errno));
101 106
 
102 107
     signal(SIGPIPE, SIG_IGN);
... ...
@@ -683,7 +688,18 @@ START_TEST(test_connections)
683 683
     ck_assert_msg(getrlimit(RLIMIT_NOFILE, &rlim) != -1,
684 684
                   "Failed to get RLIMIT_NOFILE: %s\n", strerror(errno));
685 685
     num_fds = rlim.rlim_cur - 5;
686
-    sock    = malloc(sizeof(int) * num_fds);
686
+#ifdef C_DARWIN
687
+    /* While the limit when testing on macOS appears to be aroudn 1024, though
688
+       in testing on github actions macos-latest, get "connection refused"
689
+       after ~925 give or take.
690
+       It's possible the getrlimit API is incorrect post macOS Sierra, which
691
+       may explain the issue. In any case, limiting to 850 should be safe.
692
+       It's possible there' ssome other limitation at play on the GitHUb's
693
+       macos-latest shared environment. */
694
+    num_fds = MIN(num_fds, 850);
695
+#endif
696
+
697
+    sock = malloc(sizeof(int) * num_fds);
687 698
 
688 699
     ck_assert_msg(!!sock, "malloc failed\n");
689 700
 
... ...
@@ -691,6 +707,11 @@ START_TEST(test_connections)
691 691
         /* just open connections, and let them time out */
692 692
         conn_setup_mayfail(1);
693 693
         if (sockd == -1) {
694
+            /* close the previous one, to leave space for one more connection */
695
+            i--;
696
+            close(sock[i]);
697
+            sock[i] = -1;
698
+
694 699
             num_fds = i;
695 700
             break;
696 701
         }
... ...
@@ -127,8 +127,14 @@ class TC(testcase.TestCase):
127 127
                 self.log.warning(f'Unexpected exception {exc}')
128 128
                 pass  # ignore
129 129
             self.proc = None
130
-        TC.clamd_pid.unlink(missing_ok=True)
131
-        TC.clamd_socket.unlink(missing_ok=True)
130
+        try:
131
+            TC.clamd_pid.unlink()
132
+        except Exception:
133
+            pass # missing_ok=True is too for common use.
134
+        try:
135
+            TC.clamd_socket.unlink()
136
+        except Exception:
137
+            pass # missing_ok=True is too for common use.
132 138
 
133 139
         self.verify_valgrind_log()
134 140
 
... ...
@@ -378,6 +384,8 @@ class TC(testcase.TestCase):
378 378
 
379 379
         # Ok now run check_clamd to have fun with clamd's API
380 380
         output = self.execute_command(f'{TC.check_clamd}')
381
+        self.log.info(f'check_clamd stdout: \n{output.out}')
382
+        self.log.info(f'check_clamd stderr: \n{output.err}')
381 383
         assert output.ec == 0  # success
382 384
 
383 385
         expected_results = [
... ...
@@ -162,7 +162,10 @@ class TestCase(unittest.TestCase):
162 162
         print("")
163 163
 
164 164
         log_path = Path(self.path_build / 'unit_tests' / f'{self._testMethodName}{self.log_suffix}')
165
-        log_path.unlink(missing_ok=True)
165
+        try:
166
+            log_path.unlink()
167
+        except Exception:
168
+            pass # missing_ok=True is too for common use.
166 169
         self.log = Logger(self._testMethodName, log_file=str(log_path))
167 170
 
168 171
     def tearDown(self):
... ...
@@ -607,6 +610,16 @@ class Executor(object):
607 607
             sys_env = os.environ.copy()
608 608
             sys_env.update(env_vars)
609 609
 
610
+            if sys.platform == 'darwin':
611
+                # macOS doesn't propagate 'LD_LIBRARY_PATH' or 'DYLD_LIBRARY_PATH'
612
+                # to subprocesses, presumably as a security feature.
613
+                # We will likely need these for testing and can propagate them
614
+                # manually, like so:
615
+                if "LD_LIBRARY_PATH" in sys_env:
616
+                    cmd = f"export LD_LIBRARY_PATH={sys_env['LD_LIBRARY_PATH']} && {cmd}"
617
+                if "DYLD_LIBRARY_PATH" in sys_env:
618
+                    cmd = f"export DYLD_LIBRARY_PATH={sys_env['DYLD_LIBRARY_PATH']} && {cmd}"
619
+
610 620
             self._logger.debug("Run command: %s" % (cmd,))
611 621
             self._process = subprocess.Popen(
612 622
                 cmd,
... ...
@@ -43,14 +43,6 @@ enum ptime_locale_status { not,
43 43
                            raw };
44 44
 #endif
45 45
 
46
-struct tm *localtime_r(time_t const *t, struct tm *tp)
47
-{
48
-    struct tm *copy = localtime(t);
49
-    if (!copy) return NULL;
50
-    memcpy(tp, copy, sizeof(*tp));
51
-    return tp;
52
-}
53
-
54 46
 typedef int bool;
55 47
 
56 48
 #define match_char(ch1, ch2) \
... ...
@@ -518,9 +510,10 @@ LOCALE_PARAM_DECL
518 518
                     secs += *rp++ - '0';
519 519
                 } while (*rp >= '0' && *rp <= '9');
520 520
 
521
-                if (localtime_r(&secs, tm) == NULL)
521
+                if (0 != localtime_s(tm, &secs)) {
522 522
                     /* Error in function.  */
523 523
                     return NULL;
524
+                }
524 525
             } break;
525 526
             case 'S':
526 527
                 get_number(0, 61, 2);