TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

C – Compile and execute C “scripts” in one go

123 pointsby ryanmjacobsabout 10 years ago

20 comments

lambdaabout 10 years ago
You don&#x27;t need to install anything; you could put this on the first line of your file, and achieve the same effect, with just tools you already have installed:<p><pre><code> &#x2F;&#x2F;usr&#x2F;bin&#x2F;make -s &quot;${0%.c}&quot; &amp;&amp; .&#x2F;&quot;${0%.c}&quot; &quot;$@&quot;; s=$?; rm .&#x2F;&quot;${0%.c}&quot;; exit $s </code></pre> Actually, you could extend this to any file type that Make has built-in rules for, and which uses &#x2F;&#x2F; as a comment delimiter:<p><pre><code> &#x2F;&#x2F;usr&#x2F;bin&#x2F;make -s &quot;${0%.*}&quot; &amp;&amp; .&#x2F;&quot;${0%.*}&quot; &quot;$@&quot;; s=$?; rm .&#x2F;&quot;${0%.*}&quot;; exit $s</code></pre>
评论 #9145316 未加载
评论 #9145937 未加载
评论 #9145862 未加载
评论 #9146590 未加载
评论 #9146572 未加载
cnvogelabout 10 years ago
I find this construct quite interesting....<p><pre><code> help_msg() { &gt;&amp;$1 echo &quot;Usage: $0 [file.c... &gt;&amp;$1 echo &quot;Execute C progams from the command line.&quot; ... } </code></pre> for that it puts the redirection at the beginning of the line, which is unusual and I didn&#x27;t even realize until now that it&#x27;s valid. ( example: &gt;&amp;55 redirects stdout to filescriptor number 55, and here &gt;&amp;$1 redirects stdout of echo to the filedescriptor number given as the first argument to the function)<p><pre><code> # help if we have no arguments and no stdin if [ $# -eq 0 ] &amp;&amp; [ -t 0 ]; then help_msg 2 # &lt;--- NOTE 2 = stderr exit 1 fi # help if we get the flags if [ &quot;$1&quot; == &quot;--help&quot; ] || [ &quot;$1&quot; == &quot;-h&quot; ]; then help_msg 1 - &lt;--- NOTE 1 = stdout exit 0 fi </code></pre> And second, that the author seems to switch between outputting the help_msg on stdout or stderr, depending on if stdout exists. I always was under the impression that only the actual script result ought to go to stdout, and personally I always put out general debugging, error messages, but also the usage, unconditionally to stderr.
评论 #9145133 未加载
评论 #9144885 未加载
评论 #9145008 未加载
rlonsteinabout 10 years ago
Neat hack, but if I wanted to compile, I&#x27;d just go ahead and compile. These are more interesting:<p><pre><code> http:&#x2F;&#x2F;bellard.org&#x2F;tcc&#x2F; (use -run) https:&#x2F;&#x2F;root.cern.ch&#x2F;drupal&#x2F;content&#x2F;cint https:&#x2F;&#x2F;root.cern.ch&#x2F;drupal&#x2F;content&#x2F;cling</code></pre>
评论 #9145634 未加载
评论 #9148636 未加载
sdsk8about 10 years ago
Congratulations, but <a href="http://bellard.org/tcc/" rel="nofollow">http:&#x2F;&#x2F;bellard.org&#x2F;tcc&#x2F;</a> already do that!<p>How do they compare?
评论 #9144938 未加载
评论 #9144782 未加载
DSMan195276about 10 years ago
A quick note, I see a few big issues:<p>1. There&#x27;s no guarantee that you can run anything directly out of &#x2F;tmp&#x2F;. IIRC lots of distros mount &#x2F;tmp&#x2F; with noexec specifically so you can&#x27;t do this. You might still be able to invoke ld directly to run it, but that&#x27;s still kinda a hack to get around the noexec.<p>2. You need write access to the .c file. That means you can&#x27;t install any scripts using this system-wide, because you won&#x27;t have write-access to the .c source unless you&#x27;re root.<p>IMO, the most obvious solution to the second is to make a copy of the .c source and edit that instead. AFAIK there isn&#x27;t an easy solution to the first issue though.
0942v8653about 10 years ago
This doesn&#x27;t appear to cache compiled &quot;scripts&quot;, which to me makes it kind of useless. It&#x27;s nice not to leave binaries laying around but I&#x27;d expect things to be saved (otherwise it&#x27;s pretty slow).
评论 #9145690 未加载
kazinatorabout 10 years ago
Here is a way to do it without installing a &#x2F;usr&#x2F;bin&#x2F;c.<p>All you takes is a few lines of shell code to the top of the C file.<p><a href="http://rosettacode.org/wiki/Multiline_shebang#C" rel="nofollow">http:&#x2F;&#x2F;rosettacode.org&#x2F;wiki&#x2F;Multiline_shebang#C</a><p>I contributed that, anonymously. Previously, the task had been marked &quot;omit from C&quot;, would you believe it!<p>Also, note the little &quot;Student exercise&quot; below the code. For this to be useful, you want to cache the compiler output; you want to recompile the underlying executable only if the C script has changed.<p>The inconvenience of invoking C programs obviously isn&#x27;t the real obstacle to its use as a scripting language, otherwise this kind of thing would be widely used.
hawskiabout 10 years ago
I have done something like this and use it for simple tests of my assumptions [1]. This one from OP is more polished I suppose. I must check if it supports (with shebang) putting &quot;c-script&quot;,in pipeline.<p>As was already mentioned Fabrice Bellard&#x27;s tcc is great in this regard. There were similar projects done with LLVM.<p>What I would really like to have is some kind of compiler or different C preprocessor that would implement modules, such as that building C would be as simple as building Go programs. Price for it I suppose are macros. I think it&#x27;s possible.<p>[1] <a href="http://hawski.com/ccrun" rel="nofollow">http:&#x2F;&#x2F;hawski.com&#x2F;ccrun</a>
0x09about 10 years ago
I like lli for quickly running some code (no temporaries!)<p><pre><code> $ clang -xc -c -emit-llvm -o - - | lli #include &lt;stdio.h&gt; int main(void) { puts(&quot;hi&quot;); }^D hi </code></pre> As a shell executable interpreter<p><pre><code> #!&#x2F;usr&#x2F;bin&#x2F;env bash [ -f &quot;$1&quot; ] &amp;&amp; file=&quot;$1&quot; || file=&#x2F;dev&#x2F;stdin awk &#x27;NR==1&amp;&amp;&#x2F;^#!&#x2F;{next}{print}&#x27; &quot;$file&quot; | \ clang -xc -c -emit-llvm $CFLAGS -o - - | \ lli -fake-argv0=&quot;$file&quot; $IFLAGS - </code></pre> You can even &quot;link&quot; static archives<p><pre><code> $ IFLAGS=-extra-archive=&#x2F;path&#x2F;to&#x2F;libz.a \ &gt; CFLAGS+=&#x27;-include stdio.h -include zlib.h&#x27; \ &gt; c &lt;&lt;&lt; &#x27;int main(void){puts(zlibVersion());}&#x27; 1.2.8</code></pre>
kasabaliabout 10 years ago
Beware that using another script as the executable in shebang <i>may not</i> work everywhere [0]<p>[0] <a href="http://www.in-ulm.de/~mascheck/various/shebang/#interpreter-script" rel="nofollow">http:&#x2F;&#x2F;www.in-ulm.de&#x2F;~mascheck&#x2F;various&#x2F;shebang&#x2F;#interpreter-...</a>
mikeashabout 10 years ago
I do something similar when working on single-file programs, but without any external dependencies, by making the file both a valid shell script (for my shell) and a valid C program. Here&#x27;s an example in Swift, although the same idea works for C too:<p><a href="https://gist.github.com/mikeash/70d74f7b7745cf6fbd3f" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;mikeash&#x2F;70d74f7b7745cf6fbd3f</a>
评论 #9147908 未加载
radiospielabout 10 years ago
Also: <a href="https://github.com/radiospiel/jit" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;radiospiel&#x2F;jit</a><p>which supports go, c, and flex.
1risabout 10 years ago
So<p>alias c=tcc -run<p>?
评论 #9145271 未加载
评论 #9145372 未加载
npsimonsabout 10 years ago
Nice to have another option, but been able to do this (as well as C++, FORTRAN, assembler, Java and Pascal) under Linux for a while:<p><a href="https://www.netfort.gr.jp/~dancer/software/binfmtc.html.en" rel="nofollow">https:&#x2F;&#x2F;www.netfort.gr.jp&#x2F;~dancer&#x2F;software&#x2F;binfmtc.html.en</a><p>For Debian, &quot;apt-get install binfmtc&quot;
RhysUabout 10 years ago
Shameless self plug on alternative: <a href="https://github.com/RhysU/c99sh" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;RhysU&#x2F;c99sh</a><p>Ditto: Shebang, stdin Extras: Automatic includes, nice error reporting, RC files, pkg-config, and C++ too. Lacks: Multiple file
harry8about 10 years ago
<p><pre><code> #if 0 THIS=$0 BIN=&#x2F;tmp&#x2F;$(basename $0) cc $THIS -Wall -o $BIN $BIN rm $BIN exit #else #include&lt;stdio.h&gt; int main(){printf(&quot;hello\n&quot;);} #endif</code></pre>
sigjuiceabout 10 years ago
<a href="https://gist.github.com/khirbat/1471088" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;khirbat&#x2F;1471088</a>
coherentponyabout 10 years ago
Related: <a href="https://github.com/RhysU/c99sh" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;RhysU&#x2F;c99sh</a>
ralmeida4381about 10 years ago
Interesting... C in your shell is like having a sonic screwdriver in your pocket.
评论 #9146800 未加载
to3mabout 10 years ago
&gt; &quot;We should all write more C.&quot;<p>Erm... speak for yourself :)