diff --git a/NEWS.md b/NEWS.md index d31a2a94dadbb..f31509fb35120 100644 --- a/NEWS.md +++ b/NEWS.md @@ -165,6 +165,12 @@ Library improvements * The `libjulia` library is now properly versioned and installed to the public `/lib` directory, instead of the private `/lib/julia` directory. + * System reflection is now more consistently exposed from Sys and not Base. + `OS_NAME` has been replaced by `Sys.KERNEL` and always reports the name of the kernel (as reported by `uname`). + The `@windows_only` and `@osx` family of macros have been replaced with functions such as `is_windows()` and + or `is_apple()`. There's now also an `@static` macro that will evaluate the condition of an if-statement at + compile time, for when a static branch is required. + Deprecated or removed --------------------- diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 4264658c6c226..b3fe858b9ad1a 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -204,7 +204,7 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf write_prompt(termbuf, prompt) prompt = prompt_string(prompt) # Count the '\n' at the end of the line if the terminal emulator does (specific to DOS cmd prompt) - miscountnl = @windows ? (isa(Terminals.pipe_reader(terminal), Base.TTY) && !Base.ispty(Terminals.pipe_reader(terminal))) : false + miscountnl = @static is_windows() ? (isa(Terminals.pipe_reader(terminal), Base.TTY) && !Base.ispty(Terminals.pipe_reader(terminal))) : false lindent = strwidth(prompt) # Now go through the buffer line by line @@ -1564,7 +1564,7 @@ function run_interface(terminal, m::ModalInterface) p = s.current_mode buf, ok, suspend = prompt!(terminal, m, s) while suspend - @unix_only ccall(:jl_repl_raise_sigtstp, Cint, ()) + @static if is_unix(); ccall(:jl_repl_raise_sigtstp, Cint, ()); end buf, ok, suspend = prompt!(terminal, m, s) end mode(state(s, s.current_mode)).on_done(s, buf, ok) @@ -1604,7 +1604,7 @@ function prompt!(term, prompt, s = init_state(term, prompt)) elseif state == :done return buffer(s), true, false elseif state == :suspend - @unix_only begin + if is_unix() return buffer(s), true, true end else diff --git a/base/Makefile b/base/Makefile index 270877176528f..9fd1d56cc1db1 100644 --- a/base/Makefile +++ b/base/Makefile @@ -38,7 +38,6 @@ $(BUILDDIR)/uv_constants.jl: $(SRCDIR)/../src/uv_constants.h $(build_includedir) $(BUILDDIR)/build_h.jl.phony: @echo "# This file is automatically generated in base/Makefile" > $@ - @echo "const ARCH = :$(ARCH)" >> $@ ifeq ($(XC_HOST),) @echo "const MACHINE = \"$(BUILD_MACHINE)\"" >> $@ else diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 811417afe9d2e..c056987ae25d9 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -100,7 +100,7 @@ function complete_keyword(s::String) end function complete_path(path::AbstractString, pos; use_envpath=false) - if Base.is_unix(OS_NAME) && ismatch(r"^~(?:/|$)", path) + if Base.is_unix() && ismatch(r"^~(?:/|$)", path) # if the path is just "~", don't consider the expanded username as a prefix if path == "~" dir, prefix = homedir(), "" @@ -128,13 +128,13 @@ function complete_path(path::AbstractString, pos; use_envpath=false) if startswith(file, prefix) id = try isdir(joinpath(dir, file)) catch; false end # joinpath is not used because windows needs to complete with double-backslash - push!(matches, id ? file * (@windows? "\\\\" : "/") : file) + push!(matches, id ? file * (@static is_windows() ? "\\\\" : "/") : file) end end if use_envpath && length(dir) == 0 # Look for files in PATH as well - local pathdirs = split(ENV["PATH"], @unix? ":" : ";") + local pathdirs = split(ENV["PATH"], @static is_windows() ? ";" : ":") for pathdir in pathdirs local actualpath diff --git a/base/Terminals.jl b/base/Terminals.jl index 5e1483a5f5c1b..0a4bc09325f5c 100644 --- a/base/Terminals.jl +++ b/base/Terminals.jl @@ -116,7 +116,7 @@ cmove_line_up(t::UnixTerminal, n) = (cmove_up(t, n); cmove_col(t, 0)) cmove_line_down(t::UnixTerminal, n) = (cmove_down(t, n); cmove_col(t, 0)) cmove_col(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)G") -@windows ? begin +if is_windows() function raw!(t::TTYTerminal,raw::Bool) check_open(t.in_stream) if Base.ispty(t.in_stream) @@ -132,7 +132,7 @@ cmove_col(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)G") t.in_stream.handle, raw) != -1 end end -end : begin +else function raw!(t::TTYTerminal, raw::Bool) check_open(t.in_stream) ccall(:jl_tty_set_mode, Int32, (Ptr{Void},Int32), t.in_stream.handle, raw) != -1 @@ -151,14 +151,17 @@ clear(t::UnixTerminal) = write(t.out_stream, "\x1b[H\x1b[2J") clear_line(t::UnixTerminal) = write(t.out_stream, "\x1b[0G\x1b[0K") #beep(t::UnixTerminal) = write(t.err_stream,"\x7") -@unix_only function hascolor(t::TTYTerminal) - startswith(t.term_type, "xterm") && return true - try - return success(`tput setaf 0`) - catch - return false +if is_windows() + hascolor(t::TTYTerminal) = true +else + function hascolor(t::TTYTerminal) + startswith(t.term_type, "xterm") && return true + try + return success(`tput setaf 0`) + catch + return false + end end end -@windows_only hascolor(t::TTYTerminal) = true end # module diff --git a/base/array.jl b/base/array.jl index d549be8b83e73..9fadb7cdcdd9c 100644 --- a/base/array.jl +++ b/base/array.jl @@ -696,7 +696,7 @@ function vcat{T}(arrays::Vector{T}...) if isbits(T) elsz = sizeof(T) else - elsz = div(WORD_SIZE,8) + elsz = Core.sizeof(Ptr{Void}) end for a in arrays nba = length(a)*elsz diff --git a/base/atomics.jl b/base/atomics.jl index 7cfc6efe7e957..f602eb8812666 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -3,6 +3,7 @@ using Core.Intrinsics: llvmcall import Base: setindex!, getindex, unsafe_convert +import Base.Sys: ARCH, WORD_SIZE export Atomic, @@ -16,8 +17,8 @@ export # Disable 128-bit types on 32-bit Intel sytems due to LLVM problems; # see (fixed on LLVM 3.9) # 128-bit atomics do not exist on AArch32. -if (VersionNumber(Base.libllvm_version) < v"3.9-" && Base.ARCH === :i686) || - startswith(string(Base.ARCH), "arm") +if (VersionNumber(Base.libllvm_version) < v"3.9-" && ARCH === :i686) || + startswith(string(ARCH), "arm") const inttypes = (Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64) else diff --git a/base/c.jl b/base/c.jl index db6d0e371544b..4d62a4acaae9c 100644 --- a/base/c.jl +++ b/base/c.jl @@ -16,7 +16,7 @@ typealias Cshort Int16 typealias Cushort UInt16 typealias Cint Int32 typealias Cuint UInt32 -if OS_NAME === :Windows +if is_windows() typealias Clong Int32 typealias Culong UInt32 typealias Cwchar_t UInt16 @@ -35,7 +35,7 @@ typealias Culonglong UInt64 typealias Cfloat Float32 typealias Cdouble Float64 -if OS_NAME !== :Windows +if !is_windows() const sizeof_mode_t = ccall(:jl_sizeof_mode_t, Cint, ()) if sizeof_mode_t == 2 typealias Cmode_t Int16 @@ -95,11 +95,13 @@ convert(::Type{Cstring}, s::Symbol) = Cstring(unsafe_convert(Ptr{Cchar}, s)) # in string.jl: unsafe_convert(::Type{Cwstring}, s::WString) # FIXME: this should be handled by implicit conversion to Cwstring, but good luck with that -@windows_only function cwstring(s::AbstractString) +if is_windows() +function cwstring(s::AbstractString) bytes = String(s).data 0 in bytes && throw(ArgumentError("embedded NULs are not allowed in C strings: $(repr(s))")) return push!(utf8to16(bytes), 0) end +end # conversions between UTF-8 and UTF-16 for Windows APIs diff --git a/base/checked.jl b/base/checked.jl index 217f800e06b84..752986a634a1a 100644 --- a/base/checked.jl +++ b/base/checked.jl @@ -68,7 +68,7 @@ brokenSignedInt = Union{} brokenUnsignedInt = Union{} brokenSignedIntMul = Int128 brokenUnsignedIntMul = UInt128 -if WORD_SIZE == 32 +if Core.sizeof(Ptr{Void}) == 4 brokenSignedIntMul = Union{brokenSignedIntMul, Int64} brokenUnsignedIntMul = Union{brokenUnsignedIntMul, UInt64} end diff --git a/base/client.jl b/base/client.jl index 5a2c065ae56d0..43378f9cc2744 100644 --- a/base/client.jl +++ b/base/client.jl @@ -37,10 +37,13 @@ text_colors have_color = false default_color_warn = :red default_color_info = :blue -@unix_only default_color_input = :bold -@unix_only default_color_answer = :bold -@windows_only default_color_input = :normal -@windows_only default_color_answer = :normal +if is_windows() + default_color_input = :normal + default_color_answer = :normal +else + default_color_input = :bold + default_color_answer = :bold +end color_normal = text_colors[:normal] function repl_color(key, default) @@ -77,7 +80,7 @@ function repl_cmd(cmd, out) end cd(ENV["OLDPWD"]) else - cd(@windows? dir : readchomp(`$shell -c "echo $(shell_escape(dir))"`)) + cd(@static is_windows() ? dir : readchomp(`$shell -c "echo $(shell_escape(dir))"`)) end else cd() @@ -85,7 +88,7 @@ function repl_cmd(cmd, out) ENV["OLDPWD"] = new_oldpwd println(out, pwd()) else - run(ignorestatus(@windows? cmd : (isa(STDIN, TTY) ? `$shell -i -c "($(shell_escape(cmd))) && true"` : `$shell -c "($(shell_escape(cmd))) && true"`))) + run(ignorestatus(@static is_windows() ? cmd : (isa(STDIN, TTY) ? `$shell -i -c "($(shell_escape(cmd))) && true"` : `$shell -c "($(shell_escape(cmd))) && true"`))) end nothing end @@ -323,10 +326,10 @@ function _start() global active_repl_backend if repl if !isa(STDIN,TTY) - global is_interactive |= !isa(STDIN,Union{File,IOStream}) + global is_interactive |= !isa(STDIN, Union{File, IOStream}) color_set || (global have_color = false) else - term = Terminals.TTYTerminal(get(ENV,"TERM",@windows? "" : "dumb"),STDIN,STDOUT,STDERR) + term = Terminals.TTYTerminal(get(ENV, "TERM", @static is_windows() ? "" : "dumb"), STDIN, STDOUT, STDERR) global is_interactive = true color_set || (global have_color = Terminals.hascolor(term)) quiet || REPL.banner(term,term) diff --git a/base/complex.jl b/base/complex.jl index 2e88f8efa75e0..7b6b73ff0c8d3 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -760,22 +760,12 @@ function lexcmp(a::Complex, b::Complex) end #Rounding complex numbers -# Superfluous tuple splatting in return arguments is a work around for 32-bit systems (#10027) #Requires two different RoundingModes for the real and imaginary components - -if WORD_SIZE==32 -function round{T<:AbstractFloat, MR, MI}(z::Complex{T}, ::RoundingMode{MR}, ::RoundingMode{MI}) - Complex((round(real(z), RoundingMode{MR}()), - round(imag(z), RoundingMode{MI}()))...) -end -round(z::Complex) = Complex((round(real(z)), round(imag(z)))...) -else function round{T<:AbstractFloat, MR, MI}(z::Complex{T}, ::RoundingMode{MR}, ::RoundingMode{MI}) Complex(round(real(z), RoundingMode{MR}()), round(imag(z), RoundingMode{MI}())) end round(z::Complex) = Complex(round(real(z)), round(imag(z))) -end @vectorize_1arg Complex round diff --git a/base/dSFMT.jl b/base/dSFMT.jl index 95fdf8fe02e07..5107c79e18ba4 100644 --- a/base/dSFMT.jl +++ b/base/dSFMT.jl @@ -151,9 +151,9 @@ end ## Windows entropy -@windows_only begin +if is_windows() function win32_SystemFunction036!{T}(a::Array{T}) - ccall((:SystemFunction036,:Advapi32),stdcall,UInt8,(Ptr{Void},UInt32),a,sizeof(a)) + ccall((:SystemFunction036, :Advapi32), stdcall, UInt8, (Ptr{Void}, UInt32), a, sizeof(a)) end end diff --git a/base/datafmt.jl b/base/datafmt.jl index 8dc6f0bc6bb56..7741ab3480fa5 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -42,7 +42,7 @@ readdlm(input, dlm::Char, T::Type, eol::Char; opts...) = function readdlm_auto(input, dlm::Char, T::Type, eol::Char, auto::Bool; opts...) optsd = val_opts(opts) - use_mmap = get(optsd, :use_mmap, @windows ? false : true) + use_mmap = get(optsd, :use_mmap, is_windows() ? false : true) if isa(input, AbstractString) fsz = filesize(input) if use_mmap && fsz > 0 && fsz < typemax(Int) diff --git a/base/deprecated.jl b/base/deprecated.jl index 88e541b262730..ff320abedeb4f 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -585,7 +585,7 @@ function msync end msync{T}(A::Array{T}) = msync(pointer(A), length(A)*sizeof(T)) msync(B::BitArray) = msync(pointer(B.chunks), length(B.chunks)*sizeof(UInt64)) -@unix_only begin +if is_unix() export mmap @noinline function mmap(len::Integer, prot::Integer, flags::Integer, fd, offset::Integer) depwarn("`mmap` is deprecated, use `Mmap.mmap(io, Array{T,N}, dims, offset)` instead to return an mmapped-array", :mmap) @@ -634,7 +634,7 @@ end end -@windows_only begin +if is_windows() @noinline function munmap(viewhandle::Ptr, mmaphandle::Ptr) depwarn("`munmap` is deprecated, `mmap` Arrays are automatically munmapped when finalized", :munmap) status = ccall(:UnmapViewOfFile, stdcall, Cint, (Ptr{Void},), viewhandle)!=0 @@ -654,9 +654,11 @@ end end -@unix_only @deprecate mmap_array{T,N}(::Type{T}, dims::NTuple{N,Integer}, s::IO, offset=position(s)) Mmap.mmap(s, Array{T,N}, dims, offset) +if is_unix() + @deprecate mmap_array{T,N}(::Type{T}, dims::NTuple{N,Integer}, s::IO, offset=position(s)) Mmap.mmap(s, Array{T,N}, dims, offset) +end -@windows_only begin +if is_windows() type SharedMemSpec name :: AbstractString readonly :: Bool @@ -1186,6 +1188,71 @@ end isequal(x::Char, y::Integer) = false isequal(x::Integer, y::Char) = false +#6674 and #4233 +macro windows(qm,ex) + depwarn("`@windows` is deprecated, use `@static is_windows()` instead", Symbol("@windows")) + return @static is_windows() ? esc(ex.args[1]) : esc(ex.args[2]) +end +macro unix(qm,ex) + depwarn("`@unix` is deprecated, use `@static is_unix()` instead", Symbol("@unix")) + return @static is_unix() ? esc(ex.args[1]) : esc(ex.args[2]) +end +macro osx(qm,ex) + depwarn("`@osx` is deprecated, use `@static is_apple()` instead", Symbol("@osx")) + return @static is_apple() ? esc(ex.args[1]) : esc(ex.args[2]) +end +macro linux(qm,ex) + depwarn("`@linux` is deprecated, use `@static is_linux()` instead", Symbol("@linux")) + return @static is_linux() ? esc(ex.args[1]) : esc(ex.args[2]) +end +macro windows_only(ex) + depwarn("`@windows_only` is deprecated, use `@static if is_windows()` instead", Symbol("@windows_only")) + return @static if is_windows() esc(ex) end +end +macro unix_only(ex) + depwarn("`@unix_only` is deprecated, use `@static if is_unix()` instead", Symbol("@unix_only")) + return @static if is_unix() esc(ex) end +end +macro osx_only(ex) + depwarn("`@osx_only` is deprecated, use `@static if is_apple()` instead", Symbol("@osx_only")) + return @static if is_apple() esc(ex) end +end +macro linux_only(ex) + depwarn("`@linux_only` is deprecated, use `@static if is_linux()` instead", Symbol("@linux_only")) + return @static if is_linux() esc(ex) end +end +export + @windows, + @unix, + @osx, + @linux, + @windows_only, + @unix_only, + @osx_only, + @linux_only + +const OS_NAME = + if Sys.KERNEL === :Darwin + :OSX + elseif Sys.KERNEL === :NT + :Windows + else + Sys.KERNEL + end +deprecate(:OS_NAME) # use Sys.KERNEL now + +export CPU_CORES +function _set_CPU_CORES() + global const CPU_CORES = Sys.CPU_CORES + deprecate(Base, :CPU_CORES) +end +module Init_CPU_CORES + const __init__ = Base._set_CPU_CORES +end + +@deprecate_binding WORD_SIZE Sys.WORD_SIZE + + # During the 0.5 development cycle, do not add any deprecations below this line # To be deprecated in 0.6 diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 0d0bd501447dc..0382140e80725 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -2047,36 +2047,6 @@ of a string. """ isdigit -""" - @windows - -Given `@windows? a : b`, do `a` on Windows and `b` elsewhere. See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@windows - -""" - @unix - -Given `@unix? a : b`, do `a` on Unix systems (including Linux and OS X) and `b` elsewhere. -See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@unix - -""" - @windows_only - -A macro that evaluates the given expression only on Windows systems. See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@windows_only - -""" - @unix_only - -A macro that evaluates the given expression only on Unix systems (including Linux and OS X). See -documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@unix_only - """ num2hex(f) @@ -3145,7 +3115,7 @@ addprocs(n::Integer) """ addprocs() -> List of process identifiers -Equivalent to `addprocs(CPU_CORES)` +Equivalent to `addprocs(Sys.CPU_CORES)` Note that workers do not run a `.juliarc.jl` startup script, nor do they synchronize their global state (such as global variables, new method definitions, and loaded modules) with any @@ -6356,20 +6326,6 @@ Returns the number of dimensions of `A`. """ ndims -""" - @osx - -Given `@osx? a : b`, do `a` on OS X and `b` elsewhere. See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@osx - -""" - @osx_only - -A macro that evaluates the given expression only on OS X systems. See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@osx_only - """ ishermitian(A) -> Bool @@ -8013,20 +7969,6 @@ Cumulative product of `A` along a dimension, storing the result in `B`. The dime """ cumprod! -""" - @linux - -Given `@linux? a : b`, do `a` on Linux and `b` elsewhere. See documentation [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@linux - -""" - @linux_only - -A macro that evaluates the given expression only on Linux systems. See documentation in [Handling Operating System Variation](:ref:`Handling Operating System Variation `). -""" -:@linux_only - """ complement(s) @@ -9598,7 +9540,7 @@ Matrix trace. trace """ - runtests([tests=["all"] [, numcores=iceil(CPU_CORES/2) ]]) + runtests([tests=["all"] [, numcores=iceil(Sys.CPU_CORES / 2) ]]) Run the Julia unit tests listed in `tests`, which can be either a string or an array of strings, using `numcores` processors. (not exported) diff --git a/base/env.jl b/base/env.jl index 7b3e7f1da3ef6..48631f1ab4f67 100644 --- a/base/env.jl +++ b/base/env.jl @@ -1,29 +1,6 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -@unix_only begin - -_getenv(var::AbstractString) = ccall(:getenv, Cstring, (Cstring,), var) -_hasenv(s::AbstractString) = _getenv(s) != C_NULL - -function access_env(onError::Function, var::AbstractString) - val = _getenv(var) - val == C_NULL ? onError(var) : String(val) -end - -function _setenv(var::AbstractString, val::AbstractString, overwrite::Bool=true) - ret = ccall(:setenv, Int32, (Cstring,Cstring,Int32), var, val, overwrite) - systemerror(:setenv, ret != 0) -end - -function _unsetenv(var::AbstractString) - ret = ccall(:unsetenv, Int32, (Cstring,), var) - systemerror(:unsetenv, ret != 0) -end - -end # @unix_only - -@windows_only begin - +if is_windows() const ERROR_ENVVAR_NOT_FOUND = UInt32(203) _getenvlen(var::Vector{UInt16}) = ccall(:GetEnvironmentVariableW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32),var,C_NULL,0) @@ -60,7 +37,26 @@ function _unsetenv(svar::AbstractString) systemerror(:setenv, ret == 0) end -end # @windows_only +else # !windows +_getenv(var::AbstractString) = ccall(:getenv, Cstring, (Cstring,), var) +_hasenv(s::AbstractString) = _getenv(s) != C_NULL + +function access_env(onError::Function, var::AbstractString) + val = _getenv(var) + val == C_NULL ? onError(var) : String(val) +end + +function _setenv(var::AbstractString, val::AbstractString, overwrite::Bool=true) + ret = ccall(:setenv, Int32, (Cstring,Cstring,Int32), var, val, overwrite) + systemerror(:setenv, ret != 0) +end + +function _unsetenv(var::AbstractString) + ret = ccall(:unsetenv, Int32, (Cstring,), var) + systemerror(:unsetenv, ret != 0) +end + +end # os test ## ENV: hash interface ## @@ -86,25 +82,7 @@ delete!(::EnvHash, k::AbstractString, def) = haskey(ENV,k) ? delete!(ENV,k) : de setindex!(::EnvHash, v, k::AbstractString) = _setenv(k,string(v)) push!(::EnvHash, k::AbstractString, v) = setindex!(ENV, v, k) -@unix_only begin -start(::EnvHash) = 0 -done(::EnvHash, i) = (ccall(:jl_environ, Any, (Int32,), i) === nothing) - -function next(::EnvHash, i) - env = ccall(:jl_environ, Any, (Int32,), i) - if env === nothing - throw(BoundsError()) - end - env::String - m = match(r"^(.*?)=(.*)$"s, env) - if m === nothing - error("malformed environment entry: $env") - end - (Pair{String,String}(m.captures[1], m.captures[2]), i+1) -end -end - -@windows_only begin +if is_windows() start(hash::EnvHash) = (pos = ccall(:GetEnvironmentStringsW,stdcall,Ptr{UInt16},()); (pos,pos)) function done(hash::EnvHash, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) if unsafe_load(block[1]) == 0 @@ -126,8 +104,26 @@ function next(hash::EnvHash, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) end (Pair{String,String}(m.captures[1], m.captures[2]), (pos+len*2, blk)) end + +else # !windows +start(::EnvHash) = 0 +done(::EnvHash, i) = (ccall(:jl_environ, Any, (Int32,), i) === nothing) + +function next(::EnvHash, i) + env = ccall(:jl_environ, Any, (Int32,), i) + if env === nothing + throw(BoundsError()) + end + env::String + m = match(r"^(.*?)=(.*)$"s, env) + if m === nothing + error("malformed environment entry: $env") + end + (Pair{String,String}(m.captures[1], m.captures[2]), i+1) end +end # os-test + #TODO: Make these more efficent function length(::EnvHash) i = 0 diff --git a/base/event.jl b/base/event.jl index 69209a040eb63..e91849b40b11f 100644 --- a/base/event.jl +++ b/base/event.jl @@ -146,9 +146,10 @@ function wait() assert(false) end -function pause() - @unix_only ccall(:pause, Void, ()) - @windows_only ccall(:Sleep,stdcall, Void, (UInt32,), 0xffffffff) +if is_windows() + pause() = ccall(:Sleep, stdcall, Void, (UInt32,), 0xffffffff) +else + pause() = ccall(:pause, Void, ()) end diff --git a/base/exports.jl b/base/exports.jl index bf47c04a31ca1..0dfd70f27dcf9 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -176,18 +176,15 @@ export # Global constants and variables ARGS, C_NULL, - CPU_CORES, ENDIAN_BOM, ENV, JULIA_HOME, LOAD_PATH, - OS_NAME, PROGRAM_FILE, STDERR, STDIN, STDOUT, VERSION, - WORD_SIZE, # Mathematical constants Inf, @@ -1388,14 +1385,12 @@ export @code_native, # platform-conditional code - @windows, - @unix, - @osx, - @linux, - @windows_only, - @unix_only, - @osx_only, - @linux_only, + @static, + is_windows, + is_linux, + is_apple, + is_bsd, + is_unix, # tasks @schedule, diff --git a/base/file.jl b/base/file.jl index e38b1814973dc..3efd0c731a466 100644 --- a/base/file.jl +++ b/base/file.jl @@ -40,31 +40,37 @@ function cd(dir::AbstractString) end cd() = cd(homedir()) -@unix_only function cd(f::Function, dir::AbstractString) - fd = ccall(:open,Int32,(Cstring,Int32),:.,0) - systemerror(:open, fd == -1) - try - cd(dir) - f() - finally - systemerror(:fchdir, ccall(:fchdir,Int32,(Int32,),fd) != 0) - systemerror(:close, ccall(:close,Int32,(Int32,),fd) != 0) +if is_windows() + function cd(f::Function, dir::AbstractString) + old = pwd() + try + cd(dir) + f() + finally + cd(old) + end end -end -@windows_only function cd(f::Function, dir::AbstractString) - old = pwd() - try - cd(dir) - f() - finally - cd(old) +else + function cd(f::Function, dir::AbstractString) + fd = ccall(:open, Int32, (Cstring, Int32), :., 0) + systemerror(:open, fd == -1) + try + cd(dir) + f() + finally + systemerror(:fchdir, ccall(:fchdir, Int32, (Int32,), fd) != 0) + systemerror(:close, ccall(:close, Int32, (Int32,), fd) != 0) + end end end cd(f::Function) = cd(f, homedir()) function mkdir(path::AbstractString, mode::Unsigned=0o777) - @unix_only ret = ccall(:mkdir, Int32, (Cstring,UInt32), path, mode) - @windows_only ret = ccall(:_wmkdir, Int32, (Cwstring,), path) + @static if is_windows() + ret = ccall(:_wmkdir, Int32, (Cwstring,), path) + else + ret = ccall(:mkdir, Int32, (Cstring, UInt32), path, mode) + end systemerror(:mkdir, ret != 0; extrainfo=path) end @@ -92,7 +98,12 @@ mkpath(path::AbstractString, mode::Signed) = throw(ArgumentError("mode must be a function rm(path::AbstractString; force::Bool=false, recursive::Bool=false) if islink(path) || !isdir(path) try - @windows_only if (filemode(path) & 0o222) == 0; chmod(path, 0o777); end # is writable on windows actually means "is deletable" + @static if is_windows() + # is writable on windows actually means "is deletable" + if (filemode(path) & 0o222) == 0 + chmod(path, 0o777) + end + end unlink(path) catch err if force && isa(err, UVError) && err.code==Base.UV_ENOENT @@ -106,8 +117,11 @@ function rm(path::AbstractString; force::Bool=false, recursive::Bool=false) rm(joinpath(path, p), force=force, recursive=true) end end - @unix_only ret = ccall(:rmdir, Int32, (Cstring,), path) - @windows_only ret = ccall(:_wrmdir, Int32, (Cwstring,), path) + @static if is_windows() + ret = ccall(:_wrmdir, Int32, (Cwstring,), path) + else + ret = ccall(:rmdir, Int32, (Cstring,), path) + end systemerror(:rmdir, ret != 0, extrainfo=path) end end @@ -181,38 +195,7 @@ function touch(path::AbstractString) end end -@unix_only begin -# Obtain a temporary filename. -function tempname() - d = get(ENV, "TMPDIR", C_NULL) # tempnam ignores TMPDIR on darwin - p = ccall(:tempnam, Cstring, (Cstring,Cstring), d, :julia) - systemerror(:tempnam, p == C_NULL) - s = String(p) - Libc.free(p) - return s -end - -# Obtain a temporary directory's path. -tempdir() = dirname(tempname()) - -# Create and return the name of a temporary file along with an IOStream -function mktemp(parent=tempdir()) - b = joinpath(parent, "tmpXXXXXX") - p = ccall(:mkstemp, Int32, (Cstring,), b) # modifies b - systemerror(:mktemp, p == -1) - return (b, fdio(p, true)) -end - -# Create and return the name of a temporary directory -function mktempdir(parent=tempdir()) - b = joinpath(parent, "tmpXXXXXX") - p = ccall(:mkdtemp, Cstring, (Cstring,), b) - systemerror(:mktempdir, p == C_NULL) - return String(p) -end -end - -@windows_only begin +if is_windows() function tempdir() temppath = Array(UInt16,32767) lentemppath = ccall(:GetTempPathW,stdcall,UInt32,(UInt32,Ptr{UInt16}),length(temppath),temppath) @@ -254,8 +237,39 @@ function mktempdir(parent=tempdir()) seed += 1 end end + +else # !windows +# Obtain a temporary filename. +function tempname() + d = get(ENV, "TMPDIR", C_NULL) # tempnam ignores TMPDIR on darwin + p = ccall(:tempnam, Cstring, (Cstring,Cstring), d, :julia) + systemerror(:tempnam, p == C_NULL) + s = String(p) + Libc.free(p) + return s end +# Obtain a temporary directory's path. +tempdir() = dirname(tempname()) + +# Create and return the name of a temporary file along with an IOStream +function mktemp(parent=tempdir()) + b = joinpath(parent, "tmpXXXXXX") + p = ccall(:mkstemp, Int32, (Cstring,), b) # modifies b + systemerror(:mktemp, p == -1) + return (b, fdio(p, true)) +end + +# Create and return the name of a temporary directory +function mktempdir(parent=tempdir()) + b = joinpath(parent, "tmpXXXXXX") + p = ccall(:mkdtemp, Cstring, (Cstring,), b) + systemerror(:mktempdir, p == C_NULL) + return String(p) +end + +end # os-test + function mktemp(fn::Function, parent=tempdir()) (tmp_path, tmp_io) = mktemp(parent) try @@ -405,16 +419,27 @@ function sendfile(src::AbstractString, dst::AbstractString) end end -@windows_only const UV_FS_SYMLINK_JUNCTION = 0x0002 +if is_windows() + const UV_FS_SYMLINK_JUNCTION = 0x0002 +end function symlink(p::AbstractString, np::AbstractString) - @windows_only if Base.windows_version() < Base.WINDOWS_VISTA_VER - error("Windows XP does not support soft symlinks") + @static if is_windows() + if Sys.windows_version() < Sys.WINDOWS_VISTA_VER + error("Windows XP does not support soft symlinks") + end end flags = 0 - @windows_only if isdir(p); flags |= UV_FS_SYMLINK_JUNCTION; p = abspath(p); end + @static if is_windows() + if isdir(p) + flags |= UV_FS_SYMLINK_JUNCTION + p = abspath(p) + end + end err = ccall(:jl_fs_symlink, Int32, (Cstring, Cstring, Cint), p, np, flags) - @windows_only if err < 0 && !isdir(p) - Base.warn_once("Note: on Windows, creating file symlinks requires Administrator privileges.") + @static if is_windows() + if err < 0 && !isdir(p) + Base.warn_once("Note: on Windows, creating file symlinks requires Administrator privileges.") + end end uv_error("symlink",err) end diff --git a/base/filesystem.jl b/base/filesystem.jl index ec0f18b24c69d..b36985dfc8d0a 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -45,7 +45,9 @@ import Base: skip, stat, unsafe_read, unsafe_write, utf16to8, utf8to16, uv_error, uvhandle, uvtype, write -@windows_only import Base: cwstring +if is_windows() + import Base: cwstring +end include("path.jl") include("stat.jl") diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 861b794223e48..d81c1b5503c9b 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -193,7 +193,7 @@ fma_llvm(x::Float64, y::Float64, z::Float64) = # 1.0000000009313226 = 1 + 1/2^30 # If fma_llvm() clobbers the rounding mode, the result of 0.1 + 0.2 will be 0.3 # instead of the properly-rounded 0.30000000000000004; check after calling fma -if (ARCH != :i686 && fma_llvm(1.0000305f0, 1.0000305f0, -1.0f0) == 6.103609f-5 && +if (Sys.ARCH != :i686 && fma_llvm(1.0000305f0, 1.0000305f0, -1.0f0) == 6.103609f-5 && (fma_llvm(1.0000000009313226, 1.0000000009313226, -1.0) == 1.8626451500983188e-9) && 0.1 + 0.2 == 0.30000000000000004) fma(x::Float32, y::Float32, z::Float32) = fma_llvm(x,y,z) diff --git a/base/initdefs.jl b/base/initdefs.jl index 359df57b4ef11..5ddcaa792ac3b 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -37,12 +37,12 @@ const LOAD_PATH = String[] const LOAD_CACHE_PATH = String[] function init_load_path() vers = "v$(VERSION.major).$(VERSION.minor)" - if haskey(ENV,"JULIA_LOAD_PATH") - prepend!(LOAD_PATH, split(ENV["JULIA_LOAD_PATH"], @windows? ';' : ':')) + if haskey(ENV, "JULIA_LOAD_PATH") + prepend!(LOAD_PATH, split(ENV["JULIA_LOAD_PATH"], @static is_windows() ? ';' : ':')) end - push!(LOAD_PATH,abspath(JULIA_HOME,"..","local","share","julia","site",vers)) - push!(LOAD_PATH,abspath(JULIA_HOME,"..","share","julia","site",vers)) - push!(LOAD_CACHE_PATH,abspath(JULIA_HOME,"..","usr","lib","julia")) #TODO: fixme + push!(LOAD_PATH, abspath(JULIA_HOME, "..", "local", "share", "julia", "site", vers)) + push!(LOAD_PATH, abspath(JULIA_HOME, "..", "share", "julia", "site", vers)) + #push!(LOAD_CACHE_PATH, abspath(JULIA_HOME, "..", "lib", "julia")) #TODO: add a builtin location? end # initialize the local proc network address / port @@ -76,7 +76,7 @@ function early_init() # make sure OpenBLAS does not set CPU affinity (#1070, #9639) ENV["OPENBLAS_MAIN_FREE"] = get(ENV, "OPENBLAS_MAIN_FREE", get(ENV, "GOTOBLAS_MAIN_FREE", "1")) - if CPU_CORES > 8 && !("OPENBLAS_NUM_THREADS" in keys(ENV)) && !("OMP_NUM_THREADS" in keys(ENV)) + if Sys.CPU_CORES > 8 && !("OPENBLAS_NUM_THREADS" in keys(ENV)) && !("OMP_NUM_THREADS" in keys(ENV)) # Prevent openblas from starting too many threads, unless/until specifically requested ENV["OPENBLAS_NUM_THREADS"] = 8 end diff --git a/base/int.jl b/base/int.jl index bd3d20f6e100f..44d02fe20c3ff 100644 --- a/base/int.jl +++ b/base/int.jl @@ -274,15 +274,6 @@ macro big_str(s) :(throw(ArgumentError($message))) end -## system word size ## - -""" - WORD_SIZE - -Standard word size on the current machine, in bits. -""" -const WORD_SIZE = convert(Int, Int.size)*8 - ## integer promotions ## promote_rule(::Type{Int8}, ::Type{Int16}) = Int16 @@ -298,7 +289,7 @@ for T in BitSigned_types $(sizeof(T) < sizeof(Int) ? Int : T) end @eval promote_rule{T<:Union{Int8,Int16,Int32}}(::Type{UInt32}, ::Type{T}) = - $(WORD_SIZE == 64 ? Int : UInt) + $(Core.sizeof(Int) == 8 ? Int : UInt) promote_rule(::Type{UInt32}, ::Type{Int64}) = Int64 promote_rule{T<:BitSigned64}(::Type{UInt64}, ::Type{T}) = UInt64 promote_rule{T<:Union{UInt32, UInt64}}(::Type{T}, ::Type{Int128}) = Int128 @@ -349,7 +340,7 @@ widemul(x::Number,y::Bool) = x*y ## wide multiplication, Int128 multiply and divide ## -if WORD_SIZE == 32 +if Core.sizeof(Int) == 4 function widemul(u::Int64, v::Int64) local u0::UInt64, v0::UInt64, w0::UInt64 local u1::Int64, v1::Int64, w1::UInt64, w2::Int64, t::UInt64 diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 45a9c2776def4..e73d36ff3d299 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -10,7 +10,7 @@ for use within backticks. You can change the editor by setting JULIA_EDITOR, VIS EDITOR as an environmental variable. """ function editor() - if OS_NAME == :Windows || OS_NAME == :Darwin + if is_windows() || is_apple() default_editor = "open" elseif isfile("/etc/alternatives/editor") default_editor = "/etc/alternatives/editor" @@ -42,10 +42,10 @@ function edit(path::AbstractString, line::Integer=0) cmd = line != 0 ? `$command $path -l $line` : `$command $path` elseif startswith(name, "subl") || name == "atom" cmd = line != 0 ? `$command $path:$line` : `$command $path` - elseif OS_NAME == :Windows && (name == "start" || name == "open") + elseif is_windows() && (name == "start" || name == "open") cmd = `cmd /c start /b $path` line_unsupported = true - elseif OS_NAME == :Darwin && (name == "start" || name == "open") + elseif is_apple() && (name == "start" || name == "open") cmd = `open -t $path` line_unsupported = true else @@ -82,16 +82,15 @@ less(file, line::Integer) = error("could not find source file for function") # clipboard copy and paste -@osx_only begin +if is_apple() function clipboard(x) open(pipeline(`pbcopy`, stderr=STDERR), "w") do io print(io, x) end end clipboard() = readstring(`pbpaste`) -end -@linux_only begin +elseif is_linux() _clipboardcmd = nothing function clipboardcmd() global _clipboardcmd @@ -117,9 +116,9 @@ end error("unexpected clipboard command: $c") readstring(pipeline(cmd, stderr=STDERR)) end -end -@windows_only begin # TODO: these functions leak memory and memory locks if they throw an error +elseif is_windows() + # TODO: these functions leak memory and memory locks if they throw an error function clipboard(x::AbstractString) if containsnul(x) throw(ArgumentError("Windows clipboard strings cannot contain NUL character")) @@ -155,14 +154,38 @@ end systemerror(:GlobalUnlock, 0==ccall((:GlobalUnlock, "kernel32"), stdcall, Cint, (Ptr{UInt16},), plock)) return s end -end -if !isdefined(:clipboard) - clipboard(x="") = error("clipboard functionality not implemented for $OS_NAME") +else + clipboard(x="") = error("`clipboard` function not implemented for $(Sys.KERNEL)") end # system information +function show(io::IO, info::Sys.CPUinfo, header::Bool=true, prefix::AbstractString=" ") + tck = Sys.SC_CLK_TCK + if header + println(io, info.model, ": ") + print(io, " "^length(prefix)) + if tck > 0 + @printf(io, " %5s %9s %9s %9s %9s %9s\n", + "speed", "user", "nice", "sys", "idle", "irq") + else + @printf(io, " %5s %9s %9s %9s %9s %9s ticks\n", + "speed", "user", "nice", "sys", "idle", "irq") + end + end + print(io, prefix) + if tck > 0 + @printf(io, "%5d MHz %9d s %9d s %9d s %9d s %9d s", + info.speed, info.cpu_times!user / tck, info.cpu_times!nice / tck, + info.cpu_times!sys / tck, info.cpu_times!idle / tck, info.cpu_times!irq / tck) + else + @printf(io, "%5d MHz %9d %9d %9d %9d %9d ticks", + info.speed, info.cpu_times!user, info.cpu_times!nice, + info.cpu_times!sys, info.cpu_times!idle, info.cpu_times!irq) + end +end + function versioninfo(io::IO=STDOUT, verbose::Bool=false) println(io, "Julia Version $VERSION") if !isempty(GIT_VERSION_INFO.commit_short) @@ -172,19 +195,25 @@ function versioninfo(io::IO=STDOUT, verbose::Bool=false) println(io, "DEBUG build") end println(io, "Platform Info:") - println(io, " System: ", Sys.OS_NAME, " (", Sys.MACHINE, ")") + println(io, " System: ", Sys.KERNEL, " (", Sys.MACHINE, ")") cpu = Sys.cpu_info() println(io, " CPU: ", cpu[1].model) println(io, " WORD_SIZE: ", Sys.WORD_SIZE) if verbose lsb = "" - @linux_only try lsb = readchomp(pipeline(`lsb_release -ds`, stderr=DevNull)) end - @windows_only try lsb = strip(readstring(`$(ENV["COMSPEC"]) /c ver`)) end + if is_linux() + try lsb = readchomp(pipeline(`lsb_release -ds`, stderr=DevNull)) end + end + if is_windows() + try lsb = strip(readstring(`$(ENV["COMSPEC"]) /c ver`)) end + end if lsb != "" println(io, " ", lsb) end - @unix_only println(io, " uname: ",readchomp(`uname -mprsv`)) + if is_unix() + println(io, " uname: ", readchomp(`uname -mprsv`)) + end println(io, "Memory: $(Sys.total_memory()/2^30) GB ($(Sys.free_memory()/2^20) MB free)") try println(io, "Uptime: $(Sys.uptime()) sec") end print(io, "Load Avg: ") @@ -428,37 +457,38 @@ end # file downloading downloadcmd = nothing -@unix_only function download(url::AbstractString, filename::AbstractString) - global downloadcmd - if downloadcmd === nothing - for checkcmd in (:curl, :wget, :fetch) - if success(pipeline(`which $checkcmd`, DevNull)) - downloadcmd = checkcmd - break +if is_windows() + function download(url::AbstractString, filename::AbstractString) + res = ccall((:URLDownloadToFileW,:urlmon),stdcall,Cuint, + (Ptr{Void},Cwstring,Cwstring,Cuint,Ptr{Void}),C_NULL,url,filename,0,C_NULL) + if res != 0 + error("automatic download failed (error: $res): $url") + end + filename + end +else + function download(url::AbstractString, filename::AbstractString) + global downloadcmd + if downloadcmd === nothing + for checkcmd in (:curl, :wget, :fetch) + if success(pipeline(`which $checkcmd`, DevNull)) + downloadcmd = checkcmd + break + end end end + if downloadcmd == :wget + run(`wget -O $filename $url`) + elseif downloadcmd == :curl + run(`curl -o $filename -L $url`) + elseif downloadcmd == :fetch + run(`fetch -f $filename $url`) + else + error("no download agent available; install curl, wget, or fetch") + end + filename end - if downloadcmd == :wget - run(`wget -O $filename $url`) - elseif downloadcmd == :curl - run(`curl -o $filename -L $url`) - elseif downloadcmd == :fetch - run(`fetch -f $filename $url`) - else - error("no download agent available; install curl, wget, or fetch") - end - filename -end - -@windows_only function download(url::AbstractString, filename::AbstractString) - res = ccall((:URLDownloadToFileW,:urlmon),stdcall,Cuint, - (Ptr{Void},Cwstring,Cwstring,Cuint,Ptr{Void}),C_NULL,url,filename,0,C_NULL) - if res != 0 - error("automatic download failed (error: $res): $url") - end - filename end - function download(url::AbstractString) filename = tempname() download(url, filename) @@ -482,7 +512,7 @@ end # testing -function runtests(tests = ["all"], numcores = ceil(Int,CPU_CORES/2)) +function runtests(tests = ["all"], numcores = ceil(Int, Sys.CPU_CORES / 2)) if isa(tests,AbstractString) tests = split(tests) end @@ -568,7 +598,7 @@ summarysize(obj::Symbol, seen, excl) = 0 function summarysize(obj::DataType, seen, excl) key = pointer_from_objref(obj) haskey(seen, key) ? (return 0) : (seen[key] = true) - size = 7*sizeof(Int) + 6*sizeof(Int32) + 4*nfields(obj) + ifelse(WORD_SIZE==64,4,0) + size = 7*sizeof(Int) + 6*sizeof(Int32) + 4*nfields(obj) + ifelse(Sys.WORD_SIZE == 64, 4, 0) size += summarysize(obj.parameters, seen, excl)::Int size += summarysize(obj.types, seen, excl)::Int return size diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 9b102504cdec1..4ad483f41ea79 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -184,7 +184,7 @@ function ndigits0z(x::UInt128) end ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) -const ndigits_max_mul = WORD_SIZE==32 ? 69000000 : 290000000000000000 +const ndigits_max_mul = Core.sizeof(Int32) == 4 ? 69000000 : 290000000000000000 function ndigits0znb(n::Int, b::Int) d = 0 diff --git a/base/libc.jl b/base/libc.jl index 648b1a4024c40..17c849f750e17 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -4,7 +4,9 @@ module Libc export FILE, TmStruct, strftime, strptime, getpid, gethostname, free, malloc, calloc, realloc, errno, strerror, flush_cstdio, systemsleep, time -@windows_only export GetLastError, FormatMessage +if is_windows() + export GetLastError, FormatMessage +end import Base: utf16to8 @@ -21,20 +23,22 @@ end Base.cconvert(::Type{Int32}, fd::RawFD) = fd.fd -dup(x::RawFD) = RawFD(ccall((@windows? :_dup : :dup),Int32,(Int32,),x.fd)) -dup(src::RawFD,target::RawFD) = systemerror("dup",-1== - ccall((@windows? :_dup2 : :dup2),Int32, - (Int32,Int32),src.fd,target.fd)) +dup(x::RawFD) = RawFD(ccall((@static is_windows() ? :_dup : :dup), Int32, (Int32,), x.fd)) +dup(src::RawFD, target::RawFD) = systemerror("dup", -1 == + ccall((@static is_windows() ? :_dup2 : :dup2), Int32, + (Int32, Int32), src.fd, target.fd)) # Wrapper for an OS file descriptor (for Windows) -@windows_only immutable WindowsRawSocket - handle::Ptr{Void} # On Windows file descriptors are HANDLE's and 64-bit on 64-bit Windows +if is_windows() + immutable WindowsRawSocket + handle::Ptr{Void} # On Windows file descriptors are HANDLE's and 64-bit on 64-bit Windows + end + Base.cconvert(::Type{Ptr{Void}}, fd::WindowsRawSocket) = fd.handle + _get_osfhandle(fd::RawFD) = WindowsRawSocket(ccall(:_get_osfhandle,Ptr{Void},(Cint,),fd.fd)) + _get_osfhandle(fd::WindowsRawSocket) = fd +else + _get_osfhandle(fd::RawFD) = fd end -@windows_only Base.cconvert(::Type{Ptr{Void}}, fd::WindowsRawSocket) = fd.handle - -@unix_only _get_osfhandle(fd::RawFD) = fd -@windows_only _get_osfhandle(fd::RawFD) = WindowsRawSocket(ccall(:_get_osfhandle,Ptr{Void},(Cint,),fd.fd)) -@windows_only _get_osfhandle(fd::WindowsRawSocket) = fd ## FILE (not auto-finalized) ## @@ -46,8 +50,7 @@ modestr(s::IO) = modestr(isreadable(s), iswritable(s)) modestr(r::Bool, w::Bool) = r ? (w ? "r+" : "r") : (w ? "w" : throw(ArgumentError("neither readable nor writable"))) function FILE(fd::RawFD, mode) - @unix_only FILEp = ccall(:fdopen, Ptr{Void}, (Cint, Cstring), fd, mode) - @windows_only FILEp = ccall(:_fdopen, Ptr{Void}, (Cint, Cstring), fd, mode) + FILEp = ccall((@static is_windows() ? :_fdopen : :fdopen), Ptr{Void}, (Cint, Cstring), fd, mode) systemerror("fdopen", FILEp == C_NULL) FILE(FILEp) end @@ -82,8 +85,16 @@ flush_cstdio() = ccall(:jl_flush_cstdio, Void, ()) ## time-related functions ## # TODO: check for usleep errors? -@unix_only systemsleep(s::Real) = ccall(:usleep, Int32, (UInt32,), round(UInt32,s*1e6)) -@windows_only systemsleep(s::Real) = (ccall(:Sleep, stdcall, Void, (UInt32,), round(UInt32,s*1e3)); return Int32(0)) +if is_unix() + systemsleep(s::Real) = ccall(:usleep, Int32, (UInt32,), round(UInt32, s*1e6)) +elseif is_windows() + function systemsleep(s::Real) + ccall(:Sleep, stdcall, Void, (UInt32,), round(UInt32, s * 1e3)) + return Int32(0) + end +else + error("systemsleep undefined for this OS") +end immutable TimeVal sec::Int64 @@ -148,7 +159,7 @@ function strftime(fmt::AbstractString, tm::TmStruct) if n == 0 return "" end - String(pointer(timestr), n) + return String(pointer(timestr), n) end """ @@ -174,14 +185,14 @@ function strptime(fmt::AbstractString, timestr::AbstractString) # TODO: better error message throw(ArgumentError("invalid arguments")) end - @osx_only begin + @static if is_apple() # if we didn't explicitly parse the weekday or year day, use mktime # to fill them in automatically. if !ismatch(r"([^%]|^)%(a|A|j|w|Ow)", fmt) ccall(:mktime, Int, (Ptr{TmStruct},), &tm) end end - tm + return tm end # system date in seconds @@ -202,10 +213,13 @@ getpid() = ccall(:jl_getpid, Int32, ()) function gethostname() hn = Array(UInt8, 256) - @unix_only err=ccall(:gethostname, Int32, (Ptr{UInt8}, UInt), hn, length(hn)) - @windows_only err=ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn)) + err = @static if is_windows() + ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn)) + else + ccall(:gethostname, Int32, (Ptr{UInt8}, UInt), hn, length(hn)) + end systemerror("gethostname", err != 0) - String(pointer(hn)) + return String(pointer(hn)) end ## system error handling ## @@ -245,7 +259,7 @@ Convert a Win32 system call error code to a descriptive string [only available o """ function FormatMessage end -@windows_only begin +if is_windows() GetLastError() = ccall(:GetLastError,stdcall,UInt32,()) function FormatMessage(e=GetLastError()) diff --git a/base/libdl.jl b/base/libdl.jl index 6730d3b90f5d8..504f145455a6c 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -13,8 +13,10 @@ When calling [`dlopen`](:func:`dlopen`), the paths in this list will be searched order, before searching the system locations for a valid library handle. """ const DL_LOAD_PATH = String[] -@osx_only push!(DL_LOAD_PATH, "@loader_path/julia") -@osx_only push!(DL_LOAD_PATH, "@loader_path") +if is_apple() + push!(DL_LOAD_PATH, "@loader_path/julia") + push!(DL_LOAD_PATH, "@loader_path") +end # constants to match JL_RTLD_* in src/julia.h const RTLD_LOCAL = 0x00000001 @@ -143,7 +145,7 @@ find_library(libname::Union{Symbol,AbstractString}, extrapaths=String[]) = function dlpath(handle::Ptr{Void}) p = ccall(:jl_pathname_for_handle, Cstring, (Ptr{Void},), handle) s = String(p) - @windows_only Libc.free(p) + is_windows() && Libc.free(p) return s end @@ -154,12 +156,12 @@ function dlpath(libname::Union{AbstractString, Symbol}) return path end -if OS_NAME === :Darwin +if is_apple() const dlext = "dylib" -elseif OS_NAME === :Windows +elseif is_windows() const dlext = "dll" else - #assume OS_NAME === :Linux, or similar + #assume is_linux, or similar const dlext = "so" end @@ -170,7 +172,7 @@ File extension for dynamic libraries (e.g. dll, dylib, so) on the current platfo """ dlext -@linux_only begin +if is_linux() immutable dl_phdr_info # Base address of object addr::Cuint @@ -194,18 +196,18 @@ dlext end return convert(Cint, 0)::Cint end -end #@linux_only +end # linux-only function dllist() - dynamic_libraries = Array(AbstractString,0) + dynamic_libraries = Array{AbstractString}(0) - @linux_only begin + @static if is_linux() const callback = cfunction(dl_phdr_info_callback, Cint, (Ref{dl_phdr_info}, Csize_t, Ref{Array{AbstractString,1}} )) ccall(:dl_iterate_phdr, Cint, (Ptr{Void}, Ref{Array{AbstractString,1}}), callback, dynamic_libraries) end - @osx_only begin + @static if is_apple() numImages = ccall(:_dyld_image_count, Cint, (), ) # start at 1 instead of 0 to skip self @@ -215,11 +217,11 @@ function dllist() end end - @windows_only begin + @static if is_windows() ccall(:jl_dllist, Cint, (Any,), dynamic_libraries) end - dynamic_libraries + return dynamic_libraries end end # module diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index 2f4f9d2fb343c..b6060d7b0c9ad 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -14,7 +14,7 @@ function GitRepo(path::AbstractString) end function GitRepoExt(path::AbstractString, flags::Cuint = Cuint(Consts.REPOSITORY_OPEN_DEFAULT)) - separator = @unix? ":" : ";" + separator = @static is_windows() ? ";" : ":" repo_ptr_ptr = Ref{Ptr{Void}}(C_NULL) err = ccall((:git_repository_open_ext, :libgit2), Cint, (Ptr{Ptr{Void}}, Cstring, Cuint, Cstring), diff --git a/base/loading.jl b/base/loading.jl index 689ee46c2cdce..ec8a058b1a2e8 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -4,16 +4,16 @@ # Cross-platform case-sensitive path canonicalization -if OS_NAME ∈ (:Linux, :FreeBSD) - # Case-sensitive filesystems, don't have to do anything +if is_unix() && !is_apple() + # assume case-sensitive filesystems, don't have to do anything isfile_casesensitive(path) = isfile(path) -elseif OS_NAME == :Windows +elseif is_windows() # GetLongPathName Win32 function returns the case-preserved filename on NTFS. function isfile_casesensitive(path) isfile(path) || return false # Fail fast Filesystem.longpath(path) == path end -elseif OS_NAME == :Darwin +elseif is_apple() # HFS+ filesystem is case-preserving. The getattrlist API returns # a case-preserved filename. In the rare event that HFS+ is operating # in case-sensitive mode, this will still work but will be redundant. diff --git a/base/managers.jl b/base/managers.jl index 08b52fefe43f6..b96b46d7fe6ac 100644 --- a/base/managers.jl +++ b/base/managers.jl @@ -349,7 +349,7 @@ function socket_reuse_port() # TODO: Support OSX and change the above code to call setsockopt before bind once libuv provides # early access to a socket fd, i.e., before a bind call. - @linux_only begin + @static if is_linux() try rc = ccall(:jl_tcp_reuseport, Int32, (Ptr{Void}, ), s.handle) if rc > 0 # SO_REUSEPORT is unsupported, just return the ephemerally bound socket diff --git a/base/mmap.jl b/base/mmap.jl index 832fbcbff1648..ff490610d5b99 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -2,7 +2,7 @@ module Mmap -const PAGESIZE = Int(@unix ? ccall(:jl_getpagesize, Clong, ()) : ccall(:jl_getallocationgranularity, Clong, ())) +const PAGESIZE = Int(is_unix() ? ccall(:jl_getpagesize, Clong, ()) : ccall(:jl_getallocationgranularity, Clong, ())) # for mmaps not backed by files type Anonymous <: IO @@ -21,14 +21,14 @@ const INVALID_HANDLE_VALUE = -1 gethandle(io::Anonymous) = INVALID_HANDLE_VALUE # platform-specific mmap utilities -@unix_only begin +if is_unix() -const PROT_READ = convert(Cint,1) -const PROT_WRITE = convert(Cint,2) -const MAP_SHARED = convert(Cint,1) -const MAP_PRIVATE = convert(Cint,2) -const MAP_ANONYMOUS = convert(Cint, @osx? 0x1000 : 0x20) -const F_GETFL = convert(Cint,3) +const PROT_READ = Cint(1) +const PROT_WRITE = Cint(2) +const MAP_SHARED = Cint(1) +const MAP_PRIVATE = Cint(2) +const MAP_ANONYMOUS = Cint(is_apple() ? 0x1000 : 0x20) +const F_GETFL = Cint(3) gethandle(io::IO) = fd(io) @@ -64,9 +64,8 @@ function grow!(io::IO, offset::Integer, len::Integer) seek(io, pos) return end -end # @unix_only -@windows_only begin +elseif is_windows() typealias DWORD Culong @@ -89,7 +88,10 @@ end settings(sh::Anonymous) = sh.name, sh.readonly, sh.create settings(io::IO) = Ptr{Cwchar_t}(0), isreadonly(io), true -end # @windows_only + +else + error("mmap not defined for this OS") +end # os-test # core impelementation of mmap function mmap{T,N}(io::IO, @@ -114,15 +116,13 @@ function mmap{T,N}(io::IO, file_desc = gethandle(io) # platform-specific mmapping - @unix_only begin + @static if is_unix() prot, flags, iswrite = settings(file_desc, shared) iswrite && grow && grow!(io, offset, len) # mmap the file ptr = ccall(:jl_mmap, Ptr{Void}, (Ptr{Void}, Csize_t, Cint, Cint, Cint, Int64), C_NULL, mmaplen, prot, flags, file_desc, offset_page) systemerror("memory mapping failed", reinterpret(Int,ptr) == -1) - end # @unix_only - - @windows_only begin + else name, readonly, create = settings(io) szfile = convert(Csize_t, len + offset) readonly && szfile > filesize(io) && throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions")) @@ -134,14 +134,17 @@ function mmap{T,N}(io::IO, ptr = ccall(:MapViewOfFile, stdcall, Ptr{Void}, (Ptr{Void}, DWORD, DWORD, DWORD, Csize_t), handle, readonly ? FILE_MAP_READ : FILE_MAP_WRITE, offset_page >> 32, offset_page & typemax(UInt32), (offset - offset_page) + len) ptr == C_NULL && error("could not create mapping view: $(Libc.FormatMessage())") - end # @windows_only + end # os-test # convert mmapped region to Julia Array at `ptr + (offset - offset_page)` since file was mapped at offset_page A = pointer_to_array(convert(Ptr{T}, UInt(ptr) + UInt(offset - offset_page)), dims) - @unix_only finalizer(A, x -> systemerror("munmap", ccall(:munmap,Cint,(Ptr{Void},Int),ptr,mmaplen) != 0)) - @windows_only finalizer(A, x -> begin - status = ccall(:UnmapViewOfFile, stdcall, Cint, (Ptr{Void},), ptr)!=0 - status |= ccall(:CloseHandle, stdcall, Cint, (Ptr{Void},), handle)!=0 - status || error("could not unmap view: $(Libc.FormatMessage())") + finalizer(A, function(x) + @static if is_unix() + systemerror("munmap", ccall(:munmap, Cint, (Ptr{Void}, Int), ptr, mmaplen) != 0) + else + status = ccall(:UnmapViewOfFile, stdcall, Cint, (Ptr{Void},), ptr)!=0 + status |= ccall(:CloseHandle, stdcall, Cint, (Ptr{Void},), handle)!=0 + status || error("could not unmap view: $(Libc.FormatMessage())") + end end) return A end @@ -206,9 +209,13 @@ const MS_SYNC = 4 function sync!{T}(m::Array{T}, flags::Integer=MS_SYNC) offset = rem(UInt(pointer(m)), PAGESIZE) ptr = pointer(m) - offset - @unix_only systemerror("msync", ccall(:msync, Cint, (Ptr{Void}, Csize_t, Cint), ptr, length(m)*sizeof(T), flags) != 0) - @windows_only systemerror("could not FlushViewOfFile: $(Libc.FormatMessage())", + @static if is_unix() + systemerror("msync", + ccall(:msync, Cint, (Ptr{Void}, Csize_t, Cint), ptr, length(m) * sizeof(T), flags) != 0) + else + systemerror("could not FlushViewOfFile: $(Libc.FormatMessage())", ccall(:FlushViewOfFile, stdcall, Cint, (Ptr{Void}, Csize_t), ptr, length(m)) == 0) + end end sync!(B::BitArray, flags::Integer=MS_SYNC) = sync!(B.chunks, flags) diff --git a/base/multi.jl b/base/multi.jl index 739ce36a7ab66..d30c62e6228ec 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -1667,7 +1667,7 @@ end function disable_nagle(sock) # disable nagle on all OSes ccall(:uv_tcp_nodelay, Cint, (Ptr{Void}, Cint), sock.handle, 1) - @linux_only begin + @static if is_linux() # tcp_quickack is a linux only option if ccall(:jl_tcp_quickack, Cint, (Ptr{Void}, Cint), sock.handle, 1) < 0 warn_once("Parallel networking unoptimized ( Error enabling TCP_QUICKACK : ", Libc.strerror(Libc.errno()), " )") diff --git a/base/osutils.jl b/base/osutils.jl index 95830b96935c1..cc3bada67bc86 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -1,66 +1,83 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license """ - OS_NAME + is_unix([os]) -A symbol representing the name of the operating system. Possible values are -`:Linux`, `:Darwin` (OS X), or `:Windows`. +Predicate for testing if the OS provides a Unix-like interface. +See documentation [Handling Operating System Variation](:ref:`Handling Operating System Variation `). """ -const OS_NAME = ccall(:jl_get_OS_NAME, Any, ()) - function is_unix(os::Symbol) - if (os==:Windows) return false; - elseif (os==:Linux) return true; - elseif (os==:FreeBSD) return true; - elseif (os==:Darwin) return true; - else throw(ArgumentError("unknown operating system, $(repr(os))")) - end -end - -function _os_test(qm,ex,test) - @assert qm == :? - @assert isa(ex,Expr) - @assert ex.head == :(:) - @assert length(ex.args) == 2 - if test - return esc(ex.args[1]) + if is_windows(os) + return false + elseif is_linux(os) || is_bsd(os) + return true else - return esc(ex.args[2]) + throw(ArgumentError("unknown operating system \"$os\"")) end end -macro windows(qm,ex) - _os_test(qm, ex, OS_NAME===:Windows) -end -macro unix(qm,ex) - _os_test(qm, ex, is_unix(OS_NAME)) -end -macro osx(qm,ex) - _os_test(qm, ex, OS_NAME===:Darwin) -end -macro linux(qm,ex) - _os_test(qm, ex, OS_NAME===:Linux) -end +""" + is_linux([os]) -macro windows_only(ex) - @windows? esc(ex) : nothing -end -macro unix_only(ex) - @unix? esc(ex) : nothing -end -macro osx_only(ex) - @osx? esc(ex) : nothing -end -macro linux_only(ex) - @linux? esc(ex) : nothing -end +Predicate for testing if the OS is a derivative of Linux. +See documentation [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +""" +is_linux(os::Symbol) = (os == :Linux) + +""" + is_bsd([os]) -# Windows version macros +Predicate for testing if the OS is a derivative of BSD. +See documentation [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +""" +is_bsd(os::Symbol) = (os == :FreeBSD || os == :OpenBSD || os == :NetBSD || os == :Darwin || os == :Apple) + +""" + is_windows([os]) + +Predicate for testing if the OS is a derivative of Microsoft Windows NT. +See documentation [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +""" +is_windows(os::Symbol) = (os == :Windows || os == :NT) + +""" + is_apple([os]) + +Predicate for testing if the OS is a derivative of Apple Macintosh OS X or Darwin. +See documentation [Handling Operating System Variation](:ref:`Handling Operating System Variation `). +""" +is_apple(os::Symbol) = (os == :Apple || os == :Darwin) + +""" + @static + +Partially evaluates an expression at parse time. -@windows_only function windows_version() - verinfo = ccall(:GetVersion, UInt32, ()) - (verinfo & 0xFF, (verinfo >> 8) & 0xFF) +For example, `@static is_windows() ? foo : bar` will evaluate `is_windows()` and insert either `foo` or `bar` into the expression. +This is useful in cases where a construct would be invalid on other platforms, +such as a `ccall` to a non-existent function. +""" +macro static(ex) + if isa(ex, Expr) + if ex.head === :if + cond = eval(current_module(), ex.args[1]) + if cond + return esc(ex.args[2]) + elseif length(ex.args) == 3 + return esc(ex.args[3]) + else + return nothing + end + end + end + throw(ArgumentError("invalid @static macro")) end -@unix_only windows_version() = (0,0) -WINDOWS_VISTA_VER = (6,0) +let KERNEL = ccall(:jl_get_UNAME, Any, ()) + # evaluate the zero-argument form of each of these functions + # as a function returning a static constant based on the build-time + # operating-system kernel + for f in (:is_unix, :is_linux, :is_bsd, :is_apple, :is_windows) + @eval $f() = $(getfield(current_module(),f)(KERNEL)) + end +end diff --git a/base/path.jl b/base/path.jl index 93c7f8e73929c..d4d93d073aadb 100644 --- a/base/path.jl +++ b/base/path.jl @@ -16,7 +16,7 @@ export splitdrive, splitext -@unix_only begin +if is_unix() const path_separator = "/" const path_separator_re = r"/+" const path_absolute_re = r"^/" @@ -26,8 +26,7 @@ export splitdrive(path::AbstractString) = ("",path) homedir() = ENV["HOME"] -end -@windows_only begin +elseif is_windows() const path_separator = "\\" const path_separator_re = r"[/\\]+" const path_absolute_re = r"^(?:\w+:)?[/\\]" @@ -40,6 +39,8 @@ end String(m.captures[1]), String(m.captures[2]) end homedir() = get(ENV,"HOME",string(ENV["HOMEDRIVE"],ENV["HOMEPATH"])) +else + error("path primitives for this OS need to be defined") end isabspath(path::AbstractString) = ismatch(path_absolute_re, path) @@ -124,7 +125,8 @@ normpath(a::AbstractString, b::AbstractString...) = normpath(joinpath(a,b...)) abspath(a::AbstractString) = normpath(isabspath(a) ? a : joinpath(pwd(),a)) abspath(a::AbstractString, b::AbstractString...) = abspath(joinpath(a,b...)) -@windows_only function realpath(path::AbstractString) +if is_windows() +function realpath(path::AbstractString) path = cwstring(path) buf = zeros(UInt16, length(path)) while true @@ -138,7 +140,7 @@ abspath(a::AbstractString, b::AbstractString...) = abspath(joinpath(a,b...)) end end -@windows_only function longpath(path::AbstractString) +function longpath(path::AbstractString) path = cwstring(path) buf = zeros(UInt16, length(path)) while true @@ -152,16 +154,20 @@ end end end -@unix_only function realpath(path::AbstractString) +else # !windows +function realpath(path::AbstractString) p = ccall(:realpath, Ptr{UInt8}, (Cstring, Ptr{UInt8}), path, C_NULL) systemerror(:realpath, p == C_NULL) s = String(p) Libc.free(p) return s end +end # os-test -@windows_only expanduser(path::AbstractString) = path # on windows, ~ means "temporary file" -@unix_only function expanduser(path::AbstractString) +if is_windows() +expanduser(path::AbstractString) = path # on windows, ~ means "temporary file" +else +function expanduser(path::AbstractString) i = start(path) c, i = next(path,i) if c != '~' return path end @@ -170,6 +176,7 @@ end if c == '/' return homedir()*path[i:end] end throw(ArgumentError("~user tilde expansion not yet implemented")) end +end function relpath(path::AbstractString, startpath::AbstractString = ".") isempty(path) && throw(ArgumentError("`path` must be specified")) diff --git a/base/pkg/cache.jl b/base/pkg/cache.jl index 61c09470b8dce..fe0247dc4dc3e 100644 --- a/base/pkg/cache.jl +++ b/base/pkg/cache.jl @@ -18,13 +18,15 @@ function mkcachedir() return end - @unix_only if Dir.isversioned(pwd()) - rootcache = joinpath(realpath(".."), ".cache") - if !isdir(rootcache) - mkdir(rootcache) + @static if is_unix() + if Dir.isversioned(pwd()) + rootcache = joinpath(realpath(".."), ".cache") + if !isdir(rootcache) + mkdir(rootcache) + end + symlink(rootcache, cache) + return end - symlink(rootcache, cache) - return end mkdir(cache) end diff --git a/base/pkg/reqs.jl b/base/pkg/reqs.jl index 80f67a268031f..461e15b0abaf6 100644 --- a/base/pkg/reqs.jl +++ b/base/pkg/reqs.jl @@ -91,14 +91,16 @@ function parse(lines::Vector{Line}) if isa(line,Requirement) if !isempty(line.system) applies = false - @windows_only applies |= ("windows" in line.system) - @unix_only applies |= ("unix" in line.system) - @osx_only applies |= ("osx" in line.system) - @linux_only applies |= ("linux" in line.system) - @windows_only applies &= !("!windows" in line.system) - @unix_only applies &= !("!unix" in line.system) - @osx_only applies &= !("!osx" in line.system) - @linux_only applies &= !("!linux" in line.system) + if is_windows(); applies |= ("windows" in line.system); end + if is_unix(); applies |= ("unix" in line.system); end + if is_apple(); applies |= ("osx" in line.system); end + if is_linux(); applies |= ("linux" in line.system); end + if is_bsd(); applies |= ("bsd" in line.system); end + if is_windows(); applies &= !("!windows" in line.system); end + if is_unix(); applies &= !("!unix" in line.system); end + if is_apple(); applies &= !("!osx" in line.system); end + if is_linux(); applies &= !("!linux" in line.system); end + if is_bsd(); applies &= !("!bsd" in line.system); end applies || continue end reqs[line.package] = haskey(reqs, line.package) ? diff --git a/base/poll.jl b/base/poll.jl index cb5658eeb6dec..3c54075cb8b4e 100644 --- a/base/poll.jl +++ b/base/poll.jl @@ -13,7 +13,9 @@ export import Base: @handle_as, wait, close, uvfinalize, eventloop, notify_error, stream_wait, _sizeof_uv_poll, _sizeof_uv_fs_poll, _sizeof_uv_fs_event, _uv_hook_close, associate_julia_struct, disassociate_julia_struct -@windows_only import Base.WindowsRawSocket +if is_windows() + import Base.WindowsRawSocket +end # libuv file watching event flags const UV_RENAME = 1 @@ -106,8 +108,10 @@ type _FDWatcher this.refcount = (this.refcount[1] + Int(readable), this.refcount[2] + Int(writable)) return this end - @unix_only if ccall(:jl_uv_unix_fd_is_watched, Int32, (Int32, Ptr{Void}, Ptr{Void}), fd.fd, C_NULL, eventloop()) == 1 - throw(ArgumentError("file descriptor $(fd.fd) is already being watched by libuv")) + @static if is_unix() + if ccall(:jl_uv_unix_fd_is_watched, Int32, (Int32, Ptr{Void}, Ptr{Void}), fd.fd, C_NULL, eventloop()) == 1 + throw(ArgumentError("file descriptor $(fd.fd) is already being watched by libuv")) + end end handle = Libc.malloc(_sizeof_uv_poll) this = new(handle, (Int(readable), Int(writable)), Condition(), (false, false)) @@ -120,20 +124,22 @@ type _FDWatcher FDWatchers[fd.fd] = this return this end - @windows_only function _FDWatcher(fd::WindowsRawSocket, readable::Bool, writable::Bool) - if !readable && !writable - throw(ArgumentError("must specify at least one of readable or writable to create a FDWatcher")) - end - handle = Libc.malloc(_sizeof_uv_poll) - this = new(handle, (Int(readable), Int(writable)), Condition(), (false, false)) - associate_julia_struct(handle, this) - err = ccall(:uv_poll_init_socket,Int32,(Ptr{Void}, Ptr{Void}, Ptr{Void}), - eventloop(), handle, fd.handle) - if err != 0 - Libc.free(handle) - throw(UVError("FDWatcher",err)) + @static if is_windows() + function _FDWatcher(fd::WindowsRawSocket, readable::Bool, writable::Bool) + if !readable && !writable + throw(ArgumentError("must specify at least one of readable or writable to create a FDWatcher")) + end + handle = Libc.malloc(_sizeof_uv_poll) + this = new(handle, (Int(readable), Int(writable)), Condition(), (false, false)) + associate_julia_struct(handle, this) + err = ccall(:uv_poll_init_socket,Int32,(Ptr{Void}, Ptr{Void}, Ptr{Void}), + eventloop(), handle, fd.handle) + if err != 0 + Libc.free(handle) + throw(UVError("FDWatcher",err)) + end + return this end - return this end global close function close(t::_FDWatcher, readable::Bool, writable::Bool) @@ -170,10 +176,12 @@ type FDWatcher finalizer(this, close) return this end - @windows_only function FDWatcher(fd::WindowsRawSocket, readable::Bool, writable::Bool) - this = new(_FDWatcher(fd, readable, writable), readable, writable) - finalizer(this, close) - return this + @static if is_windows() + function FDWatcher(fd::WindowsRawSocket, readable::Bool, writable::Bool) + this = new(_FDWatcher(fd, readable, writable), readable, writable) + finalizer(this, close) + return this + end end end @@ -332,7 +340,7 @@ function wait(fd::RawFD; readable=false, writable=false) end end -@windows_only begin +if is_windows() function wait(socket::WindowsRawSocket; readable=false, writable=false) fdw = _FDWatcher(socket, readable, writable) try @@ -357,7 +365,7 @@ function wait(m::FileMonitor) return filename, events end -function poll_fd(s::Union{RawFD, @windows ? WindowsRawSocket : Union{}}, timeout_s::Real=-1; readable=false, writable=false) +function poll_fd(s::Union{RawFD, is_windows() ? WindowsRawSocket : Union{}}, timeout_s::Real=-1; readable=false, writable=false) wt = Condition() fdw = _FDWatcher(s, readable, writable) try diff --git a/base/printf.jl b/base/printf.jl index 7800883b0dfe9..0e69b2f37af89 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -667,7 +667,7 @@ function gen_p(flags::String, width::Int, precision::Int, c::Char) # @gensym x blk = Expr(:block) - ptrwidth = WORD_SIZE>>2 + ptrwidth = Sys.WORD_SIZE>>2 width -= ptrwidth+2 if width > 0 && !('-' in flags) push!(blk.args, pad(width, width, ' ')) diff --git a/base/process.jl b/base/process.jl index fba0997615526..5496fd895241b 100644 --- a/base/process.jl +++ b/base/process.jl @@ -137,7 +137,7 @@ immutable FileRedirect filename::AbstractString append::Bool function FileRedirect(filename, append) - if lowercase(filename) == (@unix? "/dev/null" : "nul") + if lowercase(filename) == (@static is_windows() ? "nul" : "/dev/null") warn_once("for portability use DevNull instead of a file redirect") end new(filename, append) diff --git a/base/profile.jl b/base/profile.jl index f87f144e397ec..38f8e09297251 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -53,7 +53,11 @@ end # init with default values # Use a max size of 1M profile samples, and fire timer every 1ms -@windows? (__init__() = init(1_000_000, 0.01)) : (__init__() = init(1_000_000, 0.001)) +if is_windows() + __init__() = init(1_000_000, 0.01) +else + __init__() = init(1_000_000, 0.001) +end """ clear() @@ -208,9 +212,7 @@ end # Number of backtrace "steps" that are triggered by taking the backtrace, e.g., inside profile_bt -# May be platform-specific? -#@unix_only const btskip = 2 -#@windows_only const btskip = 0 +# TODO: may be platform-specific? const btskip = 0 ## Print as a flat list diff --git a/base/random.jl b/base/random.jl index 68a7fd5b06420..68db68f462868 100644 --- a/base/random.jl +++ b/base/random.jl @@ -27,18 +27,7 @@ type Close1Open2 <: FloatInterval end ## RandomDevice -@unix_only begin - immutable RandomDevice <: AbstractRNG - file::IOStream - - RandomDevice(unlimited::Bool=true) = new(open(unlimited ? "/dev/urandom" : "/dev/random")) - end - - rand{ T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, ::Type{T}) = read( rd.file, T) - rand!{T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, A::Array{T}) = read!(rd.file, A) -end - -@windows_only begin +if is_windows() immutable RandomDevice <: AbstractRNG buffer::Vector{UInt128} @@ -51,7 +40,16 @@ end end rand!{T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, A::Array{T}) = (win32_SystemFunction036!(A); A) -end +else # !windows + immutable RandomDevice <: AbstractRNG + file::IOStream + + RandomDevice(unlimited::Bool=true) = new(open(unlimited ? "/dev/urandom" : "/dev/random")) + end + + rand{ T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, ::Type{T}) = read( rd.file, T) + rand!{T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, A::Array{T}) = read!(rd.file, A) +end # os-test rand(rng::RandomDevice, ::Type{Close1Open2}) = reinterpret(Float64, 0x3ff0000000000000 | rand(rng, UInt64) & 0x000fffffffffffff) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index 00e58895b4e26..abaa6c8b308a2 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -477,8 +477,13 @@ complex(S1::SharedArray,S2::SharedArray) = convert(SharedArray, complex(S1.s, S2 function print_shmem_limits(slen) try - @linux_only pfx = "kernel" - @osx_only pfx = "kern.sysv" + if is_linux() + pfx = "kernel" + elseif is_apple() + pfx = "kern.sysv" + else + return + end shmmax_MB = div(parse(Int, split(readstring(`sysctl $(pfx).shmmax`))[end]), 1024*1024) page_size = parse(Int, split(readstring(`getconf PAGE_SIZE`))[end]) @@ -521,8 +526,18 @@ end # platform-specific code -@unix_only begin +if is_windows() +function _shm_mmap_array(T, dims, shm_seg_name, mode) + readonly = !((mode & JL_O_RDWR) == JL_O_RDWR) + create = (mode & JL_O_CREAT) == JL_O_CREAT + s = Mmap.Anonymous(shm_seg_name, readonly, create) + Mmap.mmap(s, Array{T,length(dims)}, dims, zero(Int64)) +end + +# no-op in windows +shm_unlink(shm_seg_name) = 0 +else # !windows function _shm_mmap_array(T, dims, shm_seg_name, mode) fd_mem = shm_open(shm_seg_name, mode, S_IRUSR | S_IWUSR) systemerror("shm_open() failed for " * shm_seg_name, fd_mem < 0) @@ -542,18 +557,4 @@ end shm_unlink(shm_seg_name) = ccall(:shm_unlink, Cint, (Cstring,), shm_seg_name) shm_open(shm_seg_name, oflags, permissions) = ccall(:shm_open, Cint, (Cstring, Cint, Cmode_t), shm_seg_name, oflags, permissions) -end # @unix_only - -@windows_only begin - -function _shm_mmap_array(T, dims, shm_seg_name, mode) - readonly = !((mode & JL_O_RDWR) == JL_O_RDWR) - create = (mode & JL_O_CREAT) == JL_O_CREAT - s = Mmap.Anonymous(shm_seg_name, readonly, create) - Mmap.mmap(s, Array{T,length(dims)}, dims, zero(Int64)) -end - -# no-op in windows -shm_unlink(shm_seg_name) = 0 - -end # @windows_only +end # os-test diff --git a/base/show.jl b/base/show.jl index 617229b261a60..7c3b2bf65249a 100644 --- a/base/show.jl +++ b/base/show.jl @@ -201,7 +201,7 @@ show(io::IO, n::Signed) = (write(io, dec(n)); nothing) show(io::IO, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) print(io::IO, n::Unsigned) = print(io, dec(n)) -show{T}(io::IO, p::Ptr{T}) = print(io, typeof(p), " @0x$(hex(UInt(p), WORD_SIZE>>2))") +show{T}(io::IO, p::Ptr{T}) = print(io, typeof(p), " @0x$(hex(UInt(p), Sys.WORD_SIZE>>2))") function show(io::IO, p::Pair) if typeof(p.first) != typeof(p).parameters[1] || diff --git a/base/socket.jl b/base/socket.jl index 2c5ee4e3e81af..a1bb1d70841e2 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -779,7 +779,7 @@ function getsockname(sock::Union{TCPServer,TCPSocket}) addrv4 = raddress[1:4] naddr = ntoh(unsafe_load(Ptr{Cuint}(pointer(addrv4)), 1)) addr = IPv4(naddr) - elseif rfamily[] == @windows? 23 : (@osx? 30 : 10) # AF_INET6 + elseif rfamily[] == @static is_windows() ? 23 : (@static is_apple() ? 30 : 10) # AF_INET6 naddr = ntoh(unsafe_load(Ptr{UInt128}(pointer(raddress)), 1)) addr = IPv6(naddr) else diff --git a/base/stream.jl b/base/stream.jl index c51c27b6359fd..dafe1a9cb84f2 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1,7 +1,9 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license import .Libc: RawFD, dup -@windows_only import .Libc: WindowsRawSocket +if is_windows() + import .Libc: WindowsRawSocket +end ## types ## typealias Callback Union{Function,Bool} @@ -164,7 +166,7 @@ type TTY <: LibuvStream sendbuf::Nullable{IOBuffer} lock::ReentrantLock throttle::Int - @windows_only ispty::Bool + @static if is_windows(); ispty::Bool; end function TTY(handle) tty = new( handle, @@ -175,8 +177,10 @@ type TTY <: LibuvStream false,Condition(), nothing, ReentrantLock(), DEFAULT_READ_BUFFER_SZ) - @windows_only tty.ispty = ccall(:jl_ispty, Cint, (Ptr{Void},), handle)!=0 - tty + @static if is_windows() + tty.ispty = ccall(:jl_ispty, Cint, (Ptr{Void},), handle) != 0 + end + return tty end end @@ -190,7 +194,7 @@ function TTY(fd::RawFD; readable::Bool = false) uv_error("TTY",ccall(:uv_tty_init,Int32,(Ptr{Void},Ptr{Void},Int32,Int32),eventloop(),handle,fd.fd,readable)) ret.status = StatusOpen ret.line_buffered = false - ret + return ret end show(io::IO,stream::LibuvServer) = print(io, typeof(stream), "(", uv_status_string(stream), ")") @@ -325,7 +329,7 @@ function close(stream::Union{LibuvStream, LibuvServer}) nothing end -@windows_only begin +if is_windows() ispty(s::TTY) = s.ispty ispty(s::IO) = false end @@ -340,15 +344,17 @@ function displaysize(io::TTY) local h::Int, w::Int default_size = displaysize() - @windows_only if ispty(io) - # io is actually a libuv pipe but a cygwin/msys2 pty - try - h, w = map(x -> parse(Int, x), split(readstring(open(Base.Cmd(String["stty", "size"]), "r", io)[1]))) - h > 0 || (h = default_size[1]) - w > 0 || (w = default_size[2]) - return h, w - catch - return default_size + @static if is_windows() + if ispty(io) + # io is actually a libuv pipe but a cygwin/msys2 pty + try + h, w = map(x -> parse(Int, x), split(readstring(open(Base.Cmd(String["stty", "size"]), "r", io)[1]))) + h > 0 || (h = default_size[1]) + w > 0 || (w = default_size[2]) + return h, w + catch + return default_size + end end end @@ -950,20 +956,28 @@ end connect(path::AbstractString) = connect(init_pipe!(PipeEndpoint(); readable=false, writable=false, julia_only=true),path) _fd(x::IOStream) = RawFD(fd(x)) -@unix_only _fd(x::LibuvStream) = RawFD(ccall(:jl_uv_handle,Int32,(Ptr{Void},),x.handle)) -@windows_only _fd(x::LibuvStream) = WindowsRawSocket( - ccall(:jl_uv_handle,Ptr{Void},(Ptr{Void},),x.handle)) +if is_windows() + _fd(x::LibuvStream) = WindowsRawSocket( + ccall(:jl_uv_handle, Ptr{Void}, (Ptr{Void},), x.handle)) +else + _fd(x::LibuvStream) = RawFD(ccall(:jl_uv_handle, Int32, (Ptr{Void},), x.handle)) +end -for (x,writable,unix_fd,c_symbol) in ((:STDIN,false,0,:jl_uv_stdin),(:STDOUT,true,1,:jl_uv_stdout),(:STDERR,true,2,:jl_uv_stderr)) +for (x, writable, unix_fd, c_symbol) in + ((:STDIN, false, 0, :jl_uv_stdin), + (:STDOUT, true, 1, :jl_uv_stdout), + (:STDERR, true, 2, :jl_uv_stderr)) f = Symbol("redirect_",lowercase(string(x))) _f = Symbol("_",f) @eval begin function ($_f)(stream) global $x - @windows? ( + @static if is_windows() ccall(:SetStdHandle,stdcall,Int32,(Int32,Ptr{Void}), - $(-10-unix_fd), Libc._get_osfhandle(_fd(stream)).handle) ) : ( - dup(_fd(stream), RawFD($unix_fd)) ) + $(-10 - unix_fd), Libc._get_osfhandle(_fd(stream)).handle) + else + dup(_fd(stream), RawFD($unix_fd)) + end $x = stream end function ($f)(handle::Union{LibuvStream,IOStream}) diff --git a/base/sysimg.jl b/base/sysimg.jl index 8a9e4d264d590..c5ae20327a50b 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -117,6 +117,7 @@ include(String(vcat(length(Core.ARGS)>=2?Core.ARGS[2].data:"".data, "build_h.jl" include(String(vcat(length(Core.ARGS)>=2?Core.ARGS[2].data:"".data, "version_git.jl".data))) # include($BUILDROOT/base/version_git.jl) include("osutils.jl") include("c.jl") +include("sysinfo.jl") # Core I/O include("io.jl") @@ -294,10 +295,6 @@ importall .DFT include("dsp.jl") importall .DSP -# system information -include("sysinfo.jl") -import .Sys.CPU_CORES - # Numerical integration include("quadgk.jl") importall .QuadGK diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 9fb2dfeabe50b..5241542d56b50 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -3,10 +3,10 @@ module Sys export CPU_CORES, - OS_NAME, WORD_SIZE, ARCH, MACHINE, + KERNEL, JIT, cpu_info, cpu_name, @@ -16,28 +16,55 @@ export CPU_CORES, free_memory, total_memory -import ..Base: WORD_SIZE, OS_NAME, ARCH, MACHINE -import ..Base: show, uv_error +import ..Base: show global CPU_CORES +""" + Sys.CPU_CORES + +The number of CPU cores in the system. +""" +:CPU_CORES + +""" + Sys.ARCH + +A symbol representing the architecture of the build configuration. +""" +const ARCH = ccall(:jl_get_ARCH, Any, ()) + + +""" + Sys.KERNEL + +A symbol representing the name of the operating system, as returned by `uname` of the build configuration. +""" +const KERNEL = ccall(:jl_get_UNAME, Any, ()) + +""" + Sys.MACHINE + +A string containing the build triple. +""" +const MACHINE = Base.MACHINE + +""" + Sys.WORD_SIZE + +Standard word size on the current machine, in bits. +""" +const WORD_SIZE = Core.sizeof(Int) * 8 function __init__() # set CPU core count - global const CPU_CORES = + global CPU_CORES = haskey(ENV,"JULIA_CPU_CORES") ? parse(Int,ENV["JULIA_CPU_CORES"]) : Int(ccall(:jl_cpu_cores, Int32, ())) - global const SC_CLK_TCK = ccall(:jl_SC_CLK_TCK, Clong, ()) - global const cpu_name = ccall(:jl_get_cpu_name, Ref{String}, ()) - global const JIT = ccall(:jl_get_JIT, Ref{String}, ()) + global SC_CLK_TCK = ccall(:jl_SC_CLK_TCK, Clong, ()) + global cpu_name = ccall(:jl_get_cpu_name, Ref{String}, ()) + global JIT = ccall(:jl_get_JIT, Ref{String}, ()) end -""" - CPU_CORES - -The number of CPU cores in the system. -""" -:CPU_CORES - type UV_cpu_info_t model::Ptr{UInt8} speed::Int32 @@ -61,36 +88,17 @@ CPUinfo(info::UV_cpu_info_t) = CPUinfo(String(info.model), info.speed, info.cpu_times!user, info.cpu_times!nice, info.cpu_times!sys, info.cpu_times!idle, info.cpu_times!irq) -function show(io::IO, info::CPUinfo, header::Bool=true, prefix::AbstractString=" ") - tck = SC_CLK_TCK - if header - println(io, info.model, ": ") - print(io, " "^length(prefix)) - if tck > 0 - @printf io " %5s %9s %9s %9s %9s %9s\n" "speed" "user" "nice" "sys" "idle" "irq" - else - @printf io " %5s %9s %9s %9s %9s %9s ticks\n" "speed" "user" "nice" "sys" "idle" "irq" - end - end - print(io, prefix) - if tck > 0 - @printf io "%5d MHz %9d s %9d s %9d s %9d s %9d s" info.speed info.cpu_times!user/tck info.cpu_times!nice/tck info.cpu_times!sys/tck info.cpu_times!idle/tck info.cpu_times!irq/tck - else - @printf io "%5d MHz %9d %9d %9d %9d %9d ticks" info.speed info.cpu_times!user info.cpu_times!nice info.cpu_times!sys info.cpu_times!idle info.cpu_times!irq - end -end - function _cpu_summary(io::IO, cpu::Array{CPUinfo}, i, j) if j-i < 9 header = true for x = i:j - if header == false println(io) end - show(io,cpu[x],header,"#$(x-i+1) ") + header || println(io) + show(io, cpu[x], header, "#$(x-i+1) ") header = false end else summary = CPUinfo(cpu[i].model,0,0,0,0,0,0) - count = j-i+1 + count = j - i + 1 for x = i:j summary.speed += cpu[i].speed summary.cpu_times!user += cpu[x].cpu_times!user @@ -100,7 +108,7 @@ function _cpu_summary(io::IO, cpu::Array{CPUinfo}, i, j) summary.cpu_times!irq += cpu[x].cpu_times!irq end summary.speed = div(summary.speed,count) - show(io,summary,true,"#1-$(count) ") + show(io, summary, true, "#1-$(count) ") end println(io) end @@ -110,17 +118,17 @@ function cpu_summary(io::IO=STDOUT, cpu::Array{CPUinfo}=cpu_info()) first = 1 for i = 2:length(cpu) if model != cpu[i].model - _cpu_summary(io,cpu,first,i-1) + _cpu_summary(io, cpu, first, i-1) first = i end end - _cpu_summary(io,cpu,first,length(cpu)) + _cpu_summary(io, cpu, first, length(cpu)) end function cpu_info() UVcpus = Array(Ptr{UV_cpu_info_t},1) count = Array(Int32,1) - uv_error("uv_cpu_info",ccall(:uv_cpu_info, Int32, (Ptr{Ptr{UV_cpu_info_t}}, Ptr{Int32}), UVcpus, count)) + Base.uv_error("uv_cpu_info",ccall(:uv_cpu_info, Int32, (Ptr{Ptr{UV_cpu_info_t}}, Ptr{Int32}), UVcpus, count)) cpus = Array(CPUinfo,count[1]) for i = 1:length(cpus) cpus[i] = CPUinfo(unsafe_load(UVcpus[1],i)) @@ -131,7 +139,7 @@ end function uptime() uptime_ = Array(Float64,1) - uv_error("uv_uptime",ccall(:uv_uptime, Int32, (Ptr{Float64},), uptime_)) + Base.uv_error("uv_uptime",ccall(:uv_uptime, Int32, (Ptr{Float64},), uptime_)) return uptime_[1] end @@ -147,14 +155,33 @@ total_memory() = ccall(:uv_get_total_memory, UInt64, ()) function get_process_title() buf = zeros(UInt8, 512) err = ccall(:uv_get_process_title, Cint, (Ptr{UInt8}, Cint), buf, 512) - uv_error("get_process_title", err) + Base.uv_error("get_process_title", err) return String(pointer(buf)) end + function set_process_title(title::AbstractString) err = ccall(:uv_set_process_title, Cint, (Cstring,), title) - uv_error("set_process_title", err) + Base.uv_error("set_process_title", err) end maxrss() = ccall(:jl_maxrss, Csize_t, ()) +if is_windows() + function windows_version() + verinfo = ccall(:GetVersion, UInt32, ()) + (Int(verinfo & 0xFF), Int((verinfo >> 8) & 0xFF)) + end +else + windows_version() = (0, 0) +end +""" + windows_version() + +Returns the version number for the Windows NT Kernel as a (major, minor) pair, +or (0, 0) if this is not running on Windows. +""" +windows_version + +const WINDOWS_VISTA_VER = (6, 0) + end # module Sys diff --git a/base/task.jl b/base/task.jl index 973b2084798ce..4e1d45bf199af 100644 --- a/base/task.jl +++ b/base/task.jl @@ -47,7 +47,7 @@ function showerror(io::IO, ex::CompositeException) end function show(io::IO, t::Task) - print(io, "Task ($(t.state)) @0x$(hex(convert(UInt, pointer_from_objref(t)), WORD_SIZE>>2))") + print(io, "Task ($(t.state)) @0x$(hex(convert(UInt, pointer_from_objref(t)), Sys.WORD_SIZE>>2))") end macro task(ex) diff --git a/base/util.jl b/base/util.jl index c23ed1498d943..406108c97fa1b 100644 --- a/base/util.jl +++ b/base/util.jl @@ -255,7 +255,9 @@ function blas_set_num_threads(n::Integer) end # OSX BLAS looks at an environment variable - @osx_only ENV["VECLIB_MAXIMUM_THREADS"] = n + @static if is_apple() + ENV["VECLIB_MAXIMUM_THREADS"] = n + end return nothing end @@ -391,7 +393,8 @@ end julia_exename() = ccall(:jl_is_debugbuild,Cint,())==0 ? "julia" : "julia-debug" -@windows_only function getpass(prompt::AbstractString) +if is_windows() +function getpass(prompt::AbstractString) print(prompt) flush(STDOUT) p = Array(UInt8, 128) # mimic Unix getpass in ignoring more than 128-char passwords @@ -417,5 +420,6 @@ julia_exename() = ccall(:jl_is_debugbuild,Cint,())==0 ? "julia" : "julia-debug" return "" end - -@unix_only getpass(prompt::AbstractString) = String(ccall(:getpass, Cstring, (Cstring,), prompt)) +else +getpass(prompt::AbstractString) = String(ccall(:getpass, Cstring, (Cstring,), prompt)) +end diff --git a/doc/manual/handling-operating-system-variation.rst b/doc/manual/handling-operating-system-variation.rst index aa81937a64dc6..6f6416bbd8ae7 100644 --- a/doc/manual/handling-operating-system-variation.rst +++ b/doc/manual/handling-operating-system-variation.rst @@ -6,33 +6,31 @@ When dealing with platform libraries, it is often necessary to provide special cases for various platforms. The variable ``OS_NAME`` can be used to write these special -cases. There are several macros intended to make this easier: ``@windows_only``, -``@unix_only``, ``@linux_only``, and ``@osx_only``. These may be used as follows:: +cases. There are several functions intended to make this easier: +``is_unix``, ``is_linux``, ``is_apple``, ``is_bsd``, and ``is_windows``. These may be used as follows:: - @windows_only begin + if is_windows() some_complicated_thing(a) end -Note that ``@linux_only`` and ``@osx_only`` are mutually exclusive subsets of ``@unix_only``\ . (This -similarly applies to ``@unix``\ .) -Additionally, there are:``@windows``, ``@unix``, ``@linux``, and ``@osx``. Their usage takes -the form of a ternary conditional operator, as demonstrated in the following examples. +Note that ``is_linux`` and ``is_apple`` are mutually exclusive subsets of ``is_unix``\ . +Additionally, there is a macro ``@static`` which makes it possible to +use these functions to conditionally hide invalid code, as demonstrated in the following examples. Simple blocks:: - ccall( (@windows? :_fopen : :fopen), ...) + ccall( (@static is_windows() ? :_fopen : :fopen), ...) Complex blocks:: - @linux? ( - begin - some_complicated_thing(a) - end - : begin - some_different_thing(a) - end - ) + @static if is_linux() + some_complicated_thing(a) + else + some_different_thing(a) + end -Chaining (parentheses optional, but recommended for readability):: +When chaining conditionals (including if/elseif/end), +the ``@static`` must be repeated for each level +(parentheses optional, but recommended for readability):: - @windows? :a : (@osx? :b : :c) + @static is_windows() ? :a : (@static is_apple() ? :b : :c) diff --git a/doc/manual/packages.rst b/doc/manual/packages.rst index dddb8df905b20..4358d2508764b 100644 --- a/doc/manual/packages.rst +++ b/doc/manual/packages.rst @@ -989,14 +989,19 @@ For example:: @osx Homebrew will require the ``Homebrew`` package only on systems where the operating system is OS X. -The system conditions that are currently supported are:: +The system conditions that are currently supported are (hierarchically): - @windows - @unix - @osx - @linux +* ``@unix`` -The ``@unix`` condition is satisfied on all UNIX systems, including OS X, Linux and FreeBSD. + * ``@linux`` + + * ``@bsd`` + + * ``@osx`` + +* ``@windows`` + +The ``@unix`` condition is satisfied on all UNIX systems, including Linux and BSD. Negated system conditionals are also supported by adding a ``!`` after the leading ``@``. Examples:: diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 2f566b589964a..97685c2159b5c 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -977,53 +977,49 @@ System Reference to the singleton ``EnvHash``\ , providing a dictionary interface to system environment variables. -.. function:: @unix +.. function:: is_unix([os]) .. Docstring generated from Julia source - Given ``@unix? a : b``\ , do ``a`` on Unix systems (including Linux and OS X) and ``b`` elsewhere. See documentation in :ref:`Handling Operating System Variation `\ . + Predicate for testing if the OS provides a Unix-like interface. See documentation :ref:`Handling Operating System Variation `\ . -.. function:: @unix_only +.. function:: is_apple([os]) .. Docstring generated from Julia source - A macro that evaluates the given expression only on Unix systems (including Linux and OS X). See documentation in :ref:`Handling Operating System Variation `\ . + Predicate for testing if the OS is a derivative of Apple Macintosh OS X or Darwin. See documentation :ref:`Handling Operating System Variation `\ . -.. function:: @osx +.. function:: is_linux([os]) .. Docstring generated from Julia source - Given ``@osx? a : b``\ , do ``a`` on OS X and ``b`` elsewhere. See documentation in :ref:`Handling Operating System Variation `\ . + Predicate for testing if the OS is a derivative of Linux. See documentation :ref:`Handling Operating System Variation `\ . -.. function:: @osx_only +.. function:: is_bsd([os]) .. Docstring generated from Julia source - A macro that evaluates the given expression only on OS X systems. See documentation in :ref:`Handling Operating System Variation `\ . + Predicate for testing if the OS is a derivative of BSD. See documentation :ref:`Handling Operating System Variation `\ . -.. function:: @linux +.. function:: is_windows([os]) .. Docstring generated from Julia source - Given ``@linux? a : b``\ , do ``a`` on Linux and ``b`` elsewhere. See documentation :ref:`Handling Operating System Variation `\ . + Predicate for testing if the OS is a derivative of Microsoft Windows NT. See documentation :ref:`Handling Operating System Variation `\ . -.. function:: @linux_only +.. function:: windows_version() .. Docstring generated from Julia source - A macro that evaluates the given expression only on Linux systems. See documentation in :ref:`Handling Operating System Variation `\ . + Returns the version number for the Windows NT Kernel as a (major, minor) pair, or (0, 0) if this is not running on Windows. -.. function:: @windows +.. function:: @static .. Docstring generated from Julia source - Given ``@windows? a : b``\ , do ``a`` on Windows and ``b`` elsewhere. See documentation in :ref:`Handling Operating System Variation `\ . + Partially evaluates an expression at parse time. -.. function:: @windows_only - - .. Docstring generated from Julia source - - A macro that evaluates the given expression only on Windows systems. See documentation in :ref:`Handling Operating System Variation `\ . + For example, ``@static is_windows() ? foo : bar`` will evaluate ``is_windows()`` and insert either ``foo`` or ``bar`` into the expression. This is useful in cases where a construct would be invalid on other platforms, such as a ``ccall`` to a non-existent function. Errors ------ diff --git a/doc/stdlib/constants.rst b/doc/stdlib/constants.rst index 64c03ad771797..3f32de5e8ccdb 100644 --- a/doc/stdlib/constants.rst +++ b/doc/stdlib/constants.rst @@ -9,12 +9,6 @@ Constants The singleton instance of type ``Void``\ , used by convention when there is no value to return (as in a C ``void`` function). Can be converted to an empty ``Nullable`` value. -.. variable:: OS_NAME - - .. Docstring generated from Julia source - - A symbol representing the name of the operating system. Possible values are ``:Linux``\ , ``:Darwin`` (OS X), or ``:Windows``\ . - .. variable:: PROGRAM_FILE .. Docstring generated from Julia source @@ -33,18 +27,6 @@ Constants The C null pointer constant, sometimes used when calling external code. -.. variable:: CPU_CORES - - .. Docstring generated from Julia source - - The number of CPU cores in the system. - -.. variable:: WORD_SIZE - - .. Docstring generated from Julia source - - Standard word size on the current machine, in bits. - .. variable:: VERSION .. Docstring generated from Julia source @@ -69,6 +51,36 @@ Constants Equivalent to ``Any`` for dispatch purposes, but signals the compiler to skip code generation specialization for that field. +.. variable:: Sys.CPU_CORES + + .. Docstring generated from Julia source + + The number of CPU cores in the system. + +.. variable:: Sys.WORD_SIZE + + .. Docstring generated from Julia source + + Standard word size on the current machine, in bits. + +.. variable:: Sys.KERNEL + + .. Docstring generated from Julia source + + A symbol representing the name of the operating system, as returned by ``uname`` of the build configuration. + +.. variable:: Sys.ARCH + + .. Docstring generated from Julia source + + A symbol representing the architecture of the build configuration. + +.. variable:: Sys.MACHINE + + .. Docstring generated from Julia source + + A string containing the build triple. + See also: :data:`STDIN` diff --git a/doc/stdlib/parallel.rst b/doc/stdlib/parallel.rst index 4078ed3eea040..cc7c53235181a 100644 --- a/doc/stdlib/parallel.rst +++ b/doc/stdlib/parallel.rst @@ -153,7 +153,7 @@ General Parallel Computing Support .. Docstring generated from Julia source - Equivalent to ``addprocs(CPU_CORES)`` + Equivalent to ``addprocs(Sys.CPU_CORES)`` Note that workers do not run a ``.juliarc.jl`` startup script, nor do they synchronize their global state (such as global variables, new method definitions, and loaded modules) with any of the other running processes. diff --git a/doc/stdlib/test.rst b/doc/stdlib/test.rst index 29d7127493109..5b31f70425c92 100644 --- a/doc/stdlib/test.rst +++ b/doc/stdlib/test.rst @@ -12,7 +12,7 @@ binary install, you can run the test suite using ``Base.runtests()``. .. currentmodule:: Base -.. function:: runtests([tests=["all"] [, numcores=iceil(CPU_CORES/2) ]]) +.. function:: runtests([tests=["all"] [, numcores=iceil(Sys.CPU_CORES / 2) ]]) .. Docstring generated from Julia source diff --git a/src/Makefile b/src/Makefile index 5e3dac5d339bb..1d16def255bb5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -24,6 +24,13 @@ FLAGS += -Wall -Wno-strict-aliasing -fno-omit-frame-pointer -fvisibility=hidden override CFLAGS += -Wold-style-definition -Wstrict-prototypes -Wc++-compat endif +FLAGS += -DJL_BUILD_ARCH='"$(ARCH)"' +ifeq ($(OS),WINNT) +FLAGS += -DJL_BUILD_UNAME='"NT"' +else +FLAGS += -DJL_BUILD_UNAME='"$(OS)"' +endif + SRCS := \ jltypes gf typemap ast builtins module interpreter \ alloc dlload sys init task array dump toplevel jl_uv jlapi signal-handling \ diff --git a/src/dump.c b/src/dump.c index d18d5147c7c11..c431365ab4c26 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1093,10 +1093,8 @@ static void jl_serialize_header(ios_t *s) write_uint16(s, JI_FORMAT_VERSION); ios_write(s, (char *) &BOM, 2); write_uint8(s, sizeof(void*)); - const char *OS_NAME = jl_symbol_name(jl_get_OS_NAME()); - const char *ARCH = jl_symbol_name(jl_get_ARCH()); - ios_write(s, OS_NAME, strlen(OS_NAME)+1); - ios_write(s, ARCH, strlen(ARCH)+1); + ios_write(s, JL_BUILD_UNAME, strlen(JL_BUILD_UNAME)+1); + ios_write(s, JL_BUILD_ARCH, strlen(JL_BUILD_ARCH)+1); ios_write(s, JULIA_VERSION_STRING, strlen(JULIA_VERSION_STRING)+1); const char *branch = jl_git_branch(), *commit = jl_git_commit(); ios_write(s, branch, strlen(branch)+1); @@ -1763,8 +1761,8 @@ JL_DLLEXPORT int jl_deserialize_verify_header(ios_t *s) read_uint16(s) == JI_FORMAT_VERSION && ios_read(s, (char *) &bom, 2) == 2 && bom == BOM && read_uint8(s) == sizeof(void*) && - readstr_verify(s, jl_symbol_name(jl_get_OS_NAME())) && !read_uint8(s) && - readstr_verify(s, jl_symbol_name(jl_get_ARCH())) && !read_uint8(s) && + readstr_verify(s, JL_BUILD_UNAME) && !read_uint8(s) && + readstr_verify(s, JL_BUILD_ARCH) && !read_uint8(s) && readstr_verify(s, JULIA_VERSION_STRING) && !read_uint8(s) && readstr_verify(s, jl_git_branch()) && !read_uint8(s) && readstr_verify(s, jl_git_commit()) && !read_uint8(s)); diff --git a/src/julia.h b/src/julia.h index cc4c9b2f38be5..79f98a6279ec3 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1225,7 +1225,7 @@ JL_DLLEXPORT int jl_cpu_cores(void); JL_DLLEXPORT long jl_getpagesize(void); JL_DLLEXPORT long jl_getallocationgranularity(void); JL_DLLEXPORT int jl_is_debugbuild(void); -JL_DLLEXPORT jl_sym_t *jl_get_OS_NAME(void); +JL_DLLEXPORT jl_sym_t *jl_get_UNAME(void); JL_DLLEXPORT jl_sym_t *jl_get_ARCH(void); // environment entries diff --git a/src/sys.c b/src/sys.c index 31c7a7b89ca78..dc6ccde93c2f3 100644 --- a/src/sys.c +++ b/src/sys.c @@ -708,28 +708,14 @@ JL_DLLEXPORT void jl_raise_debugger(void) #endif // _OS_WINDOWS_ } -JL_DLLEXPORT jl_sym_t *jl_get_OS_NAME(void) +JL_DLLEXPORT jl_sym_t *jl_get_UNAME(void) { -#if defined(_OS_WINDOWS_) - return jl_symbol("Windows"); -#elif defined(_OS_LINUX_) - return jl_symbol("Linux"); -#elif defined(_OS_FREEBSD_) - return jl_symbol("FreeBSD"); -#elif defined(_OS_DARWIN_) - return jl_symbol("Darwin"); -#else -#warning OS_NAME is Unknown - return jl_symbol("Unknown"); -#endif + return jl_symbol(JL_BUILD_UNAME); } JL_DLLEXPORT jl_sym_t *jl_get_ARCH(void) { - static jl_sym_t *ARCH = NULL; - if (!ARCH) - ARCH = (jl_sym_t*) jl_get_global(jl_base_module, jl_symbol("ARCH")); - return ARCH; + return jl_symbol(JL_BUILD_ARCH); } JL_DLLEXPORT size_t jl_maxrss(void) diff --git a/test/backtrace.jl b/test/backtrace.jl index c60ccc011692d..d12a39986568d 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -46,7 +46,7 @@ catch err end # different-file inline -const absfilepath = OS_NAME == :Windows ? "C:\\foo\\bar\\baz.jl" : "/foo/bar/baz.jl" +const absfilepath = is_windows() ? "C:\\foo\\bar\\baz.jl" : "/foo/bar/baz.jl" eval(Expr(:function, Expr(:call, :test_inline_2), Expr(:block, Expr(:line, 99, Symbol("backtrace.jl")), Expr(:block, Expr(:meta, :push_loc, Symbol(absfilepath)), diff --git a/test/ccall.jl b/test/ccall.jl index df815e9fc5259..27fb4c2fef73a 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -31,7 +31,7 @@ end @test ccall_echo_load(IntLike(993), Ptr{Int}, Ref{IntLike}) === 993 @test ccall_echo_load(IntLike(881), Ptr{IntLike}, Ref{IntLike}).x === 881 @test ccall_echo_func(532, Int, Int) === 532 -if WORD_SIZE == 64 +if Sys.WORD_SIZE == 64 # this test is valid only for x86_64 and win64 @test ccall_echo_func(164, IntLike, Int).x === 164 end diff --git a/test/checked.jl b/test/checked.jl index 3b35426e7e640..8c400b2840b76 100644 --- a/test/checked.jl +++ b/test/checked.jl @@ -242,11 +242,8 @@ end @test checked_sub(Int128(-1),Int128(-2)) === Int128(1) -if WORD_SIZE == 32 - @test_throws OverflowError checked_mul(UInt(2)^30, UInt(2)^2) -else - @test_throws OverflowError checked_mul(UInt(2)^62, UInt(2)^2) -end +@test_throws OverflowError checked_mul(UInt32(2)^30, UInt32(2)^2) +@test_throws OverflowError checked_mul(UInt64(2)^62, UInt64(2)^2) @test checked_add(UInt128(1), UInt128(2)) === UInt128(3) @test_throws OverflowError checked_add(UInt128(2)^127, UInt128(2)^127) diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 06224d9d792a0..064c5822b772b 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -58,11 +58,11 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes` # --cpu-target # NOTE: this test only holds true when there is a sys.{dll,dylib,so} shared library present. - # The tests are also limited to unix platforms at the moment because loading the system image - # not turned on for Window's binary builds at the moment. - @unix_only if Libdl.dlopen_e(splitext(String(Base.JLOptions().image_file))[1]) != C_NULL - @test !success(`$exename -C invalidtarget`) - @test !success(`$exename --cpu-target=invalidtarget`) + if Libdl.dlopen_e(splitext(String(Base.JLOptions().image_file))[1]) != C_NULL + @test !success(`$exename -C invalidtarget --precompiled=yes`) + @test !success(`$exename --cpu-target=invalidtarget --precompiled=yes`) + else + warn("--cpu-target test not runnable") end # --procs @@ -165,23 +165,24 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes` @test !success(`$exename -E "$code" --depwarn=error`) - # FIXME these should also be run on windows once the bug causing them to hang gets fixed - @unix_only let out = Pipe(), - proc = spawn(pipeline(`$exename -E "$code" --depwarn=yes`, stderr=out)) + let out = Pipe(), + proc = spawn(pipeline(`$exename -E "$code" --depwarn=yes`, stderr=out)), + output = @async readchomp(out) - wait(proc) close(out.in) + wait(proc) @test success(proc) - @test readchomp(out) == "WARNING: Foo.Deprecated is deprecated.\n likely near no file:5" + @test wait(output) == "WARNING: Foo.Deprecated is deprecated.\n likely near no file:5" end - @unix_only let out = Pipe(), - proc = spawn(pipeline(`$exename -E "$code" --depwarn=no`, stderr=out)) + let out = Pipe(), + proc = spawn(pipeline(`$exename -E "$code" --depwarn=no`, stderr=out)) + output = @async readstring(out) wait(proc) close(out.in) @test success(proc) - @test isempty(readstring(out)) + @test wait(output) == "" end end @@ -252,7 +253,7 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes` @test readchomp(`$exename -e 'println(ARGS);' ''`) == "String[\"\"]" # issue #12679 - extrapath = @windows? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" + extrapath = is_windows() ? joinpath(JULIA_HOME, "..", "Git", "usr", "bin") * ";" : "" withenv("PATH" => extrapath * ENV["PATH"]) do @test readchomp(pipeline(ignorestatus(`$exename -f --compile=yes -foo`),stderr=`cat`)) == "ERROR: unknown option `-o`" @test readchomp(pipeline(ignorestatus(`$exename -f -p`),stderr=`cat`)) == "ERROR: option `-p/--procs` is missing an argument" @@ -267,7 +268,9 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes` @test !success(`$exename --compilecache=foo -e "exit(0)"`) # issue #12671, starting from a non-directory - @unix_only if VersionNumber(Base.libllvm_version) > v"3.3" + # rm(dir) fails on windows with Permission denied + # and was an upstream bug in llvm <= v3.3 + if !is_windows() && VersionNumber(Base.libllvm_version) > v"3.3" testdir = mktempdir() cd(testdir) do rm(testdir) diff --git a/test/core.jl b/test/core.jl index 710afaa6722ca..b5e7c6b12740e 100644 --- a/test/core.jl +++ b/test/core.jl @@ -336,11 +336,7 @@ let x = (2,3) end # bits types -if WORD_SIZE == 64 - @test isa((()->Core.Intrinsics.box(Ptr{Int8},Core.Intrinsics.unbox(Int64,0)))(), Ptr{Int8}) -else - @test isa((()->Core.Intrinsics.box(Ptr{Int8},Core.Intrinsics.unbox(Int32,0)))(), Ptr{Int8}) -end +@test isa((()->Core.Intrinsics.box(Ptr{Int8}, Core.Intrinsics.unbox(Int, 0)))(), Ptr{Int8}) @test isa(convert(Char,65), Char) # conversions @@ -2198,7 +2194,7 @@ let x = [1,2,3] end # sig 2 is SIGINT per the POSIX.1-1990 standard -@unix_only begin +if !is_windows() ccall(:jl_exit_on_sigint, Void, (Cint,), 0) @test_throws InterruptException begin ccall(:kill, Void, (Cint, Cint,), getpid(), 2) diff --git a/test/dates/conversions.jl b/test/dates/conversions.jl index 630207f4de063..3706c9ef96aa7 100644 --- a/test/dates/conversions.jl +++ b/test/dates/conversions.jl @@ -47,8 +47,10 @@ @test typeof(Dates.today()) <: Dates.Date @test typeof(Dates.now(Dates.UTC)) <: Dates.DateTime -@osx_only withenv("TZ" => "UTC") do - @test abs(Dates.now() - now(Dates.UTC)) < Dates.Second(1) +if is_apple() + withenv("TZ" => "UTC") do + @test abs(Dates.now() - now(Dates.UTC)) < Dates.Second(1) + end end @test abs(Dates.now() - now(Dates.UTC)) < Dates.Hour(16) diff --git a/test/examples.jl b/test/examples.jl index 9c8b4a7b543d6..494a93deebd82 100644 --- a/test/examples.jl +++ b/test/examples.jl @@ -36,7 +36,7 @@ include(joinpath(dir, "queens.jl")) # Different cluster managers do not play well together. Since # the test infrastructure already uses LocalManager, we will test the simple # cluster manager example through a new Julia session. -@unix_only begin +if is_unix() script = joinpath(dir, "clustermanager/simple/test_simple.jl") cmd = `$(Base.julia_cmd()) $script` if !success(pipeline(cmd; stdout=STDOUT, stderr=STDERR)) && ccall(:jl_running_on_valgrind,Cint,()) == 0 diff --git a/test/file.jl b/test/file.jl index 91ae209dbad51..c122fa8a96bf4 100644 --- a/test/file.jl +++ b/test/file.jl @@ -26,7 +26,7 @@ let err = nothing end end -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER dirlink = joinpath(dir, "dirlink") symlink(subdir, dirlink) # relative link @@ -37,7 +37,7 @@ if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) cd(pwd_) end -@unix_only begin +if !is_windows() link = joinpath(dir, "afilelink.txt") symlink(file, link) # relative link @@ -67,7 +67,7 @@ chmod(file, filemode(file) | 0o222) @test filemode(file) & 0o111 == 0 @test filesize(file) == 0 -@windows_only begin +if is_windows() permissions = 0o444 @test filemode(dir) & 0o777 != permissions @test filemode(subdir) & 0o777 != permissions @@ -77,8 +77,7 @@ chmod(file, filemode(file) | 0o222) @test filemode(subdir) & 0o777 == permissions @test filemode(file) & 0o777 == permissions chmod(dir, 0o666, recursive=true) # Reset permissions in case someone wants to use these later -end -@unix_only begin +else mktempdir() do tmpdir tmpfile=joinpath(tmpdir, "tempfile.txt") touch(tmpfile) @@ -104,8 +103,11 @@ end # On windows the filesize of a folder is the accumulation of all the contained # files and is thus zero in this case. -@windows_only @test filesize(dir) == 0 -@unix_only @test filesize(dir) > 0 +if is_windows() + @test filesize(dir) == 0 +else + @test filesize(dir) > 0 +end now = time() # Allow 10s skew in addition to the time it took us to actually execute this code let skew = 10 + (now - starttime) @@ -116,13 +118,15 @@ end #@test Int(time()) >= Int(mtime(file)) >= Int(mtime(dir)) >= 0 # 1 second accuracy should be sufficient # test links -@unix_only @test islink(link) == true -@unix_only @test readlink(link) == file +if is_unix() + @test islink(link) == true + @test readlink(link) == file +end -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER @test islink(dirlink) == true @test isdir(dirlink) == true - @test readlink(dirlink) == subdir * @windows? "\\" : "" + @test readlink(dirlink) == subdir * (is_windows() ? "\\" : "") end # rm recursive TODO add links @@ -158,23 +162,26 @@ rm(c_tmpdir, recursive=true) @test_throws Base.UVError rm(c_tmpdir, recursive=true) @test rm(c_tmpdir, force=true, recursive=true) === nothing -# chown will give an error if the user does not have permissions to change files -@unix_only if get(ENV, "USER", "") == "root" || get(ENV, "HOME", "") == "/root" - chown(file, -2, -1) # Change the file owner to nobody - @test stat(file).uid !=0 - chown(file, 0, -2) # Change the file group to nogroup (and owner back to root) - @test stat(file).gid !=0 - @test stat(file).uid ==0 - chown(file, -1, 0) - @test stat(file).gid ==0 - @test stat(file).uid ==0 +if !is_windows() + # chown will give an error if the user does not have permissions to change files + if get(ENV, "USER", "") == "root" || get(ENV, "HOME", "") == "/root" + chown(file, -2, -1) # Change the file owner to nobody + @test stat(file).uid !=0 + chown(file, 0, -2) # Change the file group to nogroup (and owner back to root) + @test stat(file).gid !=0 + @test stat(file).uid ==0 + chown(file, -1, 0) + @test stat(file).gid ==0 + @test stat(file).uid ==0 + else + @test_throws Base.UVError chown(file, -2, -1) # Non-root user cannot change ownership to another user + @test_throws Base.UVError chown(file, -1, -2) # Non-root user cannot change group to a group they are not a member of (eg: nogroup) + end else - @test_throws Base.UVError chown(file, -2, -1) # Non-root user cannot change ownership to another user - @test_throws Base.UVError chown(file, -1, -2) # Non-root user cannot change group to a group they are not a member of (eg: nogroup) + # test that chown doesn't cause any errors for Windows + @test chown(file, -2, -2) == nothing end -@windows_only @test chown(file, -2, -2) == nothing # chown shouldn't cause any errors for Windows - ####################################################################### # This section tests file watchers. # ####################################################################### @@ -281,8 +288,7 @@ my_tempdir = tempdir() path = tempname() # Issue #9053. -@unix_only @test ispath(path) == false -@windows_only @test ispath(path) == true +@test ispath(path) == is_windows() (p, f) = mktemp() print(f, "Here is some text") @@ -447,7 +453,7 @@ end # issue #10506 #10434 ## Tests for directories and links to directories -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER function setup_dirs(tmpdir) srcdir = joinpath(tmpdir, "src") hidden_srcdir = joinpath(tmpdir, ".hidden_srcdir") @@ -657,7 +663,7 @@ end # issue #10506 #10434 ## Tests for files and links to files as well as directories and links to directories -@unix_only begin +if !is_windows() function setup_files(tmpdir) srcfile = joinpath(tmpdir, "srcfile.txt") hidden_srcfile = joinpath(tmpdir, ".hidden_srcfile.txt") @@ -883,15 +889,19 @@ function test_LibcFILE(FILEp) close(FILEp) end -f = open(file, "w") -write(f, "Hello, world!") -close(f) -f = open(file, "r") -test_LibcFILE(convert(Libc.FILE, f)) -close(f) -@unix_only f = RawFD(ccall(:open, Cint, (Ptr{UInt8}, Cint), file, Base.Filesystem.JL_O_RDONLY)) -@windows_only f = RawFD(ccall(:_open, Cint, (Ptr{UInt8}, Cint), file, Base.Filesystem.JL_O_RDONLY)) -test_LibcFILE(Libc.FILE(f,Libc.modestr(true,false))) +let f = open(file, "w") + write(f, "Hello, world!") + close(f) + f = open(file, "r") + test_LibcFILE(convert(Libc.FILE, f)) + close(f) + if is_windows() + f = RawFD(ccall(:_open, Cint, (Ptr{UInt8}, Cint), file, Base.Filesystem.JL_O_RDONLY)) + else + f = RawFD(ccall(:open, Cint, (Ptr{UInt8}, Cint), file, Base.Filesystem.JL_O_RDONLY)) + end + test_LibcFILE(Libc.FILE(f, Libc.modestr(true, false))) +end # issue #10994: pathnames cannot contain embedded NUL chars for f in (mkdir, cd, Base.Filesystem.unlink, readlink, rm, touch, readdir, mkpath, stat, lstat, ctime, mtime, filemode, filesize, uperm, gperm, operm, touch, isblockdev, ischardev, isdir, isfifo, isfile, islink, ispath, issetgid, issetuid, issocket, issticky, realpath, watch_file, poll_file) @@ -901,7 +911,7 @@ end @test_throws ArgumentError open("ba\0d", "w") @test_throws ArgumentError cp(file, "ba\0d") @test_throws ArgumentError mv(file, "ba\0d") -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || (Sys.windows_version() >= Sys.WINDOWS_VISTA_VER) @test_throws ArgumentError symlink(file, "ba\0d") else @test_throws ErrorException symlink(file, "ba\0d") @@ -923,7 +933,7 @@ cd(dirwalk) do touch(joinpath("sub_dir1", "file$i")) end touch(joinpath("sub_dir2", "file_dir2")) - has_symlinks = @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) + has_symlinks = !is_windows() || (Sys.windows_version() >= Sys.WINDOWS_VISTA_VER) follow_symlink_vec = has_symlinks ? [true, false] : [false] has_symlinks && symlink(abspath("sub_dir2"), joinpath("sub_dir1", "link")) for follow_symlinks in follow_symlink_vec @@ -1012,11 +1022,11 @@ rm(dirwalk, recursive=true) ############ # Clean up # ############ -@unix_only begin +if !is_windows() rm(link) rm(rellink) end -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || (Sys.windows_version() >= Sys.WINDOWS_VISTA_VER) rm(dirlink) rm(relsubdirlink) end @@ -1025,9 +1035,8 @@ rm(subdir) rm(subdir2) rm(dir) -# The following fail on Windows with "stat: operation not permitted (EPERM)" -@unix_only @test !ispath(file) -@unix_only @test !ispath(dir) +@test !ispath(file) +@test !ispath(dir) # issue #9687 let n = tempname() @@ -1079,6 +1088,7 @@ test2_12992() # issue 13559 +if !is_windows() function test_13559() fn = tempname() run(`mkfifo $fn`) @@ -1096,4 +1106,5 @@ function test_13559() close(r) rm(fn) end -@unix_only test_13559() +test_13559() +end diff --git a/test/int.jl b/test/int.jl index 95bc4f6acacfa..e000faef9f99e 100644 --- a/test/int.jl +++ b/test/int.jl @@ -54,7 +54,7 @@ end @test bswap(Int128(2)^(15*8)) == Int128(1) @test bswap(UInt128(2)^(15*8)) == UInt128(1) -@test count_zeros(10) == WORD_SIZE - 2 +@test count_zeros(10) == Sys.WORD_SIZE - 2 @test count_zeros(UInt8(10)) == 6 @test convert(Signed, UInt128(3)) === Int128(3) diff --git a/test/libdl.jl b/test/libdl.jl index f7f965ad20e58..d9933963fb1f1 100644 --- a/test/libdl.jl +++ b/test/libdl.jl @@ -5,7 +5,7 @@ dlls = Libdl.dllist() @test !isempty(dlls) @test length(dlls) > 3 # at a bare minimum, probably have some version of libstdc, libgcc, libjulia, ... -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER for dl in dlls if isfile(dl) && (Libdl.dlopen_e(dl) != C_NULL) @test Base.samefile(Libdl.dlpath(dl), dl) @@ -177,7 +177,7 @@ let dl = C_NULL end end -if OS_NAME in (:Linux, :FreeBSD) +if Sys.KERNEL in (:Linux, :FreeBSD) ccall(:jl_read_sonames, Void, ()) end diff --git a/test/misc.jl b/test/misc.jl index 7b6cc4d8e0697..4e2baa6d8c639 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -194,7 +194,11 @@ end @test Base.is_unix(:Darwin) @test Base.is_unix(:FreeBSD) @test_throws ArgumentError Base.is_unix(:BeOS) -@unix_only @test Base.windows_version() == (0,0) +if !is_windows() + @test Sys.windows_version() === (0, 0) +else + @test (Sys.windows_version()::Tuple{Int,Int})[1] > 0 +end # Issue 14173 module Tmp14173 @@ -373,11 +377,13 @@ for (X,Y,Z) in ((V16,V16,V16), (I16,V16,I16), (V16,I16,V16), (V16,V16,I16), (I16 end # clipboard functionality -@windows_only for str in ("Hello, world.","∀ x ∃ y","") - clipboard(str) - @test clipboard() == str +if is_windows() + for str in ("Hello, world.", "∀ x ∃ y", "") + clipboard(str) + @test clipboard() == str + end end -optstring = sprint(show,Base.JLOptions()) -@test startswith(optstring,"JLOptions(") -@test endswith(optstring,")") +optstring = sprint(show, Base.JLOptions()) +@test startswith(optstring, "JLOptions(") +@test endswith(optstring, ")") diff --git a/test/parallel_exec.jl b/test/parallel_exec.jl index 272fc9ed4f10f..4136476f648e1 100644 --- a/test/parallel_exec.jl +++ b/test/parallel_exec.jl @@ -226,7 +226,7 @@ test_indexing(RemoteChannel(id_other)) dims = (20,20,20) -@linux_only begin +if is_linux() S = SharedArray(Int64, dims) @test startswith(S.segname, "/jl") @test !ispath("/dev/shm" * S.segname) @@ -357,7 +357,8 @@ read!(fn3, filedata) @test all(filedata[1:4] .== 0x01) @test all(filedata[5:end] .== 0x02) -@unix_only begin # these give unlink: operation not permitted (EPERM) on Windows +if !is_windows() + # these give unlink: operation not permitted (EPERM) on Windows rm(fn); rm(fn2); rm(fn3) end @@ -820,7 +821,7 @@ if DoFullTest end sleep(0.5) # Give some time for the above error to be printed -@unix_only begin +if is_unix() # aka have ssh function test_n_remove_pids(new_pids) for p in new_pids w_in_remote = sort(remotecall_fetch(workers, p)) @@ -880,8 +881,8 @@ if DoFullTest end) @test length(new_pids) == num_workers test_n_remove_pids(new_pids) -end # @unix_only -end +end # unix-only +end # full-test # issue #7727 let A = [], B = [] diff --git a/test/path.jl b/test/path.jl index c9db47528c8f1..ecce1aba7dee7 100644 --- a/test/path.jl +++ b/test/path.jl @@ -1,10 +1,23 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -@unix_only @test expanduser("~")[1] != ENV["HOME"] - -@unix_only @test isabspath("/") == true @test isabspath("~") == false -@unix_only @test isabspath(expanduser("~")) == true +@test isabspath("/") == true # on windows, this is relatively absolute +@test isabspath("A:/") == is_windows() +@test isabspath("B:\\") == is_windows() +@test isabspath("./") == false +@test isabspath("C:") == false +@test isabspath("C:.") == false +@test isabspath("α:/") == false +@test isabspath(".:/") == false +#@test isabspath("_:/") == false # FIXME? +#@test isabspath("AB:/") == false # FIXME? +@test isabspath("\\\\") == is_windows() +if is_unix() + @test isabspath(expanduser("~")) == true + @test startswith(expanduser("~"), homedir()) +else + @test expanduser("~") == "~" +end ############################################ # This section tests relpath computation. # diff --git a/test/perf/micro/perf.jl b/test/perf/micro/perf.jl index 57a915dee31ed..72d6c7b4c237a 100644 --- a/test/perf/micro/perf.jl +++ b/test/perf/micro/perf.jl @@ -138,11 +138,11 @@ end ## printfd ## -@unix_only begin +if is_unix() function printfd(n) - open("/dev/null","w") do io + open("/dev/null", "w") do io for i = 1:n - @printf(io,"%d %d\n",i,i+1) + @printf(io, "%d %d\n", i, i + 1) end end end diff --git a/test/perf/perfutil.jl b/test/perf/perfutil.jl index 57b701d1671d5..ea7957d4677ec 100644 --- a/test/perf/perfutil.jl +++ b/test/perf/perfutil.jl @@ -97,6 +97,7 @@ macro timeit_init(ex,init,name,desc,group...) end function maxrss(name) + # FIXME: call uv_getrusage instead here @linux_only begin rus = Array(Int64, div(144,8)) fill!(rus, 0x0) diff --git a/test/pollfd.jl b/test/pollfd.jl index 1c0a178fd737c..a151b42dd663a 100644 --- a/test/pollfd.jl +++ b/test/pollfd.jl @@ -13,10 +13,10 @@ intvls = [2, .2, .1, .005] pipe_fds = cell(n) for i in 1:n - @windows ? begin + @static if is_windows() pipe_fds[i] = Array(Libc.WindowsRawSocket, 2) 0 == ccall(:wsasocketpair, Cint, (Cint, Cuint, Cint, Ptr{Libc.WindowsRawSocket}), 1, 1, 6, pipe_fds[i]) || error(Libc.FormatMessage()) - end : begin + else pipe_fds[i] = Array(RawFD, 2) @test 0 == ccall(:pipe, Cint, (Ptr{RawFD},), pipe_fds[i]) end @@ -30,18 +30,18 @@ function pfd_tst_reads(idx, intvl) t_elapsed = toq() @test !evt.timedout @test evt.readable - @test @windows ? evt.writable : !evt.writable + @test is_windows() ? evt.writable : !evt.writable # println("Expected ", intvl, ", actual ", t_elapsed, ", diff ", t_elapsed - intvl) # Disabled since this assertion fails randomly, notably on build VMs (issue #12824) # @test t_elapsed <= (intvl + 1) dout = Array(UInt8, 1) - @windows ? ( + @static if is_windows() 1 == ccall(:recv, stdcall, Cint, (Ptr{Void}, Ptr{UInt8}, Cint, Cint), pipe_fds[idx][1], dout, 1, 0) || error(Libc.FormatMessage()) - ) : ( + else @test 1 == ccall(:read, Csize_t, (Cint, Ptr{UInt8}, Csize_t), pipe_fds[idx][1], dout, 1) - ) + end @test dout[1] == Int8('A') end @@ -57,8 +57,8 @@ function pfd_tst_timeout(idx, intvl) t_elapsed = toq() # Disabled since these assertions fail randomly, notably on build VMs (issue #12824) - # @unix_only @test (intvl <= t_elapsed) # TODO: enable this test on windows when the libuv version is bumped - # @test (t_elapsed <= (intvl + 1)) + # @test intvl <= t_elapsed + # @test t_elapsed <= (intvl + 1) end @@ -87,11 +87,11 @@ for (i, intvl) in enumerate(intvls) @test event.writable if isodd(idx) - @windows ? ( - 1 == ccall(:send, stdcall, Cint, (Ptr{Void}, Ptr{UInt8}, Cint, Cint), pipe_fds[idx][2], "A", 1, 0) || error(Libc.FormatMessage()) - ) : ( - @test 1 == ccall(:write, Csize_t, (Cint, Ptr{UInt8}, Csize_t), pipe_fds[idx][2], "A", 1) - ) + @static if is_windows() + 1 == ccall(:send, stdcall, Cint, (Ptr{Void}, Ptr{UInt8}, Cint, Cint), pipe_fds[idx][2], "A", 1, 0) || error(Libc.FormatMessage()) + else + @test 1 == ccall(:write, Csize_t, (Cint, Ptr{UInt8}, Csize_t), pipe_fds[idx][2], "A", 1) + end end end notify(ready_c, all=true) @@ -100,11 +100,11 @@ end for i in 1:n for j = 1:2 - @windows ? ( + @static if is_windows() 0 == ccall(:closesocket, stdcall, Cint, (Ptr{Void},), pipe_fds[i][j]) || error(Libc.FormatMessage()) - ) : ( + else @test 0 == ccall(:close, Cint, (Cint,), pipe_fds[i][j]) - ) + end end end diff --git a/test/printf.jl b/test/printf.jl index 480df6a14aa0c..5ccbae258ce53 100644 --- a/test/printf.jl +++ b/test/printf.jl @@ -31,12 +31,14 @@ for (fmt, val) in (("%i", "42"), end # pointers -if WORD_SIZE == 64 +if Sys.WORD_SIZE == 64 @test (@sprintf "%20p" 0) == " 0x0000000000000000" @test (@sprintf "%-20p" 0) == "0x0000000000000000 " -elseif WORD_SIZE == 32 +elseif Sys.WORD_SIZE == 32 @test (@sprintf "%20p" 0) == " 0x00000000" @test (@sprintf "%-20p" 0) == "0x00000000 " +else + @test false end # float / BigFloat diff --git a/test/ranges.jl b/test/ranges.jl index 06f732acfb44d..bfd497e8c7706 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -234,7 +234,7 @@ end @test sum(0:2:100) == 2550 # overflowing sums (see #5798) -if WORD_SIZE == 64 +if Sys.WORD_SIZE == 64 @test sum(Int128(1):10^18) == div(10^18 * (Int128(10^18)+1), 2) @test sum(Int128(1):10^18-1) == div(10^18 * (Int128(10^18)-1), 2) else diff --git a/test/read.jl b/test/read.jl index 8144f033e4763..38547dedbee93 100644 --- a/test/read.jl +++ b/test/read.jl @@ -83,7 +83,7 @@ push!(l, ("TCPSocket", io)) io = (text) -> begin a = "\\\\.\\pipe\\uv-test-$(randstring(6))" b = joinpath(dir, "socket-$(randstring(6))") - socketname = @windows ? a : b + socketname = is_windows() ? a : b srv = listen(socketname) run_test_server(srv, text) connect(socketname) @@ -98,7 +98,7 @@ push!(l, ("PipeEndpoint", io)) #FIXME See https://github.com/JuliaLang/julia/issues/14747 # Reading from open(::Command) seems to deadlock on Linux/Travis #= -@windows ? nothing : begin +if !is_windows() # Windows type command not working? # See "could not spawn `type 'C:\Users\appveyor\AppData\Local\Temp\1\jul3516.tmp\file.txt'`" @@ -107,7 +107,7 @@ push!(l, ("PipeEndpoint", io)) # Pipe io = (text) -> begin write(filename, text) - open(`$(@windows ? "type" : "cat") $filename`)[1] + open(`$(is_windows() ? "type" : "cat") $filename`)[1] # Was open(`echo -n $text`)[1] # See https://github.com/JuliaLang/julia/issues/14747 end @@ -411,13 +411,14 @@ rm(f) io = Base.Filesystem.open(f, Base.Filesystem.JL_O_WRONLY | Base.Filesystem.JL_O_CREAT | Base.Filesystem.JL_O_EXCL, 0o000) @test write(io, "abc") == 3 close(io) -@unix_only if get(ENV, "USER", "") != "root" && get(ENV, "HOME", "") != "/root" +if !is_windows() && get(ENV, "USER", "") != "root" && get(ENV, "HOME", "") != "/root" # msvcrt _wchmod documentation states that all files are readable, # so we don't test that it correctly set the umask on windows @test_throws SystemError open(f) @test_throws Base.UVError Base.Filesystem.open(f, Base.Filesystem.JL_O_RDONLY) else - warn("file permissions tests skipped due to running tests as root (not recommended)") + is_windows() || warn("file permissions tests skipped due to running tests as root (not recommended)") + close(open(f)) end chmod(f, 0o400) f1 = open(f) diff --git a/test/repl.jl b/test/repl.jl index 06834cfe0d753..e6b3369c75d39 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -28,7 +28,7 @@ ccall(:jl_exit_on_sigint, Void, (Cint,), 0) # in the mix. If verification needs to be done, keep it to the bare minimum. Basically # this should make sure nothing crashes without depending on how exactly the control # characters are being used. -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER stdin_write, stdout_read, stderr_read, repl = fake_repl() repl.specialdisplay = Base.REPL.REPLDisplay(repl) @@ -398,7 +398,7 @@ begin LineEdit.enter_search(s, custom_histp, true) end # Simple non-standard REPL tests -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER stdin_write, stdout_read, stdout_read, repl = fake_repl() panel = LineEdit.Prompt("testπ"; prompt_prefix="\e[38;5;166m", @@ -443,7 +443,7 @@ ccall(:jl_exit_on_sigint, Void, (Cint,), 1) let exename = Base.julia_cmd() # Test REPL in dumb mode -@unix_only begin +if !is_windows() const O_RDWR = Base.Filesystem.JL_O_RDWR const O_NOCTTY = Base.Filesystem.JL_O_NOCTTY @@ -481,9 +481,9 @@ let exename = Base.julia_cmd() end # Test stream mode -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER outs, ins, p = readandwrite(`$exename --startup-file=no --quiet`) write(ins,"1\nquit()\n") @test readstring(outs) == "1\n" end -end +end # let exename diff --git a/test/replcompletions.jl b/test/replcompletions.jl index 26a1cfb034e0d..dbb1ee1c519dc 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -438,7 +438,7 @@ c, r, res = test_scomplete(s) # which would raise an error in the repl code. @test (String[], 0:-1, false) == test_scomplete("\$a") -@unix_only begin +if is_unix() #Assume that we can rely on the existence and accessibility of /tmp # Tests path in Julia code and closing " if it's a file @@ -589,12 +589,12 @@ let #test that it can auto complete with spaces in file/path mkdir(dir) cd(path) do open(joinpath(space_folder, "space .file"),"w") do f - s = @windows? "rm $dir_space\\\\space" : "cd $dir_space/space" + s = is_windows() ? "rm $dir_space\\\\space" : "cd $dir_space/space" c,r = test_scomplete(s) @test r == endof(s)-4:endof(s) @test "space\\ .file" in c - s = @windows? "cd(\"β $dir_space\\\\space" : "cd(\"β $dir_space/space" + s = is_windows() ? "cd(\"β $dir_space\\\\space" : "cd(\"β $dir_space/space" c,r = test_complete(s) @test r == endof(s)-4:endof(s) @test "space\\ .file\"" in c @@ -612,7 +612,7 @@ end c,r = test_complete("cd(\"folder_do_not_exist_77/file") @test length(c) == 0 -@windows_only begin +if is_windows() tmp = tempname() path = dirname(tmp) file = basename(tmp) diff --git a/test/runtests.jl b/test/runtests.jl index 969c72ee53182..c43aaebf981d2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -69,6 +69,6 @@ cd(dirname(@__FILE__)) do runtests("compile") end - @unix_only n > 1 && rmprocs(workers(), waitfor=5.0) + is_unix() && n > 1 && rmprocs(workers(), waitfor=5.0) println(" \033[32;1mSUCCESS\033[0m") end diff --git a/test/socket.jl b/test/socket.jl index c3123eb7120e3..241f6a752477f 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -90,7 +90,7 @@ wait(port) wait(tsk) mktempdir() do tmpdir - socketname = @windows ? ("\\\\.\\pipe\\uv-test-" * randstring(6)) : joinpath(tmpdir, "socket") + socketname = is_windows() ? ("\\\\.\\pipe\\uv-test-" * randstring(6)) : joinpath(tmpdir, "socket") c = Base.Condition() tsk = @async begin s = listen(socketname) @@ -171,7 +171,7 @@ begin close(a) close(b) end -if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) +if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER a = UDPSocket() b = UDPSocket() bind(a, ip"::1", UInt16(port)) @@ -243,7 +243,7 @@ end # Local-machine broadcast let # (Mac OS X's loopback interface doesn't support broadcasts) - bcastdst = @osx ? ip"255.255.255.255" : ip"127.255.255.255" + bcastdst = is_apple() ? ip"255.255.255.255" : ip"127.255.255.255" function create_socket() s = UDPSocket() diff --git a/test/spawn.jl b/test/spawn.jl index d446ae2b17ea1..86c8216d4dea2 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -11,10 +11,12 @@ #TODO: # - Windows: # - Add a test whether coreutils are available and skip tests if not -@windows_only oldpath = ENV["PATH"] -@windows_only ENV["PATH"] = joinpath(JULIA_HOME,"..","Git","usr","bin")*";"*oldpath +if is_windows() + oldpath = ENV["PATH"] + ENV["PATH"] = joinpath(JULIA_HOME, "..", "Git", "usr", "bin") * ";" * oldpath +end -valgrind_off = ccall(:jl_running_on_valgrind,Cint,()) == 0 +valgrind_off = ccall(:jl_running_on_valgrind, Cint, ()) == 0 yes = `perl -le 'while (1) {print STDOUT "y"}'` @@ -32,7 +34,7 @@ out = readstring(`echo hello` & `echo world`) @test (run(`printf " \033[34m[stdio passthrough ok]\033[0m\n"`); true) # Test for SIGPIPE being treated as normal termination (throws an error if broken) -@unix_only @test (run(pipeline(yes,`head`,DevNull)); true) +is_unix() && run(pipeline(yes, `head`, DevNull)) begin a = Base.Condition() @@ -80,11 +82,11 @@ run(pipeline(`echo hello world`, file)) rm(file) # Stream Redirection -@unix_only begin - r = Channel(1) +if !is_windows() # WINNT reports operation not supported on socket (ENOTSUP) for this test + local r = Channel(1), port, server, sock, client @async begin port, server = listenany(2326) - put!(r,port) + put!(r, port) client = accept(server) @test readstring(pipeline(client, `cat`)) == "hello world\n" close(server) @@ -103,9 +105,12 @@ end readstring(`sh -c "echo \$TEST"`); end) == "Hello World\n" pathA = readchomp(setenv(`sh -c "pwd -P"`;dir="..")) pathB = readchomp(setenv(`sh -c "cd .. && pwd -P"`)) -@unix_only @test Base.samefile(pathA, pathB) -# on windows, sh returns posix-style paths that are not valid according to ispath -@windows_only @test pathA == pathB +if is_windows() + # on windows, sh returns posix-style paths that are not valid according to ispath + @test pathA == pathB +else + @test Base.samefile(pathA, pathB) +end # Here we test that if we close a stream with pending writes, we don't lose the writes. str = "" @@ -336,12 +341,16 @@ end @test_throws ErrorException collect(eachline(pipeline(`cat _doesnt_exist__111_`, stderr=DevNull))) # make sure windows_verbatim strips quotes -@windows_only readstring(`cmd.exe /c dir /b spawn.jl`) == readstring(Cmd(`cmd.exe /c dir /b "\"spawn.jl\""`, windows_verbatim=true)) +if is_windows() + readstring(`cmd.exe /c dir /b spawn.jl`) == readstring(Cmd(`cmd.exe /c dir /b "\"spawn.jl\""`, windows_verbatim=true)) +end # make sure Cmd is nestable @test string(Cmd(Cmd(`ls`, detach=true))) == "`ls`" -@windows_only ENV["PATH"] = oldpath +if is_windows() + ENV["PATH"] = oldpath +end # equality tests for Cmd diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 7bc1231d75439..67df100da2de1 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -249,12 +249,12 @@ let s = "ba\0d" @test_throws ArgumentError Base.unsafe_convert(Cwstring, wstring(s)) end -cstrdup(s) = @windows? ccall(:_strdup, Cstring, (Cstring,), s) : ccall(:strdup, Cstring, (Cstring,), s) +cstrdup(s) = @static is_windows() ? ccall(:_strdup, Cstring, (Cstring,), s) : ccall(:strdup, Cstring, (Cstring,), s) let p = cstrdup("hello") @test String(p) == "hello" == pointer_to_string(cstrdup(p), true) Libc.free(p) end -let p = @windows? ccall(:_wcsdup, Cwstring, (Cwstring,), "tést") : ccall(:wcsdup, Cwstring, (Cwstring,), "tést") +let p = @static is_windows() ? ccall(:_wcsdup, Cwstring, (Cwstring,), "tést") : ccall(:wcsdup, Cwstring, (Cwstring,), "tést") @test wstring(p) == "tést" Libc.free(p) end diff --git a/test/strings/io.jl b/test/strings/io.jl index eda49201b39a8..6ef38d97b5bee 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -136,11 +136,11 @@ end @test "\x0f" == unescape_string("\\x0f") @test "\x0F" == unescape_string("\\x0F") -extrapath = @windows? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" +extrapath = is_windows() ? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" withenv("PATH" => extrapath * ENV["PATH"]) do if !success(`iconv --version`) warn("iconv not found, skipping unicode tests!") - @windows_only warn("Use WinRPM.install(\"win_iconv\") to run these tests") + is_windows() && warn("Use WinRPM.install(\"win_iconv\") to run these tests") else # Create unicode test data directory unicodedir = mktempdir() diff --git a/test/threads.jl b/test/threads.jl index 345a6b4fa17c3..a2083a13224d1 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -240,7 +240,7 @@ let atomic_types = [Int8, Int16, Int32, Int64, Int128, Float16, Float32, Float64] # Temporarily omit 128-bit types on 32bit x86 # 128-bit atomics do not exist on AArch32. - if Base.ARCH === :i686 || startswith(string(Base.ARCH), "arm") + if Sys.ARCH === :i686 || startswith(string(Sys.ARCH), "arm") filter!(T -> sizeof(T)<=8, atomic_types) end for T in atomic_types