Is it possible to execute a command as a super user while using cmake? - cmake

I'm working on a project that uses the proxygen library by facebook.
The latter builds itself by means of a script called deps.sh which uses to invoke apt-get as a super user.
I've successfully created a custom target with cmake using the add_custom_target directive, but it fails because of the above call with the error sudo: no tty present and no askpass program specified and it makes sense, of course.
Anyway I've not been able to find a way of executing that script, thus invoking a command as a super user, using the add_custom_target.
I can safely install the library and write a FindProxygen module for my colleagues, so that the build process remains coherent, but I'd like to know if there is a clean solution to the problem of launching a command as root from cmake and thus put the library as a submodule of the project.

You can run installation script in new terminal, so sudo, executed by this script, will work as usual.
COMMAND x-terminal-emulator -e "<...>/deps.sh"
(This may be written as part of add_custom_target, add_custom_command, execute_process, etc.)

add_custom_target(
apt-downloads ALL
COMMAND sudo apt install -y ${DEPENDENCY_LIBRARIES}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "download required dependencies straight from apt on ubuntu"
)
Worked for me

The response is pretty simple: no.
As remarked in the comments, cmake expects to find all the required libraries already installed in the system (or at least, within the search paths) and any other solution would stop the execution and wait for user inputs.
As far as I've seen around, the usual approach, the one I've used too in the above mentioned project and in another one started immediately after, is to create a script that is in charge to download, compile and prepare the project environment, the same way proxygen itself does.
The final user will be asked to firstly executes that script, thus he will be able to proceed using cmake.
That's all, thank you for the comments.

Related

Modify install prefix from meson script

I need to modify install prefix option in meson build script...
My idea is, when the user select some special option, the install prefix is getting from external tool (specifically, using ${CORSS}gcc -print-sysroot)
It's not possible to set prefix inside the meson build script itself, it's a built-in project option (check this), thus can be only set in command line:
meson --prefix `${CROSS}gcc --print-sysroot` builddir
It shouldn't be a problem as it should done once to setup build directory. But anyway it's good idea to put this in some script (since most likely several options must be configured to setup project from scratch, e.g. I guess you need also setup cross-compilation file with --cross-file <> ).
If you really need fine control over where to install, there is argument install_dir for executable() command that allows to override prefix, and a number of install related commands: install_headers(), install_data() with the same capability. There is even possibility to add custom install script with
meson.add_install_script('myscript.sh')
Check this doc page for details. But the cons of this, however, is that script can be become not portable or hard to maintain.
You can change the prefix in the meson.build by using the default_options of the project() command (https://mesonbuild.com/Reference-manual.html#project).
For example:
project('myproj', 'c', default_options : 'prefix=/my/prefix')
Note that it would be applied only the first time you configure the Meson build directory.

Including NSIS script in CMake

Is it possible to include an NSIS script from CMake that uses CPack together with NSIS? It appears that I'm limited to only a few commands (doc), but some commands suggest that there is a way to include the whole NSIS script, particulary:
CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS,
CPACK_NSIS_EXTRA_INSTALL_COMMANDS,
CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
However, when I try to call these commands:
SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "!include extra_preinstall.nsh")
Nothing happens. (Excluding /NONFATAL throws an error, so presumably the script cannot be found.)
Checking basic functionality:
SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "MessageBox MB_OK \\\"Hello world!\\\"")
Doesn't do anything with the installer.
Why doesn't a Hello World button appear? Why is the script file not found (even though I put it on every level of CMake hiearchy)?
Preinstall doesn't mean that it's executed before the install section, so you actually have to click "install", then the command is executed.
The same goes for Install and Uninstall.
As for including external scripts: including with absolute path solves everything. If absolute path is not available, it can be easily obtained using CMake tools.

CMake Fails until you remove CMake Cache

