How can I pipe stdin from a file to the executable in Xcode 4+?
Asked Answered
J

4

22

I have an mpi program and managed to compile and link it via Xcode 4. Now I want to debug it using Xcode 4.

How can I pipe the standard input to the program from a file?

In terminal I would type

mpirun -np 2 program < input.txt

I am able to run the program defining a custom executable (mpirun) in the "Info" panel of the Scheme editor, I also know that I can pass arguments in the "Arguments" panel. But Xcode 4 does not seem to accept "< input.txt" as an argument, even if I check "Use custom working directory" + add the correct directory of the input script in the "Options" panel.

This article Says it is possible to use "< input.txt" as an argument, but I guess that worked in Xcode 2 or Xcode 3, but it does not seem to work in Xcode 4 anymore.

Jaban answered 2/10, 2011 at 23:18 Comment(6)
Can you configure Xcode to use cat input.txt | mpirun -np 2 program instead? It's kind of a cheap hack, so I'm not that proud to be suggesting it...Demaggio
Thank you for that hint! I didn't manage to run it yet, but this comment led me to try the sripts feature like setting variables in the script: input=$(cat input.txt) And passing $(input) as an argument. Maybe that works. I hope however there is a neat way to do that, otherwise it would be a little disappointing. Maybe someone is out there and knows better! Thank you though for that quick idea!Jaban
Ha! Of course, a script will probably do the job well. :)Demaggio
Unfortunately it does not seem to be possible to use variables that I set in the script as arguments. If I use "< input.txt" as an argument it passes the strings "<" and "input.txt" instead of interpreting.Jaban
Did you start your script with #!/bin/sh or #!/bin/bash in addition to setting the execute permission on the script? Perhaps if the script doesn't start with the hashbang line, the kernel will try to execute the program all the same...Demaggio
In the "Pre-actions > Run Script" section I set the shell to /bin/bash and set the variables in the text field below. It does get executed (tried that by writing to file in the script), but the variables I set cannot be accessed in the "Run program > Arguments" section. Do you mean I should start the script with #!/bin/bash?Jaban
O
34

In Xcode 4.5.1:

  1. Open the scheme editor (Product menu -> Edit Scheme...)
  2. Select the Run Debug scheme
  3. In the 'Info' tab panel, change the 'Launch' radio button selection from 'Automatically' to 'Wait for MyApp.app to launch'
  4. Close the scheme editor
  5. Press the Run button to build and run your target. (Xcode's status window in the toolbar will show 'Waiting for MyApp to launch')
  6. Launch Terminal and cd to your built application's folder. (It will be something like /Users/user/Library/Developer/Xcode/DerivedData/MyApp-dmzfrqdevydjuqbexdivolfeujsj/Build/Products/Debug / )
  7. Launch your app piping in whatever you want into standard input:

    echo mydata | ./MyApp.app/Contents/MacOs/MyApp
    
  8. Switch back to Xcode and the debugger will have detected your application's launch and attached to it.

Ouzel answered 22/10, 2012 at 7:17 Comment(6)
That sounds like the solution I was looking for a year ago. Thanks for answering.Jaban
I tried doing it like this, even though I don't have that particular situation anymore. It turns out XCode attaches to only one of the processes that I spawn with the terminal-call mpirun -np 2 program < input.txt. But thanks anyways, All in all I don't think anymore that XCode 4 is capable of debugging mpi programs. Since you successfully answered the "piping" part of the question, I award you the answer, event though it's not the answer I was hoping for.Jaban
My problem with this is that you have to open a Terminal session every time you run. You may as well just copy and paste the contents of mydata to the console area every time (which is what I was trying to avoid when I went looking for this post).Diplomate
In my Xcode 6.1 C++ command line tool project, if I didn't add the following line I got the dialog, "Lost connection to "My Mac". Restore the connections to "My Mac" and run "MyApp" again, or if "MyApp" is still running, you can attach to it by selecting Debug > Attach to Process > MyApp". std::this_thread::sleep_for (std::chrono::seconds(5))Ides
Thanks user2067021, this worked for me, too, in Xcode Version 9.1 (9B55). How can I debug my code using Xcode when using your method?Charliecharline
hm, xcode 10.1 in 2019 here, getting Message from debugger: unable to attach as soon as the command-line is issued. The app is a "command-line tool" versus a regular app, tho.Lethargic
L
3

Not wanting to awaken zombies, but this is still the top search result for the question.

I've managed to get this working in XCode 9.2 - but it should be backwards compatible. It uses a subshell and sleep in a pre-action script. This will pipe from a file and stick cout to a file, and supports breakpoints.

(1) Add the following preaction.sh script into your project.

#!/bin/sh
exec > ${PROJECT_DIR}/tests/result.log 2>&1
(
sleep 1
${TARGET_BUILD_DIR}/${EXECUTABLE_NAME} < ${PROJECT_DIR}/tests/file
)&

(2) Then add it to your pre-actions on the Run menu. Pre-action setting

(3) Ensure your run Waits for executable to be launched. Run setting

(4) Turn off code signing for your target!

No Codesigning Otherwise you will get an error "Message from debugger: unable to attach"

(5) Set breakpoints and run from Xcode as normal

That's all there is to it. The entire trick rests on getting the pre-action script to spawn off a sub-shell that itself delays the process until the run action is launched.

Lohse answered 5/4, 2018 at 10:9 Comment(0)
O
2

Another approach:

In the very beginning of your program, freopen input file for stdin.

    freopen( "input.txt", "r", stdin );

Conditional macro may help you.

#ifdef DEBUG
    freopen( "input.txt", "r", stdin );
    freopen( "output.txt", "w", stdout );
#endif
Oakley answered 14/4, 2021 at 15:54 Comment(1)
Nice workaround, though modifying the source is not optimal, however,given that Xcode is so clever that its unable to do the basics (Konchog's answer), this worked for me using Xcode 12.4.Basilbasilar
D
-1

Try the following pre-action run script:

mv program program.real
echo -e '#!/bin/sh\nmpirun -np 2 program.real < input.txt' > program

Maybe this will trick XCode into executing your program as you would like it to be executed.

Demaggio answered 6/10, 2011 at 0:54 Comment(1)
No that did not work either. Thank you though for your dedication.Jaban

© 2022 - 2024 — McMap. All rights reserved.