From 52a134673dd252818138206fb64dbc9a1d3ae93e Mon Sep 17 00:00:00 2001 From: Unmanned Player <36690541+unmanned-player@users.noreply.github.com> Date: Sat, 8 Aug 2020 16:05:52 +1000 Subject: [PATCH] Rudimentary support for CMake This patch adds CMake build support for various target environments and compilers. The CMake builds and compiles all demo code against SDL-1.2, SDL-2.0 X11, Wincon and DOS. It works with GNU, OpenWatcom and MSVC compilers. FindSDL2.cmake was added as I don't know how to use find_package() in CONFIG mode. While I've heard of people using PDCurses on Apple computers, I do not own one to verify if it works. --- CMake.md | 83 +++++++++++++ CMakeLists.txt | 280 +++++++++++++++++++++++++++++++++++++++++++ cmake/FindSDL2.cmake | 173 ++++++++++++++++++++++++++ 3 files changed, 536 insertions(+) create mode 100644 CMake.md create mode 100644 CMakeLists.txt create mode 100644 cmake/FindSDL2.cmake diff --git a/CMake.md b/CMake.md new file mode 100644 index 000000000..31ee1b52a --- /dev/null +++ b/CMake.md @@ -0,0 +1,83 @@ +# CMake based build support + +This is for more modern host environments which can run CMake. If you have very old operating systems that can't run +CMake, you are better off running the Makefile based builds. The builds have been tested for following targets: + +| Compiler | SDL-1.2 | SDL-2.x | X11 | wincon | DOS | +| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | +| DGJPP | - | - | - | - | Y | +| OpenWatcom | - | - | - | Y | Y | +| MinGW | Y | Y | Y | Y | - | +| GNU (Unix) | Y | Y | Y | Y | - | +| MSVC | Y | Y | - | Y | - | + +Potentially, LLVM/clang should also work, but it's not tested yet. For Unix, the host environment was Linux when tested +on. But it could work well on Apple or other well-known POSIX hosts. + +## Variables of interest + +The CMake build accepts some interesting variables to change the back-end on which curses will work with. All variables +show here are boolean. So it's either TRUE/FALSE or ON/OFF. + +| Variable | Description | +| ------------------------- | ---------------------------------------------------------- | +| `BUILD_EXAMPLES` | Compile all demo code | +| `BUILD_TESTS` | Some platforms like SDL have test support. Compile it too. | +| `ENABLE_WIDECHAR_SUPPORT` | Enable wide-character support into curses | +| `FORCE_UTF8` | Force UTF-8 by ignoring system locale. | + +To force select platforms in some cases: + +| Variable | OS Availability | +| -------------- | ---------------- | +| `USE_SDL1` | Unix, Win32 | +| `USE_SDL2` | Unix, Win32 | +| `USE_WINCON` | Win32 | +| `USE_X11` | Unix | +| `USE_DOS` | DOS | + + +## How to + +Ensure you have CMake and necessary libraries pre-installed. Look up your OS package manager for the right dependencies. +Now, on the shell, enter the directory where PDCurses is checked-out or extracted and run: + +### Linux + + $ cmake -H. -Bbuild -DUSE_X11=On -DBUILD_EXAMPLES=On + ... + $ cmake -Bbuild --build + +In the `build` directory, you can find all example. For example, + + $ ./build/rain + +### Windows + + D:\projects\PDCurses> cmake -H. -Bbuild -DUSE_WINCON=On -DBUILD_EXAMPLES=On + ... + D:\projects\PDCurses> cmake -Bbuild --build + +And then, call (for example): + + D:\projects\PDCurses> build\rain.exe + +### DOS + +For DOS, however build a DJGPP compiler for Linux host, or download OpenWatcom for Linux/Windows hosts. The invoke CMake +as: + + $ cmake -H. -Bbuild \ + -DCMAKE_SYSTEM_NAME=DOS \ + -DCMAKE_C_COMPILER=/opt/cross/watcom/binl/wcl386 \ + -DUSE_DOS=On \ + -DBUILD_EXAMPLES=On + +CMake will complain about unknown Platform because `CMAKE_SYSTEM_NAME` is set to one that it doesn't recognise yet, but +won't stop it from building. This applies to DJGPP too. + +## Testing + +This is a rudimentary CMake script. While it works well generating binaries for DOS, Windows and Linux, it hasn't been +tested for certain compiler+target OS combinations. Several reasons affect testability including the availability of +CMake on certain hosts, it's ability to recognise certain compilers, etc. \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..10b6bca1b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,280 @@ +cmake_minimum_required(VERSION 2.8) + +project(PDCurses C) + +include(CheckIncludeFile) +include(CheckSymbolExists) +include(CheckCSourceCompiles) +include(GNUInstallDirs) + +# Basic switches +option(BUILD_EXAMPLES "Build some demo examples" OFF) +option(BUILD_TESTS "Build tests if any for the chosen platform." OFF) +# Common features. +option(ENABLE_WIDECHAR_SUPPORT "Enable wide-char support" OFF) +option(FORCE_UTF8 "Force UTF-8 by ignoring system locale." OFF) + +# Do some compiler fiddling. +set(CMAKE_POSITION_INDEPENDENT_CODE On) + +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "clang") + set(CMAKE_C_FLAGS_DEBUG "-D_DEBUG -DPDCDEBUG -DPANEL_DEBUG -O0 -ggdb -g3") + set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 -s") + set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os -s") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-D_DEBUG -DPDCDEBUG -DPANEL_DEBUG -g3 -O3") +elseif (${CMAKE_C_COMPILER_ID} STREQUAL "MSVC") + set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /DPDCDEBUG /DPANEL_DEBUG /Zi /EHsc /Oy- /Ob0") + set(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /Ox /EHc") + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE") +endif() + +if (WIN32) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + add_definitions(-D_CONSOLE) + + if (ENABLE_WIDECHAR_SUPPORT) + add_definitions(-D_UNICODE) + add_definitions(-DUNICODE) + endif() +endif() + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") + +# Back-end support. +if (UNIX OR WIN32) + set(USE_SDL1 FALSE CACHE BOOL + "Build against SDL-1.x platform") + set(USE_SDL2 FALSE CACHE BOOL + "Build against SDL-2.x platform") + set(USE_WINCON FALSE CACHE BOOL + "Build against Windows console platform") +elseif (UNIX) + set(USE_X11 FALSE CACHE BOOL + "Build against XOrg/X11 platform") +elseif (CMAKE_SYSTEM_NAME STREQUAL "DOS") + set(USE_DOS TRUE CACHE BOOL + "Build for DOS platform") +endif() + +include_directories(${CMAKE_SOURCE_DIR}) + +set(srcs_all + pdcurses/addch.c + pdcurses/addchstr.c + pdcurses/addstr.c + pdcurses/attr.c + pdcurses/beep.c + pdcurses/bkgd.c + pdcurses/border.c + pdcurses/clear.c + pdcurses/color.c + pdcurses/debug.c + pdcurses/delch.c + pdcurses/deleteln.c + pdcurses/getch.c + pdcurses/getstr.c + pdcurses/getyx.c + pdcurses/inch.c + pdcurses/inchstr.c + pdcurses/initscr.c + pdcurses/inopts.c + pdcurses/insch.c + pdcurses/insstr.c + pdcurses/instr.c + pdcurses/kernel.c + pdcurses/keyname.c + pdcurses/mouse.c + pdcurses/move.c + pdcurses/outopts.c + pdcurses/overlay.c + pdcurses/pad.c + pdcurses/panel.c + pdcurses/printw.c + pdcurses/refresh.c + pdcurses/scanw.c + pdcurses/scr_dump.c + pdcurses/scroll.c + pdcurses/slk.c + pdcurses/termattr.c + pdcurses/touch.c + pdcurses/util.c + pdcurses/window.c +) + +if (USE_X11) + find_package(X11 REQUIRED) + + set(ENABLE_WIDECHAR_SUPPORT ON) + + set(CMAKE_REQUIRED_INCLUDES ${X11_INCLUDE_DIR}/X11) + check_include_file(DECkeysym.h HAVE_DECKEYSYM_H) + check_include_file(Sunkeysym.h HAVE_SUNKEYSYM_H) + check_include_file(xpm.h HAVE_XPM_H) + check_include_file(unistd.h HAVE_UNISTD_H) + + check_symbol_exists("poll" poll.h HAVE_POLL) + check_symbol_exists("usleep" unistd.h HAVE_USLEEP) + check_symbol_exists("vsnprintf" stdio.h HAVE_VSNPRINTF) + check_symbol_exists("vsscanf" stdio.h HAVE_VSSCANF) + + check_c_source_compiles( + " + #include + + XPointer *ptr; + int main(void) {return 0;} + " + XPOINTER_TYPEDEFED + ) + + configure_file(x11/config.h.cmake.in ${CMAKE_BINARY_DIR}/config.h) + add_definitions(-DHAVE_CONFIG_H) + add_definitions(-DXCURSES) + + include_directories(${X11_INCLUDE_DIR}/X11) + include_directories(x11) + include_directories(${CMAKE_BINARY_DIR}) + + set(srcs_all + ${srcs_all} + x11/pdcclip.c + x11/pdcdisp.c + x11/pdcgetsc.c + x11/pdckbd.c + x11/pdcscrn.c + x11/pdcsetsc.c + x11/pdcutil.c + x11/sb.c + x11/scrlbox.c + ) +elseif (USE_SDL1) + find_package(SDL REQUIRED) + + include_directories(${SDL_INCLUDE_DIR}) + + set(srcs_all + ${srcs_all} + sdl1/pdcclip.c + sdl1/pdcdisp.c + sdl1/pdcgetsc.c + sdl1/pdckbd.c + sdl1/pdcscrn.c + sdl1/pdcsetsc.c + sdl1/pdcutil.c + ) +elseif (USE_SDL2) + find_package(SDL2 REQUIRED) + + include_directories(${SDL2_INCLUDE_DIR}) + + set(srcs_all + ${srcs_all} + sdl2/pdcclip.c + sdl2/pdcdisp.c + sdl2/pdcgetsc.c + sdl2/pdckbd.c + sdl2/pdcscrn.c + sdl2/pdcsetsc.c + sdl2/pdcutil.c + ) +elseif (USE_WINCON) + set(srcs_all + ${srcs_all} + wincon/pdcclip.c + wincon/pdcdisp.c + wincon/pdcgetsc.c + wincon/pdckbd.c + wincon/pdcscrn.c + wincon/pdcsetsc.c + wincon/pdcutil.c + ) +elseif (USE_DOS) + set(srcs_all + ${srcs_all} + dos/pdcclip.c + dos/pdcdisp.c + dos/pdcgetsc.c + dos/pdckbd.c + dos/pdcscrn.c + dos/pdcsetsc.c + dos/pdcutil.c + ) +endif() + +if (ENABLE_WIDECHAR_SUPPORT) + add_definitions(-DPDC_WIDE) +endif() + +if (FORCE_UTF8) + add_definitions(-DPDC_FORCE_UTF8) +endif() + +add_library(${PROJECT_NAME} ${srcs_all}) + +if (USE_X11) + target_link_libraries(${PROJECT_NAME} ${X11_Xmu_LIB}) + target_link_libraries(${PROJECT_NAME} ${X11_Xt_LIB}) + target_link_libraries(${PROJECT_NAME} ${X11_X11_LIB}) + target_link_libraries(${PROJECT_NAME} ${X11_Xpm_LIB}) + target_link_libraries(${PROJECT_NAME} ${X11_SM_LIB}) + target_link_libraries(${PROJECT_NAME} ${X11_ICE_LIB}) + target_link_libraries(${PROJECT_NAME} ${X11_Xext_LIB}) +elseif (USE_SDL1) + target_link_libraries(${PROJECT_NAME} ${SDL_LIBRARY}) +elseif (USE_SDL2) + target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARY}) +endif() + +function(gen_exe out_f srcs) + add_executable(${out_f} ${srcs}) + target_link_libraries(${out_f} ${PROJECT_NAME}) + if (USE_X11) + # -lXaw -lXmu -lXt -lX11 -lXpm -lSM -lICE -lXext + target_link_libraries(${out_f} ${X11_Xmu_LIB}) + target_link_libraries(${out_f} ${X11_Xt_LIB}) + target_link_libraries(${out_f} ${X11_X11_LIB}) + target_link_libraries(${out_f} ${X11_Xpm_LIB}) + target_link_libraries(${out_f} ${X11_SM_LIB}) + target_link_libraries(${out_f} ${X11_ICE_LIB}) + target_link_libraries(${out_f} ${X11_Xext_LIB}) + # Unfortunately, CMake's X11 as yet doesn't support Xaw in the FindX11. + # See, https://gitlab.kitware.com/cmake/cmake/-/issues/20963 + # Link directly and hope everything works fine. + target_link_libraries(${out_f} -lXaw) + endif() + if (USE_SDL1) + target_link_libraries(${out_f} ${SDL_LIBRARY}) + endif() + if (USE_SDL2) + target_link_libraries(${out_f} ${SDL2_LIBRARY}) + endif() +endfunction() + +if (BUILD_TESTS) + if (USE_SDL1) + gen_exe(sdltest sdl1/sdltest.c) + endif() + if (USE_SDL2) + gen_exe(sdltest sdl2/sdltest.c) + endif() +endif() + +if (BUILD_EXAMPLES) + include_directories(demos) + gen_exe(firework "demos/firework.c") + gen_exe(ozdemo "demos/ozdemo.c") + gen_exe(ptest "demos/ptest.c") + gen_exe(rain "demos/rain.c") + gen_exe(tui "demos/tuidemo.c;demos/tui.c") + gen_exe(testcurs "demos/testcurs.c") + gen_exe(worm "demos/worm.c") + gen_exe(xmas "demos/xmas.c") +endif() + +configure_file(FindPDCurses.cmake.in ${CMAKE_BINARY_DIR}/FindPDCurses.cmake) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(FILES curses.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(FILES panel.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake new file mode 100644 index 000000000..5631e3829 --- /dev/null +++ b/cmake/FindSDL2.cmake @@ -0,0 +1,173 @@ + +# This module defines +# SDL2_LIBRARY, the name of the library to link against +# SDL2_FOUND, if false, do not try to link to SDL2 +# SDL2_INCLUDE_DIR, where to find SDL.h +# +# This module responds to the the flag: +# SDL2_BUILDING_LIBRARY +# If this is defined, then no SDL2main will be linked in because +# only applications need main(). +# Otherwise, it is assumed you are building an application and this +# module will attempt to locate and set the the proper link flags +# as part of the returned SDL2_LIBRARY variable. +# +# Don't forget to include SDLmain.h and SDLmain.m your project for the +# OS X framework based version. (Other versions link to -lSDL2main which +# this module will try to find on your behalf.) Also for OS X, this +# module will automatically add the -framework Cocoa on your behalf. +# +# +# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration +# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library +# (SDL2.dll, libsdl2.so, SDL2.framework, etc). +# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. +# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value +# as appropriate. These values are used to generate the final SDL2_LIBRARY +# variable, but when these values are unset, SDL2_LIBRARY does not get created. +# +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# l.e.galup 9-20-02 +# +# Modified by Eric Wing. +# Added code to assist with automated building by using environmental variables +# and providing a more controlled/consistent search behavior. +# Added new modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). +# Also corrected the header search path to follow "proper" SDL guidelines. +# Added a search for SDL2main which is needed by some platforms. +# Added a search for threads which is needed by some platforms. +# Added needed compile switches for MinGW. +# +# On OSX, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# SDL2_LIBRARY to override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. +# +# Note that the header path has changed from SDL2/SDL.h to just SDL.h +# This needed to change because "proper" SDL convention +# is #include "SDL.h", not . This is done for portability +# reasons because not all systems place things in SDL2/ (see FreeBSD). + +#============================================================================= +# 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.) + +# message("") + +SET(SDL2_SEARCH_PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + ${SDL2_PATH} +) + +FIND_PATH(SDL2_INCLUDE_DIR SDL.h + HINTS + $ENV{SDL2DIR} + PATH_SUFFIXES include/SDL2 include + PATHS ${SDL2_SEARCH_PATHS} +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(PATH_SUFFIXES lib64 lib/x64 lib) +else() + set(PATH_SUFFIXES lib/x86 lib) +endif() + +FIND_LIBRARY(SDL2_LIBRARY_TEMP + NAMES SDL2 + HINTS + $ENV{SDL2DIR} + PATH_SUFFIXES ${PATH_SUFFIXES} + PATHS ${SDL2_SEARCH_PATHS} +) + +IF(NOT SDL2_BUILDING_LIBRARY) + IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL2main for compatibility even though they don't + # necessarily need it. + FIND_LIBRARY(SDL2MAIN_LIBRARY + NAMES SDL2main + HINTS + $ENV{SDL2DIR} + PATH_SUFFIXES ${PATH_SUFFIXES} + PATHS ${SDL2_SEARCH_PATHS} + ) + ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") +ENDIF(NOT SDL2_BUILDING_LIBRARY) + +# SDL2 may require threads on your system. +# The Apple build may not need an explicit flag because one of the +# frameworks may already provide it. +# But for non-OSX systems, I will use the CMake Threads package. +IF(NOT APPLE) + FIND_PACKAGE(Threads) +ENDIF(NOT APPLE) + +# MinGW needs an additional link flag, -mwindows +# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -mwindows +IF(MINGW) + SET(MINGW32_LIBRARY mingw32 "-mwindows" CACHE STRING "mwindows for MinGW") +ENDIF(MINGW) + +IF(SDL2_LIBRARY_TEMP) + # For SDL2main + IF(NOT SDL2_BUILDING_LIBRARY) + IF(SDL2MAIN_LIBRARY) + SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) + ENDIF(SDL2MAIN_LIBRARY) + ENDIF(NOT SDL2_BUILDING_LIBRARY) + + # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. + # CMake doesn't display the -framework Cocoa string in the UI even + # though it actually is there if I modify a pre-used variable. + # I think it has something to do with the CACHE STRING. + # So I use a temporary variable until the end so I can set the + # "real" variable in one-shot. + IF(APPLE) + SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") + ENDIF(APPLE) + + # For threads, as mentioned Apple doesn't need this. + # In fact, there seems to be a problem if I used the Threads package + # and try using this line, so I'm just skipping it entirely for OS X. + IF(NOT APPLE) + SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + ENDIF(NOT APPLE) + + # For MinGW library + IF(MINGW) + SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) + ENDIF(MINGW) + + # Set the final string here so the GUI reflects the final state. + SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") + # Set the temp variable to INTERNAL so it is not seen in the CMake GUI + SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") +ENDIF(SDL2_LIBRARY_TEMP) + +# message("") + +INCLUDE(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)