I have a project that I am managing using CMake and I have run into some very strange behavior that I don't understand. If I clear out my build directory, run cmake, run make, then run my program my program crashes every time because I fail an assertion somewhere in pthreads/boost threads. No matter how many times I make, and make clean this project it crashes every time I run it. However, if I then remove CMaketCache.txt, regenerate my makefiles, build and run, the program runs as expected every time.
In summary I need to follow the following steps for my code to work...
Run Cmake
Run Make
rm CMakeCache.txt
Run Make
Run program
It appears that the Make files before and after I remove CMakeCache.txt differ. What could explain this behavior?
Do you have git installed? If so, you can use this trick:
Run cmake
make
git add .
git commit -m ""
rm CMakeCache.txt
run make
git diff
Some odd things I can see in what you are saying. I don't see why your program would recompile anything just because you removed the CMakeCache.txt. Everything should be up-to-date from the first make, so something is bad there... My guess is that it is finding a different thread library or no thread library the second time.

How to compile a linux shell script to be a standalone executable *binary* (i.e. not just e.g. chmod 755)?

I'm looking for a free open source tool-set that will compile various "classic" scripting languages, e.g. Korn Shell, ksh, csh, bash etc. as an executable -- and if the script calls other programs or executables, for them to be included in the single executable.
Reasons:
To obfuscate the code for delivery to a customer so as not to reveal our Intellectual Property - for delivery onto a customer's own machine/systems for which I have no control over what permissions I can set regarding access, so the program file has to be binary whereby the workings cannot be easily seen by viewing in a text editor or hexdump viewer.
To make a single, simply deployed program for the customer without/or a minimal amount of any external dependencies.
I would prefer something simple without the need for package manager since:
I can't rely on the customer's knowledge to carry out (un) packaging instructions and
I can't rely on the policies governing their machines regarding installing packages (and indeed from third parties).
The simplest preferred approach is to be able to compile to proper machine code a single executable that will run out of the box without any dependencies.
The solution that fully meets my needs would be SHC - a free tool, or CCsh a commercial tool. Both compile shell scripts to C, which then can be compiled using a C compiler.
Links about SHC:
https://github.com/neurobin/shc
http://www.datsi.fi.upm.es/~frosal/
http://www.downloadplex.com/Linux/System-Utilities/Shell-Tools/Download-shc_70414.html
Links about CCsh:
http://www.comeaucomputing.com/faqs/ccshlit.html
You could use this: http://megastep.org/makeself/
This generates a shell script that auto-extracts a bundled tar.gz archive into the temporary directory, and then can run an arbitrary command upon extraction.
Using this tool, you can provide only one shell script to the client.
This script will then extract your ofbsh obfuscated scripts and binaries into /tmp, and run them transparently.
You can obfuscate shell scripts with something like ofbsh. You won't easily bundle other programs into a single executable for unix, though. Normally the approach for installation would be to buld a package for your platform's package manager (e.g. rpm, deb, pkg) or to provide a tarball to unravel in the appropriate directory.
If you need an executable file that unpacks the contents you might be able to use a shell archive. Take a look at the docs for shar(1) and see if that will get what you want
If you really need a scripting capability to glue multiple C programs together, take a look at the Tcl language. It has an API that is designed to trivially wrap C programs that expect to see argv[] style parameters. You can even embed the chunks of C code into a custom Tcl interpreter and glue it together with various Tcl scripts.
If you really need to make it opaque, you could encrypt the tcl scripts and wrap the whole thing in something that unencrypts the tcl scripts to a buffer and then runs the Tcl interpreter on them. Tcl can accept scripts from a file or a char* buffer, so the unencrypted scripts never have to hit the file system.
shc
I have modified the original source and upgraded to a new version with some feature addition and bug fixes.
It's here.
Example Usage:
shc -f script.sh -o binary_name
script.sh will be compiled to a binary named binary_name
Note that, you still need the required shell to be installed in your system to run this executable.
arx is a great bundler, and you may be able to integrate a obfuscator in its workflow.
Options that are available to you:
Write a logic in your code that, when the code is run for the first time on a box, it'll check to see if all the required packages exist. And if they do not, the code will automatically go get the packages itself and will install them...without asking to the user to do anything. The only question the user needs to be asked is "Is it ok to proceed with the install of the aforementioned packages? (Y/N)". Anything outside of that is too much.
Once the above code is complete (yes, i'm aware it may not be all that simple for you to code this, or may be it is, i don't know your coding capabilities), copy and paste your completed code to a site like kinglazy.com and an actual executable file will be generated for you.
There are quite a few benefits of this particular option:
Yes, you will be able to run the encrypted version of your script without exposing any proprietary information.
No one can try to "view" your script, because if they do, they'll see nothing but indecipherable, encrypted jargon which wont make sense to them.
No one can attempt to modify your script because if they do, the script will immediately become inoperable.
No one can run a debugger on your script to see how it works. If they do, the script will abort.
Also, no one can create copies of your script on the same server. If they do, it will abort and won't work. It'll only allow users to create symlinks to the original location of wherever you want the script to be.
I may be missing some things in what you asked for, but i believe the above satisfies a good portion of what you wanted.
Not sure if this works on other scripts but it certainly does for shell scripts.
You can also use the free online version of CCsh to compile a shell script into a binary:
http://www.comeaucomputing.com/tryccsh/

