Skip to content
This repository
tree: 30e7d2db48
Fetching contributors…

Cannot retrieve contributors at this time

file 453 lines (411 sloc) 16.463 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
# LuaDist CMake utility library.
# Provides variables and utility functions common to LuaDist CMake builds.
#
# Copyright (C) 2007-2011 LuaDist.
# by David Manura, Peter Drahos
# Redistribution and use of this file is allowed according to the terms of the MIT license.
# For details see the COPYRIGHT file distributed with LuaDist.
# Please note that the package source code is licensed under its own license.

## INSTALL DEFAULTS (Relative to CMAKE_INSTALL_PREFIX)
# Primary paths
set ( INSTALL_BIN bin CACHE PATH "Where to install binaries to." )
set ( INSTALL_LIB lib CACHE PATH "Where to install libraries to." )
set ( INSTALL_INC include CACHE PATH "Where to install headers to." )
set ( INSTALL_ETC etc CACHE PATH "Where to store configuration files" )
set ( INSTALL_LMOD ${INSTALL_LIB}/lua CACHE PATH "Directory to install Lua modules." )
set ( INSTALL_CMOD ${INSTALL_LIB}/lua CACHE PATH "Directory to install Lua binary modules." )
set ( INSTALL_SHARE share CACHE PATH "Directory for shared data." )

# Secondary paths
set ( INSTALL_DATA ${INSTALL_SHARE}/${PROJECT_NAME} CACHE PATH "Directory the package can store documentation, tests or other data in.")
set ( INSTALL_DOC ${INSTALL_DATA}/doc CACHE PATH "Recommended directory to install documentation into.")
set ( INSTALL_EXAMPLE ${INSTALL_DATA}/example CACHE PATH "Recommended directory to install examples into.")
set ( INSTALL_TEST ${INSTALL_DATA}/test CACHE PATH "Recommended directory to install tests into.")
set ( INSTALL_FOO ${INSTALL_DATA}/etc CACHE PATH "Where to install additional files")

# Skipable content, headers, binaries and libraries are always required
option ( SKIP_TESTING "Do not add tests." OFF)
option ( SKIP_LUA_WRAPPER "Do not build and install Lua executable wrappers." OFF)
option ( SKIP_INSTALL_DATA "Skip installing all data." OFF )
if ( NOT SKIP_INSTALL_DATA )
  option ( SKIP_INSTALL_DOC "Skip installation of documentation." OFF )
  option ( SKIP_INSTALL_EXAMPLE "Skip installation of documentation." OFF )
  option ( SKIP_INSTALL_TEST "Skip installation of tests." OFF)
  option ( SKIP_INSTALL_FOO "Skip installation of optional package content." OFF)
endif ()

# TWEAKS
# Setting CMAKE to use loose block and search for find modules in source directory
set ( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
set ( CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_MODULE_PATH} )

# In MSVC, prevent warnings that can occur when using standard libraries.
if ( MSVC )
add_definitions ( -D_CRT_SECURE_NO_WARNINGS )
endif ()

## MACROS
# Parser macro
macro ( parse_arguments prefix arg_names option_names)
  set ( DEFAULT_ARGS )
  foreach ( arg_name ${arg_names} )
    set ( ${prefix}_${arg_name} )
  endforeach ()
  foreach ( option ${option_names} )
    set ( ${prefix}_${option} FALSE )
  endforeach ()

  set ( current_arg_name DEFAULT_ARGS )
  set ( current_arg_list )
  foreach ( arg ${ARGN} )
    set ( larg_names ${arg_names} )
    list ( FIND larg_names "${arg}" is_arg_name )
    if ( is_arg_name GREATER -1 )
      set ( ${prefix}_${current_arg_name} ${current_arg_list} )
      set ( current_arg_name ${arg} )
      set ( current_arg_list )
    else ()
      set ( loption_names ${option_names} )
      list ( FIND loption_names "${arg}" is_option )
      if ( is_option GREATER -1 )
