C 또는 C++ 파일을 스크립트로 실행
그래서 이것은 아마도 긴 시도일 것입니다만, C 또는 C++ 파일을 스크립트로 실행할 수 있는 방법이 없을까요?노력했습니다.
#!/usr/bin/gcc main.c -o main; ./main
int main(){ return 0; }
하지만 이렇게 적혀있습니다.
./main.c:1:2: error: invalid preprocessing directive #!
단답형:
//usr/bin/clang "$0" && exec ./a.out "$@"
int main(){
return 0;
}
비결은 텍스트 파일이 유효한 C/C++ 코드와 셸 스크립트여야 한다는 것입니다.기억하기exit
하거나 C/C++ 코드를 호출합니다.exec
요술을
와 함께 chmod +x main.c; ./main.c
.
그녀는 쾅.#!/usr/bin/tcc -run
유닉스 계열 시스템들은 이미 셸 내에서 텍스트 파일을 실행할 것이기 때문에 필요하지 않아도 됩니다.
C++ 스크립트에서 사용했습니다.
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main() {
for (auto i: {1, 2, 3})
std::cout << i << std::endl;
return 0;
}
컴파일 라인이 너무 커지면 이 일반적인 이전 C 코드가 보여주는 것처럼 전처리기(이 답변에서 채택)를 사용할 수 있습니다.
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main() {
return 0;
}
물론 실행 파일을 캐시할 수 있습니다.
#if 0
EXEC=${0%.*}
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main() {
return 0;
}
자, 정말 별난 자바 개발자를 위해:
/*/../bin/true
CLASS_NAME=$(basename "${0%.*}")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "${CLASS_PATH}" ${CLASS_NAME}
rm -f "${CLASS_PATH}/${CLASS_NAME}.class"
exit
*/
class Main {
public static void main(String[] args) {
return;
}
}
D 프로그래머들은 구문을 깨지 않고 텍스트 파일의 처음에 셰뱅을 넣기만 하면 됩니다.
#!/usr/bin/rdmd
void main(){}
참조:
C의 경우 Tiny C 컴파일러인 tcc를 살펴볼 수 있습니다.C 코드를 스크립트로 실행하는 것은 가능한 용도 중 하나입니다.
$ cat /usr/local/bin/runc
#!/bin/bash
sed -n '2,$p' "$@" | gcc -o /tmp/a.out -x c++ - && /tmp/a.out
rm -f /tmp/a.out
$ cat main.c
#!/bin/bash /usr/local/bin/runc
#include <stdio.h>
int main() {
printf("hello world!\n");
return 0;
}
$ ./main.c
hello world!
는 seds 은 을 합니다 합니다 를 합니다..c
파일을 저장하고 해시뱅 라인을 제거합니다.2,$p
줄하는 것을 합니다.일줄를 2는다을에다을는st2일s를;에"$@"
합니다. 행를로 runc다즉 . ,"main.c"
.
sed 은 gcc 됩니다 로 의 됩니다 은 에 파이프됩니다.합격-
하고, 할때 gcc을 stdin고게은한할스다를때서는geheo야e를eogtycmoncntsodud,n한-x
파일 이름이 없기 때문입니다.
shebang 라인은 컴파일러로 전달될 것이고 #는 전처리기 지시를 나타내기 때문에 #!에서 질식할 것입니다.
당신이 할 수 있는 일은 makefile을 .c 파일에 내장하는 것입니다 (이 xkcd 스레드에서 설명된 것처럼).
#if 0
make $@ -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[]) {
bar();
return EXIT_SUCCESS;
}
#endif
#ifdef BAR_C
void bar() {
puts("bar!");
}
#endif
#if 0 #endif
, 명령이 해야 하는 합니다. makefile은 make file과 make file의 parsing input, EOF는 make file과 make file의 parsing input을 표시합니다.
CINT:
CINT는 C와 C++ 코드의 인터프리터입니다.실행 시간보다 빠른 개발이 더 중요한 상황에 유용합니다.인터프리터를 사용하면 컴파일 및 링크 주기가 크게 단축되어 빠른 개발이 용이합니다.CINT는 시간제 프로그래머도 C/C++ 프로그래밍을 즐길 수 있습니다.
이 점을 염두에 두고 설계된 ryanmjacobs/c를 확인해 보는 것이 좋습니다.좋아하는 컴파일러 주위의 래퍼 역할을 합니다.
#!/usr/bin/c
#include <stdio.h>
int main(void) {
printf("Hello World!\n");
return 0;
}
사용할 때의 좋은 점c
예를 들어 어떤 컴파일러를 사용할지 선택할 수 있습니다.
$ export CC=clang
$ export CC=gcc
따라서 좋아하는 최적화도 모두 얻을 수 있습니다!그요를 .tcc -run
!
플래그를 할 수 . shebang이 shebang으로 되는 한 shebang에 컴파일러 플래그를 추가할 수 . 그것들이 종료되는 한.--
캐릭터:
#!/usr/bin/c -Wall -g -lncurses --
#include <ncurses.h>
int main(void) {
initscr();
/* ... */
return 0;
}
c
도를 합니다.$CFLAGS
그리고.$CPPFLAGS
그것들도 세팅이 되어 있다면요.
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && { ./a.out "$@"; e="$?"; rm ./a.out; exit "$e"; }
#include <stdio.h>
int main(int argc, char const* argv[]) {
printf("Hello world!\n");
return 0;
}
이것은 인수와 종료 코드도 적절하게 전달합니다.
상당히 짧은 제안은 다음을 활용할 수 있습니다.
- 현재 셸 스크립트는 알 수 없는 유형(셰뱅 또는 인식 가능한 이진 헤더 없음)의 기본 인터프리터입니다.
"#"은 셸의 주석이고 "#if 0"은 코드를 비활성화합니다.
#if 0 F="$(dirname $0)/.$(basename $0).bin" [ ! -f $F -o $F -ot $0 ] && { c++ "$0" -o "$F" || exit 1 ; } exec "$F" "$@" #endif // Here starts my C++ program :) #include <iostream> #include <unistd.h> using namespace std; int main(int argc, char **argv) { if (argv[1]) clog << "Hello " << argv[1] << endl; else clog << "hello world" << endl; }
그러면 가능합니다.chmod +x
.cpp 파일 및 그 다음./run.cpp
.
- 컴파일러의 플래그를 쉽게 지정할 수 있습니다.
- 이진 파일은 소스와 함께 현재 디렉터리에 캐시되며 필요할 때 업데이트됩니다.
- 됩니다: 는 으로 됩니다 됩니다 으로 는 .
./run.cpp Hi
- 다시 사용하지 않습니다.
a.out
폴더에 파일을 수 하기 위해 , 에 의 을 할 할 을 에 . - 시스템에 있는 모든 c++ 컴파일러를 사용합니다.
- 바이너리는 디렉토리 목록에서 숨기도록 "."로 시작합니다.
문제:
- 동시 실행 시 어떻게 됩니까?
존 쿠겔만의 변주는 다음과 같이 쓸 수 있습니다.
#!/bin/bash
t=`mktemp`
sed '1,/^\/\/code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$@"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main() {
printf("Hi\n");
return 0;
}
여기에 또 다른 대안이 있습니다.
#if 0
TMP=$(mktemp -d)
cc -o ${TMP}/a.out ${0} && ${TMP}/a.out ${@:1} ; RV=${?}
rm -rf ${TMP}
exit ${RV}
#endif
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello world\n");
return 0;
}
저는 이 질문이 최근에 나온 질문이 아니라는 것을 알지만, 어쨌든 저는 제 대답을 혼합하기로 결정했습니다.Clang과 LLVM을 사용하면 중간 파일을 작성하거나 외부 도우미 프로그램/스크립트를 호출할 필요가 없습니다.(클랑/클랑++/lli 제외)
clang/clang++ tolli의 출력을 파이프로 연결하면 됩니다.
#if 0
CXX=clang++
CXXFLAGS="-O2 -Wall -Werror -std=c++17"
CXXARGS="-xc++ -emit-llvm -c -o -"
CXXCMD="$CXX $CXXFLAGS $CXXARGS $0"
LLICMD="lli -force-interpreter -fake-argv0=$0 -"
$CXXCMD | $LLICMD "$@" ; exit $?
#endif
#include <cstdio>
int main (int argc, char **argv) {
printf ("Hello llvm: %d\n", argc);
for (auto i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
return 3==argc;
}
그러나 위의 내용은 c/c++ 스크립트에서 stdin을 사용할 수 없습니다.bash가 셸인 경우 stdin을 사용하기 위해 다음을 수행할 수 있습니다.
#if 0
CXX=clang++
CXXFLAGS="-O2 -Wall -Werror -std=c++17"
CXXARGS="-xc++ -emit-llvm -c -o -"
CXXCMD="$CXX $CXXFLAGS $CXXARGS $0"
LLICMD="lli -force-interpreter -fake-argv0=$0"
exec $LLICMD <($CXXCMD) "$@"
#endif
#include <cstdio>
int main (int argc, char **argv) {
printf ("Hello llvm: %d\n", argc);
for (auto i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
for (int c; EOF != (c=getchar()); putchar(c));
return 3==argc;
}
shebang(#!)을 유지해야 한다는 몇 가지 제안이 있지만 gcc 컴파일러에서는 불법입니다.그래서 여러 가지 해결책들이 그것을 잘라냅니다.또한 c 코드가 잘못된 경우에 대한 컴파일러 메시지를 수정하는 전처리기 지시문을 삽입할 수 있습니다.
#!/bin/bash
#ifdef 0
xxx=$(mktemp -d)
awk 'BEGIN
{ print "#line 2 \"$0\""; first=1; }
{ if (first) first=0; else print $0 }' $0 |\
g++ -x c++ -o ${xxx} - && ./${xxx} "$@"
rv=$?
\rm ./${xxx}
exit $rv
#endif
#include <iostream>
int main(int argc,char *argv[]) {
std::cout<<"Hello world"<<std::endl;
}
이전 답변에서 말씀드린 것과 같이,tcc
당신의 컴파일러로써, 당신은 shebang을 넣을 수 있습니다.#!/usr/bin/tcc -run
소스 파일의 첫 줄로 표시됩니다.
그러나 이와 관련하여 작은 문제가 있습니다: 동일한 파일을 컴파일하고 싶다면, 컴파일하고 싶다면,gcc
던지다error: invalid preprocessing directive #!
(tcc
shebang을 무시하고 잘 컴파일 할 것입니다).
만약 당신이 아직도 다음과 같이 컴파일해야 합니다.gcc
하나의 해결책은 사용하는 것입니다.tail
shebang 라인을 소스 파일에서 잘라낸 후 pipeing을 수행하는 명령.gcc
:
tail -n+2 helloworld.c | gcc -xc -
모든 경고 및/또는 오류는 한 줄씩 꺼집니다.
파일이 shebang으로 시작하는지 확인하는 bash 스크립트를 만들어 자동화할 수 있습니다.
if [[ $(head -c2 $1) == '#!' ]]
then
tail -n+2 $1 | gcc -xc -
else
gcc $1
fi
직접 호출하는 대신 소스를 컴파일하는 데 사용합니다.gcc
.
Pedro가 솔루션에 대해 설명해 준 덕분에 공유하고 싶었을 뿐입니다.#if 0
트릭, 저는 TCC(Sugar C)에서 포크를 업데이트하여 모든 예제를 shebang으로 호출할 수 있도록 하였으며, 마지막으로 IDE에서 소스를 찾을 때 오류가 없습니다.
이제 코드가 아름답게 표시됩니다.clangd
프로젝트 소스에 대한 VS Code.표본 첫 번째 선은 다음과 같습니다.
#if 0
/usr/local/bin/sugar `basename $0` $@ && exit;
// above is a shebang hack, so you can run: ./args.c <arg 1> <arg 2> <arg N>
#endif
보다 램 하는 것이었습니다.-run
지시).
프로젝트는 https://github.com/antonioprates/sugar 에서 확인할 수 있습니다.
실행 파일로 실행하기 위한 다양한 언어에 대한 해시뱅/쉬뱅 예제
컴파일된 언어도 실행 가능한 스크립트인 것처럼 실행할 수 있습니다.
이것을 가능하게 하기 위해 제가 프로그램의 맨 위에 있는 첫 번째 줄로 사용하고 싶은 필요한 해시뱅 줄들은 다음과 같습니다.
C의 경우 (컴파일화) (기술적으로는 아래에 명시한 대로 gnu C):
///usr/bin/env ccache gcc -Wall -Wextra -Werror -O3 -std=gnu17 "$0" -o /tmp/a -lm && /tmp/a "$@"; exit
C++(컴파일)의 경우(기술적으로는 아래에 명시한 대로 gnu++):
///usr/bin/env ccache g++ -Wall -Wextra -Werror -O3 -std=gnu++17 "$0" -o /tmp/a -lm && /tmp/a "$@"; exit
및 의 C ≥ C++ ≥ C,
ccache
당신의 컴파일이 좀 더 효율적이 되도록 도와줍니다.와 함께 하기sudo apt update && sudo apt install ccache
.For Go (컴파일) (골랑)
///usr/bin/env go run "$0" "$@"; exit
...그리고 위의 행에 대한 자세한 설명은 여기에서 제 다른 답변을 참조하십시오.적절한 고쉐방 라인은 무엇입니까?
녹용(컴파일)
///usr/bin/env rustc "$0" -o /tmp/a && /tmp/a "$@"; exit
추가 도움말:
- 러스트 설치 : https://www.rust-lang.org/tools/install
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- "Rusty By Example" 공식 온라인 책 "hello world" 예제: https://doc.rust-lang.org/stable/rust-by-example/hello.html
- 러스트 설치 : https://www.rust-lang.org/tools/install
Bash용(해석)
#!/usr/bin/env bash
Python의 경우(해석)
#!/usr/bin/env python3
로 :time
네가 원한다면.
컴파일 시간을 측정하려면 다음을 추가합니다.bash -c time
해시-뱅의 시작 부근에, 다음과 같이.다음은 C++의 예입니다. (기술적으로는 gnu++17입니다.)
///usr/bin/env bash -c time ccache g++ -Wall -Wextra -Werror -O3 -std=gnu++17 "$0" -o /tmp/a -lm && /tmp/a "$@"; exit
이제 파일을 실행 파일로 표시하고 직접 실행할 수 있습니다!
# make executable
chmod +x hello_world.c # C
chmod +x hello_world.cpp # C++
chmod +x hello_world.go # Go
chmod +x hello_world.rs # Rust
chmod +x hello_world.sh # Bash
chmod +x hello_world.py # Python
# run
cd path/to/dir/containing/these/files
./hello_world.c # C
./hello_world.cpp # C++
./hello_world.go # Go
./hello_world.rs # Rust
./hello_world.sh # Bash
./hello_world.py # Python
참조:
- 제 eRCaGuy_hello_world repo에서 다양한 언어에 대한 shebang의 위의 몇 가지 용도를 보고 실행할 수 있습니다.
- 이 된 을 을 찾습니다.
language/hello_world*
아니면language/hello*
. - Ex: C: c/hello_world_extra_basic.c
- 이 된 을 을 찾습니다.
- 까지.
//
? - [내 대답] 적절한 고쉐방 대사는?
- 저도 제 블로그에 올려놨습니다. https://gabrielstaples.com/hash-bangs-to-run-compiled-languages-as-executables/
언급URL : https://stackoverflow.com/questions/2482348/run-c-or-c-file-as-a-script
'programing' 카테고리의 다른 글
Kotlin Android에서 중복되는 클래스 (0) | 2023.09.09 |
---|---|
VBA를 사용하여 전체 워크시트에서 형식 제거 (0) | 2023.09.09 |
선택적 통화 변수로 함수 만들기 (0) | 2023.09.09 |
jQuery: ajax 예외 잡기 (0) | 2023.09.09 |
오류 [ERR_REQUIR_ESM]: ES 모듈의 require()가 지원되지 않습니다. (0) | 2023.09.09 |