Bazel: BUILD fragments need to differ based on the target operating system - bazel

I have something like this in a BUILD file. I am un/commenting lines based on the operating system. Is there a graceful way to do this?
# Ubuntu
#shared_libraries = [
# "libboost_atomic.so"
#],
# OSX
shared_libraries = [
"libboost_atomic.dylib"
],

I haven't tried this however the bazel-build/rules_nodejs uses this kind of approach by wrapping the native binary and querying its's Node JS OS API.
OS Name Function(uses context given from user running node.exe)
UPDATE
Check here
Setting up a C++ Toolchain
This seems to be what you need.

Related

How to not rebuild artifacts on every invocation

I want to download and build ruby within a workspace. I've been trying to implement this by mimicking rules_go. I have that part working. The issue I'm having is it rebuilds the openssl and ruby artifacts each time ruby_download_sdk is invoked. In the code below the download artifacts are cached but the builds of openssl and ruby are always executed.
def ruby_download_sdk(name, version = None):
# TODO detect os and arch
os, arch = "osx", "x86_64"
_ruby_download_sdk(
name = name,
version = version,
)
_register_toolchains(name, os, arch)
def _ruby_download_sdk_impl(repository_ctx):
# TODO detect platform
platform = ("osx", "x86_64")
_sdk_build_file(repository_ctx, platform)
_remote_sdk(repository_ctx)
_ruby_download_sdk = repository_rule(
_ruby_download_sdk_impl,
attrs = {
"version": attr.string(),
},
)
def _remote_sdk(repository_ctx):
_download_openssl(repository_ctx, version = "1.1.1c")
_download_ruby(repository_ctx, version = "2.6.3")
openssl_path, ruby_path = "openssl/build", ""
_build(repository_ctx, "openssl", openssl_path, ruby_path)
_build(repository_ctx, "ruby", openssl_path, ruby_path)
def _build(repository_ctx, name, openssl_path, ruby_path):
script_name = "build-{}.sh".format(name)
template_name = "build-{}.template".format(name)
repository_ctx.template(
script_name,
Label("#rules_ruby//ruby/private:{}".format(template_name)),
substitutions = {
"{ssl_build}": openssl_path,
"{ruby_build}": ruby_path,
}
)
repository_ctx.report_progress("Building {}".format(name))
res = repository_ctx.execute(["./" + script_name], timeout=20*60)
if res.return_code != 0:
print("res %s" % res.return_code)
print(" -stdout: %s" % res.stdout)
print(" -stderr: %s" % res.stderr)
Any advice on how I can make bazel aware such that it doesn't rebuild these build artifacts every time?
Problem is, that bazel isn't really building your ruby and openssl. When it prepares your build tree and runs the repository rule, it just executes a shell script as instructed, which apparently happens to build, but that fact is essentially opaque to bazel (and it also happens before bazel itself would even build).
There might be other, but I see the following as your options from top of my head:
Pre-build your ruby environment and its results as external dependency. The obvious downside (which may or may not be quite a lot of pain) being you need to do so for all platforms you need to supports (incl. making sure correct detection and corresponding download). The upside being you really only build once (per platform) and also have control over tooling used across all hosts. This would likely be my primary choice.
Build ssl and ruby as any other C sources making them just another bazel target. This however means you'd need to bazelify their builds (describe and maintain bazel build of otherwise bazel unaware project).
You can continue further along the path you've started and just (sort of) leave bazel out of it. I.e. for these builds extend the magic and in the build scripts used for instance using deterministic location and perhaps manifest files of what is around (also to make corruption less likely) make it possible to determine that the build has indeed already taken place and you can just collect its previous results.

How to specify os platform in waf script?

I'm new to waf build tool and I've googled for answers but very few unhelpful links.
Does anyone know?
As wscript is essentially a python script, I suppose I could use the os package?
Don't use the os module, instead use the DEST_* variables:
ctx.load('compiler_c')
print (ctx.env.DEST_OS, ctx.env.DEST_CPU, ctx.env.DEST_BINFMT)
On my machine this would print ('linux', 'x86_64', 'elf'). Then you can dispatch on that.
You can use import at every point where you could use it any other python script.
I prefer using platform for programming a function os-agnostic instead on evaluate some attributes of os.
Writing the Build-related commands example in the waf book os-agnostic, could look something like this:
import platform
top = '.'
out = 'build_directory'
def configure(ctx):
pass
def build(ctx):
if platform.system().lower().startswith('win'):
cp = 'copy'
else:
cp = 'cp'
ctx(rule=cp+' ${SRC} ${TGT}', source='foo.txt', target='bar.txt')

Get the operating system in maxima

