From 561a18054cbc2f539f0644fc2b298fb47498a6c5 Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Mon, 14 Dec 2015 00:16:44 +0000 Subject: [PATCH] Yet another attempt to use CMake --- .appveyor.yml | 26 +- .travis.yml | 36 +- CMakeLists.txt | 333 ++++++++++++++++++ Makefile.in | 10 +- NOTICE | 2 + README.md | 30 +- ZNCConfig.cmake.in | 51 +++ cmake/CMakeFindFrameworks_fixed.cmake | 40 +++ cmake/FindPerlLibs.cmake | 94 +++++ cmake/TestCXX11.cmake | 39 ++ cmake/TestFileOffsetBits.c | 12 + cmake/TestLargeFiles.c.cmakein | 26 ++ cmake/TestLargeFiles.cmake | 122 +++++++ cmake/TestWindowsFSeek.c | 12 + cmake/copy_csocket.cmake | 26 ++ cmake/copy_csocket_cmd.cmake | 20 ++ cmake/cxx11check/CMakeLists.txt | 23 ++ cmake/cxx11check/main.cpp | 58 +++ cmake/gen_version.cmake | 76 ++++ cmake/perl_check/CMakeLists.txt | 30 ++ cmake/perl_check/main.cpp | 29 ++ cmake/render_framed_multiline.cmake | 42 +++ cmake/use_homebrew.cmake | 63 ++++ configure.ac | 4 +- configure.py | 128 +++++++ include/CMakeLists.txt | 17 + include/znc/CMakeLists.txt | 34 ++ include/znc/Modules.h | 34 +- include/znc/version.h | 5 +- include/znc/zncconfig.h.cmake.in | 53 +++ make-tarball.sh | 21 +- modules/CMakeLists.txt | 111 ++++++ modules/modperl/CMakeLists.txt | 107 ++++++ modules/modperl/Makefile.gen | 6 +- modules/modperl/Makefile.inc | 10 +- modules/modperl/module.h | 12 +- modules/modpython/CMakeLists.txt | 97 +++++ modules/modpython/Makefile.gen | 6 +- modules/modpython/Makefile.inc | 10 +- modules/modpython/module.h | 13 +- modules/modtcl/CMakeLists.txt | 18 + src/CMakeLists.txt | 100 ++++++ src/version.cpp.in | 18 + src/znc.cpp | 6 + test/CMakeLists.txt | 97 +++++ test/integration/CMakeLists.txt | 46 +++ .../{Integration.cpp => integration/main.cpp} | 0 znc-buildmod.cmake.in | 78 ++++ znc.pc.cmake.in | 20 ++ znc.service.in | 2 +- zz_msg/CMakeLists.txt | 28 ++ 51 files changed, 2204 insertions(+), 77 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 ZNCConfig.cmake.in create mode 100644 cmake/CMakeFindFrameworks_fixed.cmake create mode 100644 cmake/FindPerlLibs.cmake create mode 100644 cmake/TestCXX11.cmake create mode 100644 cmake/TestFileOffsetBits.c create mode 100644 cmake/TestLargeFiles.c.cmakein create mode 100644 cmake/TestLargeFiles.cmake create mode 100644 cmake/TestWindowsFSeek.c create mode 100644 cmake/copy_csocket.cmake create mode 100644 cmake/copy_csocket_cmd.cmake create mode 100644 cmake/cxx11check/CMakeLists.txt create mode 100644 cmake/cxx11check/main.cpp create mode 100644 cmake/gen_version.cmake create mode 100644 cmake/perl_check/CMakeLists.txt create mode 100644 cmake/perl_check/main.cpp create mode 100644 cmake/render_framed_multiline.cmake create mode 100644 cmake/use_homebrew.cmake create mode 100755 configure.py create mode 100644 include/CMakeLists.txt create mode 100644 include/znc/CMakeLists.txt create mode 100644 include/znc/zncconfig.h.cmake.in create mode 100644 modules/CMakeLists.txt create mode 100644 modules/modperl/CMakeLists.txt create mode 100644 modules/modpython/CMakeLists.txt create mode 100644 modules/modtcl/CMakeLists.txt create mode 100644 src/CMakeLists.txt create mode 100644 src/version.cpp.in create mode 100644 test/CMakeLists.txt create mode 100644 test/integration/CMakeLists.txt rename test/{Integration.cpp => integration/main.cpp} (100%) create mode 100755 znc-buildmod.cmake.in create mode 100644 znc.pc.cmake.in create mode 100644 zz_msg/CMakeLists.txt diff --git a/.appveyor.yml b/.appveyor.yml index 7ed4e17c..20bf88bb 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,23 +9,41 @@ cache: environment: matrix: - cygwin_url: https://cygwin.com/setup-x86_64.exe + build_with: cmake - cygwin_url: https://cygwin.com/setup-x86.exe + build_with: cmake + - cygwin_url: https://cygwin.com/setup-x86_64.exe + build_with: autoconf + - cygwin_url: https://cygwin.com/setup-x86.exe + build_with: autoconf install: - ps: Invoke-WebRequest $env:cygwin_url -OutFile c:\cygwin-setup.exe # libcrypt-devel is needed only on x86_64 and only for modperl... probably some dependency problem. - - c:\cygwin-setup.exe --quiet-mode --no-shortcuts --no-startmenu --no-desktop --upgrade-also --only-site --site http://cygwin.mirror.constant.com/ --root c:\cygwin-root --local-package-dir c:\cygwin-setup-cache --packages automake,gcc-g++,make,pkg-config,wget,openssl-devel,libicu-devel,zlib-devel,libcrypt-devel,perl,python3,swig,libsasl2-devel,libQt5Core-devel + - c:\cygwin-setup.exe --quiet-mode --no-shortcuts --no-startmenu --no-desktop --upgrade-also --only-site --site http://cygwin.mirror.constant.com/ --root c:\cygwin-root --local-package-dir c:\cygwin-setup-cache --packages automake,gcc-g++,make,pkg-config,wget,openssl-devel,libicu-devel,zlib-devel,libcrypt-devel,perl,python3,swig,libsasl2-devel,libQt5Core-devel,cmake - c:\cygwin-root\bin\sh -lc "echo Hi" - c:\cygwin-root\bin\sh -lc "uname -a" - c:\cygwin-root\bin\sh -lc "cat /proc/cpuinfo" - c:\cygwin-root\bin\sh -lc "cat /proc/meminfo" - c:\cygwin-root\bin\sh -lc "cygcheck -s -v > $APPVEYOR_BUILD_FOLDER/cygcheck.log 2>&1" - ps: Push-AppveyorArtifact cygcheck.log + - ps: | + if ($env:build_with -eq "cmake") { + $env:cfg_suffix = ".py" + $env:unittest = "unittest" + $env:inttest = "inttest" + } else { + $env:cfg_suffix = "" + $env:unittest = "test" + $env:inttest = "test2" + } # stdin is broken at AppVeyor, so we open it explicitly as /dev/null build_script: - git submodule update --init - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER; ./autogen.sh < /dev/null" - mkdir build - - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; ../configure --enable-charset --enable-zlib --enable-openssl --enable-perl --enable-python --enable-cyrus < /dev/null; appveyor PushArtifact config.log" + - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; ../configure$cfg_suffix --enable-charset --enable-zlib --enable-openssl --enable-perl --enable-python --enable-cyrus < /dev/null" + - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; if [[ $build_with == cmake ]]; then cmake --system-information > config.log; fi" + - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; appveyor PushArtifact config.log" - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; make VERBOSE=1 -j2 < /dev/null" - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; make install < /dev/null" - c:\cygwin-root\bin\sh -lc "znc --version" @@ -33,5 +51,5 @@ build_script: - c:\cygwin-root\bin\sh -lc "find /usr/local/lib/znc -iname '*.dll' -o -iname '*.so' | tee /tmp/files-to-rebase" - c:\cygwin-root\bin\sh -lc "rebaseall -v -T /tmp/files-to-rebase" test_script: - - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; make VERBOSE=1 test < /dev/null" - - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; make VERBOSE=1 test2 < /dev/null" + - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; make VERBOSE=1 $unittest < /dev/null" + - c:\cygwin-root\bin\sh -lc "cd $APPVEYOR_BUILD_FOLDER/build; make VERBOSE=1 $inttest < /dev/null" diff --git a/.travis.yml b/.travis.yml index 2234a1e2..c22be810 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,22 +8,31 @@ matrix: include: - os: linux compiler: gcc - env: BUILD_TYPE=normal + env: BUILD_TYPE=normal BUILD_WITH=cmake - os: linux compiler: gcc - env: BUILD_TYPE=coverage + env: BUILD_TYPE=normal BUILD_WITH=autoconf + - os: linux + compiler: gcc + env: BUILD_TYPE=coverage BUILD_WITH=autoconf - os: linux compiler: clang - env: BUILD_TYPE=asan + env: BUILD_TYPE=asan BUILD_WITH=cmake - os: linux compiler: clang - env: BUILD_TYPE=tsan + env: BUILD_TYPE=tsan BUILD_WITH=cmake - os: osx compiler: clang - env: BUILD_TYPE=normal + env: BUILD_TYPE=normal BUILD_WITH=cmake + - os: osx + compiler: clang + env: BUILD_TYPE=normal BUILD_WITH=autoconf - os: linux compiler: gcc - env: BUILD_TYPE=tarball + env: BUILD_TYPE=tarball BUILD_WITH=cmake + - os: linux + compiler: gcc + env: BUILD_TYPE=tarball BUILD_WITH=autoconf before_install: - "echo os: [$TRAVIS_OS_NAME] build: [$BUILD_TYPE]" - if [[ "$BUILD_TYPE" == "normal" ]]; then export CFGFLAGS= MYCXXFLAGS= MYLDFLAGS=; fi @@ -31,6 +40,7 @@ before_install: - if [[ "$BUILD_TYPE" == "asan" ]]; then export CFGFLAGS=--enable-debug MYCXXFLAGS="-fsanitize=address -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fPIE" MYLDFLAGS="-fsanitize=address -pie"; fi - if [[ "$BUILD_TYPE" == "tsan" ]]; then export CFGFLAGS=--enable-debug MYCXXFLAGS="-fsanitize=thread -O1 -fPIE" MYLDFLAGS="-fsanitize=thread -pie"; fi - if [[ "$BUILD_TYPE" == "coverage" ]]; then export CFGFLAGS="--enable-debug --disable-perl --disable-python" MYCXXFLAGS=--coverage MYLDFLAGS=--coverage DISABLED_ZNC_PERL_PYTHON_TEST=1; fi + - if [[ "$BUILD_WITH" == "cmake" ]]; then export CFGSUFFIX=.py UNITTEST=unittest INTTEST=inttest; else export CFGSUFFIX= UNITTEST=test INTTEST=test2; fi # UBSan randomly crashes clang, and very often :( # CFGFLAGS=--enable-debug MYCXXFLAGS="-fsanitize=undefined -O1 -fPIE -fno-sanitize-recover" MYLDFLAGS="-fsanitize=undefined -pie -fno-sanitize-recover" - if [[ "$TRAVIS_REPO_SLUG" == "znc/znc" && "$TRAVIS_PULL_REQUEST" == "false" && "$TRAVIS_BRANCH" == "master" ]]; then openssl aes-256-cbc -d -in .travis-github.enc -out ~/znc-github-key -k ${SECRET_KEY}; fi @@ -41,10 +51,12 @@ install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:teward/swig3.0; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:beineri/opt-qt551-trusty; fi # default qt5.2 from trusty doesn't support QByteArray::toStdString() - if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "tarball" ]]; then sudo add-apt-repository -y ppa:ostogvin/tjo-develop; fi # gtest+gmock + - if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_WITH" == "cmake" ]]; then sudo add-apt-repository -y ppa:george-edison55/cmake-3.x; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y libperl-dev python3-dev tcl-dev libsasl2-dev libicu-dev swig3.0 doxygen graphviz qt55base python3-yaml; fi - if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "tarball" ]]; then sudo apt-get install -y google-mock libgtest-dev; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then source /opt/qt55/bin/qt55-env.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_WITH" == "cmake" ]]; then sudo apt-get install -y cmake; fi - | if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "coverage" ]]; then sudo apt-get install -y lcov @@ -58,6 +70,7 @@ install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew list --versions; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install swig python3 icu4c jq openssl qt5; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" && "$BUILD_WITH" == "cmake" ]]; then brew upgrade cmake; fi # preinstalled cmake on travis is too old - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew info --json=v1 --installed | jq .; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PKG_CONFIG_PATH="$(brew --prefix qt5)/lib/pkgconfig:$PKG_CONFIG_PATH"; fi - "echo pkg-config path: [$PKG_CONFIG_PATH]" @@ -65,16 +78,17 @@ script: - if [[ "$BUILD_TYPE" == "tarball" ]]; then ./make-tarball.sh --nightly znc-git-2015-01-16 /tmp/znc-tarball.tar.gz; fi - if [[ "$BUILD_TYPE" == "tarball" ]]; then cd /tmp; tar xvf znc-tarball.tar.gz; fi - if [[ "$BUILD_TYPE" == "tarball" ]]; then cd /tmp/znc-git-2015-01-16; fi - - if [[ "$BUILD_TYPE" != "tarball" ]]; then ./bootstrap.sh; fi + - if [[ "$BUILD_TYPE" != "tarball" && "$BUILD_WITH" != "cmake" ]]; then ./bootstrap.sh; fi - mkdir build - cd build - - ../configure --enable-perl --enable-python --enable-tcl --enable-cyrus --enable-charset $CFGFLAGS CXXFLAGS="$CXXFLAGS $MYCXXFLAGS" LDFLAGS="$LDFLAGS $MYLDFLAGS" - - cat config.log + - ../configure$CFGSUFFIX --enable-perl --enable-python --enable-tcl --enable-cyrus --enable-charset $CFGFLAGS CXXFLAGS="$CXXFLAGS $MYCXXFLAGS" LDFLAGS="$LDFLAGS $MYLDFLAGS" + - if [[ "$BUILD_WITH" == "cmake" ]]; then cmake --system-information; else cat config.log; fi - make VERBOSE=1 - - make VERBOSE=1 test + - make VERBOSE=1 $UNITTEST - sudo make install - - make VERBOSE=1 test2 + - make VERBOSE=1 $INTTEST - cd .. + - /usr/local/bin/znc --version after_success: - test -r .travis_after_all.py && python .travis_after_all.py || echo No .travis_after_all.py found - test -r .to_export_back && echo $(cat .to_export_back) || echo No .to_export_back found diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..dc1e0778 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,333 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cmake_minimum_required(VERSION 3.0) +project(ZNC VERSION 1.7.0) +set(ZNC_VERSION 1.7.x) +set(append_git_version true) +set(alpha_version "") # e.g. "-rc1" + +set(PROJECT_VERSION "${ZNC_VERSION}") + +# https://cmake.org/pipermail/cmake/2010-September/039388.html +set(_all_targets "" CACHE INTERNAL "") +function(znc_add_library name) + add_library("${name}" ${ARGN}) + set(_all_targets "${_all_targets};${name}" CACHE INTERNAL "") +endfunction() +function(znc_add_executable name) + add_executable("${name}" ${ARGN}) + set(_all_targets "${_all_targets};${name}" CACHE INTERNAL "") +endfunction() + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + +include(TestCXX11) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED true) +if(NOT CYGWIN) + # We don't want to use -std=gnu++11 instead of -std=c++11, but among other + # things, -std=c++11 on cygwin defines __STRICT_ANSI__ which makes cygwin + # not to compile: undefined references to strerror_r, to fdopen, to + # strcasecmp, etc (their declarations in system headers are between ifdef) + set(CMAKE_CXX_EXTENSIONS false) +endif() + +include(CMakeFindFrameworks_fixed) +include(use_homebrew) +include(GNUInstallDirs) +include(CheckCXXSymbolExists) +include(copy_csocket) + +set(CMAKE_THREAD_PREFER_PTHREAD true) +set(THREADS_PREFER_PTHREAD_FLAG true) +find_package(Threads REQUIRED) +if(NOT CMAKE_USE_PTHREADS_INIT) + message(FATAL_ERROR "This compiler/OS doesn't seem to support pthreads.") +endif() + +include(TestLargeFiles) +test_large_files(HAVE_LARGE_FILES_UNUSED_VAR) +find_package(PkgConfig) + +macro(tristate_option opt help) + set(WANT_${opt} AUTO CACHE STRING ${help}) + set_property(CACHE WANT_${opt} PROPERTY STRINGS AUTO YES NO) + if(WANT_${opt} STREQUAL "AUTO") + set(TRISTATE_${opt}_REQUIRED) + else() + set(TRISTATE_${opt}_REQUIRED REQUIRED) + endif() +endmacro() + +tristate_option(OPENSSL "Support SSL") +if(WANT_OPENSSL) + find_package(OpenSSL ${TRISTATE_OPENSSL_REQUIRED}) +endif() +set(HAVE_LIBSSL "${OPENSSL_FOUND}") + +set(WANT_IPV6 true CACHE BOOL "Support IPv6") +set(HAVE_IPV6 "${WANT_IPV6}") + +tristate_option(ZLIB "Compress HTTP traffic with Zlib") +if(WANT_ZLIB) + find_package(ZLIB ${TRISTATE_ZLIB_REQUIRED}) +endif() +set(HAVE_ZLIB "${ZLIB_FOUND}") + +tristate_option(CYRUS "Support authentication with Cyrus") +if(WANT_CYRUS) + pkg_check_modules(CYRUS libsasl2) + if(NOT CYRUS_FOUND) + # libsasl2.pc is missing on 2.1.25 which is on ubuntu 14.04 + # next ubuntu version has 2.1.26 which has libsasl2.pc + # + # osx (as of El Capitan) doesn't have it either... + set(_old_cmake_required_libraries "${CMAKE_REQUIRED_LIBRARIES}") + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} -lsasl2) + check_cxx_symbol_exists(sasl_server_init "sasl/sasl.h" CYRUS_HARDCODED) + set(CMAKE_REQUIRED_LIBRARIES "${_old_cmake_required_libraries}") + if(CYRUS_HARDCODED) + set(CYRUS_LDFLAGS -lsasl2) + set(CYRUS_FOUND true) + endif() + endif() + if(TRISTATE_CYRUS_REQUIRED AND NOT CYRUS_FOUND) + message(FATAL_ERROR "Can't find Cyrus SASL 2") + endif() +endif() + +tristate_option(ICU "Support character encodings") +if(WANT_ICU) + pkg_check_modules(ICU ${TRISTATE_ICU_REQUIRED} icu-uc) +endif() +set(HAVE_ICU "${ICU_FOUND}") + +set(WANT_PERL false CACHE BOOL "Support Perl modules") +set(WANT_PYTHON false CACHE BOOL "Support Python modules") +set(WANT_PYTHON_VERSION "" CACHE STRING "Python version to use, or empty") +tristate_option(SWIG "Use SWIG to generate modperl and modpython") +set(search_swig false) +if(WANT_SWIG AND TRISTATE_SWIG_REQUIRED) + set(search_swig true) +endif() +if(WANT_PERL AND NOT EXISTS + "${PROJECT_SOURCE_DIR}/modules/modperl/generated.tar.gz") + if(WANT_SWIG) + set(search_swig true) + else() + message(FATAL_ERROR "Pregenerated modperl files are not available. " + "SWIG is required. Alternatively, build ZNC from tarball.") + endif() +endif() +if(WANT_PYTHON AND NOT EXISTS + "${PROJECT_SOURCE_DIR}/modules/modpython/generated.tar.gz") + if(WANT_SWIG) + set(search_swig true) + else() + message(FATAL_ERROR "Pregenerated modpython files are not available. " + "SWIG is required. Alternatively, build ZNC from tarball.") + endif() +endif() +if(search_swig) + find_package(SWIG 3.0.0) + if(NOT SWIG_FOUND) + message(FATAL_ERROR + "Can't find SWIG, therefore Perl and Python aren't supported. " + "Alternatively, build ZNC from tarball.") + endif() +endif() + +if(WANT_PERL) + find_package(PerlLibs 5.10 REQUIRED) +endif() +if (WANT_PYTHON) + find_package(Perl 5.10 REQUIRED) + if(WANT_PYTHON_VERSION) + find_package(PythonLibs "${WANT_PYTHON_VERSION}" EXACT REQUIRED) + else() + find_package(PythonLibs 3 REQUIRED) + endif() +endif() + +set(WANT_TCL false CACHE BOOL "Support Tcl modules") +if(WANT_TCL) + find_package(TCL QUIET) + if(NOT TCL_FOUND) + message(FATAL_ERROR "Can't find Tcl") + endif() +endif() + +# poll() is broken on Mac OS, it fails with POLLNVAL for pipe()s. +if(APPLE) + set(CSOCK_USE_POLL false) +else() + set(CSOCK_USE_POLL true) +endif() + +check_cxx_symbol_exists(getopt_long "getopt.h" HAVE_GETOPT_LONG) +check_cxx_symbol_exists(lstat "sys/types.h;sys/stat.h;unistd.h" HAVE_LSTAT) +check_cxx_symbol_exists(getpassphrase "stdlib.h" HAVE_GETPASSPHRASE) +check_cxx_symbol_exists(tcsetattr "termios.h;unistd.h" HAVE_TCSETATTR) +check_cxx_symbol_exists(clock_gettime "time.h" HAVE_CLOCK_GETTIME) + +# Note that old broken systems, such as OpenBSD, NetBSD, which don't support +# AI_ADDRCONFIG, also have thread-unsafe getaddrinfo(). Gladly, they fixed +# thread-safety before support of AI_ADDRCONFIG, so this can be abused to +# detect the thread-safe getaddrinfo(). +# +# TODO: drop support of blocking DNS at some point. OpenBSD supports +# AI_ADDRCONFIG since Nov 2014, and their getaddrinfo() is thread-safe since +# Nov 2013. NetBSD's one is thread-safe since ages ago. +check_cxx_symbol_exists(AI_ADDRCONFIG "sys/types.h;sys/socket.h;netdb.h" + HAVE_THREADED_DNS) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT CYGWIN) + # These enable some debug options in g++'s STL, e.g. invalid use of + # iterators, but they cause crashes on cygwin while loading modules + set(_GLIBCXX_DEBUG true) + set(_GLIBCXX_DEBUG_PEDANTIC true) +endif() + +if(append_git_version) + find_package(Git) +endif() + + + +file(GLOB csocket_files LIST_DIRECTORIES FALSE + "${PROJECT_SOURCE_DIR}/third_party/Csocket/Csocket.*") +if(csocket_files STREQUAL "") + message(FATAL_ERROR " It looks like git submodules are not initialized.\n" + " Run: git submodule update --init --recursive") +endif() + +install(DIRECTORY webskins + DESTINATION "${CMAKE_INSTALL_DATADIR}/znc") +install(DIRECTORY man/ + DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" + FILES_MATCHING PATTERN "znc*") + +set(WANT_SYSTEMD false CACHE BOOL "Install znc.service to systemd") +if(WANT_SYSTEMD) + configure_file("znc.service.in" "znc.service") + set(SYSTEMD_DIR "" CACHE PATH "Path to systemd units") + if(SYSTEMD_DIR STREQUAL "" AND PKG_CONFIG_EXECUTABLE) + execute_process(COMMAND "${PKG_CONFIG_EXECUTABLE}" + --variable=systemdsystemunitdir systemd + OUTPUT_VARIABLE SYSTEMD_DIR) + endif() + if(SYSTEMD_DIR STREQUAL "") + message(FATAL_ERROR "Systemd is enabled, " + "but the unit dir can't be found.") + endif() + install(FILES "${PROJECT_BINARY_DIR}/znc.service" + DESTINATION "${SYSTEMD_DIR}") +endif() + +# On cygwin, if to link modules against znc.exe directly, modperl can't call +# ZNC's functions very well. They do get called, but global variables have +# different addresses. That address actually is in modperl/ZNC.dll if to look +# at /proc/123/maps +# Example of such global variable is one returned by CZNC::Get() +# Modpython seems to work though with STATIC on cygwin... (I didn't test it +# too much though) +# +# Non-cygwin should link modules to /usr/bin/znc directly to prevent this: +# error while loading shared libraries: libznc.so: cannot open shared object file: No such file or directory +# Without need to touch LD_LIBRARY_PATH +if(CYGWIN) + set(znc_link "znclib") + set(lib_type "SHARED") + set(install_lib "znclib") + set(znclib_pc "-L${CMAKE_INSTALL_FULL_LIBDIR} -lznc") +else() + set(znc_link "znc") + set(lib_type "STATIC") + set(install_lib) + set(znclib_pc) +endif() + +configure_file("include/znc/zncconfig.h.cmake.in" "include/znc/zncconfig.h") +add_subdirectory(include) +add_subdirectory(src) +add_subdirectory(modules) +add_subdirectory(test) +add_subdirectory(zz_msg) + +add_custom_target(msg_after_all ALL + COMMAND "${CMAKE_COMMAND}" -E echo + COMMAND "${CMAKE_COMMAND}" -E echo " ZNC was successfully compiled." + COMMAND "${CMAKE_COMMAND}" -E echo + " Use 'make install' to install ZNC to '${CMAKE_INSTALL_PREFIX}'." + COMMAND "${CMAKE_COMMAND}" -E echo + VERBATIM) +add_dependencies(msg_after_all ${_all_targets}) +# @echo "" +# @echo " ZNC was successfully compiled." +# @echo " Use '$(MAKE) install' to install ZNC to '$(prefix)'." + + +configure_file("ZNCConfig.cmake.in" "ZNCConfig.cmake" @ONLY) +include(CMakePackageConfigHelpers) +write_basic_package_version_file("ZNCConfigVersion.cmake" + COMPATIBILITY AnyNewerVersion) +install(FILES + "${PROJECT_BINARY_DIR}/ZNCConfig.cmake" + "${PROJECT_BINARY_DIR}/ZNCConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_DATADIR}/znc/cmake") +configure_file("znc-buildmod.cmake.in" "znc-buildmod" @ONLY) +install(PROGRAMS "${PROJECT_BINARY_DIR}/znc-buildmod" + DESTINATION "${CMAKE_INSTALL_BINDIR}") + +configure_file("znc.pc.cmake.in" "znc.pc" @ONLY) +install(FILES "${PROJECT_BINARY_DIR}/znc.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + +macro(summary_line text var) + if(${var}) + list(APPEND summary_lines "${text} : yes") + else() + list(APPEND summary_lines "${text} : no") + endif() +endmacro() +set(summary_lines + "ZNC ${ZNC_VERSION}${alpha_version} configured" + " " + "Prefix : ${CMAKE_INSTALL_PREFIX}") +summary_line("SSL " "${OPENSSL_FOUND}") +summary_line("IPv6 " "${WANT_IPV6}") +summary_line("Async DNS" "${HAVE_THREADED_DNS}") +summary_line("Perl " "${PERLLIBS_FOUND}") +summary_line("Python " "${PYTHONLIBS_FOUND}") +summary_line("Tcl " "${TCL_FOUND}") +summary_line("Cyrus " "${CYRUS_FOUND}") +summary_line("Charset " "${ICU_FOUND}") +summary_line("Zlib " "${ZLIB_FOUND}") + +include(render_framed_multiline) +render_framed_multiline("${summary_lines}") + +message("") +message("Now you can run 'make' to compile ZNC") +message("") + +# TODO +# ==== +# +# readme: advice about cmake --system-information +# remove old configure.ac and Makefile.in +# consider mininum cmake version diff --git a/Makefile.in b/Makefile.in index ee75e119..04448287 100644 --- a/Makefile.in +++ b/Makefile.in @@ -154,7 +154,7 @@ test/gmock-main.o: $(GMOCK_DIR)/src/gmock_main.cc Makefile $(Q)$(CXX) $(CXXFLAGS) $(GTEST_FLAGS) -c -o $@ $< -MD -MF .depend/gmock-main.dep -MT $@ # Qt fails under TSAN, so CXXFLAGS/LDFLAGS can't be used. -test/Integration.o: test/Integration.cpp Makefile +test/Integration.o: test/integration/main.cpp Makefile @mkdir -p .depend test $(E) Building test object Integration... $(Q)g++ $(qt_CFLAGS) $(GTEST_FLAGS) -c -o $@ $< -MD -MF .depend/Integration.test.dep -MT $@ '-DZNC_BIN_DIR="$(bindir)"' '-DZNC_SRC_DIR="$(realpath $(srcdir))"' @@ -179,7 +179,10 @@ src/version.cpp: Makefile version.sh $(shell if [ x`cat .version_extra 2> /dev/n $(E) Building source file version.cpp... $(Q)WRITE_OUTPUT=yes $(srcdir)/version.sh "$(GIT)" > .version_extra 2> /dev/null -CLEAN += src/version.cpp src/Csocket.cpp include/znc/Csocket.h +CLEAN += src/version.cpp +endif + +CLEAN += src/Csocket.cpp include/znc/Csocket.h src/Csocket.cpp: third_party/Csocket/Csocket.cc @rm -f $@ @@ -192,10 +195,9 @@ include/znc/Csocket.h: third_party/Csocket/Csocket.h third_party/Csocket/Csocket.h third_party/Csocket/Csocket.cc: @echo It looks like git submodules are not initialized. Run: git submodule update --init --recursive @exit 1 -endif znc.service: znc.service.in - @sed -e "s:\@bindir\@:$(bindir):" $^ > $@ + @sed -e "s:\@CMAKE_INSTALL_FULL_BINDIR\@:$(bindir):" $^ > $@ CLEAN += znc.service diff --git a/NOTICE b/NOTICE index e9d961b2..c06d08d3 100644 --- a/NOTICE +++ b/NOTICE @@ -14,6 +14,8 @@ ZNC includes modified code for SSL verification by Alban Diquet (https://github. ZNC includes code from jQuery (http://jquery.com/), licensed under the MIT License. ZNC includes code from jQuery UI (http://jqueryui.com/), licensed under the MIT License. ZNC includes code from Selectize (http://brianreavis.github.io/selectize.js/), licensed under the Apache License 2.0. +ZNC includes modified code from CMakeFindFrameworks.cmake by Kitware, Inc., licensed under BSD License. +ZNC includes modified code from TestLargeFiles.cmake, licensed under Boost Software License, Version 1.0. ZNC is developed by these people: diff --git a/README.md b/README.md index 4c8e3f3e..e335c6ac 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,9 @@ Core: * GNU make * pkg-config * GCC 4.7 or clang 3.2 -* autoconf and automake (if building from git) +* Either of: + * autoconf and automake (but only if building from git, not from tarball) + * CMake ## Optional Requirements @@ -53,6 +55,32 @@ Character Encodings: ## Installing ZNC +Currently there are 2 build systems in place: CMake and `./configure`. +`./configure` will eventually be removed. +There is also `configure.py` which should make migration to CMake easier: +it accepts the same parameters as `./configure`, +but calls CMake with CMake-style parameters. + +### Installing with CMake + +Installation from source code is performed using the CMake toolchain. + +```shell +cmake . +make +make install +``` + +You can use `cmake-gui` or `ccmake` for more interactiveness. + +Note for FreeBSD users: +By default base OpenSSL is selected. +If you want the one from ports, use `-DOPENSSL_ROOT_DIR=/usr/local`. + +For troubleshooting, `cmake --system-information` will show you details. + +### Installing with `./configure` + Installation from source code is performed using the `automake` toolchain. If you are building from git, you will need to run `./autogen.sh` first to produce the `configure` script. diff --git a/ZNCConfig.cmake.in b/ZNCConfig.cmake.in new file mode 100644 index 00000000..c6108e49 --- /dev/null +++ b/ZNCConfig.cmake.in @@ -0,0 +1,51 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include("${CMAKE_CURRENT_LIST_DIR}/znc.cmake") +include(CMakeParseArguments) + +# For some reason cygwin fails to build modules if Threads::Threads +# is not found. +if(NOT CYGWIN) + set(ZNC_NO_INCLUDE_THREADS true) +endif() + +if(NOT ZNC_NO_INCLUDE_THREADS) + set(CMAKE_THREAD_PREFER_PTHREAD true) + set(THREADS_PREFER_PTHREAD_FLAG true) + find_package(Threads REQUIRED) + if(NOT CMAKE_USE_PTHREADS_INIT) + message(FATAL_ERROR "This compiler/OS doesn't seem " + "to support pthreads.") + endif() +endif() + +function(znc_setup_module) + cmake_parse_arguments(znc_mod "" "TARGET;NAME" "" ${ARGN}) + set_target_properties("${znc_mod_TARGET}" PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED true + OUTPUT_NAME "${znc_mod_NAME}" + PREFIX "" + SUFFIX ".so" + NO_SONAME true + CXX_VISIBILITY_PRESET "hidden" + COMPILE_DEFINITIONS "znc_export_lib_EXPORTS") + set(znc_link "@znc_link@") + target_link_libraries("${znc_mod_TARGET}" PUBLIC "znc_internal_${znc_link}") +endfunction() + +message(STATUS "Found ZNC @ZNC_VERSION@") diff --git a/cmake/CMakeFindFrameworks_fixed.cmake b/cmake/CMakeFindFrameworks_fixed.cmake new file mode 100644 index 00000000..89c48741 --- /dev/null +++ b/cmake/CMakeFindFrameworks_fixed.cmake @@ -0,0 +1,40 @@ +# Modification from upstream CMakeFindFrameworks.cmake from version 3.3.1: +# - add support of ${fwk}_FRAMEWORKS_ADDITIONAL input variable + +#.rst: +# CMakeFindFrameworks +# ------------------- +# +# helper module to find OSX frameworks + +#============================================================================= +# Copyright 2003-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if(NOT CMAKE_FIND_FRAMEWORKS_INCLUDED) + set(CMAKE_FIND_FRAMEWORKS_INCLUDED 1) + macro(CMAKE_FIND_FRAMEWORKS fwk) + set(${fwk}_FRAMEWORKS) + if(APPLE) + foreach(dir + ${${fwk}_FRAMEWORKS_ADDITIONAL} + ~/Library/Frameworks/${fwk}.framework + /Library/Frameworks/${fwk}.framework + /System/Library/Frameworks/${fwk}.framework + /Network/Library/Frameworks/${fwk}.framework) + if(EXISTS ${dir}) + set(${fwk}_FRAMEWORKS ${${fwk}_FRAMEWORKS} ${dir}) + endif() + endforeach() + endif() + endmacro() +endif() diff --git a/cmake/FindPerlLibs.cmake b/cmake/FindPerlLibs.cmake new file mode 100644 index 00000000..d78b0dd6 --- /dev/null +++ b/cmake/FindPerlLibs.cmake @@ -0,0 +1,94 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# perl 5.20 will fix this warning: +# https://rt.perl.org/Public/Bug/Display.html?id=120670 +set(PERL_CFLAGS -Wno-reserved-user-defined-literal -Wno-literal-suffix + CACHE STRING "Perl compiler flags") + +if(PerlLibs_FIND_VERSION_EXACT) + set(_PerlLibs_exact EXACT) +else() + set(_PerlLibs_exact) +endif() +find_package(Perl ${PerlLibs_FIND_VERSION} ${PerlLibs_exact} QUIET) + +if(PERL_FOUND) + if(PERL_INCLUDE_DIR AND PERL_LIBRARIES) + else() + execute_process( + COMMAND "${PERL_EXECUTABLE}" -MExtUtils::Embed -e perl_inc + OUTPUT_VARIABLE _PerlLibs_inc_output + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX REPLACE "^ *-I" "" _PerlLibs_include + "${_PerlLibs_inc_output}") + + execute_process( + COMMAND "${PERL_EXECUTABLE}" -MExtUtils::Embed -e ldopts + OUTPUT_VARIABLE _PerlLibs_ld_output + OUTPUT_STRIP_TRAILING_WHITESPACE) + separate_arguments(_PerlLibs_ld_output) + set(_PerlLibs_ldflags) + set(_PerlLibs_libraries) + foreach(_PerlLibs_i ${_PerlLibs_ld_output}) + if("${_PerlLibs_i}" MATCHES "^-l") + list(APPEND _PerlLibs_libraries "${_PerlLibs_i}") + else() + set(_PerlLibs_ldflags "${_PerlLibs_ldflags} ${_PerlLibs_i}") + endif() + endforeach() + + get_filename_component(_PerlLibs_dir "${CMAKE_CURRENT_LIST_FILE}" + DIRECTORY) + try_compile(_PerlLibs_try + "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/perl_check" + "${_PerlLibs_dir}/perl_check" perl_check + CMAKE_FLAGS + "-DPERL_INCLUDE_DIRS=${_PerlLibs_include}" + "-DPERL_LDFLAGS=${_PerlLibs_ldflags}" + "-DPERL_LIBRARIES=${_PerlLibs_libraries}" + "-DPERL_CFLAGS=${PERL_CFLAGS}" + OUTPUT_VARIABLE _PerlLibs_tryout) + + if(_PerlLibs_try) + set(PERL_INCLUDE_DIR "${_PerlLibs_include}" CACHE PATH + "Perl include dir") + set(PERL_LDFLAGS "${_PerlLibs_ldflags}" CACHE STRING + "Perl linker flags") + set(PERL_LIBRARIES "${_PerlLibs_libraries}" CACHE STRING + "Perl libraries") + file(APPEND + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log" + "Output using Perl:\n${_PerlLibs_tryout}\n") + else() + set(_PerlLibs_failmsg FAIL_MESSAGE "Attempt to use Perl failed") + file(APPEND + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log" + "Error using Perl:\n${_PerlLibs_tryout}\n") + endif() + endif() +else() + set(_PerlLibs_failmsg FAIL_MESSAGE "Perl not found") +endif() + +find_package_handle_standard_args(PerlLibs + REQUIRED_VARS PERL_INCLUDE_DIR PERL_LIBRARIES + VERSION_VAR PERL_VERSION_STRING + ${_PerlLibs_failmsg}) + +set(PERL_INCLUDE_DIRS "${PERL_INCLUDE_DIR}") + +mark_as_advanced(PERL_INCLUDE_DIR PERL_LDFLAGS PERL_LIBRARIES PERL_CFLAGS) diff --git a/cmake/TestCXX11.cmake b/cmake/TestCXX11.cmake new file mode 100644 index 00000000..e2b38f56 --- /dev/null +++ b/cmake/TestCXX11.cmake @@ -0,0 +1,39 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if(NOT DEFINED cxx11check) + message(STATUS "Checking for C++11 support") + get_filename_component(_CXX11Check_dir "${CMAKE_CURRENT_LIST_FILE}" + DIRECTORY) + try_compile(cxx11_supported + "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cxx11check" + "${_CXX11Check_dir}/cxx11check" cxx11check + OUTPUT_VARIABLE _CXX11Check_tryout) + if(cxx11_supported) + message(STATUS "Checking for C++11 support - supported") + SET(cxx11check 1 CACHE INTERNAL "C++11 support") + file(APPEND + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log" + "Output of C++11 check:\n${_CXX11Check_tryout}\n") + else() + file(APPEND + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log" + "Error in C++11 check:\n${_CXX11Check_tryout}\n") + message(STATUS "Checking for C++11 support - not supported") + message(FATAL_ERROR " Upgrade your compiler.\n" + " GCC 4.7+ and Clang 3.2+ are known to work.") + endif() +endif() diff --git a/cmake/TestFileOffsetBits.c b/cmake/TestFileOffsetBits.c new file mode 100644 index 00000000..bc1dcaf8 --- /dev/null +++ b/cmake/TestFileOffsetBits.c @@ -0,0 +1,12 @@ +// See TestLargeFiles.cmake for the origin of this file + +#include + +int main(int argc, char **argv) +{ + /* Cause a compile-time error if off_t is smaller than 64 bits */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; + return 0; +} + diff --git a/cmake/TestLargeFiles.c.cmakein b/cmake/TestLargeFiles.c.cmakein new file mode 100644 index 00000000..a2154132 --- /dev/null +++ b/cmake/TestLargeFiles.c.cmakein @@ -0,0 +1,26 @@ +// See TestLargeFiles.cmake for the origin of this file + +#cmakedefine _LARGEFILE_SOURCE +#cmakedefine _LARGEFILE64_SOURCE +#cmakedefine _LARGE_FILES +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} + +#include +#include +#include + +int main(int argc, char **argv) +{ + /* Cause a compile-time error if off_t is smaller than 64 bits, + * and make sure we have ftello / fseeko. + */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; + FILE *fp = fopen(argv[0],"r"); + off_t offset = ftello( fp ); + + fseeko( fp, offset, SEEK_CUR ); + fclose(fp); + return 0; +} + diff --git a/cmake/TestLargeFiles.cmake b/cmake/TestLargeFiles.cmake new file mode 100644 index 00000000..42bcdff0 --- /dev/null +++ b/cmake/TestLargeFiles.cmake @@ -0,0 +1,122 @@ +# Downloaded from https://panthema.net/2012/1119-eSAIS-Inducing-Suffix-and-LCP-Arrays-in-External-Memory/eSAIS-DC3-LCP-0.5.4/stxxl/misc/cmake/TestLargeFiles.cmake.html +# That project's license is Boost Software License, Version 1.0. + +# - Define macro to check large file support +# +# TEST_LARGE_FILES(VARIABLE) +# +# VARIABLE will be set to true if off_t is 64 bits, and fseeko/ftello present. +# This macro will also set defines necessary enable large file support, for instance +# _LARGE_FILES +# _LARGEFILE_SOURCE +# _FILE_OFFSET_BITS 64 +# HAVE_FSEEKO +# +# However, it is YOUR job to make sure these defines are set in a cmakedefine so they +# end up in a config.h file that is included in your source if necessary! + +set(_test_large_files_dir "${CMAKE_CURRENT_LIST_DIR}") + +MACRO(TEST_LARGE_FILES VARIABLE) + IF(NOT DEFINED ${VARIABLE}) + + # On most platforms it is probably overkill to first test the flags for 64-bit off_t, + # and then separately fseeko. However, in the future we might have 128-bit filesystems + # (ZFS), so it might be dangerous to indiscriminately set e.g. _FILE_OFFSET_BITS=64. + + MESSAGE(STATUS "Checking for 64-bit off_t") + + # First check without any special flags + TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}" + "${_test_large_files_dir}/TestFileOffsetBits.c") + if(FILE64_OK) + MESSAGE(STATUS "Checking for 64-bit off_t - present") + endif(FILE64_OK) + + if(NOT FILE64_OK) + # Test with _FILE_OFFSET_BITS=64 + TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}" + "${_test_large_files_dir}/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" ) + if(FILE64_OK) + MESSAGE(STATUS "Checking for 64-bit off_t - present with _FILE_OFFSET_BITS=64") + set(_FILE_OFFSET_BITS 64) + endif(FILE64_OK) + endif(NOT FILE64_OK) + + if(NOT FILE64_OK) + # Test with _LARGE_FILES + TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}" + "${_test_large_files_dir}/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_LARGE_FILES" ) + if(FILE64_OK) + MESSAGE(STATUS "Checking for 64-bit off_t - present with _LARGE_FILES") + set(_LARGE_FILES 1) + endif(FILE64_OK) + endif(NOT FILE64_OK) + + if(NOT FILE64_OK) + # Test with _LARGEFILE_SOURCE + TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}" + "${_test_large_files_dir}/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) + if(FILE64_OK) + MESSAGE(STATUS "Checking for 64-bit off_t - present with _LARGEFILE_SOURCE") + set(_LARGEFILE_SOURCE 1) + endif(FILE64_OK) + endif(NOT FILE64_OK) + + if(NOT FILE64_OK) + # now check for Windows stuff + TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}" + "${_test_large_files_dir}/TestWindowsFSeek.c") + if(FILE64_OK) + MESSAGE(STATUS "Checking for 64-bit off_t - present with _fseeki64") + set(HAVE__FSEEKI64 1) + endif(FILE64_OK) + endif(NOT FILE64_OK) + + if(NOT FILE64_OK) + MESSAGE(STATUS "Checking for 64-bit off_t - not present") + else(NOT FILE64_OK) + + # Set the flags we might have determined to be required above + configure_file("${_test_large_files_dir}/TestLargeFiles.c.cmakein" + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") + + MESSAGE(STATUS "Checking for fseeko/ftello") + # Test if ftello/fseeko are available + TRY_COMPILE(FSEEKO_COMPILE_OK "${PROJECT_BINARY_DIR}" + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") + if(FSEEKO_COMPILE_OK) + MESSAGE(STATUS "Checking for fseeko/ftello - present") + endif(FSEEKO_COMPILE_OK) + + if(NOT FSEEKO_COMPILE_OK) + # glibc 2.2 neds _LARGEFILE_SOURCE for fseeko (but not 64-bit off_t...) + TRY_COMPILE(FSEEKO_COMPILE_OK "${PROJECT_BINARY_DIR}" + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c" + COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) + if(FSEEKO_COMPILE_OK) + MESSAGE(STATUS "Checking for fseeko/ftello - present with _LARGEFILE_SOURCE") + set(_LARGEFILE_SOURCE 1) + endif(FSEEKO_COMPILE_OK) + endif(NOT FSEEKO_COMPILE_OK) + + endif(NOT FILE64_OK) + + if(FSEEKO_COMPILE_OK) + SET(${VARIABLE} 1 CACHE INTERNAL "Result of test for large file support" FORCE) + set(HAVE_FSEEKO 1) + else(FSEEKO_COMPILE_OK) + if (HAVE__FSEEKI64) + SET(${VARIABLE} 1 CACHE INTERNAL "Result of test for large file support" FORCE) + SET(HAVE__FSEEKI64 1 CACHE INTERNAL "Windows 64-bit fseek" FORCE) + else (HAVE__FSEEKI64) + MESSAGE(STATUS "Checking for fseeko/ftello - not found") + SET(${VARIABLE} 0 CACHE INTERNAL "Result of test for large file support" FORCE) + endif (HAVE__FSEEKI64) + endif(FSEEKO_COMPILE_OK) + + ENDIF(NOT DEFINED ${VARIABLE}) +ENDMACRO(TEST_LARGE_FILES VARIABLE) diff --git a/cmake/TestWindowsFSeek.c b/cmake/TestWindowsFSeek.c new file mode 100644 index 00000000..5eac9bc6 --- /dev/null +++ b/cmake/TestWindowsFSeek.c @@ -0,0 +1,12 @@ +// See TestLargeFiles.cmake for the origin of this file + +#include + +int main() +{ + __int64 off=0; + + _fseeki64(NULL, off, SEEK_SET); + + return 0; +} diff --git a/cmake/copy_csocket.cmake b/cmake/copy_csocket.cmake new file mode 100644 index 00000000..e2e38dbb --- /dev/null +++ b/cmake/copy_csocket.cmake @@ -0,0 +1,26 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +function(copy_csocket tgt source destination) + add_custom_command(OUTPUT "${destination}" + COMMAND "${CMAKE_COMMAND}" + -D "source=${source}" + -D "destination=${destination}" + -P "${PROJECT_SOURCE_DIR}/cmake/copy_csocket_cmd.cmake" + DEPENDS "${source}" "${PROJECT_SOURCE_DIR}/cmake/copy_csocket_cmd.cmake" + VERBATIM) + add_custom_target("${tgt}" DEPENDS "${destination}") +endfunction() diff --git a/cmake/copy_csocket_cmd.cmake b/cmake/copy_csocket_cmd.cmake new file mode 100644 index 00000000..fc4f250c --- /dev/null +++ b/cmake/copy_csocket_cmd.cmake @@ -0,0 +1,20 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +file(READ "${source}" content) +string(REPLACE "#include \"defines.h\"" "#include " content "${content}") +string(REPLACE "#include \"Csocket.h\"" "#include " content "${content}") +file(WRITE "${destination}" "${content}") diff --git a/cmake/cxx11check/CMakeLists.txt b/cmake/cxx11check/CMakeLists.txt new file mode 100644 index 00000000..46545390 --- /dev/null +++ b/cmake/cxx11check/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cmake_minimum_required(VERSION 3.0) +project(cxx11check) +set(CMAKE_VERBOSE_MAKEFILE true) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED true) +add_executable(main main.cpp) diff --git a/cmake/cxx11check/main.cpp b/cmake/cxx11check/main.cpp new file mode 100644 index 00000000..376ed5d6 --- /dev/null +++ b/cmake/cxx11check/main.cpp @@ -0,0 +1,58 @@ +// This file uses code from http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html (serial 5) + +// Copyright (c) 2008 Benjamin Kosnik +// Copyright (c) 2012 Zack Weinberg +// Copyright (c) 2013 Roy Stogner +// Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +// +// Copying and distribution of this file, with or without modification, are +// permitted in any medium without royalty provided the copyright notice +// and this notice are preserved. This file is offered as-is, without any +// warranty. + + +template +struct check { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); +}; + +struct Base { + virtual void f() {} +}; +struct Child : public Base { + virtual void f() override {} +}; + +typedef check> right_angle_brackets; + +int a; +decltype(a) b; + +typedef check check_type; +check_type c; +check_type&& cr = static_cast(c); + +auto d = a; +auto l = []() {}; + +// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae +// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function +// because of this +namespace test_template_alias_sfinae { +struct foo {}; + +template +using member = typename T::member_type; + +template +void func(...) {} + +template +void func(member*) {} + +void test(); + +void test() { func(0); } +} + +int main() { return 0; } diff --git a/cmake/gen_version.cmake b/cmake/gen_version.cmake new file mode 100644 index 00000000..e0993e59 --- /dev/null +++ b/cmake/gen_version.cmake @@ -0,0 +1,76 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if(nightly) + set(git_info "${nightly}") +elseif(append_git_version) + + set(git ${gitcmd} "--git-dir=${srcdir}/.git") + + execute_process(COMMAND ${git} describe --abbrev=0 HEAD + RESULT_VARIABLE git_result + ERROR_QUIET + OUTPUT_VARIABLE latest_tag) + string(STRIP "${latest_tag}" latest_tag) + + if(git_result EQUAL 0) + execute_process(COMMAND ${git} rev-parse --short HEAD + OUTPUT_VARIABLE short_id) + string(STRIP "${short_id}" short_id) + + if(latest_tag STREQUAL "") + # shallow clone + set(git_info "-git-${short_id}") + else() + # One character "x" per commit, remove newlines from output + execute_process(COMMAND ${git} log --format=tformat:x + "${latest_tag}..HEAD" + OUTPUT_VARIABLE commits_since) + string(REGEX REPLACE "[^x]" "" commits_since "${commits_since}") + string(LENGTH "${commits_since}" commits_since) + + if(commits_since EQUAL 0) + # If this commit is tagged, don't print anything + # (the assumption here is: this is a release) + set(git_info "") + # However, this shouldn't happen, as for releases + # append_git_version should be set to false + else() + set(git_info "-git-${commits_since}-${short_id}") + endif() + endif() + + execute_process(COMMAND ${gitcmd} status + --ignore-submodules=dirty + --porcelain + -- third_party/Csocket + WORKING_DIRECTORY "${srcdir}" + OUTPUT_VARIABLE franken) + string(STRIP "${franken}" franken) + if(NOT franken STREQUAL "") + message(WARNING " Csocket submodule looks outdated.\n" + " Run: git submodule update --init --recursive") + set(git_info "${git_info}-frankenznc") + endif() + else() + # Probably .git/ or git isn't found, or something + set(git_info "-git-unknown") + endif() +else() + set(git_info "") +endif() + +configure_file("${srcfile}" "${destfile}") diff --git a/cmake/perl_check/CMakeLists.txt b/cmake/perl_check/CMakeLists.txt new file mode 100644 index 00000000..cc0bfcab --- /dev/null +++ b/cmake/perl_check/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cmake_minimum_required(VERSION 3.0) +project(perl_check) +set(CMAKE_VERBOSE_MAKEFILE true) + +if(APPLE) + set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS + "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -undefined dynamic_lookup") +endif() + +add_library(main MODULE main.cpp) +target_include_directories(main PRIVATE ${PERL_INCLUDE_DIRS}) +target_compile_options(main PRIVATE "${PERL_CFLAGS}") +target_link_libraries(main PRIVATE ${PERL_LIBRARIES}) +set_target_properties(main PROPERTIES LINK_FLAGS "${PERL_LDFLAGS}") diff --git a/cmake/perl_check/main.cpp b/cmake/perl_check/main.cpp new file mode 100644 index 00000000..9d8137fa --- /dev/null +++ b/cmake/perl_check/main.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +int perlcheck(int argc, char** argv, char** env) { + PERL_SYS_INIT3(&argc, &argv, &env); + PerlInterpreter* p = perl_alloc(); + perl_construct(p); + perl_destruct(p); + perl_free(p); + PERL_SYS_TERM(); + return 0; +} diff --git a/cmake/render_framed_multiline.cmake b/cmake/render_framed_multiline.cmake new file mode 100644 index 00000000..16bebdbb --- /dev/null +++ b/cmake/render_framed_multiline.cmake @@ -0,0 +1,42 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +function(render_framed_multiline lines) + set(max_len 0) + foreach(l ${lines}) + string(LENGTH "${l}" l_len) + if(l_len GREATER max_len) + set(max_len "${l_len}") + endif() + endforeach() + set(i 0) + set(header) + while(i LESS max_len) + set(header "${header}-") + math(EXPR i "${i} + 1") + endwhile() + message("+-${header}-+") + foreach(l ${lines}) + string(LENGTH "${l}" l_len) + while(l_len LESS max_len) + set(l "${l} ") + math(EXPR l_len "${l_len} + 1") + endwhile() + message("| ${l} |") + endforeach() + message("+-${header}-+") +endfunction() + diff --git a/cmake/use_homebrew.cmake b/cmake/use_homebrew.cmake new file mode 100644 index 00000000..8884371e --- /dev/null +++ b/cmake/use_homebrew.cmake @@ -0,0 +1,63 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if(NOT APPLE) + return() +endif() + +include(FindPackageMessage) +find_program(brew brew) +if(brew) + find_package_message(brew "Homebrew found: ${brew}" "1;${brew}") +else() + find_package_message(brew "Homebrew not found" "0") + return() +endif() + +execute_process(COMMAND "${brew}" --prefix icu4c + RESULT_VARIABLE brew_icu_f + OUTPUT_VARIABLE brew_icu OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +if(brew_icu_f EQUAL 0) + find_package_message(brew_icu "ICU via Homebrew: ${brew_icu}" "${brew_icu}") + set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${brew_icu}/lib/pkgconfig") +endif() + +execute_process(COMMAND "${brew}" --prefix openssl + RESULT_VARIABLE brew_ssl_f + OUTPUT_VARIABLE brew_ssl OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +if(brew_ssl_f EQUAL 0) + find_package_message(brew_ssl "OpenSSL via Homebrew: ${brew_ssl}" + "${brew_ssl}") + set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${brew_ssl}/lib/pkgconfig") +endif() + +execute_process(COMMAND "${brew}" --prefix python3 + RESULT_VARIABLE brew_python_f + OUTPUT_VARIABLE brew_python OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +if(brew_python_f EQUAL 0) + find_package_message(brew_python "Python via Homebrew: ${brew_python}" + "${brew_python}") + list(APPEND Python_FRAMEWORKS_ADDITIONAL + "${brew_python}/Frameworks/Python.framework") +endif() + +execute_process(COMMAND "${brew}" --prefix qt5 + RESULT_VARIABLE brew_qt5_f + OUTPUT_VARIABLE brew_qt5 OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +if(brew_qt5_f EQUAL 0) + find_package_message(brew_qt5 "Qt5 via Homebrew: ${brew_qt5}" + "${brew_qt5}") +endif() diff --git a/configure.ac b/configure.ac index e69fd08c..e7f79b05 100644 --- a/configure.ac +++ b/configure.ac @@ -511,12 +511,12 @@ if test "x$PERL" != xno -o "x$PYTHON" != xno; then AC_MSG_ERROR([Could not found appropriate SWIG installation. Check config.log for details.]) fi fi - if test -r "$srcdir/modules/modperl/ZNC.cpp" -a -r "$srcdir/modules/modpython/_znc_core.cpp"; then + if test -r "$srcdir/modules/modperl/generated.tar.gz" -a -r "$srcdir/modules/modpython/generated.tar.gz"; then AC_MSG_NOTICE([modperl/modpython files are found, disabling SWIG]) USESWIG=no fi if test "x$USESWIG" = xno; then - if test ! -r "$srcdir/modules/modperl/ZNC.cpp" -o ! -r "$srcdir/modules/modpython/_znc_core.cpp"; then + if test ! -r "$srcdir/modules/modperl/generated.tar.gz" -o ! -r "$srcdir/modules/modpython/generated.tar.gz"; then AC_MSG_ERROR([Can not build modperl/modpython. Either install SWIG, or build ZNC from a tarball, or disable modperl/modpython. Check config.log for details.]) else AC_MSG_NOTICE([modperl/modpython files are found, no SWIG needed]) diff --git a/configure.py b/configure.py new file mode 100755 index 00000000..8bc6c37c --- /dev/null +++ b/configure.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +import argparse +import os +import subprocess +import sys +import re + +extra_args = [os.path.dirname(sys.argv[0])] +parser = argparse.ArgumentParser() + +def gnu_install_dir(name, cmake=None): + if cmake is None: + cmake = name.upper() + parser.add_argument('--' + name, action='append', metavar=cmake, + dest='cm_args', + type=lambda s: '-DCMAKE_INSTALL_{}={}'.format(cmake, s)) + +gnu_install_dir('prefix') +gnu_install_dir('bindir') +gnu_install_dir('sbindir') +gnu_install_dir('libexecdir') +gnu_install_dir('sysconfdir') +gnu_install_dir('sharedstatedir') +gnu_install_dir('localstatedir') +gnu_install_dir('libdir') +gnu_install_dir('includedir') +gnu_install_dir('oldincludedir') +gnu_install_dir('datarootdir') +gnu_install_dir('datadir') +gnu_install_dir('infodir') +gnu_install_dir('localedir') +gnu_install_dir('mandir') +gnu_install_dir('docdir') + + +group = parser.add_mutually_exclusive_group() +group.add_argument('--enable-debug', action='store_const', dest='build_type', + const='Debug', default='Release') +group.add_argument('--disable-debug', action='store_const', dest='build_type', + const='Release', default='Release') + +def tristate(name, cmake=None): + if cmake is None: + cmake = name.upper() + group = parser.add_mutually_exclusive_group() + group.add_argument('--enable-' + name, action='append_const', + dest='cm_args', const='-DWANT_{}=YES'.format(cmake)) + group.add_argument('--disable-' + name, action='append_const', + dest='cm_args', const='-DWANT_{}=NO'.format(cmake)) + +tristate('ipv6') +tristate('openssl') +tristate('zlib') +tristate('perl') +tristate('swig') +tristate('cyrus') +tristate('charset', 'ICU') +tristate('tcl') + +class HandlePython(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + extra_args.append('-DWANT_PYTHON=YES') + if values is not None: + x = re.search(r'\d.*', values) + if x: + extra_args.append('-DWANT_PYTHON_VERSION=' + x.group(0)) + +group = parser.add_mutually_exclusive_group() +group.add_argument('--enable-python', action=HandlePython, nargs='?', + metavar='PYTHON_VERSION') +group.add_argument('--disable-python', action='append_const', dest='cm_args', + const='-DWANT_PYTHON=NO') + +parser.add_argument('--with-gtest', action='store', dest='gtest') +parser.add_argument('--with-gmock', action='store', dest='gmock') + +class HandleSystemd(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + extra_args.append('-DWANT_SYSTEMD=YES') + if values is not None: + extra_args.append('-DWANT_SYSTEMD_DIR=' + values) + +parser.add_argument('--with-systemdsystemunitdir', action=HandleSystemd, + nargs='?', metavar='UNITDIR') + +def env_type(s): + name, value = s.split('=', 1) + return (name, value) + +parser.add_argument('env', nargs='*', type=env_type, metavar='ENV_VAR=VALUE') + +args = parser.parse_args() + +cm_args = args.cm_args or [] + +for env_key, env_value in args.env: + os.environ[env_key] = env_value +if args.gtest: + os.environ['GTEST_ROOT'] = args.gtest +if args.gmock: + os.environ['GMOCK_ROOT'] = args.gmock + +if os.environ.get('CXX') is not None: + extra_args.append('-DCMAKE_CXX_COMPILER=' + os.environ['CXX']) + +try: + os.remove('CMakeCache.txt') +except OSError: + pass +subprocess.check_call(['cmake', '-DCMAKE_BUILD_TYPE=' + args.build_type] + + cm_args + extra_args) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 00000000..17003377 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +add_subdirectory(znc) diff --git a/include/znc/CMakeLists.txt b/include/znc/CMakeLists.txt new file mode 100644 index 00000000..afa3a0a1 --- /dev/null +++ b/include/znc/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +copy_csocket(copy_csocket_h + "${PROJECT_SOURCE_DIR}/third_party/Csocket/Csocket.h" + "${CMAKE_CURRENT_BINARY_DIR}/Csocket.h") + +# __attribute__((__visibility__("default")) macro comes from +# generate_export_header(), which wants a library. +# we don't really care which library is that. +# Macro defined by this generated header is used in Modules.h +# Name of this pseudolibrary matches the define passed to modules. +add_library(znc_export_lib SHARED IMPORTED) +include(GenerateExportHeader) +generate_export_header(znc_export_lib) + +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/" "${CMAKE_CURRENT_BINARY_DIR}/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/znc" + FILES_MATCHING + PATTERN "*.h" + PATTERN CMakeFiles EXCLUDE) diff --git a/include/znc/Modules.h b/include/znc/Modules.h index 64d7196f..7c7ecf45 100644 --- a/include/znc/Modules.h +++ b/include/znc/Modules.h @@ -50,24 +50,28 @@ class CModInfo; #endif #endif -#if HAVE_VISIBILITY -#define MODULE_EXPORT __attribute__((__visibility__("default"))) +#ifdef BUILD_WITH_CMAKE +#include +#elif HAVE_VISIBILITY +#define ZNC_EXPORT_LIB_EXPORT __attribute__((__visibility__("default"))) #else -#define MODULE_EXPORT +#define ZNC_EXPORT_LIB_EXPORT #endif -#define MODCOMMONDEFS(CLASS, DESCRIPTION, TYPE) \ - extern "C" { \ - MODULE_EXPORT bool ZNCModInfo(double dCoreVersion, CModInfo& Info); \ - bool ZNCModInfo(double dCoreVersion, CModInfo& Info) { \ - if (dCoreVersion != VERSION) return false; \ - Info.SetDescription(DESCRIPTION); \ - Info.SetDefaultType(TYPE); \ - Info.AddType(TYPE); \ - Info.SetLoader(TModLoad); \ - TModInfo(Info); \ - return true; \ - } \ +#define MODCOMMONDEFS(CLASS, DESCRIPTION, TYPE) \ + extern "C" { \ + ZNC_EXPORT_LIB_EXPORT bool ZNCModInfo(double dCoreVersion, \ + CModInfo& Info); \ + ZNC_EXPORT_LIB_EXPORT bool ZNCModInfo(double dCoreVersion, \ + CModInfo& Info) { \ + if (dCoreVersion != VERSION) return false; \ + Info.SetDescription(DESCRIPTION); \ + Info.SetDefaultType(TYPE); \ + Info.AddType(TYPE); \ + Info.SetLoader(TModLoad); \ + TModInfo(Info); \ + return true; \ + } \ } /** Instead of writing a constructor, you should call this macro. It accepts all diff --git a/include/znc/version.h b/include/znc/version.h index 468134e7..d0490162 100644 --- a/include/znc/version.h +++ b/include/znc/version.h @@ -1,13 +1,16 @@ #ifndef ZNC_VERSION_H #define ZNC_VERSION_H +#ifndef BUILD_WITH_CMAKE // The following defines are for #if comparison (preprocessor only likes ints) #define VERSION_MAJOR 1 #define VERSION_MINOR 7 #define VERSION_PATCH -1 // This one is for display purpose #define VERSION_STR "1.7.x" -// This one is for ZNCModInfo +#endif + +// This one is for ZNCModInfo #define VERSION (VERSION_MAJOR + VERSION_MINOR / 10.0) // You can add -DVERSION_EXTRA="stuff" to your CXXFLAGS! diff --git a/include/znc/zncconfig.h.cmake.in b/include/znc/zncconfig.h.cmake.in new file mode 100644 index 00000000..b1da6db8 --- /dev/null +++ b/include/znc/zncconfig.h.cmake.in @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ZNCCONFIG_H +#define ZNCCONFIG_H + +#define BUILD_WITH_CMAKE 1 + +#define VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define VERSION_PATCH @PROJECT_VERSION_PATCH@ +#define VERSION_STR "@PROJECT_VERSION@" + +#cmakedefine _GLIBCXX_DEBUG 1 +#cmakedefine _GLIBCXX_DEBUG_PEDANTIC 1 + +#define HAVE_PTHREAD 1 +#cmakedefine HAVE_THREADED_DNS 1 +#cmakedefine HAVE_LIBSSL 1 +#cmakedefine HAVE_IPV6 1 +#cmakedefine HAVE_ZLIB 1 +#cmakedefine CSOCK_USE_POLL 1 + +#cmakedefine HAVE_GETOPT_LONG 1 +#cmakedefine HAVE_LSTAT 1 +#cmakedefine HAVE_TCSETATTR 1 +#cmakedefine HAVE_GETPASSPHRASE 1 +#cmakedefine HAVE_CLOCK_GETTIME 1 + +#cmakedefine HAVE_ICU 1 +#define U_USING_ICU_NAMESPACE 1 + +#cmakedefine _LARGE_FILES 1 +#cmakedefine _LARGEFILE_SOURCE 1 +#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ + +#define _MODDIR_ "@CMAKE_INSTALL_FULL_LIBDIR@/znc" +#define _DATADIR_ "@CMAKE_INSTALL_FULL_DATADIR@/znc" + +#endif /* ZNCCONFIG_H */ diff --git a/make-tarball.sh b/make-tarball.sh index ad6f2e38..2c6fdbac 100755 --- a/make-tarball.sh +++ b/make-tarball.sh @@ -2,7 +2,8 @@ set -e TMPDIR=`mktemp -d` -trap 'rm -rf $TMPDIR' EXIT +TMPDIR2=`mktemp -d` +trap 'rm -rf $TMPDIR $TMPDIR2' EXIT if [ ! -f include/znc/main.h ] ; then echo "Can't find source!" @@ -39,23 +40,25 @@ TARGZ=`readlink -f -- $TARGZ` echo "Exporting . to $TMPDIR/$ZNCDIR..." git checkout-index --all --prefix=$TMPDIR/$ZNCDIR/ -sed -e 's:#include "Csocket.h":#include :' third_party/Csocket/Csocket.cc > $TMPDIR/$ZNCDIR/src/Csocket.cpp -sed -e 's:#include "defines.h":#include :' third_party/Csocket/Csocket.h > $TMPDIR/$ZNCDIR/include/znc/Csocket.h +mkdir -p --mode=0755 $TMPDIR/$ZNCDIR/third_party/Csocket +cp -p third_party/Csocket/Csocket.cc third_party/Csocket/Csocket.h $TMPDIR/$ZNCDIR/third_party/Csocket/ +( + cd $TMPDIR2 + cmake $TMPDIR/$ZNCDIR -DWANT_PERL=yes -DWANT_PYTHON=yes + make modperl_dist modpython_dist +) ( - which swig3.0 && SWIG=`which swig3.0` || SWIG=`which swig` cd $TMPDIR/$ZNCDIR - echo "Generating configure" AUTOMAKE_FLAGS="--add-missing --copy" ./autogen.sh rm -r autom4te.cache/ - mkdir -p modules/.depend - make -C modules -f modperl/Makefile.gen srcdir=. SWIG=$SWIG PERL=`which perl` - make -C modules -f modpython/Makefile.gen srcdir=. SWIG=$SWIG PERL=`which perl` - rm -rf modules/.depend rm .travis* .appveyor* rm make-tarball.sh sed -e "s/THIS_IS_NOT_TARBALL//" -i Makefile.in echo '#include ' > src/version.cpp echo "const char* ZNC_VERSION_EXTRA = VERSION_EXTRA \"$DESC\";" >> src/version.cpp + if [ "x$DESC" != "x" ]; then + echo $DESC > .nightly + fi ) ( cd $TMPDIR diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt new file mode 100644 index 00000000..54846a75 --- /dev/null +++ b/modules/CMakeLists.txt @@ -0,0 +1,111 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This is not recommended, but whatever. +file(GLOB all_modules LIST_DIRECTORIES FALSE "*") + +function(add_cxx_module mod modpath) + znc_add_library("module_${mod}" MODULE "${modpath}") + set_target_properties("module_${mod}" PROPERTIES + OUTPUT_NAME "${mod}" + PREFIX "" + SUFFIX ".so" + NO_SONAME true + CXX_VISIBILITY_PRESET "hidden" + COMPILE_DEFINITIONS "znc_export_lib_EXPORTS") + if(moddef_${mod}) + target_compile_definitions("module_${mod}" ${moddef_${mod}}) + endif() + if(modcompile_${mod}) + target_compile_options("module_${mod}" ${modcompile_${mod}}) + endif() + if(modinclude_${mod}) + target_include_directories("module_${mod}" ${modinclude_${mod}}) + endif() + if(moddepend_${mod}) + add_dependencies("module_${mod}" ${moddepend_${mod}}) + endif() + target_link_libraries("module_${mod}" PRIVATE ${znc_link} ${modlink_${mod}}) + set_target_properties("module_${mod}" PROPERTIES "" "" ${modprop_${mod}}) + install(TARGETS "module_${mod}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/znc") +endfunction() + +function(add_perl_module mod modpath) +endfunction() + +function(add_python_module mod modpath) +endfunction() + +if(CYRUS_FOUND) + set(modcompile_cyrusauth PRIVATE ${CYRUS_CFLAGS}) + set(modlink_cyrusauth ${CYRUS_LDFLAGS}) +else() + set(moddisable_cyrusauth true) +endif() + +if(PERLLIBS_FOUND) + add_subdirectory(modperl) +else() + set(moddisable_modperl true) +endif() + +if(PYTHONLIBS_FOUND) + add_subdirectory(modpython) +else() + set(moddisable_modpython true) +endif() + +if(TCL_FOUND) + add_subdirectory(modtcl) +else() + set(moddisable_modtcl true) +endif() + +foreach(modpath ${all_modules}) + string(REGEX MATCH "/([-a-zA-Z0-9_]+)\\.([a-z]+)$" unused "${modpath}") + set(mod "${CMAKE_MATCH_1}") + set(modtype "${CMAKE_MATCH_2}") + + set(modenabled true) + + if(moddisable_${mod}) + set(modenabled false) + endif() + + if(NOT OPENSSL_FOUND) + file(READ "${modpath}" modcontent) + string(FIND "${modcontent}" "REQUIRESSL" requiressl) + if(NOT requiressl EQUAL "-1") + set(modenabled false) + endif() + endif() + + if(modenabled) + if(modtype STREQUAL "cpp") + add_cxx_module("${mod}" "${modpath}") + endif() + if(modtype STREQUAL "pm") + add_perl_module("${mod}" "${modpath}") + endif() + if(modtype STREQUAL "py") + add_python_module("${mod}" "${modpath}") + endif() + endif() +endforeach() + +install(DIRECTORY data/ + DESTINATION "${CMAKE_INSTALL_DATADIR}/znc/modules") diff --git a/modules/modperl/CMakeLists.txt b/modules/modperl/CMakeLists.txt new file mode 100644 index 00000000..0150b694 --- /dev/null +++ b/modules/modperl/CMakeLists.txt @@ -0,0 +1,107 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set(modinclude_modperl PUBLIC ${PERL_INCLUDE_DIRS} + "${CMAKE_CURRENT_BINARY_DIR}/.." PARENT_SCOPE) +set(modcompile_modperl PUBLIC "${PERL_CFLAGS}" PARENT_SCOPE) +set(modlink_modperl PUBLIC ${PERL_LIBRARIES} PARENT_SCOPE) +set(modprop_modperl LINK_FLAGS "${PERL_LDFLAGS}" PARENT_SCOPE) +set(moddef_modperl PUBLIC "SWIG_TYPE_TABLE=znc" PARENT_SCOPE) +set(moddepend_modperl modperl_functions modperl_swigruntime PARENT_SCOPE) + +if(APPLE) + set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS + "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -undefined dynamic_lookup") +endif() + +if(SWIG_FOUND) + add_custom_command( + OUTPUT perlfunctions.cpp + COMMAND "${PERL_EXECUTABLE}" + "${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl" + "${CMAKE_CURRENT_SOURCE_DIR}/functions.in" + "perlfunctions.cpp" + VERBATIM) + + add_custom_command( + OUTPUT swigperlrun.h + COMMAND "${SWIG_EXECUTABLE}" -perl -c++ -shadow -external-runtime + "swigperlrun.h" + VERBATIM) + + add_custom_command( + OUTPUT modperl_biglib.cpp ZNC.pm + COMMAND "${SWIG_EXECUTABLE}" -perl -c++ -shadow + "-I${PROJECT_BINARY_DIR}/include" + "-I${PROJECT_SOURCE_DIR}/include" + "-I${CMAKE_CURRENT_SOURCE_DIR}/.." + -DZNC_EXPORT_LIB_EXPORT + -outdir "${CMAKE_CURRENT_BINARY_DIR}" + -o "${CMAKE_CURRENT_BINARY_DIR}/modperl_biglib.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/modperl.i" + DEPENDS "modperl.i" + VERBATIM) +else() + add_custom_command( + OUTPUT swigperlrun.h ZNC.pm modperl_biglib.cpp perlfunctions.cpp + COMMAND "${CMAKE_COMMAND}" -E tar xz + "${CMAKE_CURRENT_SOURCE_DIR}/generated.tar.gz" + VERBATIM) +endif() +add_custom_target(modperl_functions DEPENDS "perlfunctions.cpp") +add_custom_target(modperl_swigruntime DEPENDS "swigperlrun.h") + +execute_process(COMMAND "${PERL_EXECUTABLE}" + -MConfig "-eprint $Config::Config{dlext}" + OUTPUT_VARIABLE perl_ext) + +znc_add_library(modperl_lib MODULE modperl_biglib.cpp) +target_include_directories(modperl_lib PRIVATE + "${PROJECT_BINARY_DIR}/include" + "${PROJECT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/.." + "${CMAKE_CURRENT_SOURCE_DIR}/.." + ${PERL_INCLUDE_DIRS}) +target_link_libraries(modperl_lib ${znc_link}) +set_target_properties(modperl_lib PROPERTIES + PREFIX "" + SUFFIX ".${perl_ext}" + OUTPUT_NAME "ZNC" + NO_SONAME true + LINK_FLAGS "${PERL_LDFLAGS}") +target_compile_options(modperl_lib PRIVATE "${PERL_CFLAGS}") +target_compile_definitions(modperl_lib PRIVATE "SWIG_TYPE_TABLE=znc") +if(CYGWIN) + target_link_libraries(modperl_lib module_modperl) +endif() + +install(TARGETS modperl_lib + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/znc/modperl") +install(FILES "startup.pl" "${CMAKE_CURRENT_BINARY_DIR}/ZNC.pm" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/znc/modperl") + +function(add_perl_module mod modpath) + install(FILES "${modpath}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/znc") +endfunction() + +# This target is used to generate tarball which doesn't depend on SWIG. +add_custom_target(modperl_dist + COMMAND "${CMAKE_COMMAND}" -E tar cz + "${CMAKE_CURRENT_SOURCE_DIR}/generated.tar.gz" + "swigperlrun.h" "ZNC.pm" "modperl_biglib.cpp" "perlfunctions.cpp" + DEPENDS swigperlrun.h ZNC.pm modperl_biglib.cpp perlfunctions.cpp + VERBATIM) +add_dependencies(modperl_dist copy_csocket_h) diff --git a/modules/modperl/Makefile.gen b/modules/modperl/Makefile.gen index 3c6cb6e8..a99d45d6 100644 --- a/modules/modperl/Makefile.gen +++ b/modules/modperl/Makefile.gen @@ -17,18 +17,18 @@ endif .SECONDARY: -all: modperl/ZNC.cpp modperl/ZNC.pm modperl/perlfunctions.cpp modperl/swigperlrun.h +all: modperl/modperl_biglib.cpp modperl/ZNC.pm modperl/perlfunctions.cpp modperl/swigperlrun.h modperl/swigperlrun.h: @mkdir -p modperl $(Q)$(SWIG) -perl5 -c++ -shadow -external-runtime $@ -modperl/ZNC.cpp: modperl/modperl.i modperl/module.h modperl/CString.i +modperl/modperl_biglib.cpp: modperl/modperl.i modperl/module.h modperl/CString.i $(E) Generating ZNC API for Perl... @mkdir -p modperl .depend $(Q)$(SWIG) -perl5 -c++ -shadow -outdir modperl -I$(srcdir) -I$(srcdir)/../include -I../include -MD -MF .depend/modperl.swig.dep -w362,315,401,402 -o $@ $< -modperl/ZNC.pm: modperl/ZNC.cpp +modperl/ZNC.pm: modperl/modperl_biglib.cpp modperl/perlfunctions.cpp: modperl/codegen.pl modperl/functions.in @mkdir -p modperl diff --git a/modules/modperl/Makefile.inc b/modules/modperl/Makefile.inc index 489db924..2e9d92f6 100644 --- a/modules/modperl/Makefile.inc +++ b/modules/modperl/Makefile.inc @@ -27,7 +27,7 @@ PERLHOOK := modperl_install CLEAN += modperl/ZNC.$(PERLCEXT_EXT) modperl/ZNC.o modperl/gen ifneq "$(SWIG)" "" # Only delete these files if we can regenerate them -CLEAN += modperl/ZNC.pm modperl/swigperlrun.h modperl/ZNC.cpp modperl/perlfunctions.cpp +CLEAN += modperl/ZNC.pm modperl/swigperlrun.h modperl/modperl_biglib.cpp modperl/perlfunctions.cpp endif all: modperl_all @@ -46,7 +46,7 @@ modperl/ZNC.$(PERLCEXT_EXT): modperl/ZNC.o Makefile modperl.so $(E) Linking ZNC Perl bindings library... $(Q)$(CXX) $(MODFLAGS) $(LDFLAGS) $(MODLINK) -o $@ $< $(PERL_LD) $(PERLDEPONMOD) $(LIBS) -modperl/ZNC.o: modperl/ZNC.cpp Makefile +modperl/ZNC.o: modperl/modperl_biglib.cpp Makefile @mkdir -p modperl @mkdir -p .depend $(E) Building ZNC Perl bindings library... @@ -54,6 +54,12 @@ modperl/ZNC.o: modperl/ZNC.cpp Makefile ifneq "$(SWIG)" "" include $(srcdir)/modperl/Makefile.gen +else +modperl/swigperlrun.h modperl/ZNC.pm modperl/perlfunctions.cpp: modperl/modperl_biglib.cpp +modperl/modperl_biglib.cpp: modperl/generated.tar.gz + @mkdir -p modperl + $(E) Unpacking ZNC Perl bindings... + $(Q)tar -xf $^ -C modperl endif modperl.o: modperl/perlfunctions.cpp modperl/swigperlrun.h diff --git a/modules/modperl/module.h b/modules/modperl/module.h index a35ad9fd..4f8be0be 100644 --- a/modules/modperl/module.h +++ b/modules/modperl/module.h @@ -22,10 +22,7 @@ #include -#if HAVE_VISIBILITY -#pragma GCC visibility push(default) -#endif -class CPerlModule : public CModule { +class ZNC_EXPORT_LIB_EXPORT CPerlModule : public CModule { SV* m_perlObj; VWebSubPages* _GetSubPages(); @@ -167,7 +164,7 @@ enum ELoadPerlMod { Perl_LoadError, }; -class CPerlTimer : public CTimer { +class ZNC_EXPORT_LIB_EXPORT CPerlTimer : public CTimer { SV* m_perlObj; public: @@ -190,7 +187,7 @@ inline CPerlTimer* CreatePerlTimer(CPerlModule* pModule, unsigned int uInterval, perlObj); } -class CPerlSocket : public CSocket { +class ZNC_EXPORT_LIB_EXPORT CPerlSocket : public CSocket { SV* m_perlObj; public: @@ -241,6 +238,3 @@ inline int GetVersionMinor() { return VERSION_MINOR; } inline double GetVersion() { return VERSION; } inline CString GetVersionExtra() { return ZNC_VERSION_EXTRA; } -#if HAVE_VISIBILITY -#pragma GCC visibility pop -#endif diff --git a/modules/modpython/CMakeLists.txt b/modules/modpython/CMakeLists.txt new file mode 100644 index 00000000..7901ec20 --- /dev/null +++ b/modules/modpython/CMakeLists.txt @@ -0,0 +1,97 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set(modinclude_modpython PUBLIC ${PYTHON_INCLUDE_DIRS} + "${CMAKE_CURRENT_BINARY_DIR}/.." PARENT_SCOPE) +set(modlink_modpython PUBLIC ${PYTHON_LIBRARIES} PARENT_SCOPE) +set(moddef_modpython PUBLIC "SWIG_TYPE_TABLE=znc" PARENT_SCOPE) +set(moddepend_modpython modpython_functions modpython_swigruntime PARENT_SCOPE) + +if(APPLE) + set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS + "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -undefined dynamic_lookup") +endif() + +if(SWIG_FOUND) + add_custom_command( + OUTPUT "pyfunctions.cpp" + COMMAND "${PERL_EXECUTABLE}" + "${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl" + "${CMAKE_CURRENT_SOURCE_DIR}/functions.in" + "pyfunctions.cpp") + + add_custom_command( + OUTPUT "swigpyrun.h" + COMMAND "${SWIG_EXECUTABLE}" -python -py3 -c++ -shadow -external-runtime + "swigpyrun.h" + VERBATIM) + + add_custom_command( + OUTPUT "modpython_biglib.cpp" "znc_core.py" + COMMAND "${SWIG_EXECUTABLE}" -python -py3 -c++ -shadow + "-I${PROJECT_BINARY_DIR}/include" + "-I${PROJECT_SOURCE_DIR}/include" + "-I${CMAKE_CURRENT_SOURCE_DIR}/.." + -DZNC_EXPORT_LIB_EXPORT + -outdir "${CMAKE_CURRENT_BINARY_DIR}" + -o "${CMAKE_CURRENT_BINARY_DIR}/modpython_biglib.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/modpython.i" + DEPENDS "modpython.i" + VERBATIM) +else() + add_custom_command( + OUTPUT swigpyrun.h znc_core.py modpython_biglib.cpp pyfunctions.cpp + COMMAND "${CMAKE_COMMAND}" -E tar xz + "${CMAKE_CURRENT_SOURCE_DIR}/generated.tar.gz" + VERBATIM) +endif() +add_custom_target(modpython_functions DEPENDS "pyfunctions.cpp") +add_custom_target(modpython_swigruntime DEPENDS "swigpyrun.h") + +znc_add_library(modpython_lib MODULE modpython_biglib.cpp) +target_include_directories(modpython_lib PRIVATE + "${PROJECT_BINARY_DIR}/include" + "${PROJECT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/.." + "${CMAKE_CURRENT_SOURCE_DIR}/.." + ${PYTHON_INCLUDE_DIRS}) +target_link_libraries(modpython_lib ${znc_link} ${PYTHON_LIBRARIES}) +set_target_properties(modpython_lib PROPERTIES + PREFIX "_" + OUTPUT_NAME "znc_core" + NO_SONAME true) +target_compile_definitions(modpython_lib PRIVATE "SWIG_TYPE_TABLE=znc") +if(CYGWIN) + target_link_libraries(modpython_lib module_modpython) +endif() + +install(TARGETS modpython_lib + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/znc/modpython") +install(FILES "znc.py" "${CMAKE_CURRENT_BINARY_DIR}/znc_core.py" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/znc/modpython") + +function(add_python_module mod modpath) + install(FILES "${modpath}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/znc") +endfunction() + +# This target is used to generate tarball which doesn't depend on SWIG. +add_custom_target(modpython_dist + COMMAND "${CMAKE_COMMAND}" -E tar cz + "${CMAKE_CURRENT_SOURCE_DIR}/generated.tar.gz" + "swigpyrun.h" "znc_core.py" "modpython_biglib.cpp" "pyfunctions.cpp" + DEPENDS swigpyrun.h znc_core.py modpython_biglib.cpp pyfunctions.cpp + VERBATIM) +add_dependencies(modpython_dist copy_csocket_h) diff --git a/modules/modpython/Makefile.gen b/modules/modpython/Makefile.gen index 331ff029..5c39b6cc 100644 --- a/modules/modpython/Makefile.gen +++ b/modules/modpython/Makefile.gen @@ -17,18 +17,18 @@ endif .SECONDARY: -all: modpython/_znc_core.cpp modpython/znc_core.py modpython/pyfunctions.cpp modpython/swigpyrun.h +all: modpython/modpython_biglib.cpp modpython/znc_core.py modpython/pyfunctions.cpp modpython/swigpyrun.h modpython/swigpyrun.h: @mkdir -p modpython $(Q)$(SWIG) -python -py3 -c++ -shadow -external-runtime $@ -modpython/_znc_core.cpp: modpython/modpython.i modpython/module.h modpython/cstring.i +modpython/modpython_biglib.cpp: modpython/modpython.i modpython/module.h modpython/cstring.i $(E) Generating ZNC API for python... @mkdir -p modpython .depend $(Q)$(SWIG) -python -py3 -c++ -shadow -outdir modpython -I$(srcdir) -I$(srcdir)/../include -I../include -MD -MF .depend/modpython.swig.dep -w362,315,401 -o $@ $< -modpython/znc_core.py: modpython/_znc_core.cpp +modpython/znc_core.py: modpython/modpython_biglib.cpp modpython/pyfunctions.cpp: modpython/codegen.pl modpython/functions.in @mkdir -p modpython diff --git a/modules/modpython/Makefile.inc b/modules/modpython/Makefile.inc index 6aa9e79e..9ecb622b 100644 --- a/modules/modpython/Makefile.inc +++ b/modules/modpython/Makefile.inc @@ -23,7 +23,7 @@ CLEAN += modpython/_znc_core.$(PYCEXT_EXT) CLEAN += modpython/_znc_core.o modpython/compiler.o ifneq "$(SWIG)" "" # Only delete these files if we can regenerate them -CLEAN += modpython/_znc_core.cpp modpython/znc_core.py +CLEAN += modpython/modpython_biglib.cpp modpython/znc_core.py CLEAN += modpython/swigpyrun.h modpython/pyfunctions.cpp endif ifneq "$(srcdir)" "." @@ -44,7 +44,7 @@ all: modpython_all endif modpython_all: modpython/_znc_core.$(PYCEXT_EXT) -modpython/_znc_core.o: modpython/_znc_core.cpp Makefile +modpython/_znc_core.o: modpython/modpython_biglib.cpp Makefile @mkdir -p modpython @mkdir -p .depend $(E) Building ZNC python bindings library... @@ -56,6 +56,12 @@ modpython/_znc_core.$(PYCEXT_EXT): modpython/_znc_core.o Makefile modpython.so ifneq "$(SWIG)" "" include $(srcdir)/modpython/Makefile.gen +else +modpython/swigpyrun.h modpython/znc_core.py modpython/pyfunctions.cpp: modpython/modpython_biglib.cpp +modpython/modpython_biglib.cpp: modpython/generated.tar.gz + @mkdir -p modpython + $(E) Unpacking ZNC python bindings... + $(Q)tar -xf $^ -C modpython endif modpython.o: modpython/pyfunctions.cpp modpython/swigpyrun.h diff --git a/modules/modpython/module.h b/modules/modpython/module.h index fe70c630..5c1acb43 100644 --- a/modules/modpython/module.h +++ b/modules/modpython/module.h @@ -27,10 +27,7 @@ class String { class CModPython; -#if HAVE_VISIBILITY -#pragma GCC visibility push(default) -#endif -class CPyModule : public CModule { +class ZNC_EXPORT_LIB_EXPORT CPyModule : public CModule { PyObject* m_pyObj; CModPython* m_pModPython; VWebSubPages* _GetSubPages(); @@ -216,7 +213,7 @@ inline CPyModule* CreatePyModule(CUser* pUser, CIRCNetwork* pNetwork, pModPython); } -class CPyTimer : public CTimer { +class ZNC_EXPORT_LIB_EXPORT CPyTimer : public CTimer { PyObject* m_pyObj; CModPython* m_pModPython; @@ -246,7 +243,7 @@ inline CPyTimer* CreatePyTimer(CPyModule* pModule, unsigned int uInterval, pyObj); } -class CPySocket : public CSocket { +class ZNC_EXPORT_LIB_EXPORT CPySocket : public CSocket { PyObject* m_pyObj; CModPython* m_pModPython; @@ -332,7 +329,3 @@ class CModulesIter { CModules* m_pModules; CModules::const_iterator m_it; }; - -#if HAVE_VISIBILITY -#pragma GCC visibility pop -#endif diff --git a/modules/modtcl/CMakeLists.txt b/modules/modtcl/CMakeLists.txt new file mode 100644 index 00000000..b86459d7 --- /dev/null +++ b/modules/modtcl/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set(modinclude_modtcl PRIVATE ${TCL_INCLUDE_PATH} PARENT_SCOPE) +set(modlink_modtcl PRIVATE ${TCL_LIBRARY} PARENT_SCOPE) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..816b28c2 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,100 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +znc_add_library(znclib ${lib_type} "ZNCString.cpp" "znc.cpp" "IRCNetwork.cpp" + "IRCSock.cpp" "Client.cpp" "Chan.cpp" "Nick.cpp" "Server.cpp" + "Modules.cpp" "MD5.cpp" "Buffer.cpp" "Utils.cpp" "FileUtils.cpp" + "HTTPSock.cpp" "Template.cpp" "ClientCommand.cpp" "Socket.cpp" + "SHA256.cpp" "WebModules.cpp" "Listener.cpp" "Config.cpp" "ZNCDebug.cpp" + "Threads.cpp" "Query.cpp" "SSLVerifyHost.cpp" "Message.cpp" "Csocket.cpp" + "versionc.cpp" "User.cpp") +znc_add_executable(znc "main.cpp") +target_link_libraries(znc PRIVATE znclib) + +copy_csocket(copy_csocket_cc + "${PROJECT_SOURCE_DIR}/third_party/Csocket/Csocket.cc" + "${CMAKE_CURRENT_BINARY_DIR}/Csocket.cpp") + +# make-tarball.sh can create this file, it'll contain -nightly-20151221-71eaf94 +if(EXISTS "${PROJECT_SOURCE_DIR}/.nightly") + file(READ "${PROJECT_SOURCE_DIR}/.nightly" nightly) + string(STRIP "${nightly}" nightly) +else() + set(nightly "") +endif() + +add_custom_target(version + COMMAND "${CMAKE_COMMAND}" + -D "nightly=${nightly}" + -D "alpha_version=${alpha_version}" + -D "append_git_version=${append_git_version}" + -D "gitcmd=${GIT_EXECUTABLE}" + -D "srcdir=${PROJECT_SOURCE_DIR}" + -D "srcfile=${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in" + -D "destfile=${CMAKE_CURRENT_BINARY_DIR}/versionc.cpp" + -P "${PROJECT_SOURCE_DIR}/cmake/gen_version.cmake" + # This is versionc to avoid possible conflict with version.cpp generated + # by make-tarball.sh + BYPRODUCTS "versionc.cpp" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + VERBATIM) + +add_dependencies(znclib copy_csocket_h copy_csocket_cc version) + +set(znc_include_dirs + "$" + "$" + "$") +target_link_libraries(znclib ${CMAKE_DL_LIBS} Threads::Threads) +if(OPENSSL_FOUND) + target_link_libraries(znclib ${OPENSSL_LIBRARIES}) + list(APPEND znc_include_dirs "${OPENSSL_INCLUDE_DIR}") +endif() +if(ZLIB_FOUND) + target_link_libraries(znclib ${ZLIB_LIBRARIES}) + list(APPEND znc_include_dirs ${ZLIB_INCLUDE_DIRS}) +endif() +if(ICU_FOUND) + target_link_libraries(znclib ${ICU_LDFLAGS}) + list(APPEND znc_include_dirs ${ICU_INCLUDE_DIRS}) +endif() +target_include_directories(znc PUBLIC ${znc_include_dirs}) +target_include_directories(znclib PUBLIC ${znc_include_dirs}) + +set_target_properties(znclib ${znc_link} PROPERTIES + COMPILE_OPTIONS "-include;znc/zncconfig.h" + INTERFACE_COMPILE_OPTIONS "-include;znc/zncconfig.h" + POSITION_INDEPENDENT_CODE true + INTERFACE_POSITION_INDEPENDENT_CODE true + # This option is relevant only on non-cygwin + ENABLE_EXPORTS true) +# The following options are relevant only on cygwin +set_target_properties(znclib PROPERTIES + OUTPUT_NAME "znc" + SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") + + + + +install(TARGETS znc ${install_lib} + EXPORT znc + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + # this one is libznc.dll.a for cygwin + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") +install(EXPORT znc + DESTINATION "${CMAKE_INSTALL_DATADIR}/znc/cmake" + NAMESPACE znc_internal_) diff --git a/src/version.cpp.in b/src/version.cpp.in new file mode 100644 index 00000000..f2408787 --- /dev/null +++ b/src/version.cpp.in @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +const char* ZNC_VERSION_EXTRA = VERSION_EXTRA "@alpha_version@" "@git_info@"; diff --git a/src/znc.cpp b/src/znc.cpp index 4a181a2a..d8264a7d 100644 --- a/src/znc.cpp +++ b/src/znc.cpp @@ -159,6 +159,12 @@ CString CZNC::GetCompileOptionsString() { "yes" #else "no" +#endif + ", build: " +#ifdef BUILD_WITH_CMAKE + "cmake" +#else + "autoconf" #endif ; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..6e3d59f4 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,97 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# No CTest here, and no "make test" either: +# http://public.kitware.com/Bug/view.php?id=8438 +# http://public.kitware.com/Bug/view.php?id=8774 + +include(ExternalProject) +include(FindPackageMessage) + +# There is FindGTest.cmake, but it doesn't find gmock +#message(STATUS "Looking for GTest/GMock") +find_path(GTEST_ROOT src/gtest-all.cc + HINTS ENV GTEST_ROOT + PATHS "${PROJECT_SOURCE_DIR}/third_party/googletest/googletest") +find_path(GMOCK_ROOT src/gmock-all.cc + HINTS ENV GMOCK_ROOT + PATHS "${PROJECT_SOURCE_DIR}/third_party/googletest/googlemock") + +set(gtest_error_msg "not found, testing will be disabled.") +set(gtest_error_msg "${gtest_error_msg} You can set environment variables") +set(gtest_error_msg "${gtest_error_msg} GTEST_ROOT and GMOCK_ROOT") +if(GTEST_ROOT) + find_package_message(gtest "Found GoogleTest: ${GTEST_ROOT}" + "${GTEST_ROOT}") +else() + find_package_message(gtest "GoogleTest ${gtest_error_msg}" "${GTEST_ROOT}") + return() +endif() +if(GMOCK_ROOT) + find_package_message(gmock "Found GoogleMock: ${GMOCK_ROOT}" + "${GMOCK_ROOT}") +else() + find_package_message(gmock "GoogleMock ${gtest_error_msg}" "${GMOCK_ROOT}") + return() +endif() + +# Force the simple internal regex engine to get consistent behavior on all +# platforms. See +# https://code.google.com/p/chromium/issues/detail?id=317224 for more details. +set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS + "GTEST_HAS_POSIX_RE=0") + +add_executable(unittest_bin EXCLUDE_FROM_ALL + "${GMOCK_ROOT}/src/gmock_main.cc" + "${GTEST_ROOT}/src/gtest-all.cc" + "${GMOCK_ROOT}/src/gmock-all.cc" + "ThreadTest.cpp" "NickTest.cpp" "ClientTest.cpp" "NetworkTest.cpp" + "MessageTest.cpp" "ModulesTest.cpp" "IRCSockTest.cpp" "QueryTest.cpp" + "StringTest.cpp" "ConfigTest.cpp" "BufferTest.cpp" "UtilsTest.cpp") +target_link_libraries(unittest_bin PRIVATE znclib) +target_include_directories(unittest_bin PRIVATE + "${GTEST_ROOT}" "${GTEST_ROOT}/include" + "${GMOCK_ROOT}" "${GMOCK_ROOT}/include") +add_custom_target(unittest COMMAND unittest_bin) + +find_package(Qt5Network 5.4 QUIET HINTS ${brew_qt5}) +if(Qt5Network_FOUND) + find_package_message(qt "Found Qt ${Qt5Network_VERSION}" + "1;${Qt5Network_VERSION}") + # Use different compiler flags, because Qt fails with sanitizers, + # and we don't need sanitizers to test the test itself anyway. + externalproject_add(inttest_bin + EXCLUDE_FROM_ALL true + BUILD_ALWAYS true + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/integration" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/integration" + INSTALL_COMMAND "" + CMAKE_CACHE_ARGS + # Note the space in the end: protect from CXXFLAGS env var, but + # still support custom flags + "-DCMAKE_CXX_FLAGS:string=${INTEGRATION_TEST_CXX_FLAGS} " + "-DGTEST_ROOT:path=${GTEST_ROOT}" + "-DGMOCK_ROOT:path=${GMOCK_ROOT}" + "-DZNC_BIN_DIR:path=${CMAKE_INSTALL_FULL_BINDIR}" + "-DZNC_SRC_DIR:path=${PROJECT_SOURCE_DIR}" + "-DQt5_HINTS:path=${brew_qt5}") + add_custom_target(inttest COMMAND + "${CMAKE_CURRENT_BINARY_DIR}/integration/inttest") + add_dependencies(inttest inttest_bin) +else() + find_package_message(qt + "Qt >= 5.4 not found, integration testing will be disabled" "0") +endif() diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt new file mode 100644 index 00000000..06bb694c --- /dev/null +++ b/test/integration/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cmake_minimum_required(VERSION 3.0) +project(ZNCIntegrationTest) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED true) + +set(CMAKE_THREAD_PREFER_PTHREAD true) +set(THREADS_PREFER_PTHREAD_FLAG true) +find_package(Threads REQUIRED) + +find_package(Qt5Network 5.4 HINTS ${Qt5_HINTS}) + +# Force the simple internal regex engine to get consistent behavior on all +# platforms. See +# https://code.google.com/p/chromium/issues/detail?id=317224 for more details. +set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS + "GTEST_HAS_POSIX_RE=0") + +add_executable(inttest "main.cpp" + "${GMOCK_ROOT}/src/gmock_main.cc" + "${GTEST_ROOT}/src/gtest-all.cc" + "${GMOCK_ROOT}/src/gmock-all.cc") + +target_link_libraries(inttest Qt5::Network Threads::Threads) +target_include_directories(inttest PUBLIC + "${GTEST_ROOT}" "${GTEST_ROOT}/include" + "${GMOCK_ROOT}" "${GMOCK_ROOT}/include") +target_compile_definitions(inttest PRIVATE + "ZNC_BIN_DIR=\"${ZNC_BIN_DIR}\"" + "ZNC_SRC_DIR=\"${ZNC_SRC_DIR}\"") diff --git a/test/Integration.cpp b/test/integration/main.cpp similarity index 100% rename from test/Integration.cpp rename to test/integration/main.cpp diff --git a/znc-buildmod.cmake.in b/znc-buildmod.cmake.in new file mode 100755 index 00000000..3dfaeb7e --- /dev/null +++ b/znc-buildmod.cmake.in @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +import argparse +import glob +import os +import shutil +import subprocess +import tempfile + +parser = argparse.ArgumentParser( + description='Build external ZNC modules and place the results to ' + 'current directory. Several modules can be built at once.', + epilog='Adjustable environment variables: CXXFLAGS, LDFLAGS, LIBS') +parser.add_argument('-v', '--verbose', action='count', default=0, + help='use -vvv for more verbosity') +parser.add_argument('files', nargs='+', metavar='file.cpp', + help="path to the module's source file") +args = parser.parse_args() + +with tempfile.TemporaryDirectory() as cmdir: + with open(os.path.join(cmdir, 'CMakeLists.txt'), 'w') as cm: + print('cmake_minimum_required(VERSION 3.0)', file=cm) + print('project(ExternalModules)', file=cm) + print('find_package(ZNC @ZNC_VERSION_MAJOR@.@ZNC_VERSION_MINOR@ PATHS ' + '@CMAKE_INSTALL_FULL_DATADIR@/znc)', file=cm) + if args.verbose > 0: + print('set(CMAKE_VERBOSE_MAKEFILE true)', file=cm) + + for mod_cpp in args.files: + mod, _ = os.path.splitext(os.path.basename(mod_cpp)) + print(file=cm) + print('add_library(module_{} MODULE {})'.format( + mod, os.path.abspath(mod_cpp)), file=cm) + print('znc_setup_module(TARGET module_{} NAME {})'.format(mod, mod), + file=cm) + print('target_link_libraries(module_{} PRIVATE {})'.format( + mod, os.environ.get('LIBS', '')), file=cm) + + if args.verbose > 0: + with open(os.path.join(cmdir, 'CMakeLists.txt')) as cm: + print(cm.read()) + + with tempfile.TemporaryDirectory() as build: + command = ['cmake', '-G@CMAKE_GENERATOR@', + '-DCMAKE_C_COMPILER=@CMAKE_C_COMPILER@', + '-DCMAKE_CXX_COMPILER=@CMAKE_CXX_COMPILER@', + '-DCMAKE_CXX_FLAGS={} @CMAKE_CXX_FLAGS@'.format( + os.environ.get('CXXFLAGS', '')), + '-DCMAKE_MODULE_LINKER_FLAGS={} @CMAKE_MODULE_LINKER_FLAGS@'.format( + os.environ.get('LDFLAGS', '')), + cmdir] + if args.verbose > 1: + cmd.append('--debug-output') + if args.verbose > 2: + cmd.append('--trace') + if args.verbose > 0: + print(command) + subprocess.check_call(command, cwd=build) + subprocess.check_call(['cmake', '--build', '.'], cwd=build) + + for so in glob.iglob(os.path.join(build, '*.so')): + shutil.copy(so, os.getcwd()) diff --git a/znc.pc.cmake.in b/znc.pc.cmake.in new file mode 100644 index 00000000..50c01b7b --- /dev/null +++ b/znc.pc.cmake.in @@ -0,0 +1,20 @@ +# You can access these with e.g. pkg-config --variable=moddir znc +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +datarootdir=${prefix}/@CMAKE_INSTALL_DATAROOTDIR@ +bindir=${exec_prefix}/@CMAKE_INSTALL_BINDIR@ +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +datadir=${prefix}/@CMAKE_INSTALL_DATADIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +cxx=@CMAKE_CXX_COMPILER@ +version=@ZNC_VERSION@ +moddir=${libdir}/znc +moddatadir=${datadir}/znc + +Name: ZNC +Description: An advanced IRC proxy +Version: ${version} +URL: http://znc.in +Cflags: @CMAKE_CXX_FLAGS@ -I@CMAKE_INSTALL_FULL_INCLUDEDIR@ -include znc/zncconfig.h -Dznc_export_lib_EXPORTS +Libs: @znclib_pc@ diff --git a/znc.service.in b/znc.service.in index 2a9d3b06..a6c9e68d 100644 --- a/znc.service.in +++ b/znc.service.in @@ -3,7 +3,7 @@ Description=ZNC, an advanced IRC bouncer After=network.target [Service] -ExecStart=@bindir@/znc -f +ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/znc -f User=znc [Install] diff --git a/zz_msg/CMakeLists.txt b/zz_msg/CMakeLists.txt new file mode 100644 index 00000000..46618d70 --- /dev/null +++ b/zz_msg/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# Copyright (C) 2004-2016 ZNC, see the NOTICE file for details. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This is implementation detail of CMake, but this install() runs last. +# Details are at https://cmake.org/pipermail/cmake/2011-July/045615.html + +install(CODE "message(\" +****************************************************************** + ZNC was successfully installed. + You can use '${CMAKE_INSTALL_FULL_BINDIR}/znc --makeconf' + to generate a config file. + + If you need help with using ZNC, please visit our wiki at: + http://znc.in\")") +