cmake_minimum_required(VERSION 3.10) # project specification project(nimisewi VERSION 0.3.2 DESCRIPTION "small program that generates random toki pona noun phrase" HOMEPAGE_URL "https://fsl.aaoth.xyz/nimisewi.c/home") # get compiler name and version execute_process(COMMAND ${CMAKE_C_COMPILER} "--version" OUTPUT_VARIABLE _PROJECT_C_COMPILER_VERSION) string(REGEX REPLACE "\n" ";" PROJECT_C_COMPILER_VERSION ${_PROJECT_C_COMPILER_VERSION}) list(APPEND PROJECT_C_COMPILER_STRING ${PROJECT_C_COMPILER_VERSION}) list(POP_FRONT PROJECT_C_COMPILER_STRING PROJECT_C_COMPILER_VERSION) # configuration header configure_file(config.h.in config.h) # main executable add_executable(nimisewi main.c nimisewi.c ${PROJECT_BINARY_DIR}/nimitoki.c) target_include_directories(nimisewi PUBLIC "${PROJECT_BINARY_DIR}") # supplementary executable add_executable(makenimitoki makenimitoki.c) target_include_directories(makenimitoki PUBLIC "${PROJECT_BINARY_DIR}") add_custom_command( OUTPUT ${PROJECT_BINARY_DIR}/nimitoki.c ${PROJECT_BINARY_DIR}/nimitoki.h COMMAND makenimitoki ${PROJECT_SOURCE_DIR}/nimitoki.txt DEPENDS makenimitoki) # includes include(CheckIncludeFile) include(CheckSymbolExists) include(CheckCSourceCompiles) # warning message set(WARNING_STATIC_BUILD "static build won't work here") # check libraries cmake_host_system_information(RESULT OS_NAME QUERY OS_NAME) message(VERBOSE "OS_NAME is ${OS_NAME}") if(OS_NAME MATCHES "Linux") check_include_file("bsd/string.h" HAVE_BSD_STRING_H) check_include_file("bsd/stdlib.h" HAVE_BSD_STDLIB_H) if(HAVE_BSD_STRING_H AND HAVE_BSD_STDLIB_H) set(CMAKE_REQUIRED_LIBRARIES "bsd") check_symbol_exists(strlcat "bsd/string.h" HAVE_STRLCAT) if (HAVE_STRLCAT) list(APPEND EXTRA_DEFINITIONS HAVE_BSD_STRING_H HAVE_STRLCAT) endif() # HAVE_STRLCAT check_symbol_exists(arc4random_uniform "bsd/stdlib.h" HAVE_ARC4RANDOM_UNIFORM) if (HAVE_ARC4RANDOM_UNIFORM) list(APPEND EXTRA_DEFINITIONS HAVE_BSD_STDLIB_H HAVE_ARC4RANDOM_UNIFORM) endif() # HAVE_ARC4RANDOM_UNIFORM # check static libraries set(CMAKE_REQUIRED_LINK_OPTIONS "-static") check_c_source_compiles( "#include\nint main(void){return 0;}" HAVE_LIBBSD_STATIC) if(NOT ANDROID) # libpthread and libmd are needed when linking statically on linux. # these test aren't really checking particular functions, but # they are here to make sure that program could be linked statically unset(CMAKE_REQUIRED_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES "pthread") check_c_source_compiles( "#include\nint main(void){return 0;}" HAVE_LIBPTHREAD_STATIC) unset(CMAKE_REQUIRED_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES "md") check_c_source_compiles( "#include\nint main(void){return 0;}" HAVE_LIBMD_STATIC) if(NOT (HAVE_LIBBSD_STATIC AND HAVE_LIBPTHREAD_STATIC AND HAVE_LIBMD_STATIC)) message(WARNING ${WARNING_STATIC_BUILD}) endif() # NOT (HAVE_LIBBSD_STATIC AND ...) list(APPEND EXTRA_LIBS bsd pthread md) else() # NOT ANDROID if(NOT (HAVE_LIBBSD_STATIC)) message(WARNING ${WARNING_STATIC_BUILD}) endif() list(APPEND EXTRA_LIBS bsd) endif() # NOT ANDROID unset(CMAKE_REQUIRED_LIBRARIES) unset(CMAKE_REQUIRED_LINK_OPTIONS) endif() # HAVE_BSD_STRING_H AND HAVE_BSD_STDLIB_H endif() # OS_NAME MATCHES "Linux" if(OS_NAME MATCHES "(.*BSD)|(DragonFly)") check_symbol_exists(strlcat "string.h" HAVE_STRLCAT) if(HAVE_STRLCAT) list(APPEND EXTRA_DEFINITIONS HAVE_STRLCAT) endif() # HAVE_STRLCAT check_symbol_exists(arc4random_uniform "stdlib.h" HAVE_ARC4RANDOM_UNIFORM) if(HAVE_ARC4RANDOM_UNIFORM) list(APPEND EXTRA_DEFINITIONS HAVE_ARC4RANDOM_UNIFORM) endif() # HAVE_ARC4RANDOM_UNIFORM check_symbol_exists(pledge "unistd.h" HAVE_PLEDGE) if(HAVE_PLEDGE) list(APPEND EXTRA_DEFINITIONS HAVE_PLEDGE) endif() # HAVE_PLEDGE endif() # OS_NAME MATCHES "(.*BSD)|(DragonFly)" set(CMAKE_REQUIRED_LINK_OPTIONS "-static") check_c_source_compiles( "#include\nint main(void){return 0;}" HAVE_LIBC_STATIC ) if(NOT HAVE_LIBC_STATIC) message(WARNING ${WARNING_STATIC_BUILD}) endif() # NOT HAVE_LIBC_STATIC target_link_libraries(nimisewi PUBLIC ${EXTRA_LIBS}) target_compile_definitions(nimisewi PRIVATE ${EXTRA_DEFINITIONS}) set(NIMISEWI_CGI_STATIC_BUILD FALSE) if(HAVE_LIBC_STATIC) if(HAVE_BSD_STRING_H AND HAVE_BSD_STDLIB_H) if(HAVE_LIBBSD_STATIC) set(NIMISEWI_CGI_STATIC_BUILD TRUE) endif() # HAVE_LIBBSD_STATIC else() # HAVE_BSD_STRING_H AND ... set(NIMISEWI_CGI_STATIC_BUILD TRUE) endif() # HAVE_BSD_STRING_H AND ... endif() # HAVE_LIBBSD_STATIC # optional binaries option(BUILD_CGI "build cgi version of nimisewi" OFF) if(BUILD_CGI) add_executable(nimisewi.cgi cgi.c nimisewi.c ${PROJECT_BINARY_DIR}/nimitoki.c) option(CGI_INSTALL_DIR "specify installation directory of cgi script") if(CGI_INSTALL_DIR) set_property(TARGET nimisewi.cgi PROPERTY CGI_INSTALL_DIR ${CGI_INSTALL_DIR}) else() # CGI_INSTALL_DIR set_property(TARGET nimisewi.cgi PROPERTY CGI_INSTALL_DIR "var/www/htdocs/cgi-bin") endif() # CGI_INSTALL_DIR target_include_directories(nimisewi.cgi PUBLIC "${PROJECT_BINARY_DIR}") target_compile_definitions(nimisewi.cgi PRIVATE ${EXTRA_DEFINITIONS}) target_link_libraries(nimisewi.cgi PUBLIC ${EXTRA_LIBS}) if(NIMISEWI_CGI_STATIC_BUILD) target_link_options(nimisewi.cgi PUBLIC -static) endif() # NIMISEWI_CGI_STATIC_BUILD endif() # BUILD_CGI option(BUILD_GEMINI_CGI "build cgi version of nimisewi for gemini protocol" OFF) if(BUILD_GEMINI_CGI) add_executable(nimisewi_gemini.cgi cgi_gemini.c nimisewi.c ${PROJECT_BINARY_DIR}/nimitoki.c) option(GEMINI_CGI_INSTALL_DIR "specify installation directory of cgi script") if(GEMINI_CGI_INSTALL_DIR) set_property(TARGET nimisewi_gemini.cgi PROPERTY GEMINI_CGI_INSTALL_DIR ${GEMINI_CGI_INSTALL_DIR}) else() # GEMINI_CGI_INSTALL_DIR set_property(TARGET nimisewi_gemini.cgi PROPERTY GEMINI_CGI_INSTALL_DIR "var/gemini/cgi-bin") endif() # GEMINI_CGI_INSTALL_DIR target_include_directories(nimisewi_gemini.cgi PUBLIC "${PROJECT_BINARY_DIR}") target_compile_definitions(nimisewi_gemini.cgi PRIVATE ${EXTRA_DEFINITIONS}) target_link_libraries(nimisewi_gemini.cgi PUBLIC ${EXTRA_LIBS}) if(NIMISEWI_CGI_STATIC_BUILD) target_link_options(nimisewi_gemini.cgi PUBLIC -static) endif() # NIMISEWI_CGI_STATIC_BUILD endif() # BUILD_GEMINI_CGI # installation install(TARGETS nimisewi DESTINATION bin) if(BUILD_CGI) install(TARGETS nimisewi.cgi DESTINATION $) endif() # BUILD_CGI if(BUILD_GEMINI_CGI) install(TARGETS nimisewi_gemini.cgi DESTINATION $) endif() # BUILD_GEMINI_CGI # packaging include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_PROJECT_VERSION_MAJOR ${nimisewi_VERSION_MAJOR}) set(CPACK_PROJECT_VERSION_MINOR ${nimisewi_VERSION_MINOR}) set(CPACK_PROJECT_VERSION_PATCH ${nimisewi_VERSION_PATCH}) set(CPACK_PACKAGE_FILE_NAME ${CMAKE_PROJECT_NAME}-${nimisewi_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}) set(CPACK_GENERATOR "TGZ" "ZIP") set(CPACK_SOURCE_GENERATOR "TGZ" "ZIP") set(CPACK_SOURCE_IGNORE_FILES \.fslckout \.fossil-settings build/ utils/ download.md ) set(CPACK_STRIP_FILES TRUE) include(CPack) # testing enable_testing() add_test(NAME runs COMMAND nimisewi) add_test(NAME version COMMAND nimisewi -v) set_tests_properties(version PROPERTIES PASS_REGULAR_EXPRESSION "nimisewi [0-9]\.[0-9]\.[0-9]\n[a-z ]+(\n([A-Z_]+(\n)?)+)?") if(BUILD_CGI) add_test(NAME cgi COMMAND nimisewi.cgi) set_tests_properties(cgi PROPERTIES PASS_REGULAR_EXPRESSION "Status: 200 OK\rContent-Type: text\/html\r\r<.*>") endif() # BUILD_CGI if(BUILD_GEMINI_CGI) add_test(NAME gemini_cgi COMMAND nimisewi_gemini.cgi) set_tests_properties(gemini_cgi PROPERTIES PASS_REGULAR_EXPRESSION "20 text\/gemini\r\n.*") endif() # BUILD_GEMINI_CGI