set ( ${prefix}_${arg} TRUE )
      else ()
set ( current_arg_list ${current_arg_list} ${arg} )
      endif ()
    endif ()
  endforeach ()
  set ( ${prefix}_${current_arg_name} ${current_arg_list} )
endmacro ()

# INSTALL_LUA_EXECUTABLE ( target source )
# Automatically generate a binary wrapper for lua application and install it
# The wrapper and the source of the application will be placed into /bin
# If the application source did not have .lua suffix then it will be added
# USE: lua_executable ( sputnik src/sputnik.lua )
macro ( install_lua_executable _name _source )
  get_filename_component ( _source_name ${_source} NAME_WE )
  if ( NOT SKIP_LUA_WRAPPER )
    enable_language ( C )
  
    find_package ( Lua51 REQUIRED )
    include_directories ( ${LUA_INCLUDE_DIR} )

    set ( _wrapper ${CMAKE_CURRENT_BINARY_DIR}/${_name}.c )
    set ( _code
"// Not so simple executable wrapper for Lua apps
#include <stdio.h>
#include <signal.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

lua_State *L\;

static int getargs (lua_State *L, char **argv, int n) {
int narg\;
int i\;
int argc = 0\;
while (argv[argc]) argc++\;
narg = argc - (n + 1)\;
luaL_checkstack(L, narg + 3, \"too many arguments to script\")\;
for (i=n+1\; i < argc\; i++)
lua_pushstring(L, argv[i])\;
lua_createtable(L, narg, n + 1)\;
for (i=0\; i < argc\; i++) {
lua_pushstring(L, argv[i])\;
lua_rawseti(L, -2, i - n)\;
}
return narg\;
}

static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar\;
lua_sethook(L, NULL, 0, 0)\;
luaL_error(L, \"interrupted!\")\;
}

static void laction (int i) {
signal(i, SIG_DFL)\;
lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1)\;
}

static void l_message (const char *pname, const char *msg) {
if (pname) fprintf(stderr, \"%s: \", pname)\;
fprintf(stderr, \"%s\\n\", msg)\;
fflush(stderr)\;
}

static int report (lua_State *L, int status) {
if (status && !lua_isnil(L, -1)) {
  const char *msg = lua_tostring(L, -1)\;
  if (msg == NULL) msg = \"(error object is not a string)\"\;
  l_message(\"${_source_name}\", msg)\;
  lua_pop(L, 1)\;
}
return status\;
}

static int traceback (lua_State *L) {
if (!lua_isstring(L, 1))
  return 1\;
lua_getfield(L, LUA_GLOBALSINDEX, \"debug\")\;
if (!lua_istable(L, -1)) {
  lua_pop(L, 1)\;
  return 1\;
}
lua_getfield(L, -1, \"traceback\")\;
if (!lua_isfunction(L, -1)) {
  lua_pop(L, 2)\;
  return 1\;
}
lua_pushvalue(L, 1)\;
lua_pushinteger(L, 2)\;
lua_call(L, 2, 1)\;
return 1\;
}

static int docall (lua_State *L, int narg, int clear) {
int status\;
int base = lua_gettop(L) - narg\;
lua_pushcfunction(L, traceback)\;
lua_insert(L, base)\;
signal(SIGINT, laction)\;
status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base)\;
signal(SIGINT, SIG_DFL)\;
lua_remove(L, base)\;
if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0)\;
return status\;
}

int main (int argc, char **argv) {
L=lua_open()\;
lua_gc(L, LUA_GCSTOP, 0)\;
luaL_openlibs(L)\;
lua_gc(L, LUA_GCRESTART, 0)\;
int narg = getargs(L, argv, 0)\;
lua_setglobal(L, \"arg\")\;

// Script
char script[500] = \"./${_source_name}.lua\"\;
lua_getglobal(L, \"_PROGDIR\")\;
if (lua_isstring(L, -1)) {
  sprintf( script, \"%s/${_source_name}.lua\", lua_tostring(L, -1))\;
}
lua_pop(L, 1)\;

// Run
int status = luaL_loadfile(L, script)\;
lua_insert(L, -(narg+1))\;
if (status == 0)
  status = docall(L, narg, 0)\;
else
  lua_pop(L, narg)\;

report(L, status)\;
lua_close(L)\;
return status\;
};
")
    file ( WRITE ${_wrapper} ${_code} )
    add_executable ( ${_name} ${_wrapper} )
    target_link_libraries ( ${_name} ${LUA_LIBRARY} )
    install ( TARGETS ${_name} DESTINATION ${INSTALL_BIN} )
  endif()
  install ( PROGRAMS ${_source} DESTINATION ${INSTALL_BIN} RENAME ${_source_name}.lua )
endmacro ()

# INSTALL_LIBRARY
# Installs any libraries generated using "add_library" into apropriate places.
# USE: install_library ( libexpat )
macro ( install_library )
  foreach ( _file ${ARGN} )
    install ( TARGETS ${_file} RUNTIME DESTINATION ${INSTALL_BIN} LIBRARY DESTINATION ${INSTALL_LIB} ARCHIVE DESTINATION ${INSTALL_LIB} )

  endforeach()
endmacro ()

# INSTALL_EXECUTABLE
# Installs any executables generated using "add_executable".
# USE: install_executable ( lua )
macro ( install_executable )
  foreach ( _file ${ARGN} )
    install ( TARGETS ${_file} RUNTIME DESTINATION ${INSTALL_BIN} )
  endforeach()
endmacro ()

# INSTALL_HEADER
# Install a directories or files into header destination.
# USE: install_header ( lua.h luaconf.h ) or install_header ( GL )
# NOTE: If headers need to be installed into subdirectories use the INSTALL command directly
macro ( install_header )
  parse_arguments ( _ARG "INTO" "" ${ARGN} )
  foreach ( _file ${_ARG_DEFAULT_ARGS} )
    if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
      install ( DIRECTORY ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO} PATTERN "Makefile*" EXCLUDE )
    else ()
      install ( FILES ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO} )
    endif ()
  endforeach()
endmacro ()

# INSTALL_DATA ( files/directories )
# This installs additional data files or directories.
# USE: install_data ( extra data.dat )
macro ( install_data )
  if ( NOT SKIP_INSTALL_DATA )
    parse_arguments ( _ARG "INTO" "" ${ARGN} )
    foreach ( _file ${_ARG_DEFAULT_ARGS} )
      if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
        install ( DIRECTORY ${_file} DESTINATION ${INSTALL_DATA}/${_ARG_INTO} PATTERN "Makefile*" EXCLUDE )
      else ()
        install ( FILES ${_file} DESTINATION ${INSTALL_DATA}/${_ARG_INTO} )
      endif ()
    endforeach()
  endif()
endmacro ()

# INSTALL_DOC ( files/directories )
# This installs documentation content
# USE: install_doc ( doc/ )
macro ( install_doc )
  if ( NOT SKIP_INSTALL_DATA AND NOT SKIP_INSTALL_DOC )
    parse_arguments ( _ARG "INTO" "" ${ARGN} )
    foreach ( _file ${_ARG_DEFAULT_ARGS} )
      if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
        install ( DIRECTORY ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO} PATTERN "Makefile*" EXCLUDE )
      else ()
        install ( FILES ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO} )
      endif ()
    endforeach()
  endif()
endmacro ()

# INSTALL_EXAMPLE ( files/directories )
# This installs additional data
# USE: install_example ( examples/ exampleA.lua )
macro ( install_example )
  if ( NOT SKIP_INSTALL_DATA AND NOT SKIP_INSTALL_EXAMPLE )
    parse_arguments ( _ARG "INTO" "" ${ARGN} )
    foreach ( _file ${_ARG_DEFAULT_ARGS} )
      if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
        install ( DIRECTORY ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO} PATTERN "Makefile*" EXCLUDE )
      else ()
        install ( FILES ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO} )
      endif ()
    endforeach()
  endif()
endmacro ()

# INSTALL_TEST ( files/directories )
# This installs tests
# USE: install_example ( examples/ exampleA.lua )
macro ( install_test )
  if ( NOT SKIP_INSTALL_DATA AND NOT SKIP_INSTALL_TEST )
    parse_arguments ( _ARG "INTO" "" ${ARGN} )
    foreach ( _file ${_ARG_DEFAULT_ARGS} )
      if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
        install ( DIRECTORY ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO} PATTERN "Makefile*" EXCLUDE )
      else ()
        install ( FILES ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO} )
      endif ()
    endforeach()
  endif()
