Skip to content

Commit c3600d4

Browse files
arhelmusfacebook-github-bot
authored andcommitted
Forced watchman daemon to always operate in non elevated mode on Windows (#878)
Summary: Recently I found that its impossible to access elevated Watchman daemon from non-elevated process on Windows. ``` events.js:174 throw er; // Unhandled 'error' event ^ Error: connect EPERM \\.\pipe\watchman at PipeConnectWrap.afterConnect [as oncomplete] (net.js:1106:14) Emitted 'error' event at: at Socket.<anonymous> (C:\open\ovrsource\unity\socialvr\_js\node_modules\fb-watchman\index.js:118:12) at Socket.emit (events.js:198:13) at emitErrorNT (internal/streams/destroy.js:91:8) at emitErrorAndCloseNT (internal/streams/destroy.js:59:3) at process._tickCallback (internal/process/next_tick.js:63:19) ``` To fix this, it was suggested by wez to use [his library](https://github.com/wez/EleDo) to force Watchman daemon always start in normal mode on Windows. In this stack of commits I did integrated his library into project and used it to force daemon restart in normal mode when spawned from elevated terminal. To make it happen, I checked-in library sources and created proxy project which depends on the initial library and contains header bindings and cmake configuration. I did copy pasted Rust cmake macroses from another facebook project - eden, and also created analogue of autogen.sh but for Windows - autogen.cmd. Pull Request resolved: facebook/watchman#878 Test Plan: Launch elevated terminal Start watchman.exe produced from sources Observe daemon starting and answering In process monitor, observe watchman.exe process running under user group Reviewed By: fanzeyi Differential Revision: D25595879 Pulled By: arhelmus fbshipit-source-id: 15eb29adcf5bd4a5708b6533a1b2bacbf13f431c
1 parent 77af933 commit c3600d4

File tree

3 files changed

+296
-0
lines changed

3 files changed

+296
-0
lines changed
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
include(FBCMakeParseArgs)
2+
3+
set(
4+
USE_CARGO_VENDOR AUTO CACHE STRING
5+
"Download Rust Crates from an internally vendored location"
6+
)
7+
set_property(CACHE USE_CARGO_VENDOR PROPERTY STRINGS AUTO ON OFF)
8+
9+
set(RUST_VENDORED_CRATES_DIR "$ENV{RUST_VENDORED_CRATES_DIR}")
10+
if("${USE_CARGO_VENDOR}" STREQUAL "AUTO")
11+
if(EXISTS "${RUST_VENDORED_CRATES_DIR}")
12+
set(USE_CARGO_VENDOR ON)
13+
else()
14+
set(USE_CARGO_VENDOR OFF)
15+
endif()
16+
endif()
17+
18+
if(USE_CARGO_VENDOR)
19+
if(NOT EXISTS "${RUST_VENDORED_CRATES_DIR}")
20+
message(
21+
FATAL "vendored rust crates not present: "
22+
"${RUST_VENDORED_CRATES_DIR}"
23+
)
24+
endif()
25+
26+
set(RUST_CARGO_HOME "${CMAKE_BINARY_DIR}/_cargo_home")
27+
file(MAKE_DIRECTORY "${RUST_CARGO_HOME}")
28+
29+
file(
30+
TO_NATIVE_PATH "${RUST_VENDORED_CRATES_DIR}"
31+
ESCAPED_RUST_VENDORED_CRATES_DIR
32+
)
33+
string(
34+
REPLACE "\\" "\\\\"
35+
ESCAPED_RUST_VENDORED_CRATES_DIR
36+
"${ESCAPED_RUST_VENDORED_CRATES_DIR}"
37+
)
38+
file(
39+
WRITE "${RUST_CARGO_HOME}/config"
40+
"[source.crates-io]\n"
41+
"replace-with = \"vendored-sources\"\n"
42+
"\n"
43+
"[source.vendored-sources]\n"
44+
"directory = \"${ESCAPED_RUST_VENDORED_CRATES_DIR}\"\n"
45+
)
46+
endif()
47+
48+
# Cargo is a build system in itself, and thus will try to take advantage of all
49+
# the cores on the system. Unfortunately, this conflicts with Ninja, since it
50+
# also tries to utilize all the cores. This can lead to a system that is
51+
# completely overloaded with compile jobs to the point where nothing else can
52+
# be achieved on the system.
53+
#
54+
# Let's inform Ninja of this fact so it won't try to spawn other jobs while
55+
# Rust being compiled.
56+
set_property(GLOBAL APPEND PROPERTY JOB_POOLS rust_job_pool=1)
57+
58+
# This function creates an interface library target based on the static library
59+
# built by Cargo. It will call Cargo to build a staticlib and generate a CMake
60+
# interface library with it.
61+
#
62+
# This function requires `find_package(Python COMPONENTS Interpreter)`.
63+
#
64+
# You need to set `lib:crate-type = ["staticlib"]` in your Cargo.toml to make
65+
# Cargo build static library.
66+
#
67+
# ```cmake
68+
# rust_static_library(<TARGET> [CRATE <CRATE_NAME>])
69+
# ```
70+
#
71+
# Parameters:
72+
# - TARGET:
73+
# Name of the target name. This function will create an interface library
74+
# target with this name.
75+
# - CRATE_NAME:
76+
# Name of the crate. This parameter is optional. If unspecified, it will
77+
# fallback to `${TARGET}`.
78+
#
79+
# This function creates two targets:
80+
# - "${TARGET}": an interface library target contains the static library built
81+
# from Cargo.
82+
# - "${TARGET}.cargo": an internal custom target that invokes Cargo.
83+
#
84+
# If you are going to use this static library from C/C++, you will need to
85+
# write header files for the library (or generate with cbindgen) and bind these
86+
# headers with the interface library.
87+
#
88+
function(rust_static_library TARGET)
89+
fb_cmake_parse_args(ARG "" "CRATE" "" "${ARGN}")
90+
91+
if(DEFINED ARG_CRATE)
92+
set(crate_name "${ARG_CRATE}")
93+
else()
94+
set(crate_name "${TARGET}")
95+
endif()
96+
97+
set(cargo_target "${TARGET}.cargo")
98+
set(target_dir $<IF:$<CONFIG:Debug>,debug,release>)
99+
set(staticlib_name "${CMAKE_STATIC_LIBRARY_PREFIX}${crate_name}${CMAKE_STATIC_LIBRARY_SUFFIX}")
100+
set(rust_staticlib "${CMAKE_CURRENT_BINARY_DIR}/${target_dir}/${staticlib_name}")
101+
102+
set(cargo_cmd cargo)
103+
if(WIN32)
104+
set(cargo_cmd cargo.exe)
105+
endif()
106+
107+
set(cargo_flags build $<IF:$<CONFIG:Debug>,,--release> -p ${crate_name})
108+
if(USE_CARGO_VENDOR)
109+
set(extra_cargo_env "CARGO_HOME=${RUST_CARGO_HOME}")
110+
set(cargo_flags ${cargo_flags})
111+
endif()
112+
113+
add_custom_target(
114+
${cargo_target}
115+
COMMAND
116+
"${CMAKE_COMMAND}" -E remove -f "${CMAKE_CURRENT_SOURCE_DIR}/Cargo.lock"
117+
COMMAND
118+
"${CMAKE_COMMAND}" -E env
119+
"CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR}"
120+
${extra_cargo_env}
121+
${cargo_cmd}
122+
${cargo_flags}
123+
COMMENT "Building Rust crate '${crate_name}'..."
124+
JOB_POOL rust_job_pool
125+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
126+
BYPRODUCTS
127+
"${CMAKE_CURRENT_BINARY_DIR}/debug/${staticlib_name}"
128+
"${CMAKE_CURRENT_BINARY_DIR}/release/${staticlib_name}"
129+
)
130+
131+
add_library(${TARGET} INTERFACE)
132+
add_dependencies(${TARGET} ${cargo_target})
133+
set_target_properties(
134+
${TARGET}
135+
PROPERTIES
136+
INTERFACE_STATICLIB_OUTPUT_PATH "${rust_staticlib}"
137+
INTERFACE_INSTALL_LIBNAME
138+
"${CMAKE_STATIC_LIBRARY_PREFIX}${crate_name}_rs${CMAKE_STATIC_LIBRARY_SUFFIX}"
139+
)
140+
target_link_libraries(
141+
${TARGET}
142+
INTERFACE "$<BUILD_INTERFACE:${rust_staticlib}>"
143+
)
144+
endfunction()
145+
146+
# This function instructs cmake to define a target that will use `cargo build`
147+
# to build a bin crate referenced by the Cargo.toml file in the current source
148+
# directory.
149+
# It accepts a single `TARGET` parameter which will be passed as the package
150+
# name to `cargo build -p TARGET`. If binary has different name as package,
151+
# use optional flag BINARY_NAME to override it.
152+
# The cmake target will be registered to build by default as part of the
153+
# ALL target.
154+
function(rust_executable TARGET)
155+
fb_cmake_parse_args(ARG "" "BINARY_NAME" "" "${ARGN}")
156+
157+
set(crate_name "${TARGET}")
158+
set(cargo_target "${TARGET}.cargo")
159+
set(target_dir $<IF:$<CONFIG:Debug>,debug,release>)
160+
161+
if(DEFINED ARG_BINARY_NAME)
162+
set(executable_name "${ARG_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
163+
else()
164+
set(executable_name "${crate_name}${CMAKE_EXECUTABLE_SUFFIX}")
165+
endif()
166+
167+
set(cargo_cmd cargo)
168+
if(WIN32)
169+
set(cargo_cmd cargo.exe)
170+
endif()
171+
172+
set(cargo_flags build $<IF:$<CONFIG:Debug>,,--release> -p ${crate_name})
173+
if(USE_CARGO_VENDOR)
174+
set(extra_cargo_env "CARGO_HOME=${RUST_CARGO_HOME}")
175+
set(cargo_flags ${cargo_flags})
176+
endif()
177+
178+
add_custom_target(
179+
${cargo_target}
180+
ALL
181+
COMMAND
182+
"${CMAKE_COMMAND}" -E remove -f "${CMAKE_CURRENT_SOURCE_DIR}/Cargo.lock"
183+
COMMAND
184+
"${CMAKE_COMMAND}" -E env
185+
"CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR}"
186+
${extra_cargo_env}
187+
${cargo_cmd}
188+
${cargo_flags}
189+
COMMENT "Building Rust executable '${crate_name}'..."
190+
JOB_POOL rust_job_pool
191+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
192+
BYPRODUCTS
193+
"${CMAKE_CURRENT_BINARY_DIR}/debug/${executable_name}"
194+
"${CMAKE_CURRENT_BINARY_DIR}/release/${executable_name}"
195+
)
196+
197+
set_property(TARGET "${cargo_target}"
198+
PROPERTY EXECUTABLE "${CMAKE_CURRENT_BINARY_DIR}/${target_dir}/${executable_name}")
199+
endfunction()
200+
201+
# This function can be used to install the executable generated by a prior
202+
# call to the `rust_executable` function.
203+
# It requires a `TARGET` parameter to identify the target to be installed,
204+
# and an optional `DESTINATION` parameter to specify the installation
205+
# directory. If DESTINATION is not specified then the `bin` directory
206+
# will be assumed.
207+
function(install_rust_executable TARGET)
208+
# Parse the arguments
209+
set(one_value_args DESTINATION)
210+
set(multi_value_args)
211+
fb_cmake_parse_args(
212+
ARG "" "${one_value_args}" "${multi_value_args}" "${ARGN}"
213+
)
214+
215+
if(NOT DEFINED ARG_DESTINATION)
216+
set(ARG_DESTINATION bin)
217+
endif()
218+
219+
get_target_property(foo "${TARGET}.cargo" EXECUTABLE)
220+
221+
install(
222+
PROGRAMS "${foo}"
223+
DESTINATION "${ARG_DESTINATION}"
224+
)
225+
endfunction()
226+
227+
# This function installs the interface target generated from the function
228+
# `rust_static_library`. Use this function if you want to export your Rust
229+
# target to external CMake targets.
230+
#
231+
# ```cmake
232+
# install_rust_static_library(
233+
# <TARGET>
234+
# INSTALL_DIR <INSTALL_DIR>
235+
# [EXPORT <EXPORT_NAME>]
236+
# )
237+
# ```
238+
#
239+
# Parameters:
240+
# - TARGET: Name of the Rust static library target.
241+
# - EXPORT_NAME: Name of the exported target.
242+
# - INSTALL_DIR: Path to the directory where this library will be installed.
243+
#
244+
function(install_rust_static_library TARGET)
245+
fb_cmake_parse_args(ARG "" "EXPORT;INSTALL_DIR" "" "${ARGN}")
246+
247+
get_property(
248+
staticlib_output_path
249+
TARGET "${TARGET}"
250+
PROPERTY INTERFACE_STATICLIB_OUTPUT_PATH
251+
)
252+
get_property(
253+
staticlib_output_name
254+
TARGET "${TARGET}"
255+
PROPERTY INTERFACE_INSTALL_LIBNAME
256+
)
257+
258+
if(NOT DEFINED staticlib_output_path)
259+
message(FATAL_ERROR "Not a rust_static_library target.")
260+
endif()
261+
262+
if(NOT DEFINED ARG_INSTALL_DIR)
263+
message(FATAL_ERROR "Missing required argument.")
264+
endif()
265+
266+
if(DEFINED ARG_EXPORT)
267+
set(install_export_args EXPORT "${ARG_EXPORT}")
268+
endif()
269+
270+
set(install_interface_dir "${ARG_INSTALL_DIR}")
271+
if(NOT IS_ABSOLUTE "${install_interface_dir}")
272+
set(install_interface_dir "\${_IMPORT_PREFIX}/${install_interface_dir}")
273+
endif()
274+
275+
target_link_libraries(
276+
${TARGET} INTERFACE
277+
"$<INSTALL_INTERFACE:${install_interface_dir}/${staticlib_output_name}>"
278+
)
279+
install(
280+
TARGETS ${TARGET}
281+
${install_export_args}
282+
LIBRARY DESTINATION ${ARG_INSTALL_DIR}
283+
)
284+
install(
285+
FILES ${staticlib_output_path}
286+
RENAME ${staticlib_output_name}
287+
DESTINATION ${ARG_INSTALL_DIR}
288+
)
289+
endfunction()

build/fbcode_builder/getdeps.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ def parse_project_arg(arg, arg_type):
114114
elif len(parts) == 1:
115115
project = args.project
116116
path = parts[0]
117+
# On Windows path contains colon, e.g. C:\open
118+
elif os.name == "nt" and len(parts) == 3:
119+
project = parts[0]
120+
path = parts[1] + ":" + parts[2]
117121
else:
118122
raise UsageError(
119123
"invalid %s argument; too many ':' characters: %s" % (arg_type, arg)

build/fbcode_builder/manifests/watchman

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ folly
1919
pcre
2020
googletest
2121

22+
[dependencies.fb=on]
23+
rust
24+
2225
[shipit.pathmap]
2326
fbcode/watchman = .
2427
fbcode/eden/fs = eden/fs

0 commit comments

Comments
 (0)