bzr: Ignore attributes when committing / pulling - attributes

I have one system with msys2, and another system with Ubuntu.
Files in Unix have the executable attribute.
Files in msys2 (NTFS based) do not have the executable attribute (although msys2 "fakes" it by looking for the shebang in the first line of each file, at least for ls).
When exchanging files with bzr (via commit, e.g.), I would like bzr to ignore the executable attribute as a parameter for determining what to commit. Otherwise, when committing from my msys2 system I would mess the repository.
Is this possible?
EDIT:
Actually, msys2 does not have other attributes as well, so I would like to ignore all that differs from Unix.

On Windows, Bazaar ignores the executable bit based on the sys.platform variable. However, apparently that's not set to win32 on msys2 but to msys2. You can manually fix this in Bazaar by changing the supports_executable() function in bzrlib/osutils.py from:
return sys.platform != "win32"
to
return sys.platform not in ("win32", "msys", "msys2")
Newer versions of Breezy, the successor to Bazaar, address this by not reading the executable bit from the filesystem if the filesystem (e.g. FAT, NTFS, etc) does not support executable bits rather than checking sys.platform.

Related

Who handles the paths in Cygwin

I am curious to find out who handles the paths in cygwin.
For instance if I do the following, it works:
cd C:\
However when I do:
$ pwd
/cygdrive/c
Who is responsible for the discrepancy here?
The reason I am curious is that "cd C:" among'st other tools accept windows paths but when it comes to displaying them they show something different.
If I do include the cygwin bin folder in my path (under regular cmd) then I know it all works as in cmd, so what is it thats causing this convertion, is it the bash/shell?
I am curious to find out who handles the paths in cygwin.
Largely, a small bit of C++ code in winsup/cygwin/path.cc. A particularly important function is normalize_posix_path. This code ends up compiled in the DLL cygwin1.dll which is used by all Cygwin applications.
All paths in Cygwin are "POSIX" paths resolved by the Cygwin DLL itself. The normalize_posix_path function recognizes the presence of certain syntax in paths (drive letter names and backslashes), and arranges for them to be treated as "Win32 paths".
That is the reason why you can feed c:/Users/... to a Cygwin program, as an alternative to /cygdrive/c/Users/....
$ pwd
/cygdrive/c
How this works is that Cygwin maintains a native Win32 current working directory, and so it knows perfectly well that this is C:\. However, this native information is mapped backwards to a POSIX path. Cygwin does this by scanning through its mount table where it sees that C:\ is "mounted" as /cygdrive/c. (The pwd utility is just reporting what Cygwin's implementation of the POSIX getcwd function is returning. The backwards mapping happens inside that function). Note that since Cygwin is operating in a virtual POSIX namespace created by its mount table, that space contains abstract places which have no Win32 native counterpart. For instance, you can cd to the /dev directory where you have entries like tty. This has no native location, and so getcwd will just report the POSIX path. Cygwin tries to keep the Cygwin-internal current working directory in sync with the Win32 one when there is a corespondence; it does so without using the SetCurrentDirectory Win32 function, and without maintaining the concept that Windows drives have individual current working directories.
If I do include the cygwin bin folder in my path (under regular cmd) then I know it all works as in cmd, so what is it thats causing this convertion, is it the bash/shell?
Actually, it does not all work as in cmd! Though Cygwin programs understand "Win32-ish" paths, the support is not complete. You can pass a path like D:file.txt to a truly native Windows program. It resolves via the current directory associated with the D drive, which could be D:\bob\documents, in which case the path stands for D:\bob\documents\file.txt. If there is no such directory then it stands for D:\file.txt. A Cygwin program will not understand this drive-relative path. In fact, D:file.txt won't even be recognized as a drive-letter reference (as of Cygwin 2.5.2). This is because the colon is not followed by a directory separator character (backslash or slash).

How do I deploy Qt libraries with an application?

This should be really simple, but I'm having trouble. I want to include some shared Qt libraries with my application in the installation folder so the user doesn't have to download Qt separately. On Windows, this seemed to work fine, but Ubuntu complains about not being to find the Qt libraries when they are in the same folder as the application.
How do I add the installation directory to shared library search path?
I was able to add the installation directory to shared library search path by adding the following lines to the .pro file, which set the rpath of the binary to $ORIGIN (the install folder). I needed to add the location of QT libs on my current machine (/usr/lib/qt5.5 and /usr/lib/qt5.5/lib) so that the project would build in QtCreator.
unix:!macx {
# suppress the default RPATH if you wish
QMAKE_LFLAGS_RPATH=
# add your own with quoting gyrations to make sure $ORIGIN gets to the command line unexpanded
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\':/usr/lib/qt5.5:/usr/lib/qt5.5/lib"
}
(The unix:!macx line makes it apply to linux only)
Windows, Linux and OSX behave quite differently. Windows is easiest: dump all the dll's in the application dir. OSX is next and Linux is most difficult.
Linux has certain search paths for searching shared objects. These search paths are mainly system libraries and possibly some user libraries. As you do not want to mess around with system files of your user one would prefer to have the shared objects in the application dir. This is possible but you have to tell Linux to read that directory. You can do this with setting the environment variable LD_LIBRARY_PATH. You can do this with a script. See my answer.

Moving a compiled Haskell program

I want to compile a Haskell program on one Linux box, and then run it on another Linux box. However, this doesn't seem to work at all. I get errors about missing libraries.
Presumably when I install GHC, the package manager also installs all the libraries and stuff that it needs. [I note with some irritation that at least one packaging system fails to install GCC, which GHC apparently can't function without...] But of course, the target system does not have these dependencies installed. So if I copy the compiled binary to the target system, it just fails to run.
Is there some way around this problem? I'm used to working with Windows, where if you compile something, it just works on all Windows systems. (At least, it does until you actually try to use non-standard facilities like database access or something...) I compiled Hello World in Haskell, copied it to another Linux box, and it complained about libgmp.so.10 missing or some cryptic mumbo-jumbo like that.
Just to make things interesting: I only have FTP access to the target machine, not shell access. I'm not even completely sure what OS it's running. So I can change my build machine any way I want, but I can't do anything to the target machine other than copy files to it.
Linux behaves just like Windows in this regard. If you compile a Haskell executable on Linux, it will run on any Linux distribution with the right libraries. The problem is that in Windows, the Haskell executables aren't compiled with a dynamic version of libgmp; they are compiled with a static version (so that the library is compiled into the executable) exactly because it can be so difficult to handle dlls on Windows when distributing executables. It is comparably easy to handle the installation of new libraries on Linux.
What you can do is to copy the libgmp.so.10 (which might be a symbolic link to a different file) out of /usr/lib into the same directory as your executable. You can then set the LD_LIBRARY_PATH environment variable to ".", meaning the current directory, before launching your executable. This will make Linux look for libraries in the same directory as executables that it launches, making it find the library. This can be done with a launcher script:
#!/bin/sh
export LD_LIBRARY_PATH=.
`dirname "$0"`/myexecutable "$#"
Saving this script and marking it as executable with chmod +x myscript will make your executable work.
You can use the ldd command to check what other libraries your executable might need and that aren't on the target system.
If you wish to move executable between machines, you have to link in statically, making single executable without external library dependencies. How to do it depends on compiler, and ghc has -static flag, that 'links static version of haskell libraries'.
btw, check, that you do not try to run 64-bit executable on 32 bit machine. 32-bit executable on 64 bit machine should work in most cases, but... well, it depends on configuration of target box, so check that this is not the case as well.

Why are Cygwin import libraries installed with mode 755?

I have a library that I originally developed for Linux. I am now in the process of porting it to Cygwin. I have noticed that every library on my Cygwin system is installed like this:
DLL (cygfoo.dll) installed to /usr/bin mode 755
Static archive (libfoo.a) installed to /usr/lib mode 644
Import library (libfoo.dll.a) installed to /usr/lib mode 755
The first two make perfect sense to me. DLLs are executables so they should be mode 755. Static archives are not executables, so they are mode 644. The third one, however, seems odd to me. Import libraries are in fact static archives, not executables (ar -t libfoo.dll.a lists the contents of the archive). Shouldn't they also be installed mode 644?
Why is it the convention on Cygwin to install import libraries with mode 755?
Back to 2000:
On NTFS partitions, NT/W2K require the execute permission for DLLs to
allow loading a DLL on process startup.
That's no problem unless a person using ntsec gets a tar archive
packed by a person not using ntsec or packing on a FAT partition.
Since Cygwin fakes the execute permission only for the suffixes "exe",
"bat", "com", DLLs are treated as non executable by the stat() call
when ntsec isn't set.
When a person using ntsec unpacks that tar archive, the start of an
application which requires one of the DLLs from the archive will fail
with the Windows message
"The application failed to initialize properly (0xc0000022)"
which isn't that meaningful for most of the users.
To solve that problem we would have to do a simple step. Fake execute
permissions for DLLs when ntsec isn't set or the file system doesn't
support ACLs (FAT/FAT32).
Here: http://cygwin.com/ml/cygwin-developers/2000-10/msg00044.html
The only answer that occurs to me is that the installer is looking for the ".dll" string in the filename to activate the executable attribute (x) of the copied files... should been looking for /.+\.dll$/ (.dll only at the end).
It is understandable that the impedance mismatch between OS's/filesystems force the installer/copier to have a strategy to decide attribute values at the installer operation (it is easier than have to map a attribute list to the copied file... and in windows only have to look for .exe, .com and .dll)
To confirm this rename your "libfoo.dll.a" to "libfoo.dxx.a" and test it...
This is a Windows requirement: since the .dll file contains code that will be executed, it requires the executable bit to be set.
Remove permission to execute the file, and Windows won't let any of the code inside it be executed, even if the process doing the executing is separate.
Side note: it's a common misconception that there's no +x bit for Windows. That's technically true; Windows doesn't use POSIX rwx permissions, although Cygwin does try to provide an interface that resembles them. Windows does use ACLs (Access Control Lists) for permissions, however, and these do have a concept of "execute permissions", which is what Cygwin maps down to its +x bit.
There's a long discussion on the Cygwin mailing list about this, if you want sources/further reading.
Seems it's just a lazy hack resulting in this behavior for filenames containing ".dll". See hasanyasin's answer for the reasoning behind the "fix" (here).

What's the accepted method for deploying a linux application that relies on shared libraries?

I have an application that relies on Qt, GDCM, and VTK, with the main build environment being Qt. All of these libraries are cross-platform and compile on Windows, Mac, and Linux. I need to deploy the application to Linux after deploying on Windows. The versions of vtk and gdcm I'm using are trunk versions from git (about a month old), more recent than what I can get apt-get on Ubuntu 11.04, which is my current (and only) Linux deployment target.
What is the accepted method for deploying an application that relies on these kinds of libraries?
Should I be statically linking here, to avoid LD_LIBRARY_PATH? I see conflicting reports on LD_LIBRARY_PATH; tutorials like this one suggest that it's the 'right way' to modify the library path to use shared libraries through system reboots. Others suggest that I should never set LD_LIBRARY_PATH. In the default version of GDCM, the installation already puts libraries into the /usr/local/lib directory, so those libraries get seen when I run ldd <my program>. VTK, on the other hand, puts its libraries into /usr/local/lib/vtk-5.9, which is not part of the LD_LIBRARY_PATH on most user's machines, and so is not found unless some change is made to the system. Copying the VTK files into '/usr/local/lib' does not allow 'ldd' to see the files.
So, how can I make my application see VTK to use the libraries?
On windows, deploying the dlls is very straightforward, because I can just include them in the installer, and the application finds them because they are in the local directory. That approach does not work in Linux, so I was going to have the users install Qt, GDCM, and VTK from whatever appropriate source and use the default locations, and then have the application point to those default locations. However, since VTK is putting things into a non-standard location, should I also expect users to modify LD_LIBRARY_PATH? Should I include the specific versions of the libraries that I want and then figure out how to make the executable look in the local directory for those libraries and ignore the ones it finds in the library path?
Every "serious" commercial application I have ever seen uses LD_LIBRARY_PATH. They invariably include a shell script that looks something like this:
#!/bin/sh
here="${0%/*}" # or you can use `dirname "$0"`
LD_LIBRARY_PATH="$here"/lib:"$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH
exec "$0".bin "$#"
They name this script something like .wrapper and create a directory tree that looks like this:
.wrapper
lib/ (directory full of .so files)
app1 -> .wrapper (symlink)
app1.bin (executable)
app2 -> .wrapper (symlink)
app2.bin (executable)
Now you can copy this whole tree to wherever you want, and you can run "/path/to/tree/app1" or "/path/to/tree/app2 --with --some --arguments" and it will work. So will putting /path/to/tree in your PATH.
Incidentally, this is also how Firefox and Chrome do it, more or less.
Whoever told you not to use LD_LIBRARY_PATH is full of it, IMHO.
Which system libraries you want to put in lib depends on which Linux versions you want to officially support.
Do not even think about static linking. The glibc developers do not like it, they do not care about supporting it, and they somehow manage to break it a little harder with every release.
Good luck.
In general, you're best off depending on the 'normal' versions of the libraries for whatever distribution you're targetting (and saying you don't support dists that don't support recent enough versions of the lib), but if you REALLY need to depend on a bleeding edge version of some shared lib, you can link your app with -Wl,-rpath,'$ORIGIN' and then install a copy of the exact version you want in the same directory as your executable.
Note that if you use make, you'll need $$ in the makefile to get a single $ into the argument that is actually sent to the linker. The single qutoes are needed so the shell doesn't munge things...
Well, there are two options for deploying Linux application.
The correct way:
make a package for your app and for the libraries, if they are so special, that they can't be installed from standard repositories
There are two major package formats. RPM and DEB.
The easy way:
make a self-extract file that will install the "windows way" into /opt.
You can have libraries in the same directory as the executable, it's just not the preferred way.

Resources