Is it possible to get the operating system in maxima? I have some code that needs the unix / or windows \ for path names. How can I find out which operating system the code is running in?
To give some context, I have the following code:
windows: false$
divider: "/"$
if (windows) then divider: "\\"$
initfile: concat(maxima_userdir, divider, "maxima-init.mac");
load(operatingsystem)$
dir: getcurrentdirectory();
if (substring(dir, slength(dir)) # divider) then dir: concat(dir, divider)$
repo: concat(dir, "$$$.mac")$
live: concat(dir, "live_packages", divider, "$$$.mac")$
with_stdout(initfile, printf(true, ""))$
with_stdout(initfile, printf(true, concat("file_search_maxima: append (file_search_maxima, [
~s,
~s
]);"), repo, live))$
Take a look at the output of build_info, specifically the field host (i.e. foo#host where foo : build_info()). See ? build_info for more information.
On my (Linux) system I get: x86_64-unknown-linux-gnu I think on MS Windows you'll get a string containing windows or at least win or maybe win32.
There may be other ways to figure out the system type so let me know if that doesn't work for you. Also it is possible that there is a global variable floating around which tells the path separator; I would have to look for that.
If you're not adverse to writing a little bit of Lisp code, another approach is to use the file and directory functions in Common Lisp, which are more extensive than in Maxima. See the section on filenames in the Common Lisp Hyperspec. I think maybe MERGE-PATHNAMES and/or MAKE-PATHNAME might be relevant.

Is it possible to keep my Nix packages in sync across machines not running NixOS?

I know with NixOS, you can simply copy over the configuration.nix file to sync your OS state including installed packages between machines.
Is it possible then, to do the same using Nix the package manager on a non-NixOS OS to sync only the installed packages?
Please note, that at least since 30.03.2017 (corresponding to 17.03 Nix/NixOS channel/release), as far as I understand the official, modern, supported and suggested solution is to use the so called overlays.
See the chapter titled "Overlays" in the nixpkgs manual for a nice guide on how to use the new approach.
As a short summary: you can put any number of files with .nix extension in $HOME/.config/nixpkgs/overlays/ directory. They will be processed in alphabetical order, and each one can modify the set of available Nix packages. Each of the files must be written as in the following pattern:
self: super:
{
boost = super.boost.override {
python = self.python3;
};
rr = super.callPackage ./pkgs/rr {
stdenv = self.stdenv_32bit;
};
}
The super set corresponds to the "old" set of packages (before the overlay was applied). If you want to refer to the old version of a package (as in boost above), or callPackage, you should reference it via super.
The self set corresponds to the eventual, "future" set of packages, representing the final result after all overlays are applied. (Note: don't be scared when sometimes using them might get rejected by Nix, as it would result in infinite recursion. Probably you should rather just use super in those cases instead.)
Note: with the above changes, the solution I mention below in the original answer seems "deprecated" now — I believe it should still work as of April 2017, but I have no idea for how long. It appears marked as "obsolete" in the nixpkgs repository.
Old answer, before 17.03:
Assuming you want to synchronize apps per-user (as non-NixOS Nix keeps apps visible on per-user basis, not system-wide, as far as I know), it is possible to do it declaratively. It's just not well advertised in the manual — though it seems quite popular among long-time Nixers!
You must create a text file at: $HOME/.nixpkgs/config.nix — e.g.:
$ mkdir -p ~/.nixpkgs
$ $EDITOR ~/.nixpkgs/config.nix
then enter the following contents:
{
packageOverrides = defaultPkgs: with defaultPkgs; {
home = with pkgs; buildEnv {
name = "home";
paths = [
nethack mc pstree #...your favourite pkgs here...
];
};
};
}
Then you should be able to install all listed packages with:
$ nix-env -i home
or:
$ nix-env -iA nixos.home # *much* faster than above
In paths you can put stuff in a similar way like in /etc/nixos/configuration.nix on NixOS. Also, home is actually a "fake package" here. You can add more custom package definitions beside it, and then include them your "paths".
(Side note: I'm hoping to write a blog post with what I learned on how exactly this works, and also showing how to extend it with more customizations. I'll try to remember to link it here if I succeed.)

Mozilla Addon Development check environment

I am developing a Firefox add on, I pretend my add on to be able to run in both desktop and mobile devices. I think more or less everything is compatible with both environments, however there are pieces of code that I would like to run depending on whether the current device is mobile or desktop, so the question is if there is something like system.isMobile() that can be used in the following way:
var system = require("sdk/system");
if(system.isMobile())
console.log("firefox for android");
else
console.log("normal firefox");
As you can find at the system api documentation, there is a variable telling the operating system.
code:
var system = require("sdk/system");
console.log("system platform = " + system.platform);
output:
system platform = linux
disclaimer: I didn't tested on mobile environment.
You can use the System High-Level API. system.platform will contain the information on the type of OS the user is running.
You can use it like so:
var system = require("sdk/system");
var platform = system.platform // Will contain platform, i.e. Windows, Linux, etc.
// You can log this data to the console
console.log("System Platform = " + platform);
When you call system.platform, it will usually return one of the values listed on this page, converted to lowercase

Resources