0

I want to build my program using make and then launch the created executable via bash script, but bash can't find the executable, although it was created and i can launch it manually. The problem only exist on linux mint 19 in Gnome-terminal. Edit: The exact error message is: "/path/to/my/executable: no such file or directory"

I have a cross-platform project where i need to run cmake, then build the project and finally launch the created executable. I have a bash script to automate the process: Edit: Its only the part that causes the trouble ;)

for TASK in $@; do
    if [[ $TASK == "make" ]]; then
        call cmake here, this creates a .sln or a make file
    elif [[ $TASK == "build" ]]; then
        if  [[ $OS == 'CYGWIN_NT-10.0' ]]; then
            MSBuild.exe "./build/debug/myproject.sln"
        elif [[ $OS == 'Linux' ]]; then
            cd ./build/debug/ && make
        else
            error...
        fi
    elif [[ $TASK == "run" ]]; then
        if  [[ $OS == 'CYGWIN_NT-10.0' ]]; then
            ./build/debug/Debug/program.exe
        elif [[ $OS == 'Linux' ]]; then
            ./build/debug/program
        else
            error...
        fi
    else
        error...
    fi
done

Calling "./script.sh make build run" should, for example, call cmake to create the build files, then call the build program (make on linux or msbuild on windows) and then launch the created executable. This works fine on windows 10 in a cygwin terminal. On Linux the call "./script.sh build run" fails, because it can't find the executable. However "./script.sh build && ./build/debug/program" works nicely. Surprisingly "./script.sh build && ./script.sh run" also works as expected. Why is that? Is there any Bug in the bash script? And why does it work on Cygwin but not on linux mint?

Lukas-T
  • 11,133
  • 3
  • 20
  • 30
  • 1
    Paste the actual error message as well? Btw, this is **not** the actual script, I'm almost certain that `call cmake here, this creates a .sln or a make file` doesn't work ;) – tink May 30 '19 at 09:38
  • 1
    If you developed the script on Windows, the EOL is probably the first problem. Also see [How to use dos2unix?](https://stackoverflow.com/q/23210500/608639), [How to use Shellcheck](http://github.com/koalaman/shellcheck), [How to debug a bash script?](http://unix.stackexchange.com/q/155551/56041) (U&L.SE), [How to debug a bash script?](http://stackoverflow.com/q/951336/608639) (SO), [How to debug bash script?](http://askubuntu.com/q/21136) (AskU), [Debugging Bash scripts](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html), etc. – jww May 30 '19 at 09:41
  • 1
    The construct `if [[ TASK == .. ]]; ...; elif [[ TASK == ...; elif [[ TASK ...` desperately wants to be replaced with a `case` statement. – William Pursell May 30 '19 at 09:52
  • What is the first line of your shell script, and/or how do you invoke it? If it says `#!/bin/sh` instead of `#!/bin/bash`, then that's your problem. You have written a script which relies explicitly on non-POSIX, non-standard extensions that only exist in the bash shell. If you use `#!/bin/sh` then it won't work on any system where `/bin/sh` is not actually bash (which is true, for example, on all Debian and Ubuntu systems). – MadScientist May 30 '19 at 16:18
  • of course it is not the whole script, just the part that causes the problems. I thought it would be good to simplify as much as possible ;) – Lukas-T May 31 '19 at 08:02
  • I will add some clarifications, thanks for the hint! And thank you @WilliamPursell for the advice to use a case statement :) – Lukas-T May 31 '19 at 08:21
  • @jww im using it on cygwin bash, which also use LF instead of CRLF. If line endings would be the problem, the script wouldn't run at all. – Lukas-T May 31 '19 at 08:29
  • @MadScientist im using `#!/bin/bash` no problem there ;) – Lukas-T May 31 '19 at 08:31

1 Answers1

0

Ok, I solved it. Asking questions seems to be the first step to finding a solution. The problem seems to be, that the call "./script.sh build run" first evaluates the build command "cd ./build/debug/ && make". I thougth such commands would spawn a new sub shell, where the cd and make commands are then evaluated and then the shell would continue in the original working directory. Apparently this does not happen and the working directory of the executing script is changed to "./build/debug". The next command "run" tries to execute "./build/debug/program" but since the current working directory is changed, it is essentially looking for "./build/debug/build/debug/program" which does not exist. I added the line

cd ../../

to the code for the build-command. It now looks like this

...
elif [[ $OS == 'Linux' ]]; then
    cd ./build/debug/ && make
    cd ../../
else
...

I don't know exactly why, but it works this way on linux.

Lukas-T
  • 11,133
  • 3
  • 20
  • 30
  • 1
    `cd` doesn't spawn a sub-shell, and `&&` doesn't spawn a subshell. If you want to spawn a subshell, you can use `()`. So if you write `(cd ./build/debug && make)` then you will get the behaviour you want. Alternatively if you know you're using GNU make you can use `make -C build/debug` and avoid the `cd` altogether. – MadScientist May 31 '19 at 12:36