How to set the build area for rpmbuild per-invocation - build-process

I'm modifying an automated build, and want to tell rpmbuild to use a specific build area when invoking it.
This is similar to an existing question, but more specific.
I don't want to run any of the build commands as the root user; the aim is only to have an RPM, not to install anything into the system.
I don't want to require the user to change their dotfiles (e.g. $HOME/.rpmrc); the build should be self-contained and not affect the user's existing settings.
I don't want to hard-code the location into the foo.spec file; that file should be useable as-is if the user wants to build in a different location.
The --buildroot option is not what I need; that sets a pseudo-root filesystem for the make part of the build process, but I need to specify the “build area” for the entire RPM build process.
What I'm looking for is a hypothetical --build-area FOODIR option that can be given to the rpmbuild command, or an equivalent environment variable. It should thus affect just that single invocation of the command and cause it to use a specified user-writable location for its build area.
I've seen references to a _topdir macro that seems to be what I'm talking about, but it doesn't appear to be configurable per invocation.
It would be ideal if rpmbuild could set up its own environment in that location when it needs it, but I don't mind setting up the directories for that per build, since that can be automated as part of the build. The goal is to have that user-writable location exist only for the duration of the build run, and then clean up by deleting that entire location once the RPM file is generated.

It's not documented, but the _topdir macro determines the build area.
So you can set this per-invocation with rpmbuild --define "_topdir ${PWD}/foobar" ... to set the directory to whatever you want.
--define is the key to setting values for any macro, not just _topdir.

The --buildroot option is not what you are looking for. The name is a bit misleading as it is not changing the buildroot but instead is setting the root for the install phase of the build. RPM is basically doing a "make install" as part of the build and is then packing the results of this. The buildroot option allows you to do this install into for example /tmp/myinstallroot.
I recently had to integrate rpm package building into an automated build and had the same problem. What i did was to generate a custom .rpmmacros file with %topdir set appropriately. I then just temporarily changes HOME to the location of that custom .rpmmacros file.
"HOME=mytopdir rpmbuild ...".

Related

Different local and remote organisation R Project and GitHub

I want to version control my R scripts so I've created an R project and a GitHub repo. My scripts are scattered through several directories within the same directory where the R project is.
I would like that my GitHub repository harbors only the scripts, independently of the folders they are locally stored in. However when I run the below command:
git add folder/file.R
git commit -m "my_message"
git push -u origin master
A directory named folder is created containing file.R but I'd like to just see file.R without the folder. Do you know how can I do this? Also, would it be good practice? My local folders are organized so each directory contains its own scripts and results, that's the reason the scripts are separated.
Thank you very much
is there a way to add the file.R without specifying the path?
Not using git add, no. The design constraint for git add is that it should store the file's name exactly as it appears, including the forward slashes, so if the file's name is folder/file.R, that's the file's name.
You have some options here though:
You can make a parallel directory where you put the files with the names you want them to have. Run git init in that directory, copy the folder/file.R file to file.R in that directory. Then cd ../gitdir or whatever is appropriate to get there, and git add file.R.
This method is probably the best because it's the simplest.
You can write your own programs using git hash-file -w and git update-index, which are two of Git's plumbing commands. A plumbing command, in Git, is basically a command that exists so that you can build user-facing commands: they're not meant to be run by humans but rather by other programs. So you write a program (in whatever language you like) that uses these plumbing programs to achieve whatever you want.
In particular, you can create or find a Git blob object holding the contents of file.R as read from anywhere you like, then use git update-index to create an index entry holding whatever path you like and referring to the blob object you created (or found) with git hash-object with the -w flag.
Since Git is a suite of tools, not a solution, you can come up with your own method. The tools in Git are made with particular approaches in mind, but they are flexible enough to be repurposed.

How to build a rpm that installs host dependent files

I have to build one rpm that copies the contents of file A to /path/to/tartetfile if the hostname is A. In all other cases the contents of B should be copied to /path/to/targetfile. I'm aware that this may be a misusage of rpm, but I still have to do it like this. Do you have any ideas how to get this done in an elegant way?
My solution at the moment would be to create an empty /path/to/targetfile in my BUILD directory as well as a /tmp/contents.tar.gz that contains the files A and B. In the postinstall routine i then would extract the relevant parts of /tmp/contents.tar.gz to /path/to/targetfile and delete the tarball afterwards. In the pre-uninstall routine I'd then touch the /tmp/contents.tar.gz to supress rpm reporting errors for an already deleted file.
To me this seems to be a very dirty way to get this done. Do you have better ones?
If you plan on abusing rpm for things it was not desinged for, you'll have to do dirty tricks.
I don't see another workaround for you. I fail to see the use of removing the tar.gz etc, unless that (little?) extra space is really a problem for you. I would propose:
package all files (A and B) into some specific directory (/usr/lib/your-package or whatever), not in compressed format.
in the %post section create just symlinks so that /path/to/targetfile points to /usr/lib/your-package/A or /usr/lib/your-package/B (symlinks take up almost no space). This has the additional value that ls -l /path/to/targetfile will show you which which file it points to, giving you the information whether this is file A or B.
in your %files section declare %ghost /path/to/targetfile for a nice cleanup upon removal.

dotnet publish output folder?