Why do I get 'divide by zero` errors when I try to run my script with Rakudo?

I just built Rakudo and Parrot so that I could play with it and get started on learning Perl 6. I downloaded the Perl 6 book and happily typed in the first demo program (the tennis tournament example).
When I try to run the program, I get an error:
Divide by zero
current instr.: '' pc -1 ((unknown file):-1)
I have my perl6 binary in the build directory. I added a scripts directory under the rakudo build directory:
rakudo
|- perl6
\- scripts
|- perlbook_02.01
\- scores
If I try to run even a simple hello world script from my scripts directory I get the same error:
#!/home/daotoad/rakudo/perl6
use v6;
say "Hello nurse!";
However if I run it from the rakudo directory it works.
It sounds like there are some environment variables I need to set, but I am at a lost as to what the are and what values to give them.
Any thoughts?
Update:
I'd rather not install rakudo at this point, I'd rather just run things from the build directory. This will allow me to keep my changes to my system minimal as I try out different Perl6 builds (Rakudo * is out very soon).
The README file encouraged me to think that this was possible:
$ cd rakudo
$ perl Configure.pl --gen-parrot
$ make
This will create a "perl6" or "perl6.exe" executable in the
current (rakudo) directory. Programs can then be run from
the build directory using a command like:
$ ./perl6 hello.pl
Upon rereading, I found a reference to the fact that it is necessary to install rakudo before running scripts outside the build directory:
Once built, Rakudo's make install target will install Rakudo
and its libraries into the Parrot installation that was used to
create it. Until this step is performed, the "perl6" executable
created by make above can only be reliably run from the root of
Rakudo's build directory. After make install is performed,
the installed executable can be run from any directory (as long as
the Parrot installation that was used to create it remains intact).
So it looks like I need to install rakudo to play with Perl 6.
The next question is, where rakudo be installed? README says into the Parrot install used to build.
I used the --gen-parrot option in my build, which looks like it installs into rakudo/parrot-install. So rakudo will be installed into my rakudo\parrot-install?
Reading the Makefile, supports this conclusion. I ran make install, and it did install into parrot_install.
This part of the build/install process is unclear for a newbie to Perl6. I'll see if I can up with a documentation patch to clarify things.
Off the top of my head:
Emphasize running make install before running scripts outside of build. This requirement is currently burried in the middle of a paragraph and can be easily missed by someone skimming the docs (me).
Explicitly state that with --gen-parrot will install perl6 into the parrot_install directory.
Did you run make install in Rakudo?
It's necessary to do it to be able to use Rakudo outside its build directory (and that's why both the README and http://rakudo.org/how-to-get-rakudo tell you to do it.
Don't worry, the default install location is local (in parrot_install/bin/perl inside your rakudo directory).
In response to your update I've now updated the README:
http://github.com/rakudo/rakudo/commit/261eb2ae08fee75a0a0e3935ef64c516e8bc2b98
I hope you find that clearer than before. If you still see room for improvement, please consider submitting a patch to rakudobug#perl.org.