How do you attach an icon resource to a Rust application? I've seen how it's done in C but I'm not clear on how it works in Rust. This would be on Windows. I know that Linux and OS X work differently. If anyone has any tips on this for OS X that would be great too.
Windows
An easy way to set the icon for your .exe file is with the winres crate. First, add winres as a build dependency in your Cargo.toml:
[target.'cfg(windows)'.build-dependencies]
winres = "0.1"
Then, add a build script (a file named build.rs next to your Cargo.toml):
use std::io;
#[cfg(windows)] use winres::WindowsResource;
fn main() -> io::Result<()> {
#[cfg(windows)] {
WindowsResource::new()
// This path can be absolute, or relative to your crate root.
.set_icon("assets/icon.ico")
.compile()?;
}
Ok(())
}
Note that this does not update the icon shown in the taskbar or title bar. Setting that must be done via your GUI framework, e.g. iced recently added a way to configure this.
macOS
To set the icon on macOS, you need to bundle the executable into an .app. An .app is actually a directory, not a file. It looks something like this:
My App.app
Contents
Info.plist — This XML file includes information about your app, including the name of the binary and the location of the icon file:
<key>CFBundleExecutable</key>
<string>myapp</string>
<key>CFBundleIconFile</key>
<string>AppIcon.icns</string>
MacOS
myapp — The binary from target/release
Resources
AppIcon.icns
macOS apps are typically distributed as .dmg files. A release script could build the binary, bundle it into an .app, and then bundle that into a .dmg, along with a symlink to /Applications to make it easier for the user to “install” the app by moving it there.
Here are sample .dmg contents, and the corresponding release script.
Rust has no notion of icon files for windows, so you would do it the same way as you do in C, albeit via the Rust foreign function interface (FFI). There exist FFI wrappers for windows APIs, notably winapi.
Here is an example that shows how to associate an icon with an executable (by way of an .rc file).
Related
I am trying to make a python module in rust. I am continuing to fail to get the files that I need to generate. I followed this tutorial almost exactly.
https://mycognosist.github.io/tutorial-rust-python-lib.html
Here is my toml file.
name = "pylib"
version = "0.1.0"
authors = ["Atops"]
edition = "2018"
[lib]
name = "status"
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies.cpython]
version = "0.5"
features = ["extension-module"]
Here is the code for lib.rs
extern crate cpython;
use cpython::{PyResult, Python, py_fn, py_module_initializer};
pub extern fn hello(_py: Python, val: String) -> PyResult<String> {
match &*val {
"hello" => Ok("world".to_string()),
_ => Ok("afdfs".to_string()),
}
}
py_module_initializer!(status, initstatus, Pyinit_status, |py, m|{
m.add(py, "__doc__", "asdhgdfs")?;
m.add(py, "hello", py_fn!(py, hello(val: String)))?;
Ok(())
});
I navigate to the appropriate folder with my cargo.toml file and use cargo build --release, as specified in the tutorial. It finishes with a few warnings about certain things being "not FFI-safe". When it finishes a new folder is created called "target". I go through there to where the files for the library should be, but the appropriate files don't seem to have been generated. I have these.
target\release
These don't seem to be usable for me. I am not sure what I have done wrong.
I copied every single one of these files to another folder and tried importing them in python. This did not work. I tried changing them to .so files, this did not work. It seems that windows is supposed to output a dll here, but the dll file did not work when attempting to import. It did not work as a dll file or a so file. I am not sure what to do here. Also, it seems that when these files are generated in every other tutorial or guide I see, there is a "lib" prefix on the name of each. I get no such prefix.
A dll file contains shared object code for COFF systems (like Windows) while a so file generally contains shared object code for ELF (and other) systems like Linux.
Renaming them will not work under any circumstance. If you have one and need the other, you need to rebuild them on the correct, matching, operating system.
I think you might be following instructions for Linux (due to the lib prefixes) on a Windows machine and then expecting some of the instructions to work. They might work, if you can identify all the "changes" between the platform and modify the Linux instructions to match the Windows platform; but until you know how to translate one environment's instructions to the other, it might be easier if you just find a set of Windows instructions that only refer to dll files and don't mention so files.
I gather there is no universal standard for putting version numbers into executables on Linux, in contrast to Windows which requires a certain structure for those details.
FreePascal has made its own standard and Delphi lets you define Version information for a Linux executable.
If we can put Version information in, we must be able to get it back out? How? Specifically on Linux64?
I have searched *.pas and *.inc in Studio\19.0\source\rtl\posix and I have not found anything on 'version' nor 'fileinfo' that could help.
Back with Kylix, I used to use argp_program_version from libc.
On a clean new DUnitX project, after adding {$ *.res} to the DPR so that the version information will stick, I can look at Project Options for Linux64 and I can see that they have a CFBundleVersion number defaulting to 1.0.0 for the project. How can I get the CFBundleVersion at runtime in my Linux64 executable?
Or, if that is not possible, could/should Delphi match the FreePascal standard and put the fileinfo into something which both Lazarus and Delphi could view at runtime??
This excerpt (metioned at both Windows and MacOS/iOS sections) from https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Version_Info may help:
Go to Tools > Options > IDE > Environment Variables and add a new User variable called SAVEVRC with Value=TRUE. This variable enables the generation of a .vrc file with an auto generated build number and other information.
another excerpt from there (not sure if related to the aforementioned SAVEVRC or not) is:
Note: If you define the VersionInfo resource and add it to the project via a $R directive in the project file, the compiler will ignore settings of Version Info at Project Options dialog box and use the custom resource data instead, given an application can have only one VersionInfo resource on Windows.
I am writing an extension for the Scratch text editor application on Elementary OS Luna. But the documentation is practically non-existent for extension creation and I have no idea how to proceed after writing my main code for the extension.
I've already written the extension. I cannot use or test it yet as it needs to be "installed". I spent hours looking for docs but they do not exist. I did however, find a comment on the scratch launchpad page that says
Generally you have to generate a pluginname.so file and put it in
lib/scratch/plugins/pluginname with a pluginname.plugin file
Great. This seems like the last part of creating an extension for Scratch. What is a .so file, and how do I generate one? I've already created the other necessary files like the .plugin file and the .vala file.
Yes, I have searched for .so files but all I found were random things about it like using it with C, or C++ headers but obviously that won't work for me, since I'm using Vala?
How do I generate a .so file? What do I generate it from?
I think the The Vala tutorial could be helpful on creating the actual Shared library or Shared Object.
You can use the autotools, cmake or you can compile and link a shared library directly from the command line, quoted from the Vala tutorial:
Compilation and linking using Command Line
Vala is not yet capable of directly creating dynamic or static
libraries. To create a library, proceed with the -c (compile only)
switch and link the object files with your favourite linker, i.e.
libtool or ar.
$ valac -c ...(source files)
$ ar cx ...(object files)
or by compiling the intermediate C code with gcc
$ valac -C ...(source files)
$ gcc -o my-best-library.so --shared -fPIC ...(compiled C code files)...
From the Scratch Wiki
Due to browser security restrictions, Scratch 2.0 cannot interact with
hardware devices directly. Instead, hardware extensions come with a
helper app, a separate application that the user must install and run
on their computer. Scratch communicates with the helper app via HTTP
requests, and the helper app talks to the hardware. In the future,
some extensions may package their helper apps as browser plugins.
Here are the steps for creating and testing a Scratch extension:
Create an extension description file
Create your helper app and start it
Open the Scratch 2 Offline Editor
Import the extension description (shift-click on "File" and select "Import Experimental Extension" from the menu)
The new extension blocks will appear in the More Blocks palette
Test your extension and iterate!
Helper apps can be written in any language that supports server sockets, such as Python, Node.js, Java, C, etc.
Like you I've chased around the wiki but I cannot find an example with source. So all I can do is to address your question generally.
If you look at Build .so file from .c file using gcc command line you'll see how a simple .so can be created. However what code goes into a Scratch extension I don't know. Sorry.
Edit: More googling and I've found a sample from Nathan Dinsmore on GitHub that doesn't use C rather it uses JavaScript, and though it doesn't create a .so extension, it does have what appears to be a full description of creating an extension. He also provides a couple of tutorials.
Edit++ : And here is another sample written in Java.
I have installed Qt designer 4.8.2, Pyside, and Python 3.3. When I create a form with Qt designer I am not able to see the code when clicking on view code. The error message is:"Unable to launch C:\Qt\4.8.2\bin\uic".
I have the pyuic under C:\Python33\Lib\site-packages\PyQt4\uic. Please help.
Just create a directory where it search for uic.exe file and copy existing uic.exe file to that directory.
My example :
When I clicked View Code it shows Error asking for file uic.exe in path
C:\python374\Lib\site-packages\pyqt5_tools\Qt\bin\bin
But I found uicexe file is in C:\python374\Lib\site-packages\pyqt5_tools\Qt\bin folder
So I created another bin folder and copied uic.exe into that folder . That solved my problem.
If you were looking to generate python code, you would do this from the console. So, if you saved your file from the program as 'untitled', the default, run this:
pyuic5 -m untitled.ui -o untitled.py
Making sure your working directory is the file location of 'untitled.ui'. It will then spit untitled.py into the same place.
Create a folder called bin inside the folder and move the exe inside uic.exe. It shows the code when click the view code from the QT designer.
Although you can certainly use Qt Designer for creating UIs for PySide/PyQt, you should be aware that it is primarily a C++ tool - it doesn't have any built in support for Python. So the "View Code..." command you refer to only produces C++ code - which is probably not much use to you if you intend using PySide or PyQt.
Qt Designer UI files are in an XML format (they usually have a .ui extension).
To use them with Python, there are basically two options:
Load the .ui files directly into your application.
Convert the .ui files into Python modules using an external tool.
There are several differences between PySide and PyQt in how these two options are implemented.
For PyQt, the full documention for both options can be found here.
For PySide, the documentation for option 1 can be found here - but it does not look like there is any documentation for option 2. However, the external tool for PySide (which is called pyside-uic) works very similarly to the one for PyQt (which is called called pyuic4).
If you need more general information about how to get started using Qt with Python, try the PySide Wiki or the PyQt Wiki.
To make
Form -> View code
work, directly from Qt Designer using either Qt4 or Qt5, you can just create a symbolic link from where Qt Designer is looking, pointing to where your pyuic5.exe executable is. With your example, it would be:
mklink /H "C:\Qt\4.8.2\bin\uic.exe" "C:\Python33\Lib\site-packages\PyQt4\pyuic4.exe"
Which is:
mklink /H "Path\to\uic.exe\file\Qt\designer\is\looking\for" "Path\to\actual\location\of\pyuic4.exe\or\pyuic5.exe\file"
Make sure the folder where "C:\Qt\4.8.2\bin\uic.exe" will reside exists obviously.
For Linux computers
If anyone still stuck with this problem and you are using Linux.
You can find the required uic file in venv-path/python3.x/site-packages/PySide2/uic
Copy this file, and create a new folder bin inside the Qt folder.venv-path/python3.x/site-packages/PySide2/Qt/bin
now place the uic file there, such that, the final uic path is:
venv-path/python3.x/site-packages/PySide2/Qt/bin/uic
Note::
venv-path is the path to you python virtual-environment.
3.x is the appropriate version of the Python in the virtual-environment. (In my case it's 3.8)
Final Result:
python -c "import os; import PySide6; src = PySide6.__path__[0]; dst = src + '/bin'; os.mkdir(dst) if not os.path.exists(dst) else None; os.symlink(src + '/uic.exe', dst + '/uic.exe')"
I had the same error\warning message on Windows with pyside6-designer, I just run the above line as administrator and everything now works as expected (The line, simply creates a link of the uic.exe inside a bin-folder under the Pyside6 module's folder).
This question already has answers here:
Is there a Linux equivalent of Windows' "resource files"?
(2 answers)
Closed 4 years ago.
I'm looking for a way to embed text files in my binaries (like windows resource system). I need something thats also platform independent (works in windows and linux). I found Qt resource management to be what I need but I'm not keen on my app depending on Qt for this alone. I also found this tool at http://www.taniwha.com/~paul/res/ .. but it is too platform specific.
The xxd utility can be used to create a C source file, containing your binary blobs as an array (with the -i command line option). You can compile that to an object which is linked into your executable.
xxd should be portable to most platforms.
If you're using QT 4.5, you can make sure that program is only dependent on one small piece of QT, such as libqtcore. QResource is a part of libqtcore.
You can simlpy append all kinds of data to your normal binary. Works in both Windows and Linux. You'll have to open your own binary at runtime and read the data from there.
However, I have to agree that embedding data in binaries is a strange idea. It's common practice to include such data as separate files packaged with the application.
That is not such a great idea. On Linux, for example, data is expected to be installed in a subdirectory of "$datadir" which is, by default, defined to be "$prefix/share", where "$prefix" is the installation prefix. On Mac OS X, resources are expected to be installed in $appbundle/Contents/Resources, where $appbundle is the name of the folder ending in ".app". On Windows, installing data in a folder that is a sibling of the executable is not an uncommon practice. You may be better off using the CMake build system, and using its CPack packaging features for installing/bundling in the default, preferred platform-specific manner.
Although bundling your resources into the executable, itself, may seem cool, it is actually a dangerous idea... for example, will the embedded data be allocated in an executable page? What will happen if you attempt to overwrite or modify the data? What if you want to tweak or modify the data at runtime? Things to think about.
This looks very promising: https://github.com/cyrilcode/embed-resource
CMake based and platform-independent.
As I also do not like the idea of converting files into C arrays only to have them converted back to binaries, I created my own resource compiler using LLVM and Clang:
https://github.com/nohajc/resman
I tested it on Windows, Linux and macOS but it can potentially be run on any platform supported by LLVM.
It is used like this:
Create header file, e.g. res_list.h
#pragma once
#include "resman.h"
// Define a global variable for each file
// It will be used to refer to the resource
constexpr resman::Resource<1> gRes1("resource_file1.jpg"); // resource with ID 1
constexpr resman::Resource<2> gRes2("resource_file2.txt"); // resource with ID 2
constexpr resman::Resource<3> gRes3("resource_file3.mp3"); // resource with ID 3
...
Run resource compiler
$ rescomp res_list.h -o res_bundle.o
Link res_bundle.o to your project
Use the resource files
#include "res_list.h"
...
resman::ResourceHandle handle{gRes1};
// ResourceHandle provides convenient interface to do things like:
// iterate over bytes
for (char c : handle) { ... }
// convert bytes to string
std::string str{handle.begin(), handle.end()};
// query size and id
unsigned size = handle.size();
unsigned id = handle.id();
The resource compiler parses res_list.h (using Clang) but instead of generating cpp files, it goes straight to the native object file (or static library) format (using LLVM).