diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 2b2ef5532..31e6862c0 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -15,6 +15,8 @@ install(TARGETS proxy install(FILES init.sh DESTINATION tools) +add_subdirectory(./hermit_proxy) # Show include files in IDE file(GLOB_RECURSE TOOLS_INCLUDES "*.h") add_custom_target(tools_includes_ide SOURCES ${TOOLS_INCLUDES}) + diff --git a/tools/hermit_proxy/.gitignore b/tools/hermit_proxy/.gitignore deleted file mode 100644 index eb5a316cb..000000000 --- a/tools/hermit_proxy/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target diff --git a/tools/hermit_proxy/CMakeLists.txt b/tools/hermit_proxy/CMakeLists.txt new file mode 100755 index 000000000..65b26a4fe --- /dev/null +++ b/tools/hermit_proxy/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +include(ExternalProject) + +find_package(rustc) +find_package(rustdoc) +find_package(cargo) +include(Rust) + +ExternalProject_Add( + hermit_proxy + DOWNLOAD_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND cargo build + BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}" + INSTALL_COMMAND "" + LOG_BUILD ON) + +install(FILES target/debug/hermit_proxy DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tools/hermit_proxy/Cargo.lock b/tools/hermit_proxy/Cargo.lock old mode 100644 new mode 100755 index 036f5057b..7aec2ec66 --- a/tools/hermit_proxy/Cargo.lock +++ b/tools/hermit_proxy/Cargo.lock @@ -1,12 +1,12 @@ [root] -name = "hermitcore_proxy" +name = "hermit_proxy" version = "0.0.1" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "elf 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -26,6 +26,11 @@ name = "bitflags" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "0.5.3" @@ -80,7 +85,17 @@ dependencies = [ [[package]] name = "inotify" -version = "0.3.0" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inotify-sys" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -192,6 +207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" +"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" @@ -199,7 +215,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2c858c42ac0b88532f48fca88b0ed947cad4f1f64d904bcd6c9f138f7b95d70" "checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf" -"checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" +"checksum inotify 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "225d83a068eae55f4e374c7026d78f31d2d5f54ded985c3b477cb66a66560a31" +"checksum inotify-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c13b3df0799ab6ba49e0dcfa9d3f0e787cd6895b693053f98609bc718ffd0dd5" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" diff --git a/tools/hermit_proxy/Cargo.toml b/tools/hermit_proxy/Cargo.toml old mode 100644 new mode 100755 index be80a4004..1712b41ae --- a/tools/hermit_proxy/Cargo.toml +++ b/tools/hermit_proxy/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "hermitcore_proxy" +name = "hermit_proxy" version = "0.0.1" authors = ["bytesnake "] @@ -9,7 +9,7 @@ nix = "0.8.0" memmap = "0.5.2" elf = "0.0.10" errno = "0.2.3" -inotify = "0.3" +inotify = "0.4" byteorder = "1" log = "0.3" env_logger = "0.3" diff --git a/tools/hermit_proxy/cmake/Findcargo.cmake b/tools/hermit_proxy/cmake/Findcargo.cmake new file mode 100644 index 000000000..4544fc82d --- /dev/null +++ b/tools/hermit_proxy/cmake/Findcargo.cmake @@ -0,0 +1,25 @@ +# Copyright (c) 2014 SiegeLord +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. + +find_program(CARGO_EXECUTABLE cargo) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(cargo DEFAULT_MSG CARGO_EXECUTABLE) +mark_as_advanced(CARGO_EXECUTABLE) diff --git a/tools/hermit_proxy/cmake/Findrustc.cmake b/tools/hermit_proxy/cmake/Findrustc.cmake new file mode 100644 index 000000000..dc6b53837 --- /dev/null +++ b/tools/hermit_proxy/cmake/Findrustc.cmake @@ -0,0 +1,33 @@ +# Copyright (c) 2014 SiegeLord +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. + +find_program(RUSTC_EXECUTABLE rustc) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(rustc DEFAULT_MSG RUSTC_EXECUTABLE) +mark_as_advanced(RUSTC_EXECUTABLE) + +execute_process(COMMAND ${RUSTC_EXECUTABLE} -Vv + OUTPUT_VARIABLE RUSTC_TARGET_TRIPLE + OUTPUT_STRIP_TRAILING_WHITESPACE) +string(REGEX MATCH "host:[ \t](.*)\nrel" RUSTC_TARGET_TRIPLE "${RUSTC_TARGET_TRIPLE}") +string(REGEX REPLACE "host:[ \t](.*)\nrel" "\\1" RUSTC_TARGET_TRIPLE "${RUSTC_TARGET_TRIPLE}") +set(RUSTC_TARGET_TRIPLE "${RUSTC_TARGET_TRIPLE}" CACHE STRING "Target triple you can pass to rustc (not passed by default)") +mark_as_advanced(RUSTC_TARGET_TRIPLE) diff --git a/tools/hermit_proxy/cmake/Findrustdoc.cmake b/tools/hermit_proxy/cmake/Findrustdoc.cmake new file mode 100644 index 000000000..a3650e4aa --- /dev/null +++ b/tools/hermit_proxy/cmake/Findrustdoc.cmake @@ -0,0 +1,25 @@ +# Copyright (c) 2014 SiegeLord +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. + +find_program(RUSTDOC_EXECUTABLE rustdoc) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(rustdoc DEFAULT_MSG RUSTDOC_EXECUTABLE) +mark_as_advanced(RUSTDOC_EXECUTABLE) diff --git a/tools/hermit_proxy/cmake/Rust.cmake b/tools/hermit_proxy/cmake/Rust.cmake new file mode 100644 index 000000000..49348d92a --- /dev/null +++ b/tools/hermit_proxy/cmake/Rust.cmake @@ -0,0 +1,356 @@ +# Copyright (c) 2014 SiegeLord +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. + +# Defines a few macros, variables and a function to help with compiling Rust +# programs/libraries and documentation with CMake. +# +# This file utilizes several global variables: +# +# RUSTC_EXECUTABLE - Filename of the rustc executable. You can fill it in using the Findrustc package. +# RUSTDOC_EXECUTABLE - Filename of the rustc executable. You can fill it in using the Findrustdoc package. +# RUSTC_FLAGS - These get passed to rustc. +# RUSTDOC_FLAGS - These flags get passed to rustdoc. + +include(CMakeParseArguments) + +if(NOT RUSTC_FLAGS) + set(RUSTC_FLAGS "" CACHE STRING "Flags to pass to the Rust compiler.") +endif() +mark_as_advanced(RUSTC_FLAGS) + +if(NOT RUSTDOC_FLAGS) + set(RUSTDOC_FLAGS "" CACHE STRING "Flags to pass to Rustdoc.") +endif() +mark_as_advanced(RUSTDOC_FLAGS) + +# Fetches the dependencies of a Rust crate with local crate root located at +# local_root_file and places them into out_var. Optionally also builds the crate. +# +# Optional arguments: +# OTHER_RUSTC_FLAGS flags - Other flags to pass to rustc. +# DESTINATION destination - If compiling, where to place the compilation artifacts. +# COMPILE - Whether or not to produce artifacts (it won't by default). +# NOTE! This will force the compillation of this crate every time the +# project is reconfigured, so use with care! +# +# NOTE: Only the first target's dependencies are fetched! +function(get_rust_deps local_root_file out_var) + cmake_parse_arguments("OPT" "COMPILE" "DESTINATION" "OTHER_RUSTC_FLAGS" ${ARGN}) + + set(root_file "${CMAKE_CURRENT_SOURCE_DIR}/${local_root_file}") + + set(dep_dir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/.cmake_rust_dependencies") + file(MAKE_DIRECTORY "${dep_dir}") + + if(OPT_COMPILE) + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}") + set(flags --out-dir "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}") + message(STATUS "Compiling Rust dependency info for crate root ${local_root_file}") + # XXX: It'd be nice if this wasn't a separate operation (need to handle the dep file location being different, or rewrite this macro thing) + execute_process(COMMAND ${RUSTC_EXECUTABLE} ${RUSTC_FLAGS} ${OPT_OTHER_RUSTC_FLAGS} ${flags} "${root_file}") + endif() + + set(flags "-Zno-analysis") + message(STATUS "Getting Rust dependency info for crate root ${local_root_file}") + + execute_process(COMMAND ${RUSTC_EXECUTABLE} ${RUSTC_FLAGS} ${OPT_OTHER_RUSTC_FLAGS} ${flags} --emit dep-info -o "${dep_dir}/deps.d" "${root_file}") + + # Read and parse the dependency information + file(STRINGS "${dep_dir}/deps.d" crate_deps LIMIT_COUNT 1) + file(REMOVE "${dep_dir}/deps.d") + string(REGEX REPLACE ".*: (.*)" "\\1" crate_deps "${crate_deps}") + string(STRIP "${crate_deps}" crate_deps) + string(REPLACE " " ";" crate_deps "${crate_deps}") + + # Make the dependencies be relative to the source directory + set(crate_deps_relative "") + foreach(var IN ITEMS ${crate_deps}) + file(TO_CMAKE_PATH "${var}" var) + file(RELATIVE_PATH var "${CMAKE_CURRENT_SOURCE_DIR}" "${var}") + list(APPEND crate_deps_relative "${var}") + # Hack to re-run CMake if the file changes + configure_file("${var}" "${dep_dir}/${var}" COPYONLY) + endforeach() + + set(${out_var} "${crate_deps_relative}" PARENT_SCOPE) +endfunction() + +# Adds a target to build a rust crate with the crate root located at local_root_file. +# The compilation output is placed inside DESTINATION within the build directory. +# +# Please pass the crate dependencies obtained through get_rust_deps to the dependencies argument in +# addition to other targets/files you want this target to depend on. +# +# Optional arguments: +# +# ALL - Pass this to make this crate be built by default. +# DESTINATION dest - Where to place the compilation artifacts. +# TARGET_NAME target - Target name for the command to build this crate. +# DEPENDS depends - List of dependencies of this crate. +# OTHER_RUSTC_FLAGS flags - Other flags to pass to rustc. +# +# This function sets two variables: +# +# ${target_name}_FULL_TARGET - This is what you would use as a set of dependencies +# for other targets when you want them to depend on the +# output of this target. +# +# ${target_name}_ARTIFACTS - The actual files generated by this command. +# You'd use this as a set of files to install/copy elsewhere. +function(rust_crate local_root_file) + cmake_parse_arguments("OPT" "ALL" "DESTINATION;TARGET_NAME" "DEPENDS;OTHER_RUSTC_FLAGS" ${ARGN}) + + if(NOT OPT_TARGET_NAME) + set(OPT_TARGET_NAME CRATE) + endif() + + if(OPT_ALL) + set(ALL_ARG "ALL") + else() + set(ALL_ARG "") + endif() + + set(root_file "${CMAKE_CURRENT_SOURCE_DIR}/${local_root_file}") + + execute_process(COMMAND ${RUSTC_EXECUTABLE} ${RUSTC_FLAGS} ${OPT_OTHER_RUSTC_FLAGS} --print file-names "${root_file}" + OUTPUT_VARIABLE rel_crate_filenames + OUTPUT_STRIP_TRAILING_WHITESPACE) + + # Split up the names into a list + string(REGEX MATCHALL "[^\n\r]+" rel_crate_filenames "${rel_crate_filenames}") + + set(comment "Building ") + set(crate_filenames "") + set(first TRUE) + foreach(name IN ITEMS ${rel_crate_filenames}) + if(${first}) + set(first FALSE) + else() + set(comment "${comment}, ") + endif() + set(comment "${comment}${OPT_DESTINATION}/${name}") + list(APPEND crate_filenames "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}/${name}") + endforeach() + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}") + + add_custom_command(OUTPUT ${crate_filenames} + COMMAND ${RUSTC_EXECUTABLE} ${RUSTC_FLAGS} ${OPT_OTHER_RUSTC_FLAGS} --out-dir "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}" "${root_file}" + DEPENDS ${crate_deps_list} + DEPENDS ${OPT_DEPENDS} + COMMENT "${comment}") + + add_custom_target("${OPT_TARGET_NAME}" + ${ALL_ARG} + DEPENDS ${crate_filenames}) + + set("${OPT_TARGET_NAME}_ARTIFACTS" "${crate_filenames}" PARENT_SCOPE) + # CMake Bug #10082 + set("${OPT_TARGET_NAME}_FULL_TARGET" "${OPT_TARGET_NAME};${crate_filenames}" PARENT_SCOPE) +endfunction() + +# Like rust_crate, but fetches the crate dependencies for you. This is convenient +# but inefficient if you want to compile the crate several times with different +# configurations (e.g. with --test and without) or if you want to build documentation. +# +# Optional arguments: +# +# ALL - Pass this to make this crate be built by default. +# DESTINATION dest - Where to place the compilation artifacts. +# TARGET_NAME target - Target name for the command to build this crate. +# DEPENDS depends - List of dependencies of this crate. +# OTHER_RUSTC_FLAGS flags - Other flags to pass to rustc. +# +# This function sets two variables: +# +# ${target_name}_FULL_TARGET - This is what you would use as a set of dependencies +# for other targets when you want them to depend on the +# output of this target. +# +# ${target_name}_ARTIFACTS - The actual files generated by this command. +# You'd use this as a set of files to install/copy elsewhere. +function(rust_crate_auto local_root_file) + cmake_parse_arguments("OPT" "ALL" "DESTINATION;TARGET_NAME" "DEPENDS;OTHER_RUSTC_FLAGS" ${ARGN}) + + if(NOT OPT_TARGET_NAME) + set(OPT_TARGET_NAME CRATE) + endif() + + if(OPT_ALL) + set(ALL_ARG "ALL") + else() + set(ALL_ARG "") + endif() + + get_rust_deps(${local_root_file} crate_deps_list + OTHER_RUSTC_FLAGS ${OPT_OTHER_RUSTC_FLAGS}) + + rust_crate("${local_root_file}" + ${ALL_ARG} + TARGET_NAME "${OPT_TARGET_NAME}" + DESTINATION "${OPT_DESTINATION}" + DEPENDS "${crate_deps_list};${OPT_DEPENDS}" + OTHER_RUSTC_FLAGS ${OPT_OTHER_RUSTC_FLAGS}) + set("${OPT_TARGET_NAME}_ARTIFACTS" "${${OPT_TARGET_NAME}_ARTIFACTS}" PARENT_SCOPE) + set("${OPT_TARGET_NAME}_FULL_TARGET" "${${OPT_TARGET_NAME}_FULL_TARGET}" PARENT_SCOPE) +endfunction(rust_crate_auto) + +# Like rust_crate, but this time it generates documentation using rust_doc. +# +# Optional arguments: +# +# ALL - Pass this to make this crate be built by default. +# DESTINATION dest - Where to place the compilation artifacts. +# TARGET_NAME target - Target name for the command to build this crate. +# DEPENDS depends - List of dependencies of this crate. +# OTHER_RUSTC_FLAGS flags - Other flags to pass to rustc. +# OTHER_RUSTDOC_FLAGS flags - Other flags to pass to rustdoc. +# +# This function sets two variables: +# +# ${target_name}_FULL_TARGET - This is what you would use as a set of dependencies +# for other targets when you want them to depend on the +# output of this target. +# +# ${target_name}_ARTIFACTS - The actual files generated by this command. +# You'd use this as a set of files to install/copy elsewhere. +function(rust_doc local_root_file) + cmake_parse_arguments("OPT" "ALL" "DESTINATION;TARGET_NAME" "DEPENDS;OTHER_RUSTDOC_FLAGS;OTHER_RUSTC_FLAGS" ${ARGN}) + + if(NOT OPT_TARGET_NAME) + set(OPT_TARGET_NAME DOC) + endif() + + if(OPT_ALL) + set(ALL_ARG "ALL") + else() + set(ALL_ARG "") + endif() + + set(root_file "${CMAKE_CURRENT_SOURCE_DIR}/${local_root_file}") + + execute_process(COMMAND ${RUSTC_EXECUTABLE} ${RUSTC_FLAGS} ${OPT_OTHER_RUSTC_FLAGS} --print crate-name "${root_file}" + OUTPUT_VARIABLE crate_name + OUTPUT_STRIP_TRAILING_WHITESPACE) + + set(doc_dir "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}/${crate_name}") + set(src_dir "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}/src/${crate_name}") + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}") + + add_custom_command(OUTPUT "${doc_dir}/index.html" "${doc_dir}" "${src_dir}" + COMMAND ${RUSTDOC_EXECUTABLE} ${RUSTDOC_FLAGS} ${OPT_OTHER_RUSTDOC_FLAGS} -o "${CMAKE_CURRENT_BINARY_DIR}/${OPT_DESTINATION}" "${root_file}" + DEPENDS ${crate_deps_list} + DEPENDS ${OPT_DEPENDS}) + + add_custom_target("${OPT_TARGET_NAME}" + ${ALL_ARG} + DEPENDS "${doc_dir}/index.html") + + set("${OPT_TARGET_NAME}_ARTIFACTS" "${doc_dir};${src_dir}" PARENT_SCOPE) + # CMake Bug #10082 + set("${OPT_TARGET_NAME}_FULL_TARGET" "${OPT_TARGET_NAME};${doc_dir}/index.html" PARENT_SCOPE) +endfunction() + +# Like rust_crate_auto, but this time it generates documentation using rust_doc. +# +# Optional arguments: +# +# ALL - Pass this to make this crate be built by default. +# DESTINATION dest - Where to place the compilation artifacts. +# TARGET_NAME target - Target name for the command to build this crate. +# DEPENDS depends - List of dependencies of this crate. +# OTHER_RUSTC_FLAGS flags - Other flags to pass to rustc. +# OTHER_RUSTDOC_FLAGS flags - Other flags to pass to rustdoc. +# +# This function sets two variables: +# +# ${target_name}_FULL_TARGET - This is what you would use as a set of dependencies +# for other targets when you want them to depend on the +# output of this target. +# +# ${target_name}_ARTIFACTS - The actual files generated by this command. +# You'd use this as a set of files to install/copy elsewhere. +function(rust_doc_auto local_root_file) + cmake_parse_arguments("OPT" "ALL" "DESTINATION;TARGET_NAME" "DEPENDS;OTHER_RUSTC_FLAGS;OTHER_RUSTDOC_FLAGS" ${ARGN}) + + if(NOT OPT_TARGET_NAME) + set(OPT_TARGET_NAME DOC) + endif() + + if(OPT_ALL) + set(ALL_ARG "ALL") + else() + set(ALL_ARG "") + endif() + + get_rust_deps(${local_root_file} crate_deps_list + OTHER_RUSTC_FLAGS ${OPT_OTHER_RUSTC_FLAGS}) + + rust_doc("${local_root_file}" + ${ALL_ARG} + TARGET_NAME "${OPT_TARGET_NAME}" + DESTINATION "${OPT_DESTINATION}" + DEPENDS "${crate_deps_list};${OPT_DEPENDS}" + OTHER_RUSTC_FLAGS ${OPT_OTHER_RUSTC_FLAGS} + OTHER_RUSTDOC_FLAGS ${OPT_OTHER_RUSTDOC_FLAGS}) + set("${OPT_TARGET_NAME}_ARTIFACTS" "${${OPT_TARGET_NAME}_ARTIFACTS}" PARENT_SCOPE) + set("${OPT_TARGET_NAME}_FULL_TARGET" "${${OPT_TARGET_NAME}_FULL_TARGET}" PARENT_SCOPE) +endfunction() + +# Creates a dummy cargo project named ${name} to fetch crates.io dependencies. +# The package will be created in the ${CMAKE_CURRENT_BINARY_DIR}. Typically you +# would then pass "-L ${CMAKE_CURRENT_BINARY_DIR}/target/debug/deps" to rustc so +# it can pick up the dependencies. +# +# Optional arguments: +# +# OTHER_CARGO_FLAGS - Flags to pass to cargo. +# PACKAGE_NAMES - List of package names to fetch. +# PACKAGE_VERSIONS - List of package versions to fetch. +function(cargo_dependency name) + cmake_parse_arguments("OPT" "" "" "OTHER_CARGO_FLAGS;PACKAGE_NAMES;PACKAGE_VERSIONS" ${ARGN}) + + list(LENGTH OPT_PACKAGE_NAMES num_packages) + list(LENGTH OPT_PACKAGE_VERSIONS num_versions) + message(STATUS "" ${OPT_PACKAGE_NAMES} " : " ${OPT_PACKAGE_VERSIONS}) + + if(NOT ${num_packages} EQUAL ${num_versions}) + message(FATAL_ERROR "Number of cargo packages doesn't match the number of cargo versions.") + endif() + + set(cargo_dependency_dir "${CMAKE_CURRENT_BINARY_DIR}/${name}") + file(MAKE_DIRECTORY "${cargo_dependency_dir}") + file(MAKE_DIRECTORY "${cargo_dependency_dir}/src") + + set(CARGO_TOML [package] \n name = \"cargo_deps_fetcher\" \n version = \"0.0.0\" \n authors = [\"none\"] \n) + + math(EXPR num_packages "${num_packages} - 1") + foreach(pkg_idx RANGE 0 ${num_packages}) + list(GET OPT_PACKAGE_NAMES ${pkg_idx} pkg_name) + list(GET OPT_PACKAGE_VERSIONS ${pkg_idx} pkg_version) + set(CARGO_TOML ${CARGO_TOML} \n [dependencies.${pkg_name}] \n version = \"${pkg_version}\" \n) + endforeach() + + file(WRITE "${cargo_dependency_dir}/Cargo.toml" ${CARGO_TOML}) + file(WRITE "${cargo_dependency_dir}/src/lib.rs" "") + + execute_process(COMMAND ${CARGO_EXECUTABLE} build ${CARGO_FLAGS} ${OPT_OTHER_CARGO_FLAGS} + WORKING_DIRECTORY ${cargo_dependency_dir}) +endfunction() diff --git a/tools/hermit_proxy/src/error.rs b/tools/hermit_proxy/src/error.rs index 54406990e..dc347ffe8 100644 --- a/tools/hermit_proxy/src/error.rs +++ b/tools/hermit_proxy/src/error.rs @@ -13,7 +13,8 @@ pub enum Error { MissingFrequency, MultiIsleFailed, CannotCreateTmpFile(usize), - QEmu((String, String)) + QEmu((String, String)), + MissingBinary } impl fmt::Debug for Error { @@ -31,7 +32,8 @@ impl fmt::Debug for Error { Error::MissingFrequency => write!(f, "Couldn't get the CPU frequency from you system. (is /proc/cpuinfo missing?)"), Error::MultiIsleFailed => write!(f, "The Multi isle was selected on a system without supported, please load the kernel driver."), Error::CannotCreateTmpFile(_) => write!(f, "Couldn't create a tmp file in /tmp."), - Error::QEmu((_, ref stderr)) => write!(f, "The qemu binary has encountered an error: {}", stderr) + Error::QEmu((_, ref stderr)) => write!(f, "The qemu binary has encountered an error: {}", stderr), + Error::MissingBinary => write!(f, "Please specify a binary.") } } } diff --git a/tools/hermit_proxy/src/hermit.rs b/tools/hermit_proxy/src/hermit.rs index fc369b5ea..9eb165f0e 100644 --- a/tools/hermit_proxy/src/hermit.rs +++ b/tools/hermit_proxy/src/hermit.rs @@ -2,8 +2,7 @@ use std::env; use std::fs::File; use std::path::Path; use std::io::{Write, Read, BufReader, BufRead}; -use inotify::INotify; -use inotify::ffi::{IN_MODIFY, IN_CREATE}; +use inotify::{Inotify, watch_mask}; use hermit_env; use qemu::QEmu; @@ -68,28 +67,38 @@ impl IsleKind { } Ok(false) - - //debug!("HERMIT - isle log contains: {}", result); - - //Ok(result == "TCP server is listening.") } - pub fn wait_available(&self) -> Result<()> { + pub fn wait_available(&mut self) -> Result<()> { debug!("HERMIT - wait to be available"); - let mut ino = INotify::init().unwrap(); + let mut ino = Inotify::init().unwrap(); match *self { - IsleKind::QEMU(_) => ino.add_watch(Path::new("/tmp"), IN_MODIFY | IN_CREATE).unwrap(), - IsleKind::MULTI(_) => ino.add_watch(Path::new("/sys/hermit"), IN_MODIFY | IN_CREATE).unwrap(), + IsleKind::QEMU(_) => ino.add_watch(Path::new("/tmp"), watch_mask::MODIFY | watch_mask::CREATE).unwrap(), + IsleKind::MULTI(_) => ino.add_watch(Path::new("/sys/hermit"), watch_mask::MODIFY | watch_mask::CREATE).unwrap(), IsleKind::UHYVE(_) => return Ok(()) }; + let mut buffer = [0; 1024]; loop { - let events = ino.wait_for_events().unwrap(); + //debug!("Wait ... "); + if let Some(_) = ino.read_events(&mut buffer).unwrap().next() { + if self.is_available()? { + return Ok(()); + } + } - if self.is_available()? { - return Ok(()); + if let IsleKind::QEMU(ref mut obj) = *self { + let (stdout,stderr) = obj.output(); + + if stderr != "" { + return Err(Error::QEmu((stdout, stderr))); + } + + if stdout != "" { + debug!("stdout: {}", stdout); + } } } } diff --git a/tools/hermit_proxy/src/main.rs b/tools/hermit_proxy/src/main.rs index 64d996971..cb0f35383 100644 --- a/tools/hermit_proxy/src/main.rs +++ b/tools/hermit_proxy/src/main.rs @@ -37,17 +37,20 @@ extern fn exit(_:i32) { fn main() { env_logger::init().unwrap(); + // register a signal let sig_action = signal::SigAction::new(signal::SigHandler::Handler(exit), signal::SaFlags::empty(), signal::SigSet::empty()); unsafe { signal::sigaction(signal::SIGINT, &sig_action).unwrap(); signal::sigaction(signal::SIGTERM, &sig_action).unwrap(); } - if let Some(path) = env::args().skip(1).next() { - let isle = hermit::IsleKind::new(&path).unwrap(); + // create the isle, wait to be available and start it + env::args().skip(1).next().ok_or(error::Error::MissingBinary) + .and_then(|path| hermit::IsleKind::new(&path)) + .and_then(|mut isle| { + isle.wait_available()?; + isle.run()?; - isle.wait_available(); - - isle.run(); - } + Ok(()) + }).unwrap(); } diff --git a/tools/hermit_proxy/src/qemu.rs b/tools/hermit_proxy/src/qemu.rs index bc3dec0ed..d763039ba 100644 --- a/tools/hermit_proxy/src/qemu.rs +++ b/tools/hermit_proxy/src/qemu.rs @@ -5,6 +5,7 @@ use std::process::{Stdio, Child, Command}; use libc; use std::fs::File; use std::io::Read; +use std::process::{ChildStdout, ChildStderr}; use hermit_env; use socket::Socket; @@ -16,6 +17,8 @@ const TMPNAME: &'static str = "/tmp/hermit-XXXXXX"; pub struct QEmu { socket: Socket, child: Child, + stdout: ChildStdout, + stderr: ChildStderr, tmp_file: String, pid_file: String, } @@ -26,10 +29,14 @@ impl QEmu { let pidf = utils::create_tmp_file(PIDNAME)?; let mut child = QEmu::start_with(path, &tmpf, &pidf)?.spawn().expect("Couldn't find qemu binary!"); + let stdout = child.stdout.take().unwrap(); + let stderr = child.stderr.take().unwrap(); Ok(QEmu { socket: Socket::new_qemu(), child: child, + stdout: stdout, + stderr: stderr, tmp_file: tmpf, pid_file: pidf }) @@ -111,8 +118,19 @@ impl QEmu { cmd.args(args).stdout(Stdio::piped()).stderr(Stdio::piped()); + Ok(cmd) } + + pub fn output(&mut self) -> (String, String) { + let mut stderr = String::new(); + let mut stdout = String::new(); + + self.stdout.read_to_string(&mut stdout); + self.stderr.read_to_string(&mut stderr); + + (stdout, stderr) + } } impl Drop for QEmu {