endmacro ()

# INSTALL_FOO ( files/directories )
# This installs optional content
# USE: install_foo ( examples/ exampleA.lua )
macro ( install_foo )
  if ( NOT SKIP_INSTALL_DATA AND NOT SKIP_INSTALL_FOO )
    parse_arguments ( _ARG "INTO" "" ${ARGN} )
    foreach ( _file ${_ARG_DEFAULT_ARGS} )
      if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
        install ( DIRECTORY ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO} PATTERN "Makefile*" EXCLUDE )
      else ()
        install ( FILES ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO} )
      endif ()
    endforeach()
  endif()
endmacro ()

# INSTALL_LUA_MODULE
# This macro installs a lua source module into destination given by lua require syntax.
# Binary modules are also supported where this funcion takes sources and libraries to compile separated by LINK keyword
# USE: install_lua_module ( socket.http src/http.lua )
# USE2: install_lua_module ( mime.core src/mime.c )
# USE3: install_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} )
macro (install_lua_module _name )
  string ( REPLACE "." "/" _module "${_name}" )
  string ( REPLACE "." "_" _target "${_name}" )
  
  set ( _lua_module "${_module}.lua" )
  set ( _bin_module "${_module}${CMAKE_SHARED_MODULE_SUFFIX}" )
  
  parse_arguments ( _MODULE "LINK" "" ${ARGN} )
  get_filename_component ( _ext ${ARGV1} EXT )
  if ( _ext STREQUAL ".lua" )
      get_filename_component ( _path ${_lua_module} PATH )
      get_filename_component ( _filename ${_lua_module} NAME )
      install ( FILES ${ARGV1} DESTINATION ${INSTALL_LMOD}/${_path} RENAME ${_filename} )
  else ()
     enable_language ( C )
     get_filename_component ( _module_name ${_bin_module} NAME_WE )
     get_filename_component ( _module_path ${_bin_module} PATH )
     
     find_package ( Lua51 REQUIRED )
     include_directories ( ${LUA_INCLUDE_DIR} )
   
     add_library( ${_target} MODULE ${_MODULE_DEFAULT_ARGS})
     target_link_libraries ( ${_target} ${LUA_LIBRARY} ${_MODULE_LINK} )
     set_target_properties ( ${_target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${_module_path}" PREFIX "" OUTPUT_NAME "${_module_name}" )
     
     install ( TARGETS ${_target} DESTINATION ${INSTALL_CMOD}/${_module_path} )
  endif ()
endmacro ()

# ADD_LUA_TEST
# Runs Lua script `_testfile` under CTest tester.
# Optional argument `_testcurrentdir` is current working directory to run test under
# (defaults to ${CMAKE_CURRENT_BINARY_DIR}).
# Both paths, if relative, are relative to ${CMAKE_CURRENT_SOURCE_DIR}.
# Under LuaDist, set test=true in config.lua to enable testing.
# USE: add_lua_test ( test/test1.lua )
macro ( add_lua_test _testfile )
if ( NOT SKIP_TESTING )
include ( CTest )
find_program ( LUA NAMES lua lua.bat )
get_filename_component ( TESTFILEABS ${_testfile} ABSOLUTE )
get_filename_component ( TESTFILENAME ${_testfile} NAME )
get_filename_component ( TESTFILEBASE ${_testfile} NAME_WE )

# Write wrapper script.
set ( TESTWRAPPER ${CMAKE_CURRENT_BINARY_DIR}/${TESTFILENAME} )
set ( TESTWRAPPERSOURCE
"local configuration = ...
local sodir = '${CMAKE_CURRENT_BINARY_DIR}' .. (configuration == '' and '' or '/' .. configuration)
package.path = sodir .. '/?.lua\;' .. sodir .. '/?.lua\;' .. package.path
package.cpath = sodir .. '/?.so\;' .. sodir .. '/?.dll\;' .. package.cpath
arg[0] = '${TESTFILEABS}'
return dofile '${TESTFILEABS}'
" )
if ( ${ARGC} GREATER 1 )
set ( _testcurrentdir ${ARGV1} )
get_filename_component ( TESTCURRENTDIRABS ${_testcurrentdir} ABSOLUTE )
# note: CMake 2.6 (unlike 2.8) lacks WORKING_DIRECTORY parameter.
#old:
# set ( TESTWRAPPERSOURCE
#"require 'lfs'; lfs.chdir('${TESTCURRENTDIRABS}' )
#${TESTWRAPPERSOURCE}" )
set ( _pre ${CMAKE_COMMAND} -E chdir "${TESTCURRENTDIRABS}" )
endif ()
file ( WRITE ${TESTWRAPPER} ${TESTWRAPPERSOURCE})
add_test ( NAME ${TESTFILEBASE} COMMAND ${_pre} ${LUA} ${TESTWRAPPER} $<CONFIGURATION> )
endif ()
# see also http://gdcm.svn.sourceforge.net/viewvc/gdcm/Sandbox/CMakeModules/UsePythonTest.cmake
endmacro ()

# Converts Lua source file `_source` to binary string embedded in C source
# file `_target`. Optionally compiles Lua source to byte code (not available
# under LuaJIT2, which doesn't have a bytecode loader). Additionally, Lua
# versions of bin2c [1] and luac [2] may be passed respectively as additional
# arguments.
#
# [1] http://lua-users.org/wiki/BinToCee
# [2] http://lua-users.org/wiki/LuaCompilerInLua
function ( add_lua_bin2c _target _source )
find_program ( LUA NAMES lua lua.bat )
execute_process ( COMMAND ${LUA} -e "string.dump(function()end)" RESULT_VARIABLE _LUA_DUMP_RESULT ERROR_QUIET )
if ( NOT ${_LUA_DUMP_RESULT} )
SET ( HAVE_LUA_DUMP true )
endif ()
message ( "-- string.dump=${HAVE_LUA_DUMP}" )

if ( ARGV2 )
get_filename_component ( BIN2C ${ARGV2} ABSOLUTE )
set ( BIN2C ${LUA} ${BIN2C} )
else ()
find_program ( BIN2C NAMES bin2c bin2c.bat )
endif ()
if ( HAVE_LUA_DUMP )
if ( ARGV3 )
get_filename_component ( LUAC ${ARGV3} ABSOLUTE )
set ( LUAC ${LUA} ${LUAC} )
else ()
find_program ( LUAC NAMES luac luac.bat )
endif ()
endif ( HAVE_LUA_DUMP )
message ( "-- bin2c=${BIN2C}" )
message ( "-- luac=${LUAC}" )

get_filename_component ( SOURCEABS ${_source} ABSOLUTE )
if ( HAVE_LUA_DUMP )
get_filename_component ( SOURCEBASE ${_source} NAME_WE )
add_custom_command (
OUTPUT ${_target} DEPENDS ${_source}
COMMAND ${LUAC} -o ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo ${SOURCEABS}
COMMAND ${BIN2C} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo ">${_target}" )
else ()
add_custom_command (
OUTPUT ${_target} DEPENDS ${SOURCEABS}
COMMAND ${BIN2C} ${_source} ">${_target}" )
endif ()
endfunction()
Something went wrong with that request. Please try again.