makeBinWriter
pkgs.writers.makeBinWriter
Functor
Docs pulled from | This Revision | 10 minutes ago
makeBinWriter
returns a derivation which compiles the given script into an executable format.
This function is the base implementation for other compile language writers
, such as writeHaskell
and writeRust
.
Inputs
- config (AttrSet)
-
compileScript
(String)- The script that compiles the given content into an executable.
-
strip
(Boolean, Default: true)- Whether to strip the executable or not.
-
makeWrapperArgs
(Optional, [ String ], Default: [])- Arguments forwarded to (
makeWrapper
)[#fun-makeWrapper]
nameOrPath
(String)- The name of the script or the path to the script.
When a
string
starting with "/" is passed, the script will be created at the specified path in $out. For example,"/bin/hello"
will create a script at$out/bin/hello
. Any otherstring
is interpreted as a filename. It must be a POSIX filename starting with a letter, digit, dot, or underscore. Spaces or special characters are not allowed.
Examples
pkgs.writers.makeBinWriter
example
// main.c
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
return 0;
}
:b makeBinWriter { compileScript = "${pkgs.gcc}/bin/gcc -o $out $contentPath"; } "hello" ./main.c
out -> /nix/store/f6crc8mwj3lvcxqclw7n09cm8nb6kxbh-hello
The above example creates an executable named hello
that outputs Hello, World!
when executed.
> /nix/store/f6crc8mwj3lvcxqclw7n09cm8nb6kxbh-hello
Hello, World!
Noogle detected
This is a Functor
Learn about functors
Implementation
The following is the current implementation of this function.
makeBinWriter =
{
compileScript,
strip ? true,
makeWrapperArgs ? [ ],
}:
nameOrPath: content:
assert
(types.path.check nameOrPath)
|| (builtins.match "([0-9A-Za-z._])[0-9A-Za-z._-]*" nameOrPath != null);
assert (types.path.check content) || (types.str.check content);
let
nameIsPath = types.path.check nameOrPath;
name = last (builtins.split "/" nameOrPath);
path = if nameIsPath then nameOrPath else "/bin/${name}";
# The inner derivation which creates the executable under $out/bin (never at $out directly)
# This is required in order to support wrapping, as wrapped programs consist of at least two files: the executable and the wrapper.
inner =
pkgs.runCommandLocal name
(
{
inherit makeWrapperArgs;
nativeBuildInputs = [ makeBinaryWrapper ];
meta.mainProgram = name;
}
// (
if (types.str.check content) then
{
inherit content;
passAsFile = [ "content" ];
}
else
{ contentPath = content; }
)
)
''
${compileScript}
${lib.optionalString strip "${lib.getBin buildPackages.bintools-unwrapped}/bin/${buildPackages.bintools-unwrapped.targetPrefix}strip -S $out"}
# Sometimes binaries produced for darwin (e. g. by GHC) won't be valid
# mach-o executables from the get-go, but need to be corrected somehow
# which is done by fixupPhase.
${lib.optionalString pkgs.stdenvNoCC.hostPlatform.isDarwin "fixupPhase"}
mv $out tmp
mkdir -p $out/$(dirname "${path}")
mv tmp $out/${path}
if [ -n "''${makeWrapperArgs+''${makeWrapperArgs[@]}}" ]; then
wrapProgram $out/${path} ''${makeWrapperArgs[@]}
fi
'';
in
if nameIsPath then
inner
# In case nameOrPath is a name, the user intends the executable to be located at $out.
# This is achieved by creating a separate derivation containing a symlink at $out linking to ${inner}/bin/${name}.
# This breaks the override pattern.
# In case this turns out to be a problem, we can still add more magic
else
pkgs.runCommandLocal name { } ''
ln -s ${inner}/bin/${name} $out
'';