Is there a way to use zig compiler as a library inside zig?
After looking both in zig documentation, issues and on the internet, I can't find an answer to this question.
In one of the issues it is said that this can be done at the current time, but I couldn't find any examples of how to do it.
It is currently non-trivial to use the zig compiler as a library due to the difficulty in including libraries with complicated build requirements. Once the package manager is released, it will likely become much easier.
For now, I would recommend calling the zig compiler as a system command
var zig = std.ChildProcess.init(&.{"zig", "build-exe", "demo.zig"}, allocator);
try zig.spawn();
try zig.wait();
However, if you really want to, here is how to use zig 0.9.0-dev.1611+f3ba72cf5 as a library
Reasons not to do this before the package manager is released:
This requires making a mess of your build.zig file, and your build.zig file has to be kept up to date with the compiler's build.zig file
This will make your project build really slowly due to the current slow speed of the stage1 zig compiler
This example does not show how to enable stage1 and the LLVM extensions in the zig package it makes. Enabling stage1 and LLVM extensions will require looking at zig's build.zig file and copying in stuff about linking libraries and include directories and c source and stuff.
This build.zig was made by finding all the instances of .addOption in the zig compiler's build.zig and recreating them in our own build.zig file.
// build.zig
const std = #import("std");
pub fn build(b: *std.build.Builder) !void {
const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions();
const exe_options = b.addOptions();
const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse 4;
const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
const enable_logging = b.option(bool, "log", "Whether to enable logging") orelse false;
const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false;
exe_options.addOption(u32, "mem_leak_frames", mem_leak_frames);
exe_options.addOption(bool, "skip_non_native", skip_non_native);
exe_options.addOption(bool, "have_llvm", false);
exe_options.addOption(bool, "llvm_has_m68k", false);
exe_options.addOption(bool, "llvm_has_csky", false);
exe_options.addOption(bool, "llvm_has_ve", false);
exe_options.addOption(bool, "llvm_has_arc", false);
const version = "0.0.0";
exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
const semver = try std.SemanticVersion.parse(version);
exe_options.addOption(std.SemanticVersion, "semver", semver);
exe_options.addOption(bool, "enable_logging", enable_logging);
exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
exe_options.addOption(bool, "enable_tracy", false);
exe_options.addOption(bool, "enable_tracy_callstack", false);
exe_options.addOption(bool, "enable_tracy_allocation", false);
exe_options.addOption(bool, "is_stage1", false);
exe_options.addOption(bool, "omit_stage2", false);
const exe = b.addExecutable("tmp", "sample.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.addOptions("build_options", exe_options);
exe.addPackage(.{
.name = "zig",
.path = .{ .path = "src/main.zig" },
.dependencies = &[_]std.build.Pkg{
.{ .name = "build_options", .path = exe_options.getSource() },
},
});
exe.install();
const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
// sample.zig
const zig = #import("zig");
pub fn main() !void {
return zig.main(); // just calls into the zig compiler main function. you'll have to look into how https://github.com/ziglang/zig/blob/master/src/main.zig works in order to do more complicated stuff.
}
note: I recommend building this with -Dskip-non-native otherwise it will take a very long time to build due to the speed of the current stage1 compiler
zig build run -Dskip-non-native -- build-exe demo.zig
Related
I am using windows-rs (Latest version from GitHub, because it contains some fixes the stable version on Crates.io doesn't have).
My goal is to develop a small software that automatically forces the screen to be re-detected and set to the highest resolution (It's for a school with a weird setup where teachers have to turn projectors on before the PC for resolutions to get detected, but often forget that, leading the PCs to have a very low resolution, and the higher resolutions not being detected).
For re-initializing the screen, I have the following function:
// Some imports may be unused here, I haven't checked them yet, the full file has more functions
use windows::Win32::Graphics::Gdi::{ChangeDisplaySettingsA, EnumDisplaySettingsA, DEVMODEA, SDC_FORCE_MODE_ENUMERATION, SDC_APPLY, SDC_SAVE_TO_DATABASE, SDC_USE_SUPPLIED_DISPLAY_CONFIG, QDC_ALL_PATHS};
use windows::Win32::Media::Audio::Endpoints::IAudioEndpointVolume;
use windows::Win32::Media::Audio::{IMMDeviceEnumerator, MMDeviceEnumerator};
use windows::Win32::Devices::Display::{GetDisplayConfigBufferSizes, QueryDisplayConfig, SetDisplayConfig, DISPLAYCONFIG_TOPOLOGY_ID};
use windows::core::GUID;
use windows::Win32::System::Com::{CoInitialize, CoCreateInstance, CLSCTX_ALL};
// Forces Windows to reinit display settings
pub fn force_reinit_screen() -> i32 {
let mut path_count = 0;
let mut mode_count = 0;
let result = unsafe { GetDisplayConfigBufferSizes(QDC_ALL_PATHS, &mut path_count, &mut mode_count) };
println!("GetDisplayConfigBufferSizes returned {}", result);
let mut path_array = Vec::with_capacity(path_count as usize);
let mut mode_array = Vec::with_capacity(mode_count as usize);
let result = unsafe {
QueryDisplayConfig(
QDC_ALL_PATHS,
&mut path_count,
path_array.as_mut_ptr(),
&mut mode_count,
mode_array.as_mut_ptr(),
::core::mem::transmute(::core::ptr::null::<DISPLAYCONFIG_TOPOLOGY_ID>()),
)
};
println!("QueryDisplayConfig returned {}", result);
let flags = SDC_FORCE_MODE_ENUMERATION | SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_SAVE_TO_DATABASE;
let result = unsafe { SetDisplayConfig(Some(&path_array), Some(&mode_array), flags) };
result
}
However, it does not work on any computer I've tried this on (Returns code 87, which seems to mean bad parameters). What am I doing wrong?
Im trying to port https://github.com/markkraay/mnist-from-scratch to rust as an introduction to ML and the rust programming language.
I've decided to use nalgebra instead of rewriting a matrix library. However, im running into an error stating function or associated item not found in `Matrix<f64, Dynamic, Dynamic, VecStorage<f64, Dynamic, Dynamic>> when attempting to run new_random() on a DMatrix and I cant see how to fix It.
For context this is my code
pub fn new(input: usize, hidden: usize, output: usize, learning_rate: usize) -> NeuralNetwork {
let hidden_weights = na::DMatrix::<f64>::new_random(hidden, input);
let output_weights = na::DMatrix::<f64>::new_random(output, hidden);
NeuralNetwork {
input,
hidden,
output,
learning_rate,
hidden_weights,
output_weights
}
}
Ive tried removing <f64> so that it is instead
na::DMatrix::new_random(hidden, input);
but there is no difference
To use new_random you have to enable the rand feature of nalgebra like so in Cargo.toml:
[dependencies]
nalgebra = { version = "0.31.4", features = ["rand"] }
after that your code should work as you posted it.
If you have cargo-edit installed you can also do:
cargo add nalgebra --features rand
I have a project which possesses and uses G2O library, it runs on both platforms(win/Unix).
(WINDOW PASSED / UNIX CRASHED)
We can see in both platforms, these lines:
g2o::SparseOptimizer optimizer;
g2o::BlockSolver_6_3::LinearSolverType * linearSolver;
linearSolver = new g2o::LinearSolverDense<g2o::BlockSolver_6_3::PoseMatrixType>();
Next steps, in window os we have this:
g2o::BlockSolver_6_3 * solver_ptr = new g2o::BlockSolver_6_3(linearSolver);
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
But Unix system can't compile those lines because it says
my_file_G2o.cpp: *In member function 'int Refiner_G2O::refinePose(cv::Mat&, const std::vector >&, const std::vector&, const cv::Mat&, float, std::vector&)': my_file_G2o.cpp --> no matching function for call to 'g2o::BlockSolver::BlockSolver(g2o::BlockSolver::LinearSolverType&)'*
^
In file included from G2o/include/g2o/core/block_solver.h:199:0,
G2o/include/g2o/core/block_solver.hpp:40:1: note: candidate: g2o::BlockSolver::BlockSolver(std::unique_ptr) [with Traits = g2o::BlockSolverTraits<6, 3>; typename Traits::LinearSolverType = g2o::LinearSolver >]
BlockSolver::BlockSolver(std::unique_ptr linearSolver)
When I see these errors, I complete my Unix code with this new block
auto solver_ptr = g2o::make_unique<g2o::BlockSolver_6_3>(linearSolver); // [SEGFAULT LINE]
auto solver = g2o::make_unique<g2o::OptimizationAlgorithmLevenberg>(solver_ptr);
optimizer.setAlgorithm(solver.get());
So now, I can build/run but I meet a segfault on the line with [SEGFAULT LINE] tag.
EDIT: After step to step debug with debug build I have a few news pieces of information:
g2o::SparseOptimizer optimizer; // debug says: "optimize: g2o::SparseOptimize
g2o::BlockSolver_6_3::LinearSolverType * linearSolver = NULL; // debug says : linearSolver: NULL
linearSolver = new g2o::LinearSolverDense<g2o::BlockSolver_6_3::PoseMatrixType>(); // debug says: linear solver: 0x7fe39cba9140
if (linearSolver == NULL) // debug says : not null.
exit (84);
auto solver_ptr = g2o::make_unique<g2o::BlockSolver< g2o::BlockSolver_6_3 >>(linearSolver);
// DEBUG --> And here, with "step into" he go to this "/usr/include/c++/6/bits/move.h"
and in the ligne 48 we can see this function:
`template<typename T, typename ...ArgTs>
std::unique_ptr<T> make_unique(ArgTs&& ...args) //DEBUG says: args#0:
-var-create: unable to create variable object.
{
return std::unique_ptr<T>(g2o::make_unique<T>(std::forward<ArgTs>
(args)...));
};`
And he segfault because she have a bad args.
I don't understand, why? if someone has an idea I want to understand how in Window it works and not in Unix system, will feel wonderful if you help.
LINUX Version: Ubuntu 16.04
CMAKE Version: 3.11.4
Best regards,
SOLVED:
G2O optimise:
g2o::SparseOptimizer optimizer;
auto linearSolver = std::make_unique<g2o::LinearSolverDense<g2o::BlockSolver_6_3::PoseMatrixType>>();
auto solver = new g2o::OptimizationAlgorithmLevenberg(std::make_unique<g2o::BlockSolver_6_3>(std::move(linearSolver)));
optimizer.setAlgorithm(solver);
MISC.H:
template<typename T, typename ...ArgTs>
std::unique_ptr<T> make_unique(ArgTs&& ...args)
{
return std::unique_ptr<T>(new T(std::forward<ArgTs>(args)...));
};
I am trying to use a ChromeWorker to launch a background process, like so:
var worker = new ChromeWorker(data.url("stun-manager.js"));
worker.addEventListener('message', function(e) {
console.log(e.data);
}, false);
worker.postMessage({'cmd': 'start', 'msg': 'Hi'});
But where exactly do I declare all my ctypes and such? Interestingly, in stun-manager.js, if I have the following:
dump ("Message 1");
var {Cu} = require("chrome");
dump ("Message 2");
/*import js-ctypes */
var {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm")
var stun_driver = ctypes.open("C:\\Users\\derek_000\\Documents\\Visual Studio 2012\\Projects\\stunnel507\\stunnel507\\bin\\win32\\stun_driver.dll");
const launch_stun = stun_driver.declare("launch_stun", ctypes.default_abi, ctypes.int32_t, ctypes.int32_t, ctypes.char.ptr.ptr);
let argv_t = ctypes.ArrayType(ctypes.char.ptr);
let argc = 2;
let argv = new argv_t(argc);
var conf_path = "C:\\Users\\derek_000\\Documents\\Visual Studio 2012\\Projects\\stunnel507\\stunnel507\\stunnel.conf";
argv[0] = ctypes.char.array()(conf_path);
argv[1] = ctypes.char.array()(conf_path);
self.addEventListener('message', function (e) {
var data = e.data;
switch (data.cmd) {
case 'start':
self.postMessage("Value of launch_stun " + self.launch_stun);
self.postMessage('WORKER STARTED: ' + data.msg);
self.postMessage("debug" + self.argv_t);
self.postMessage("test: " + self.argv_t);
self.postMessage(self.argv[0].readString());
launch_stun(argc, argv );
break;
case 'stop':
self.postMessage('WORKER STOPPED: ' + data.msg +
'. (buttons will no longer work)');
self.close(); // Terminates the worker.
break;
default:
self.postMessage('Unknown command: ' + data.msg);
};
}, false);
"Message 2" is never printed to the screen, and "Message 1" is. It's almost like I am getting a silent fail from one of those other lines, but this is the exact code I have used to launch this from main.js, before I tried to use ChromeWorker.
Any ideas? I guess it seems like stun-manager.js is failing silently, and on a related note, I can't even find it in the Browser Toolbox to debug, but I do see my main.js file there.
Two simple examples of using ChromeWorker (and also an advancement of ChromeWorker, PromiseWorker, which rocks by the way):
GitHub :: Noitidart / ChromeWorker
GitHub :: Noitidart / PromiseWorker
You can't do var {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm") in the worker (your worker is stun-manager.js). That's causing an error, remove that. You can just use ctypes without importing anything, ChromeWorker's autoamtically have it. That should fix it.
I'll look more over your code, but definitely check out the ChromeWorker repo it will help a lot, its a very basic messaging thing between worker and main.
This may not be a purely programming related question, but I come across this often during development. When my app crashes and I choose to kill it, Windows automatically throws up a "Checking for a solution..." dialog box. When I hit the cancel button on that I get another dialog box that says "Restarting the program..." Is there a way to prevent this behavior? When I stop an app I'd prefer if it were silently killed. I'm using Windows 7 if the platform is important.
Although Microsoft recommends using a newer replacement API available only on Windows Vista and later, there is an API which works for all versions of Windows from XP onward: AddERExcludedApplication(). This function takes the module name without path information (e.g., "myprogram.exe") for which error reporting is to be disabled.
The new method available only Windows Vista and later is to call WerAddExcludedApplication() function. This API allows you to specify whether it should change the HKEY_CURRENT_USER registry hive, or the HKEY_LOCAL_MACHINE registry hive. Be sure to set this for the HKCU if the HKLM set fails, such as:
typedef BOOL (*ADD_MER_EXCLUDED_APP_XP) (PCWSTR);
typedef BOOL (*ADD_MER_EXCLUDED_APP_VISTA) (PCWSTR, BOOL);
bool disable_microsoft_error_reporting(PCWSTR wz_app)
{
const WCHAR * const WZ_MER_DLL_XP = L"faultrep.dll";
const char * const SZ_MER_PROC_XP = "AddERExcludedApplicationW";
const WCHAR * const WZ_MER_DLL_VISTA = L"wer.dll";
const char * const SZ_MER_PROC_VISTA = "WerAddExcludedApplicationW";
const int WER_EXCLUDE_FOR_ALL_USERS = TRUE;
const int WER_EXCLUDE_FOR_THIS_USER = FALSE;
HANDLE hlib_error_reports_xp = NULL;
HANDLE hlib_error_reports_vista = NULL;
ADD_MER_EXCLUDED_APP_XP add_mer_excluded_app_xp = NULL;
ADD_MER_EXCLUDED_APP_VISTA add_mer_excluded_app_vista = NULL;
bool success = false;
// First, attempt the API that has been around since XP.
hlib_error_reports_xp = LoadLibrary(WZ_MER_DLL_XP);
if (hlib_error_reports_xp)
{
add_mer_excluded_app_xp = (ADD_MER_EXCLUDED_APP_XP)GetProcAddress(hlib_error_reports_xp, SZ_MER_PROC_XP);
if (add_mer_excluded_app_xp)
success = add_mer_excluded_app_xp(wz_app);
FreeLibrary(hlib_error_reports_xp);
hlib_error_reports_xp = NULL;
add_mer_excluded_app_xp = NULL;
if (success)
return true;
}
// That did not succeed. Attempt the Vista API.
hlib_error_reports_vista = LoadLibrary(WZ_MER_DLL_VISTA);
if (hlib_error_reports_vista)
{
add_mer_excluded_app_vista = (ADD_MER_EXCLUDED_APP_VISTA)GetProcAddress(hlib_error_reports_vista, SZ_MER_PROC_VISTA);
if (add_mer_excluded_app_vista)
{
success = (S_OK == add_mer_excluded_app_vista(wz_app, WER_EXCLUDE_FOR_ALL_USERS));
if (!success)
success = (S_OK == add_mer_excluded_app_vista(wz_app, WER_EXCLUDE_FOR_THIS_USER));
}
FreeLibrary(hlib_error_reports_vista);
hlib_error_reports_vista = NULL;
add_mer_excluded_app_vista = NULL;
if (success)
return true;
}
// Nothing worked. Fail.
return false;
}
To further curtail the execution of the WER components, imeplement an unhandled exception filter and pass it to: SetUnhandledExceptionFilter() function. To shunt WER, your filter must never return EXCEPTION_CONTINUE_SEARCH or EXCEPTION_EXECUTE_HANDLER.
One of the drawbacks of implementing the SetUnhandledExceptionFilter() function is that it interferes with Just-in-time debugging.
You mention you want the app to be "silently killed." In that case:
LONG WINAPI global_exception_filter(struct _EXCEPTION_POINTERS *exception_info)
{
ExitProcess(0xDEDD000D);
}
int WINAPI WinMain(
HINSTANCE _hinstance,
HINSTANCE hinstance_prev,
LPSTR sz_cmd_line,
int cmd_show
)
{
SetUnhandledExceptionFilter(global_exception_filter);
/* ... */
}
Will cause the application to immediately vanish upon unhandled exception. N.B., the exit code to return is a matter of taste.
Check out the answers on these questions:
How do I disable the ‘Debug / Close Application’ dialog on Windows Vista?
Hide Error Report window
I realize that others have answered with ways to work around this, but...
Let's not forget that the best way to protect against this is to write a program that doesn't crash. :-) You shouldn't be seeing this if you are using memory correctly and not hanging the GUI thread.
Altering the behavior of an application crash is a great way to introduce subtle and deadly bugs. See also this blog post from Microsoft's Raymond Chen.
Take a look at the Windows Error Reporting APIs.