From e63b1876f0ebda8504802a2f178d110bc7d4e04e Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Mon, 19 Feb 2018 00:49:29 -0800 Subject: [PATCH 1/3] De-macroify `info_onchange()` since I don't have `__source__` to work with on 0.6. :( --- src/LoggingUtils.jl | 15 ++++++--------- src/PlatformEngines.jl | 12 ++++++++++-- src/Prefix.jl | 30 +++++++++++++++++++++++++----- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/LoggingUtils.jl b/src/LoggingUtils.jl index d0cc5a6..0b253b6 100644 --- a/src/LoggingUtils.jl +++ b/src/LoggingUtils.jl @@ -1,7 +1,7 @@ print_cache = Dict() """ - @info_onchange(msg, key) + info_onchange(msg, key, location) This macro is used to gate verbose messages within a function; within functions such as `verify()`, we want to print out that we successfully verified a file @@ -15,13 +15,10 @@ execution path is branch A, A, B, A, B, B, B, A then what will be printed is message A, B, A, B, A. In essence, this method calls `info()` only when the message generated by this particular method changes. """ -macro info_onchange(msg, key) - return quote - local location = string(@__FILE__, @__LINE__) - local cache_val = get(print_cache, $(esc(key)), nothing) - if cache_val != location - info($(esc(msg))) - print_cache[$(esc(key))] = location - end +function info_onchange(msg, key, location) + local cache_val = get(print_cache, key, nothing) + if cache_val != location + info(msg) + print_cache[key] = location end end \ No newline at end of file diff --git a/src/PlatformEngines.jl b/src/PlatformEngines.jl index 3838c39..8576190 100644 --- a/src/PlatformEngines.jl +++ b/src/PlatformEngines.jl @@ -462,7 +462,11 @@ function download_verify(url::AbstractString, hash::AbstractString, if isfile(dest) file_existed = true if verbose - info("Destination file $(dest) already exists, verifying...") + info_onchange( + "Destination file $(dest) already exists, verifying...", + "download_verify_$(dest)", + @__LINE__, + ) end # verify download, if it passes, return happy. If it fails, (and @@ -478,7 +482,11 @@ function download_verify(url::AbstractString, hash::AbstractString, rethrow() end if verbose - info("Verification failed, re-downloading...") + info_onchange( + "Verification failed, re-downloading...", + "download_verify_$(dest)", + @__LINE__, + ) end end end diff --git a/src/Prefix.jl b/src/Prefix.jl index 083f051..6eb7cb8 100644 --- a/src/Prefix.jl +++ b/src/Prefix.jl @@ -453,29 +453,49 @@ function verify(path::AbstractString, hash::AbstractString; verbose::Bool = fals if stat(hash_path).mtime >= stat(path).mtime # If all of that is true, then we're good! if verbose - @info_onchange("Hash cache is consistent, returning true", "verify_$(hash_path)") + info_onchange( + "Hash cache is consistent, returning true", + "verify_$(hash_path)", + @__LINE__, + ) end return true else if verbose - @info_onchange("File has been modified, hash cache invalidated", "verify_$(hash_path)") + info_onchange( + "File has been modified, hash cache invalidated", + "verify_$(hash_path)", + @__LINE__, + ) end end else if verbose - @info_onchange("Verification hash mismatch, hash cache invalidated", "verify_$(hash_path)") + info_onchange( + "Verification hash mismatch, hash cache invalidated", + "verify_$(hash_path)", + @__LINE__, + ) end end else if verbose - @info_onchange("No hash cache found", "verify_$(hash_path)") + info_onchange( + "No hash cache found", + "verify_$(hash_path)", + @__LINE__, + ) end end open(path) do file calc_hash = bytes2hex(sha256(file)) if verbose - info("Calculated hash $calc_hash for file $path") + info_onchange( + "Calculated hash $calc_hash for file $path", + "hash_$(hash_path)", + @__LINE__, + ) end if calc_hash != hash From fe1b85f143e2d9ad0f56f0dc29a511f2a7a4cd63 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Mon, 19 Feb 2018 00:50:27 -0800 Subject: [PATCH 2/3] Enable deeper debugging of `verify()` through `report_cache_status` --- src/Prefix.jl | 30 ++++++++++++++++++++++++++---- test/runtests.jl | 20 ++++++++++++++++---- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/Prefix.jl b/src/Prefix.jl index 6eb7cb8..ed522c3 100644 --- a/src/Prefix.jl +++ b/src/Prefix.jl @@ -422,7 +422,8 @@ function list_tarball_files(path::AbstractString; verbose::Bool = false) end """ - verify(path::String, hash::String; verbose::Bool) + verify(path::AbstractString, hash::AbstractString; + verbose::Bool = false, report_cache_status::Bool = false) Given a file `path` and a `hash`, calculate the SHA256 of the file and compare it to `hash`. If an error occurs, `verify()` will throw an error. This method @@ -434,8 +435,14 @@ with the calculated hash being stored within the `".sha256"` file.. If a contained within matches the given `hash` parameter, and its modification time shows that the file located at `path` has not been modified since the last verification. + +If `report_cache_status` is set to `true`, then the return value will be a +`Symbol` giving a granular status report on the state of the hash cache, in +addition to the `true`/`false` signifying whether verification completed +successfully. """ -function verify(path::AbstractString, hash::AbstractString; verbose::Bool = false) +function verify(path::AbstractString, hash::AbstractString; verbose::Bool = false, + report_cache_status::Bool = false) if length(hash) != 64 msg = "Hash must be 256 bits (64 characters) long, " msg *= "given hash is $(length(hash)) characters long" @@ -444,6 +451,7 @@ function verify(path::AbstractString, hash::AbstractString; verbose::Bool = fals # Fist, check to see if the hash cache is consistent hash_path = "$(path).sha256" + status = :hash_consistent # First, it must exist if isfile(hash_path) @@ -459,7 +467,14 @@ function verify(path::AbstractString, hash::AbstractString; verbose::Bool = fals @__LINE__, ) end - return true + status = :hash_cache_consistent + + # If we're reporting our status, then report it! + if report_cache_status + return true, status + else + return true + end else if verbose info_onchange( @@ -468,6 +483,7 @@ function verify(path::AbstractString, hash::AbstractString; verbose::Bool = fals @__LINE__, ) end + status = :file_modified end else if verbose @@ -477,6 +493,7 @@ function verify(path::AbstractString, hash::AbstractString; verbose::Bool = fals @__LINE__, ) end + status = :hash_cache_mismatch end else if verbose @@ -486,6 +503,7 @@ function verify(path::AbstractString, hash::AbstractString; verbose::Bool = fals @__LINE__, ) end + status = :hash_cache_missing end open(path) do file @@ -511,7 +529,11 @@ function verify(path::AbstractString, hash::AbstractString; verbose::Bool = fals write(file, hash) end - return true + if report_cache_status + return true, status + else + return true + end end """ diff --git a/test/runtests.jl b/test/runtests.jl index 0dc8936..cb9d31f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -485,14 +485,18 @@ end # Check that verifying with the right hash works info("This should say; no hash cache found") - @test verify(foo_path, foo_hash; verbose=true) + ret, status = verify(foo_path, foo_hash; verbose=true, report_cache_status=true) + @test ret == true + @test status == :hash_cache_missing # Check that it created a .sha256 file @test isfile("$(foo_path).sha256") # Check that it verifies the second time around properly info("This should say; hash cache is consistent") - @test verify(foo_path, foo_hash; verbose=true) + ret, status = verify(foo_path, foo_hash; verbose=true, report_cache_status=true) + @test ret == true + @test status == :hash_cache_consistent # Sleep for imprecise filesystems sleep(2) @@ -500,15 +504,23 @@ end # Get coverage of messing with different parts of the verification chain touch(foo_path) info("This should say; file has been modified") - @test verify(foo_path, foo_hash; verbose=true) + ret, status = verify(foo_path, foo_hash; verbose=true, report_cache_status=true) + @test ret == true + @test status == :file_modified + + # Ensure that we throw an exception when we can't verify properly @test_throws ErrorException verify(foo_path, "0"^32; verbose=true) + + # Ensure that messing with the hash file works properly touch(foo_path) @test verify(foo_path, foo_hash; verbose=true) open("$(foo_path).sha256", "w") do file write(file, "this is not the right hash") end info("This should say; hash has changed") - @test verify(foo_path, foo_hash; verbose=true) + ret, status = verify(foo_path, foo_hash; verbose=true, report_cache_status=true) + @test ret == true + @test status == :hash_cache_mismatch end end From 41c611ead2654fdc51c3240d4fcc21cfe4c5b61d Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Mon, 19 Feb 2018 00:51:40 -0800 Subject: [PATCH 3/3] Rework `Products` API to contain variable names. This obviates the need for `write_deps_file()` to be a macro, and will make our API throughout multiple build stages be much more consistent. --- src/Products.jl | 265 ++++++++++++++++++----------------- test/LibFoo.jl/deps/build.jl | 60 ++++---- test/runtests.jl | 16 +-- 3 files changed, 176 insertions(+), 165 deletions(-) diff --git a/src/Products.jl b/src/Products.jl index 684bffe..4af7aef 100644 --- a/src/Products.jl +++ b/src/Products.jl @@ -1,11 +1,45 @@ export Product, LibraryProduct, FileProduct, ExecutableProduct, satisfied, - locate, @write_deps_file + locate, write_deps_file """ A `Product` is an expected result after building or installation of a package. + +Examples of `Product`s include `LibraryProduct`, `ExecutableProduct` and +`FileProduct`. All `Product` types must define the following minimum set of +functionality: + +* `locate(::Product)`: given a `Product`, locate it within the wrapped `Prefix` + returning its location as a string + +* `satisfied(::Product)`: given a `Product`, determine whether it has been + successfully satisfied (e.g. it is locateable and it passes all callbacks) + +* `variable_name(::Product)`: return the variable name assigned to a `Product` """ abstract type Product end +""" + satisfied(p::Product; platform::Platform = platform_key(), verbose = false) + +Given a `Product`, return `true` if that `Product` is satisfied, e.g. whether +a file exists that matches all criteria setup for that `Product`. +""" +function satisfied(p::Product; platform::Platform = platform_key(), + verbose::Bool = false) + return locate(p; platform=platform, verbose=verbose) != nothing +end + + +""" + variable_name(p::Product) + +Return the variable name associated with this `Product` as a string +""" +function variable_name(p::Product) + return string(p.variable_name) +end + + """ A `LibraryProduct` is a special kind of `Product` that not only needs to exist, but needs to be `dlopen()`'able. You must know which directory the library @@ -18,9 +52,11 @@ build configuration. struct LibraryProduct <: Product dir_path::String libnames::Vector{String} + variable_name::String """ - `LibraryProduct(prefix::Prefix, libname::AbstractString)` + LibraryProduct(prefix::Prefix, libname::AbstractString, + varname::Symbol) Declares a `LibraryProduct` that points to a library located within the `libdir` of the given `Prefix`, with a name containing `libname`. As an @@ -35,26 +71,31 @@ struct LibraryProduct <: Product Libraries matching the search pattern are rejected if they are not `dlopen()`'able. """ - function LibraryProduct(prefix::Prefix, libname::AbstractString) - return LibraryProduct(libdir(prefix), [libname]) + function LibraryProduct(prefix::Prefix, libname::AbstractString, + varname::Symbol) + return LibraryProduct(libdir(prefix), [libname], varname) end - function LibraryProduct(prefix::Prefix, libnames::Vector{S}) where {S <: AbstractString} - return new(libdir(prefix), libnames) + function LibraryProduct(prefix::Prefix, libnames::Vector{S}, + varname::Symbol) where {S <: AbstractString} + return new(libdir(prefix), libnames, varname) end """ - `LibraryProduct(dir_path::AbstractString, libname::AbstractString)` + LibraryProduct(dir_path::AbstractString, libname::AbstractString, + varname::Symbol) For finer-grained control over `LibraryProduct` locations, you may directly pass in the `dir_path` instead of auto-inferring it from `libdir(prefix)`. """ - function LibraryProduct(dir_path::AbstractString, libname::AbstractString) - return new(dir_path, [libname]) + function LibraryProduct(dir_path::AbstractString, libname::AbstractString, + varname::Symbol) + return new(dir_path, [libname], varname) end - function LibraryProduct(dir_path::AbstractString, libnames::Vector{S}) where {S <: AbstractString} - return new(dir_path, libnames) + function LibraryProduct(dir_path::AbstractString, libnames::Vector{S}, + varname::Symbol) where {S <: AbstractString} + return new(dir_path, libnames, varname) end end @@ -134,25 +175,28 @@ automatically, if it is not already present). """ struct ExecutableProduct <: Product path::AbstractString + variable_name::Symbol """ - `ExecutableProduct(prefix::Prefix, binname::AbstractString)` + `ExecutableProduct(prefix::Prefix, binname::AbstractString, + varname::Symbol)` Declares an `ExecutableProduct` that points to an executable located within the `bindir` of the given `Prefix`, named `binname`. """ - function ExecutableProduct(prefix::Prefix, binname::AbstractString) - return ExecutableProduct(joinpath(bindir(prefix), binname)) + function ExecutableProduct(prefix::Prefix, binname::AbstractString, + varname::Symbol) + return new(joinpath(bindir(prefix), binname), varname) end """ - `ExecutableProduct(binpath::AbstractString)` + `ExecutableProduct(binpath::AbstractString, varname::Symbol)` For finer-grained control over `ExecutableProduct` locations, you may directly pass in the full `binpath` instead of auto-inferring it from `bindir(prefix)`. """ - function ExecutableProduct(binpath::AbstractString) - return new(binpath) + function ExecutableProduct(binpath::AbstractString, varname::Symbol) + return new(binpath, varname) end end @@ -203,6 +247,7 @@ A `FileProduct` represents a file that simply must exist to be satisfied. """ struct FileProduct <: Product path::AbstractString + variable_name::Symbol end """ @@ -223,139 +268,103 @@ function locate(fp::FileProduct; platform::Platform = platform_key(), return nothing end - -""" -`satisfied(p::Product; platform::Platform = platform_key(), - verbose::Bool = false)` - -Given a `Product`, return `true` if that `Product` is satisfied, e.g. whether -a file exists that matches all criteria setup for that `Product`. -""" -function satisfied(p::Product; platform::Platform = platform_key(), - verbose::Bool = false) - return locate(p; platform=platform, verbose=verbose) != nothing -end - - """ -`@write_deps_file(products...)` + write_deps_file(depsjl_path::AbstractString, products::Vector{Product}; + verbose::Bool = false) -Helper macro to generate a `deps.jl` file out of a mapping of variable name -to `Product` objects. Call using something like: +Generate a `deps.jl` file that contains the variables referred to by the +products within `products`. As an example, running the following code: - fooifier = ExecutableProduct(...) - libbar = LibraryProduct(...) - @write_deps_file fooifier libbar + fooifier = ExecutableProduct(..., :foo_exe) + libbar = LibraryProduct(..., :libbar) + write_deps_file(joinpath(@__DIR__, "deps.jl"), [fooifier, libbar]) -If any `Product` object cannot be satisfied (e.g. `LibraryProduct` objects must -be `dlopen()`-able, `FileProduct` objects must exist on the filesystem, etc...) -this macro will error out. Ensure that you have used `install()` to install -the binaries you wish to write a `deps.jl` file for, and, optionally that you -have used `activate()` on the `Prefix` in which the binaries were installed so -as to make sure that the binaries are locatable. +Will generate a `deps.jl` file that contains definitions for the two variables +`foo_exe` and `libbar`. If any `Product` object cannot be satisfied (e.g. +`LibraryProduct` objects must be `dlopen()`-able, `FileProduct` objects must +exist on the filesystem, etc...) this method will error out. Ensure that you +have used `install()` to install the binaries you wish to write a `deps.jl` +file for. -The result of this macro call is a `deps.jl` file containing variables named -the same as the keys of the passed-in dictionary, holding the full path to the +The result of this method is a `deps.jl` file containing variables named as +defined within the `Product` objects passed in to it, holding the full path to the installed binaries. Given the example above, it would contain code similar to: - global const fooifier = "/deps/usr/bin/fooifier" + global const foo_exe = "/deps/usr/bin/fooifier" global const libbar = "/deps/usr/lib/libbar.so" -This file is intended to be `include()`'ed from within the `__init__()` method -of your package. Note that all files are checked for consistency on package -load time, and if an error is discovered, package loading will fail, asking -the user to re-run `Pkg.build("package_name")`. +This `deps.jl` file is intended to be `include()`'ed from within the top-level +source of your package. Note that all files are checked for consistency on +package load time, and if an error is discovered, package loading will fail, +asking the user to re-run `Pkg.build("package_name")`. """ -macro write_deps_file(capture...) - # props to @tshort for his macro wizardry - names = :($(capture)) - products = esc(Expr(:tuple, capture...)) - - # We have to create this dummy_source, because we cannot, in a single line, - # have both `@__FILE__` and `__source__` interpreted by the same julia. - dummy_source = VERSION >= v"0.7.0-" ? __source__.file : "" - - # Set this to verbose if we've requested it from build.jl - verbose = "--verbose" in ARGS - - return quote - # First pick up important pieces of information from the call-site - const source = VERSION >= v"0.7.0-" ? $("$(dummy_source)") : @__FILE__ - const depsjl_path = joinpath(dirname(source), "deps.jl") - const package_name = basename(dirname(dirname(source))) - const platform = platform_key() - escape_path = path -> replace(path, "\\", "\\\\") - - const rebuild = strip(""" - Please re-run Pkg.build(\\\"$(package_name)\\\"), and restart Julia. - """) - - # Begin by ensuring that we can satisfy every product RIGHT NOW - for product in $(products) - # Check to make sure that we've passed in the right kind of - # objects, e.g. subclasses of `Product` - if !(typeof(product) <: Product) - msg = "Cannot @write_deps_file for $product, which is " * - "of type $(typeof(product)), which is not a " * - "subtype of `Product`!" - error(msg) - end - - if !satisfied(product; verbose=$(verbose)) - error("$product is not satisfied, cannot generate deps.jl!") - end - end +function write_deps_file(depsjl_path::AbstractString, + products::Vector{Product}; verbose::Bool=false) + # helper function to escape paths + escape_path = path -> replace(path, "\\", "\\\\") + + # Grab the package name as the name of the top-level directory of a package + package_name = basename(dirname(dirname(depsjl_path))) + + # We say this a couple of times + const rebuild = strip(""" + Please re-run Pkg.build(\\\"$(package_name)\\\"), and restart Julia. + """) + + # Begin by ensuring that we can satisfy every product RIGHT NOW + if any(.!(satisfied.(products; verbose=verbose))) + error("$product is not satisfied, cannot generate deps.jl!") + end - # If things look good, let's generate the `deps.jl` file - open(depsjl_path, "w") do depsjl_file - # First, dump the preamble + # If things look good, let's generate the `deps.jl` file + open(depsjl_path, "w") do depsjl_file + # First, dump the preamble + println(depsjl_file, strip(""" + ## This file autogenerated by BinaryProvider.write_deps_file(). + ## Do not edit. + ## + ## Include this file within your main top-level source, and call + ## `check_deps()` from within your module's `__init__()` method + """)) + + # Next, spit out the paths of all our products + for product in products + # Escape the location so that e.g. Windows platforms are happy with + # the backslashes in a string literal + escaped_path = escape_path(locate(product, platform=platform_key(), + verbose=verbose)) println(depsjl_file, strip(""" - ## This file autogenerated by BinaryProvider.@write_deps_file. - ## Do not edit. + const $(variable_name(product)) = \"$(escaped_path)\" """)) + end - # Next, spit out the paths of all our products - for idx in 1:$(length(capture)) - product = $(products)[idx] - name = $(names)[idx] - - # Escape the location so that e.g. Windows platforms are happy - # with the backslashes in a string literal - escaped_path = escape_path(locate(product, platform=platform)) - println(depsjl_file, strip(""" - const $(name) = \"$(escaped_path)\" - """)) - end + # Next, generate a function to check they're all on the up-and-up + println(depsjl_file, "function check_deps()") - # Next, generate a function to check they're all on the up-and-up - println(depsjl_file, "function check_deps()") + for product in products + varname = variable_name(product) - for idx in 1:$(length(capture)) - product = $(products)[idx] - name = $(names)[idx] + # Add a `global $(name)` + println(depsjl_file, " global $(varname)"); - # Add a `global $(name)` - println(depsjl_file, " global $(name)"); + # Check that any file exists + println(depsjl_file, """ + if !isfile($(varname)) + error("\$($(varname)) does not exist, $(rebuild)") + end + """) - # Check that any file exists + # For Library products, check that we can dlopen it: + if typeof(product) <: LibraryProduct println(depsjl_file, """ - if !isfile($(name)) - error("\$($(name)) does not exist, $(rebuild)") + if Libdl.dlopen_e($(varname)) == C_NULL + error("\$($(varname)) cannot be opened, $(rebuild)") end """) - - # For Library products, check that we can dlopen it: - if typeof(product) <: LibraryProduct - println(depsjl_file, """ - if Libdl.dlopen_e($(name)) == C_NULL - error("\$($(name)) cannot be opened, $(rebuild)") - end - """) - end end - - # Close the `check_deps()` function - println(depsjl_file, "end") end + + # Close the `check_deps()` function + println(depsjl_file, "end") end end diff --git a/test/LibFoo.jl/deps/build.jl b/test/LibFoo.jl/deps/build.jl index 325e185..5db4ab3 100644 --- a/test/LibFoo.jl/deps/build.jl +++ b/test/LibFoo.jl/deps/build.jl @@ -1,36 +1,38 @@ using BinaryProvider -# BinaryProvider support -const prefix = Prefix(joinpath(dirname(@__FILE__),"usr")) -const platform = platform_key() - +# Parse some basic command-line arguments +const verbose = "--verbose" in ARGS +const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr"))) + # These are the two binary objects we care about -libfoo = LibraryProduct(prefix, "libfoo") -fooifier = ExecutableProduct(prefix, "fooifier") +libfoo = LibraryProduct(prefix, "libfoo", :libfoo) +fooifier = ExecutableProduct(prefix, "fooifier", :fooifier) +products = [libfoo, fooifier] -# This is where we download things from, for different platforms -const bin_prefix = "https://github.com/staticfloat/small_bin/raw/74b7fd81e3fbc8963b14b0ebbe5421e270d8bdcf" -const download_info = Dict( - Linux(:i686) => ("$bin_prefix/libfoo.i686-linux-gnu.tar.gz", "1398353bcbbd88338189ece9c1d6e7c508df120bc4f93afbaed362a9f91358ff"), - Linux(:x86_64) => ("$bin_prefix/libfoo.x86_64-linux-gnu.tar.gz", "b9d57a6e032a56b1f8641771fa707523caa72f1a2e322ab99eeeb011f13ad9f3"), - Linux(:aarch64) => ("$bin_prefix/libfoo.aarch64-linux-gnu.tar.gz", "19d9da0e6e7fb506bf4889eb91e936fda43493a39cd4fd7bd5d65506cede6f95"), - Linux(:armv7l) => ("$bin_prefix/libfoo.arm-linux-gnueabihf.tar.gz", "8e33c1a0e091e6e5b8fcb902e5d45329791bb57763ee9cbcde49c1ec9bd8532a"), - Linux(:ppc64le) => ("$bin_prefix/libfoo.powerpc64le-linux-gnu.tar.gz", "b48a64d48be994ec99b1a9fb60e0af7f4415a57596518cb90a340987b79fad81"), - MacOS() => ("$bin_prefix/libfoo.x86_64-apple-darwin14.tar.gz", "661b71edb433ab334b0fef70db3b5c45d35f2b3bee0d244f54875f1ec899c10f"), - Windows(:i686) => ("$bin_prefix/libfoo.i686-w64-mingw32.tar.gz", "3d4a8d4bf0169007a42d809a1d560083635b1540a1bc4a42108841dcb6d2aaea"), - Windows(:x86_64) => ("$bin_prefix/libfoo.x86_64-w64-mingw32.tar.gz", "2d08fbc9a534cd021f36b6bbe86ddabb2dafbedeb589581240aa4a8c5b896055"), -) -if platform in keys(download_info) - # Grab the url and tarball hash for this particular platform - url, tarball_hash = download_info[platform] +# Download binaries from hosted location +bin_prefix = "https://github.com/staticfloat/small_bin/raw/74b7fd81e3fbc8963b14b0ebbe5421e270d8bdcf" - # Build and install it - install(url, tarball_hash; prefix=prefix, force=true, verbose=true) +# Listing of files generated by BinaryBuilder: +download_info = Dict( + Linux(:i686, :glibc) => ("$bin_prefix/libfoo.i686-linux-gnu.tar.gz", "1398353bcbbd88338189ece9c1d6e7c508df120bc4f93afbaed362a9f91358ff"), + Linux(:x86_64, :glibc) => ("$bin_prefix/libfoo.x86_64-linux-gnu.tar.gz", "b9d57a6e032a56b1f8641771fa707523caa72f1a2e322ab99eeeb011f13ad9f3"), + Linux(:aarch64, :glibc) => ("$bin_prefix/libfoo.aarch64-linux-gnu.tar.gz", "19d9da0e6e7fb506bf4889eb91e936fda43493a39cd4fd7bd5d65506cede6f95"), + Linux(:armv7l, :glibc) => ("$bin_prefix/libfoo.arm-linux-gnueabihf.tar.gz", "8e33c1a0e091e6e5b8fcb902e5d45329791bb57763ee9cbcde49c1ec9bd8532a"), + Linux(:ppc64le, :glibc) => ("$bin_prefix/libfoo.powerpc64le-linux-gnu.tar.gz", "b48a64d48be994ec99b1a9fb60e0af7f4415a57596518cb90a340987b79fad81"), + MacOS() => ("$bin_prefix/libfoo.x86_64-apple-darwin14.tar.gz", "661b71edb433ab334b0fef70db3b5c45d35f2b3bee0d244f54875f1ec899c10f"), + Windows(:i686) => ("$bin_prefix/libfoo.i686-w64-mingw32.tar.gz", "3d4a8d4bf0169007a42d809a1d560083635b1540a1bc4a42108841dcb6d2aaea"), + Windows(:x86_64) => ("$bin_prefix/libfoo.x86_64-w64-mingw32.tar.gz", "2d08fbc9a534cd021f36b6bbe86ddabb2dafbedeb589581240aa4a8c5b896055"), +) +# First, check to see if we're all satisfied +if any(!satisfied(p; verbose=verbose) for p in products) + if platform_key() in keys(download_info) + # Download and install binaries + url, tarball_hash = download_info[platform_key()] + install(url, tarball_hash; prefix=prefix, force=true, verbose=true) + else + error("Your platform $(Sys.MACHINE) is not supported by this package!") + end - # Finaly, write out a deps file containing paths to libfoo and fooifier - @write_deps_file libfoo fooifier -else - error("Your platform $(Sys.MACHINE) is not recognized, we cannot install Libfoo!") + # Finally, write out a deps.jl file + write_deps_file(joinpath(@__DIR__, "deps.jl"), products) end - - diff --git a/test/runtests.jl b/test/runtests.jl index cb9d31f..8403f46 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -263,10 +263,10 @@ end # Test that basic satisfication is not guaranteed e_path = joinpath(bindir(prefix), "fooifier") l_path = joinpath(libdir(prefix), "libfoo.$(Libdl.dlext)") - e = ExecutableProduct(prefix, "fooifier") - ef = FileProduct(e_path) - l = LibraryProduct(prefix, "libfoo") - lf = FileProduct(l_path) + e = ExecutableProduct(prefix, "fooifier", :fooifier) + ef = FileProduct(e_path, :fooifier) + l = LibraryProduct(prefix, "libfoo", :libfoo) + lf = FileProduct(l_path, :libfoo) @test !satisfied(e; verbose=true) @test !satisfied(ef; verbose=true) @@ -330,7 +330,7 @@ end for ext in ["1.so", "so", "so.1", "so.1.2", "so.1.2.3"] temp_prefix() do prefix l_path = joinpath(libdir(prefix), "libfoo.$ext") - l = LibraryProduct(prefix, "libfoo") + l = LibraryProduct(prefix, "libfoo", :libfoo) mkdir(dirname(l_path)) touch(l_path) @test satisfied(l; verbose=true, platform=foreign_platform) @@ -341,7 +341,7 @@ end for ext in ["so.1.2.3a", "so.1.a"] temp_prefix() do prefix l_path = joinpath(libdir(prefix), "libfoo.$ext") - l = LibraryProduct(prefix, "libfoo") + l = LibraryProduct(prefix, "libfoo", :libfoo) mkdir(dirname(l_path)) touch(l_path) @test !satisfied(l; verbose=true, platform=foreign_platform) @@ -547,8 +547,8 @@ const libfoo_downloads = Dict( url, hash = libfoo_downloads[platform] @test install(url, hash; prefix=prefix, verbose=true) - fooifier = ExecutableProduct(prefix, "fooifier") - libfoo = LibraryProduct(prefix, "libfoo") + fooifier = ExecutableProduct(prefix, "fooifier", :fooifier) + libfoo = LibraryProduct(prefix, "libfoo", :libfoo) @test satisfied(fooifier; verbose=true) @test satisfied(libfoo; verbose=true)