diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 2f052e1805..67f6f75522 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -18,13 +18,51 @@ endfunction() # Needed to for include_next includes to work from within mbedtls include_directories("${COMPONENT_PATH}/port/include") -# Needed in order to workaround issue with improper conversion to native path -# when building on MSYS2. This ensures that when building on MSYS, Unix style -# paths are used. -set(msystem $ENV{MSYSTEM}) +# Workaround issue with creating symbolic links due to issues with native +# path conversion (TO_NATIVE_PATH). The following summarizes what CMake invocations +# this workaround is for: +# +# 1. CMake from command line + Ninja = No errors +# 2. CMake from command line + MinGW Makefiles = Forward slash for paths, mklink mistakes path for a switch +# 3. CMake from MSYS + Ninja = No errors +# 4. CMake from MSYS + Unix Makefiles/MSYS Makefiles = Forward slash for paths, mklink mistakes path for a switch +# +# There are references to the issue in case (2) and (4) in https://github.com/ARMmbed/mbedtls/issues/1496, +# https://cmake.org/pipermail/cmake/2006-July/010193.html, and https://cmake.org/Bug/view.php?id=5939. +# +# This workaround is meant to circumvent logic inside link_to_source() function in mbedtls/mbedtls/CMakeLists.txt. +if(CMAKE_HOST_WIN32) + set(msystem $ENV{MSYSTEM}) + if(MSYS OR msystem) + # Solves case (4). When in MSYS environment, instead opt to use the Unix equivalent of mklink. + set(CMAKE_HOST_UNIX 1) + else() + # Solves case (2). When invoked from command line, create the symbolic links ahead of link_to_source() invocations + # using a 'hybrid' path format resilient intermediary - in this case a Python wrapper for mklink. This is more unweildy + # than necessary, since string(REPLACE "/" "\\" ... does not actually work. + set(target_links "mbedtls/include/mbedtls" + "mbedtls/scripts") + foreach(target_link ${target_links}) + file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/${target_link} link) + file(TO_NATIVE_PATH ${COMPONENT_PATH}/${target_link} target) -if(MSYS OR msystem) - set(CMAKE_HOST_UNIX 1) + if(NOT EXISTS ${link}) + if (IS_DIRECTORY ${target}) + set(command ${PYTHON} ${COMPONENT_PATH}/mklink.py /j ${link} ${target}) + else() + set(command ${PYTHON} ${COMPONENT_PATH}/mklink.py /h ${link} ${target}) + endif() + + execute_process(COMMAND ${command} + RESULT_VARIABLE result + ERROR_VARIABLE output) + + if (NOT ${result} EQUAL 0) + message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}") + endif() + endif() + endforeach() + endif() endif() # Import mbedtls library targets diff --git a/components/mbedtls/mklink.py b/components/mbedtls/mklink.py new file mode 100644 index 0000000000..4195e4f333 --- /dev/null +++ b/components/mbedtls/mklink.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Wrapper for symbolic link creation on Windows that works around issues +# with native path conversion. See the component CMakeLists.txt for more details. +# +# Copyright 2018 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import argparse +import subprocess + +parser = argparse.ArgumentParser() +parser.add_argument("type") +parser.add_argument("link") +parser.add_argument("target") + +args = parser.parse_args() + +link = os.path.abspath(args.link) +target = os.path.abspath(args.target) + +try: + os.makedirs(os.path.dirname(link)) +except WindowsError: + pass + +mklink_cmd = ["mklink", args.type, link, target] + +subprocess.call(mklink_cmd, shell=True)