emscripten.toolchain.cmake 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #
  2. # Copyright (c) 2008-2016 the Urho3D project.
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. # THE SOFTWARE.
  21. #
  22. if (DEFINED CMAKE_CROSSCOMPILING)
  23. return ()
  24. endif ()
  25. if (CMAKE_TOOLCHAIN_FILE)
  26. # Reference toolchain variable to suppress "unused variable" warning
  27. mark_as_advanced (CMAKE_TOOLCHAIN_FILE)
  28. endif ()
  29. # this one is important
  30. set (CMAKE_SYSTEM_NAME Linux)
  31. # this one not so much
  32. set (CMAKE_SYSTEM_VERSION 1)
  33. # specify the cross compiler
  34. if (CMAKE_HOST_WIN32)
  35. set (TOOL_EXT .bat)
  36. endif ()
  37. if (NOT EMSCRIPTEN_ROOT_PATH)
  38. if (DEFINED ENV{EMSCRIPTEN_ROOT_PATH})
  39. file (TO_CMAKE_PATH $ENV{EMSCRIPTEN_ROOT_PATH} EMSCRIPTEN_ROOT_PATH)
  40. elseif (DEFINED ENV{EMSCRIPTEN})
  41. file (TO_CMAKE_PATH $ENV{EMSCRIPTEN} EMSCRIPTEN_ROOT_PATH)
  42. endif ()
  43. endif ()
  44. if (NOT EXISTS ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT})
  45. message (FATAL_ERROR "Could not find Emscripten cross compilation tool. "
  46. "Use EMSCRIPTEN_ROOT_PATH environment variable or build option to specify the location of the toolchain. "
  47. "Or use the canonical EMSCRIPTEN environment variable by calling emsdk_env script.")
  48. endif ()
  49. if (NOT EMCC_VERSION)
  50. execute_process (COMMAND ${EMSCRIPTEN_ROOT_PATH}/emcc${TOOL_EXT} --version RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE EMCC_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
  51. if (EXIT_CODE EQUAL 0)
  52. string (REGEX MATCH "[^ .]+\\.[^.]+\\.[^ ]+" EMCC_VERSION "${EMCC_VERSION}") # Stringify as it could be empty when an error has occured
  53. else ()
  54. message (FATAL_ERROR "Could not determine the emcc version. Make sure you have installed and activated the Emscripten SDK correctly.")
  55. endif ()
  56. set (EMCC_VERSION ${EMCC_VERSION} CACHE STRING "emcc version being used in this build tree") # Cache the result even when there was error in determining the version
  57. endif ()
  58. set (COMPILER_PATH ${EMSCRIPTEN_ROOT_PATH})
  59. # ccache support could only be enabled for emcc prior to 1.31.3 when the CCACHE_CPP2 env var is also set to 1, newer emcc version could enable ccache support without this caveat (see https://github.com/kripken/emscripten/issues/3365 for more detail)
  60. # The CCACHE_CPP2 env var tells ccache to fallback to use original input source file instead of preprocessed one when passing on the compilation task to the compiler proper
  61. if (NOT CMAKE_C_COMPILER AND "$ENV{USE_CCACHE}" AND NOT CMAKE_HOST_WIN32 AND ("$ENV{CCACHE_CPP2}" OR NOT EMCC_VERSION VERSION_LESS 1.31.3))
  62. if (NOT $ENV{PATH} MATCHES ${EMSCRIPTEN_ROOT_PATH})
  63. message (FATAL_ERROR "The bin directory containing the compiler toolchain (${EMSCRIPTEN_ROOT_PATH}) has not been added in the PATH environment variable. "
  64. "This is required to enable ccache support for Emscripten compiler toolchain.")
  65. endif ()
  66. execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
  67. if (EXIT_CODE EQUAL 0)
  68. foreach (name emcc em++)
  69. execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${name})
  70. endforeach ()
  71. set (COMPILER_PATH ${CMAKE_BINARY_DIR})
  72. else ()
  73. message (WARNING "ccache may not have been installed on this host system. "
  74. "This is required to enable ccache support for Emscripten compiler toolchain. CMake has been configured to use the actual compiler toolchain instead of ccache. "
  75. "In order to rectify this, the build tree must be regenerated after installing ccache.")
  76. endif ()
  77. endif ()
  78. set (CMAKE_C_COMPILER ${COMPILER_PATH}/emcc${TOOL_EXT} CACHE PATH "C compiler")
  79. set (CMAKE_CXX_COMPILER ${COMPILER_PATH}/em++${TOOL_EXT} CACHE PATH "C++ compiler")
  80. set (CMAKE_AR ${EMSCRIPTEN_ROOT_PATH}/emar${TOOL_EXT} CACHE PATH "archive")
  81. set (CMAKE_RANLIB ${EMSCRIPTEN_ROOT_PATH}/emranlib${TOOL_EXT} CACHE PATH "ranlib")
  82. set (CMAKE_LINKER ${EMSCRIPTEN_ROOT_PATH}/emlink.py CACHE PATH "linker")
  83. # Specific to Emscripten
  84. set (EMRUN ${EMSCRIPTEN_ROOT_PATH}/emrun${TOOL_EXT} CACHE PATH "emrun")
  85. set (EMPACKAGER python ${EMSCRIPTEN_ROOT_PATH}/tools/file_packager.py CACHE PATH "file_packager.py")
  86. set (EMBUILDER python ${EMSCRIPTEN_ROOT_PATH}/embuilder.py CACHE PATH "embuilder.py")
  87. # specify the system root
  88. if (NOT EMSCRIPTEN_SYSROOT)
  89. if (DEFINED ENV{EMSCRIPTEN_SYSROOT})
  90. file (TO_CMAKE_PATH $ENV{EMSCRIPTEN_SYSROOT} EMSCRIPTEN_SYSROOT)
  91. else ()
  92. set (EMSCRIPTEN_SYSROOT ${EMSCRIPTEN_ROOT_PATH}/system)
  93. endif ()
  94. if (NOT EXISTS ${EMSCRIPTEN_SYSROOT})
  95. message (FATAL_ERROR "Could not find Emscripten system root. "
  96. "Use EMSCRIPTEN_SYSROOT environment variable or build option to specify the location of system root.")
  97. endif ()
  98. set (EMSCRIPTEN_ROOT_PATH ${EMSCRIPTEN_ROOT_PATH} CACHE STRING "Root path to Emscripten cross-compiler tools (Emscripten cross-compiling build only)" FORCE)
  99. set (EMSCRIPTEN_SYSROOT ${EMSCRIPTEN_SYSROOT} CACHE PATH "Path to Emscripten system root (Emscripten cross-compiling build only)" FORCE)
  100. endif ()
  101. set (CMAKE_FIND_ROOT_PATH ${EMSCRIPTEN_SYSROOT})
  102. # only search libraries, and headers in the target directories
  103. set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  104. set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  105. set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
  106. # Still perform the compiler checks except for those stated otherwise below
  107. foreach (LANG C CXX)
  108. # Since currently CMake does not able to identify Emscripten compiler toolchain, set the compiler identification explicitly
  109. set (CMAKE_${LANG}_COMPILER_ID_RUN TRUE)
  110. set (CMAKE_${LANG}_COMPILER_ID Clang)
  111. # The ABI info could not be checked as per normal as CMake does not understand the test build output from Emscripten, so bypass it also
  112. set (CMAKE_${LANG}_ABI_COMPILED TRUE)
  113. set (CMAKE_${LANG}_SIZEOF_DATA_PTR 4) # Assume it is always 32-bit for now (we could have used our CheckCompilerToolChains.cmake module here)
  114. # There could be a bug in CMake itself where setting CMAKE_EXECUTABLE_SUFFIX variable outside of the scope, where it processes the platform configuration files, does not being honored by try_compile() command and as a result all the check macros that depend on try_compile() do not work properly when the CMAKE_EXECUTABLE_SUFFIX variable is only being set later futher down the road; At least one of the CMake devs has the opinion that this is the intended behavior but it is an unconvincing explanation because setting CMAKE_EXECUTABLE_SUFFIX variable later does have the desired effect everywhere else EXCEPT the try_compile() command
  115. # We are forced to set CMAKE_EXECUTABLE_SUFFIX_C and CMAKE_EXECUTABLE_SUFFIX_CXX here as a workaround; we could not just set CMAKE_EXECUTABLE_SUFFIX directly because CMake processes platform configuration files after the toolchain file and since we tell CMake that we are cross-compiling for 'Linux' platform via CMAKE_SYSTEM_NAME variable, CMake initializes the CMAKE_EXECUTABLE_SUFFIX to empty string (as expected for Linux platform); the workaround avoids our setting from being overwritten by platform configuration files by using the C and CXX language variants of the variable
  116. # The executable suffix needs to be .js for the below Emscripten-specific compiler setting to be effective
  117. set (CMAKE_EXECUTABLE_SUFFIX_${LANG} .js)
  118. endforeach ()
  119. # Set required compiler flags for internal CMake various check_xxx() macros which rely on the error to occur for the check to be performed correctly
  120. set (CMAKE_REQUIRED_FLAGS "-s ERROR_ON_UNDEFINED_SYMBOLS=1")
  121. # Use response files on Windows host
  122. if (CMAKE_HOST_WIN32)
  123. foreach (lang C CXX)
  124. foreach (cat LIBRARIES OBJECTS INCLUDES)
  125. set (CMAKE_${lang}_USE_RESPONSE_FILE_FOR_${cat} 1)
  126. endforeach ()
  127. set (CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
  128. endforeach ()
  129. endif ()
  130. set (WEB 1)
  131. set (EMSCRIPTEN 1)