aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Jylänki <jujjyl@gmail.com>2013-09-03 15:14:06 +0300
committerJukka Jylänki <jujjyl@gmail.com>2013-09-04 10:41:59 +0300
commit9de7165f9157812a827f96a73c70dea1d909b763 (patch)
treeee3b5be05d9b191baa6797a55439c4334e0d6798
parent6eaaebf4dd9c1dbd38dba929199cd3121b666c0f (diff)
Improve CMake toolchain file to use response files. Avoid the compiler detection mechanism that could throw CMake off depending on what is in Windows PATH. Use CMAKE_EXECUTABLE_SUFFIX to specify whether to build .html or .js.
-rw-r--r--cmake/Platform/Emscripten.cmake88
-rw-r--r--tests/cmake/target_html/CMakeLists.txt8
-rw-r--r--tests/cmake/target_js/CMakeLists.txt18
-rw-r--r--tests/test_other.py12
4 files changed, 107 insertions, 19 deletions
diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake
index aafd38a8..a8667cd9 100644
--- a/cmake/Platform/Emscripten.cmake
+++ b/cmake/Platform/Emscripten.cmake
@@ -16,33 +16,105 @@
set(CMAKE_SYSTEM_NAME Emscripten)
set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_CROSSCOMPILING TRUE)
+
+# Do a no-op access on the CMAKE_TOOLCHAIN_FILE variable so that CMake will not issue a warning on it being unused.
+if (CMAKE_TOOLCHAIN_FILE)
+endif()
+
+# Locate where the Emscripten compiler resides in relative to this toolchain file.
if ("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
- set(CMAKE_FIND_ROOT_PATH "$ENV{EMSCRIPTEN}")
+ get_filename_component(GUESS_EMSCRIPTEN_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../" ABSOLUTE)
+ if (EXISTS "${GUESS_EMSCRIPTEN_ROOT_PATH}/emranlib")
+ set(EMSCRIPTEN_ROOT_PATH "${GUESS_EMSCRIPTEN_ROOT_PATH}")
+ message(STATUS "Guessed ${EMSCRIPTEN_ROOT_PATH}")
+ endif()
+endif()
+
+# If not found by above search, locate using the EMSCRIPTEN environment variable.
+if ("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
+ set(EMSCRIPTEN_ROOT_PATH "$ENV{EMSCRIPTEN}")
+endif()
+
+# Abort if not found.
+if ("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
+ message(FATAL_ERROR "Could not locate the Emscripten compiler toolchain directory! Either set the EMSCRIPTEN environment variable, or pass -DEMSCRIPTEN_ROOT_PATH=xxx to CMake to explicitly specify the location of the compiler!")
+endif()
+
+# Normalize, convert Windows backslashes to forward slashes or CMake will crash.
+get_filename_component(EMSCRIPTEN_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}" ABSOLUTE)
+
+set(CMAKE_FIND_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}")
+
+if (CMAKE_HOST_WIN32)
+ set(EMCC_SUFFIX ".bat")
else()
- set(CMAKE_FIND_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}")
+ set(EMCC_SUFFIX "")
endif()
# Specify the compilers to use for C and C++
if ("${CMAKE_C_COMPILER}" STREQUAL "")
- set(CMAKE_C_COMPILER "emcc.bat")
- set(CMAKE_CXX_COMPILER "em++.bat")
- set(CMAKE_AR "emar.bat")
- set(CMAKE_RANLIB "emranlib.bat")
+ set(CMAKE_C_COMPILER "${EMSCRIPTEN_ROOT_PATH}/emcc${EMCC_SUFFIX}")
+endif()
+if ("${CMAKE_CXX_COMPILER}" STREQUAL "")
+ set(CMAKE_CXX_COMPILER "${EMSCRIPTEN_ROOT_PATH}/em++${EMCC_SUFFIX}")
+endif()
+
+if ("${CMAKE_AR}" STREQUAL "")
+ set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar${EMCC_SUFFIX}")
endif()
+if ("${CMAKE_RANLIB}" STREQUAL "")
+ set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib${EMCC_SUFFIX}")
+endif()
+
+# Don't do compiler autodetection, since we are cross-compiling.
+include(CMakeForceCompiler)
+CMAKE_FORCE_C_COMPILER("${CMAKE_C_COMPILER}" Clang)
+CMAKE_FORCE_CXX_COMPILER("${CMAKE_CXX_COMPILER}" Clang)
+
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+SET(CMAKE_LINK_LIBRARY_SUFFIX "")
+SET(CMAKE_STATIC_LIBRARY_PREFIX "")
+SET(CMAKE_STATIC_LIBRARY_SUFFIX ".bc")
+SET(CMAKE_SHARED_LIBRARY_PREFIX "")
+SET(CMAKE_SHARED_LIBRARY_SUFFIX ".bc")
+IF (NOT CMAKE_EXECUTABLE_SUFFIX)
+ SET(CMAKE_EXECUTABLE_SUFFIX ".js")
+endif()
+SET(CMAKE_DL_LIBS "" )
+
+SET(CMAKE_FIND_LIBRARY_PREFIXES "")
+SET(CMAKE_FIND_LIBRARY_SUFFIXES ".bc")
+
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+
+set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@")
+set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@")
+
# Specify the program to use when building static libraries. Force Emscripten-related command line options to clang.
-set(CMAKE_CXX_ARCHIVE_CREATE "${CMAKE_CXX_COMPILER} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>")
-set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_C_COMPILER} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_CXX_ARCHIVE_CREATE "${CMAKE_CXX_COMPILER} ${CMAKE_START_TEMP_FILE} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
+set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_C_COMPILER} ${CMAKE_START_TEMP_FILE} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
# Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten.
# There seems to be some kind of bug with CMake, so you might need to define this manually on the command line with "-DEMSCRIPTEN=1".
set(EMSCRIPTEN 1)
+# We are cross-compiling, so unset the common CMake variables that represent the target platform. Leave UNIX define enabled, since Emscripten
+# mimics a Linux environment.
+SET(WIN32)
+SET(APPLE)
+
+set(CMAKE_C_SIZEOF_DATA_PTR 4)
+set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
+
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELEASE")
set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_MINSIZEREL")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELWITHDEBINFO")
diff --git a/tests/cmake/target_html/CMakeLists.txt b/tests/cmake/target_html/CMakeLists.txt
index 9f891e71..8b0528eb 100644
--- a/tests/cmake/target_html/CMakeLists.txt
+++ b/tests/cmake/target_html/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8)
-project(hello_world_gles.html)
+project(hello_world_gles)
file(GLOB sourceFiles ../../hello_world_gles.c)
@@ -10,5 +10,7 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi
SET(linkFlags "-O2")
endif()
-add_executable(hello_world_gles.html ${sourceFiles})
-set_target_properties(hello_world_gles.html PROPERTIES LINK_FLAGS "${linkFlags}")
+SET(CMAKE_EXECUTABLE_SUFFIX ".html")
+
+add_executable(hello_world_gles ${sourceFiles})
+set_target_properties(hello_world_gles PROPERTIES LINK_FLAGS "${linkFlags}")
diff --git a/tests/cmake/target_js/CMakeLists.txt b/tests/cmake/target_js/CMakeLists.txt
index 860b70a9..a1228c73 100644
--- a/tests/cmake/target_js/CMakeLists.txt
+++ b/tests/cmake/target_js/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8)
-project(hello_world.js)
+project(hello_world)
file(GLOB sourceFiles ../../hello_world.cpp)
@@ -10,5 +10,17 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi
SET(linkFlags "-O2")
endif()
-add_executable(hello_world.js ${sourceFiles})
-set_target_properties(hello_world.js PROPERTIES LINK_FLAGS "${linkFlags}")
+if (WIN32)
+ message(FATAL_ERROR "WIN32 should not be defined when cross-compiling!")
+endif()
+
+if (APPLE)
+ message(FATAL_ERROR "APPLE should not be defined when cross-compiling!")
+endif()
+
+if (NOT CMAKE_C_SIZEOF_DATA_PTR)
+ message(FATAL_ERROR "CMAKE_C_SIZEOF_DATA_PTR was not defined!")
+endif()
+
+add_executable(hello_world ${sourceFiles})
+set_target_properties(hello_world PROPERTIES LINK_FLAGS "${linkFlags}")
diff --git a/tests/test_other.py b/tests/test_other.py
index c6f5c333..1723db91 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -281,9 +281,11 @@ f.close()
if os.name == 'nt':
make_command = 'mingw32-make'
+ generator = 'MinGW Makefiles'
emscriptencmaketoolchain = path_from_root('cmake', 'Platform', 'Emscripten.cmake')
else:
make_command = 'make'
+ generator = 'Unix Makefiles'
emscriptencmaketoolchain = path_from_root('cmake', 'Platform', 'Emscripten_unix.cmake')
cmake_cases = ['target_js', 'target_html']
@@ -301,11 +303,11 @@ f.close()
cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+emscriptencmaketoolchain,
'-DCMAKE_BUILD_TYPE=' + configuration,
'-DCMAKE_MODULE_PATH=' + path_from_root('cmake').replace('\\', '/'),
- '-G' 'Unix Makefiles', cmakelistsdir]
+ '-G', generator, cmakelistsdir]
ret = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
- if ret[1] != None and len(ret[1].strip()) > 0:
+ if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
print >> sys.stderr, ret[1] # If there were any errors, print them directly to console for diagnostics.
- if 'error' in ret[1].lower():
+ if len(ret) > 1 and ret[1] != None and 'error' in ret[1].lower():
print >> sys.stderr, 'Failed command: ' + ' '.join(cmd)
print >> sys.stderr, 'Result:\n' + ret[1]
raise Exception('cmake call failed!')
@@ -314,9 +316,9 @@ f.close()
# Build
cmd = [make_command]
ret = Popen(cmd, stdout=PIPE).communicate()
- if ret[1] != None and len(ret[1].strip()) > 0:
+ if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
print >> sys.stderr, ret[1] # If there were any errors, print them directly to console for diagnostics.
- if 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
+ if len(ret) > 0 and ret[0] != None and 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
print >> sys.stderr, 'Failed command: ' + ' '.join(cmd)
print >> sys.stderr, 'Result:\n' + ret[0]
raise Exception('make failed!')