The dotnet publish command published into the projects bin/netcoreapp2.2/Debug/publish folder. Where netcoreapp2.2 presumably changes with the dotnet version and Debug changes with whatever configuration the -c parameter specifies.
For CI/CD purposes this is clearly undesirable. Alternatively one can pass -o to pass an explicit output path, but again, in a CI/CI environment this path should be inside the project folder structure, e.g. something like:
dotnet publish -o publish
But, because the publish command globs up all files, it picks up previous publish attempts and recursively stores them. This can be mitigated by either cleaning the publish folder explicitly, and/or adding a to the csproj for the project but now there is a dependency between the build script and the csproj: if the publish path is changed in the build scripts for any reason without a corresponding csproj update things break.
So, the least fragile option seems to be to use the default output path as thats automatically excluded from globbing, but how to remove the version & configuration sensitivity? Is there a particularly safe way to get dotnet to tell my CI/CD environment what its output path for build / publish is?
IMP: I do not have enough so reputation to add comment
refer : dotnet publish
you could use relative path with -o option and you may end up avoiding folder name with run-time, platform identification explicitly.
or why do not you consider using build command with publish profile where you can specify explicit path. but generally relative path is less error prone.
Hope this may help you !

How to make use of the INSTALL_ROOT that resides in generated Makefiles?

qmake generates the following (among the others) rule for installing a target:
-$(INSTALL_PROGRAM) "$(TARGET)" "$(INSTALL_ROOT)/$(TARGET)"
I cannot set INSTALL_ROOT with something like this in a *.pro file
isEmpty(INSTALL_ROOT) {
INSTALL_ROOT=/usr
}
because INSTALL_ROOT is somehow local to generated Makefiles. According to what I've found out so far INSTALL_ROOT is empty by default. It could be used like
INSTALL_ROOT=$HOME make install
when invoking make, which is fine. However I want to be able to specify default installation root, say /usr. I can do it introducing a new variable PREFIX as suggested here.
Then generated rule will look like (if PREFIX was set to /usr)
-$(INSTALL_PROGRAM) "$(TARGET)" "$(INSTALL_ROOT)/usr/$(TARGET)"
however
INSTALL_ROOT=$HOME make install
installs target to /home/<user_name>/usr/$(TARGET) which is not that one would expect.
So setting INSTALL_ROOT to some default value will produce consistent behavior, which is superior to adding PREFIX, but how to set INSTALL_ROOT in a *.pro file?
What is the purpose of INSTALL_ROOT is it supposed to be used at all?
INSTALL_ROOT is for use with package building systems, like NSIS, debian, or any other way for parcelling up built software and delivering it.
For this purpose you want the result of
INSTALL_ROOT=$PWD/package_root make install
to create a tree under $PWD/package_root that exactly mimics that on your target system you plan to deliver to. Note that you need INSTALL_ROOT to be a full path (hence the $PWD), not a relative path.
When you create your package you can compress that tree into an archive and then your installation process simply uncompresses the same tree on to the target file-system.
$PWD/package_root/usr/bin/my_binary
would get installed to
/usr/bin/my_binary
on the target.
So that is the answer to the question what INSTALL_ROOT is for. To answer how to specify "default installation root" requires more information about what you want to achieve.
Have a look at the output of qmake -query:
sez#ubuntu-11.10:~$ qmake -query
QT_INSTALL_PREFIX:/usr
QT_INSTALL_DATA:/usr/share/qt4
QT_INSTALL_DOCS:/usr/share/qt4/doc
QT_INSTALL_HEADERS:/usr/include/qt4
QT_INSTALL_LIBS:/usr/lib/i386-linux-gnu
QT_INSTALL_BINS:/usr/bin
<snipped>
QT_VERSION:4.7.4
and the use of the INSTALLS variable in qmake: http://doc.qt.digia.com/qt/qmake-environment-reference.html#installs - and How do I specify input the QMake INSTALLS variable?
By default if you just do
target.path = $$[QT_INSTALL_BINS]
INSTALLS += target
Then your binary will get installed in whatever qt thinks is the right place, QT_INSTALL_BINS. You can change those defaults of course by setting target.path to something else. Qt supplies those paths but its up to you to use them or not.
You could do
MY_DEFAULT_INSTALL=/opt/myproj
somedocs.files = docs/index.html
somedocs.path = $$MY_DEFAULT_INSTALL/docs
target.path = $$MY_DEFAULT_INSTALL/bin
INSTALLS += somedocs target
for example, where MY_DEFAULT_INSTALL is the one place in your .pro file that defines the default for installs.
I'm answering for Windows here. You appear to be using UNIX, Linux, or Mac OS X so you may have to make a few changes.
INSTALL_ROOT is a poorly documented feature that appears to have been added so that those without root or admin access can install Qt in their local filesystem. It's actually a bit of a hack since, as you have already seen, it is not possible to specify an arbitrary target, but you can always move the files to the desired location afterwards.

Directory for files generated by Make during installation from configure, make and make install

Just assume we are installing some libraries from its source distributed by the way GNU promoted. When using "./configure --prefix" to specify where to install.
(1) does Make generate the binaries under the current directory? Does Make install then copies them from the current directory (which is from where Make is run) to $prefix? If the answers are yes, I have two questions, each for different cases.
(2) when the current directory and $prefix are not the same, can I remove all the files generated by Make under current directories to save some space?
(3) when the current directory and $prefix are the same, will make install do nothing or copy the files to themselves? Can I just skip the make install step?
The answer to your first question is probably yes.
As for the rest, you may find a make clean which will tidy up the files created by the initial make.
I think the makefile will be able to handle the situation where current directory and $prefix are not the same, and do the right thing.
The current directory would not usually be the destination of files created by makefiles.
(of course it depends on how the makefile is written, so I can't give definite answers, but I've generally been impressed with the makefiles I've used)
You are absolutely right: make just creates files in current directory and make install copies it to the destination directories, based on $prefix and other variables maintained by configure script.
You can wipe out the whole directory you've ran the build at. It will not be used, because, well, that's what "install" means: you build in one directory and the the files are placed in the proper places of your system.
Usually install destination and the directory you build in differ. The hierarchy of the files being installed usually do not relate to directory hierarchy of the build system. Just install to the other dir: it's cheap to create just yet another directory.

Resources