프로그램 사용/gcc2010. 3. 4. 11:23

학교에서 컴파일러 배운지도 오래되서 기억도 가물가물하는데,
아무튼 컴파일이라는 과정은 생각보다 여러단계를 거친다.

1단계는 #define 이나 #include 등의 매크로프로세서를 처리하는 과정
2단계는 매크로 처리된 C언어를 컴파일하는 과정(문법 확인)
3단계를 컴파일 된 결과물인 어셈블리 코드를 오브젝트로 변환하는 과정
4단계는 오브젝트들을 서로 묶어주는 과정
5단계는 이런 묶인 녀석들을 메모리에서 돌아가도록 하는 로더라는 녀석을 붙이는 과정을 거친다.

이렇게 단계가 나누어져 있다 보니,
gcc에서는 단계별 결과를 추출해 낼수 있다.

예를들어, 매크로가 복잡해서 소스 추적이 힘들경우
매크로 프로세서를 거친 결과만을 뽑아내고 싶다고 한다면
gcc -E 옵션을 사용하면 매크로가 제외된(처리된) 결과가 stdout으로 나온다.
gcc -E 소스파일 > 저장할 파일
이런식으로 한단계만 거쳐 디버깅에 사용할 수도 있다.

추가적으로, Makefile 에서
CPP 는 C++이 아니라 C PreProcessor = 매크로 프로세서 이고
CC 는 C Compiler
AS 는 Assembler
LD 는 Loader (링커) 를 의미한다.

2010/03/02 - [프로그램 사용/gcc] - gcc의 linker 옵션
2010/01/27 - [프로그램 사용/gcc] - gcc 매크로만 확장하기 (preprocessor/전처리기)
Posted by 구차니
프로그램 사용/gcc2010. 3. 2. 17:34
gcc 옵션중에 헷갈리는게 있다.
-L과 -l이 그녀석인데, 비슷비슷해서 조금 헷갈린다.

아무튼 -L은 디렉토리(경로)를
-l은 특정 라이브러리 파일을 설정하는데 사용된다.

       -l library
           Search the library named library when linking.  (The second alternative with the library as a separate argu-
           ment is only for POSIX compliance and is not recommended.)

           It makes a difference where in the command you write this option; the linker searches and processes libraries
           and object files in the order they are specified.  Thus, foo.o -lz bar.o searches library z after file foo.o
           but before bar.o.  If bar.o refers to functions in z, those functions may not be loaded.

           The linker searches a standard list of directories for the library, which is actually a file named libli-
           brary.a.  The linker then uses this file as if it had been specified precisely by name.

           The directories searched include several standard system directories plus any that you specify with -L.

           Normally the files found this way are library files---archive files whose members are object files.  The
           linker handles an archive file by scanning through it for members which define symbols that have so far been
           referenced but not defined.  But if the file that is found is an ordinary object file, it is linked in the
           usual fashion.  The only difference between using an -l option and specifying a file name is that -l sur-
           rounds library with lib and .a and searches several directories.

       -Ldir
           Add directory dir to the list of directories to be searched for -l.

       LIBRARY_PATH
           The value of LIBRARY_PATH is a colon-separated list of directories, much like PATH.  When configured as a
           native compiler, GCC tries the directories thus specified when searching for special linker files, if it
           can’t find them using GCC_EXEC_PREFIX.  Linking using GCC also uses these directories when searching for
           ordinary libraries for the -l option (but directories specified with -L come first).

[링크 : http://linux.die.net/man/1/gcc]
Posted by 구차니
프로그램 사용/gcc2010. 2. 11. 16:05
gcc -static [파일이름]

위와 같이 컴파일 하면 정적으로 링크한다.
예를들어 /sbin/init 등이 제대로 되는지 확인할때
init를 임의로 만들어 정적으로 컴파일 후에 /sbin/init 치환하면
/lib 뒤질일 없이 바로 실행이 가능하므로 디버깅이 용이해진다.

하지만, 용량이 무지 커지니 주의!

-static
On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect.

[링크: http://linux.die.net/man/1/gcc]

[링크 : http://www.faqs.org/docs/Linux-mini/NFS-Root.html#toc5]
[링크 : http://lists.busybox.net/pipermail/busybox/2007-May/061479.html]
[링크 : http://www.linuxquestions.org/questions/linux-kernel-70/2.4.36.3-busyboxs-init-hangs-at-freeing-unused-kernel-memory-645556/]
Posted by 구차니
프로그램 사용/gcc2010. 2. 10. 10:45
gcc에서 지원하고 있는 언어를 확인하고 싶을때 사용하는 방법으로
gcc의 버전 정보중에 --enable-languages 의 값을 확인하면 된다.

$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.2 20070626 (Red Hat 4.1.2-13)

$ sh4-linux-gcc -v
Using built-in specs.
Target: sh4-linux
Configured with: ../configure --host=i686-pc-linux-gnu --target=sh4-linux --prefix=/opt/STM/STLinux-2.2/devkit/sh4 --exec-prefix=/opt/STM/STLinux-2.2/devkit/sh4 --bindir=/opt/STM/STLinux-2.2/devkit/sh4/bin --sbindir=/opt/STM/STLinux-2.2/devkit/sh4/sbin --sysconfdir=/opt/STM/STLinux-2.2/devkit/sh4/etc --datadir=/opt/STM/STLinux-2.2/devkit/sh4/share --includedir=/opt/STM/STLinux-2.2/devkit/sh4/include --libdir=/opt/STM/STLinux-2.2/devkit/sh4/lib --libexecdir=/opt/STM/STLinux-2.2/devkit/sh4/libexec --localstatedir=/opt/STM/STLinux-2.2/devkit/sh4/var --sharedstatedir=/opt/STM/STLinux-2.2/devkit/sh4/share --mandir=/opt/STM/STLinux-2.2/devkit/sh4/man --infodir=/opt/STM/STLinux-2.2/devkit/sh4/info --program-prefix=sh4-linux- --with-local-prefix=/opt/STM/STLinux-2.2/devkit/sh4 --with-sysroot=/opt/STM/STLinux-2.2/devkit/sh4/target --enable-languages=c,c++ --enable-threads=posix --enable-nls --enable-c99 --enable-long-long --with-system-zlib --enable-shared --enable-multilib --enable-symvers=gnu --enable-__cxa_atexit --with-gxx-include-dir=${prefix}/target/usr/include/c++/4.1.1
Thread model: posix
gcc version 4.1.1 (STMicroelectronics/Linux Base 4.1.1-23)


[링크 : http://korea.gnu.org/manual/release/install/configure.html]
Posted by 구차니
프로그램 사용/gcc2010. 1. 27. 17:18
#if 문이라던가 각종 전처리기용 문구들은
여러가지 확장을 통해서 컴파일을 하기 때문에 source insight 등의 힘을 빌려도 분석하기 어려운 면이 있다.

일반적으로 컴파일러는 전처리기 - 컴파일 - 어셈블 - 링크 과정을 거치는데(아마도?)
전처리기 까지만 거친 결과를 stdout 으로 출력해준다.

$ man gcc
       -E  Stop after the preprocessing stage; do not run the compiler proper.
            The output is in the form of preprocessed source code, which is sent to the standard output.

           Input files which don't require preprocessing are ignored.

[링크 : http://linux.die.net/man/1/gcc]

$ cat test.c
#if 1
int test;
#else
int tt;
#endif

int main()
{
        return 0;
}

$ gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"

int test;




int main()
{
 return 0;
}


#include 하는 모든 파일을 확장하기 때문에, #include <stdio.h>만 해도 내용이 엄청 길어진다.
그리고 줄단위로 처리하기 때문에 사라진 #if 문 대신 엔터만 남아 위와 같이 휑~하게 나왔다.


[링크 : http://cafe.naver.com/devctrl/949]
Posted by 구차니
프로그램 사용/gcc2009. 9. 21. 21:33
--sysroot=dir
    Use dir as the logical root directory for headers and libraries. For example, if the compiler would normally search for headers in /usr/include and libraries in /usr/lib, it will instead search dir/usr/include and dir/usr/lib.

    If you use both this option and the -isysroot option, then the --sysroot option will apply to libraries, but the -isysroot option will apply to header files.

    The GNU linker (beginning with version 2.16) has the necessary support for this option. If your linker does not support this option, the header file aspect of --sysroot will still work, but the library aspect will not.

-isysroot dir
    This option is like the --sysroot option, but applies only to header files.  See the --sysroot option for
    more information.

[링크 : http://linux.die.net/man/1/gcc]

기본값은 /usr/include 인데, -sysroot로 기본 디렉토리를 변경 시키면
<stdio.h> 와 같은 파일도 찾지 못해 link 에러를 발생시키며 컴파일이 실패된다.

$ more test.c
#include <stdio.h>

int main(int argc, char **argv)
{
        printf("hello world\n");
        return 0;
}

$ gcc --sysroot=/ test.c
/usr/bin/ld: this linker was not configured to use sysroots
collect2: ld returned 1 exit status



아무튼, 크로스컴파일과 같이 특정 include 디렉토리를 사용해야 할 경우,
--sysroot 를 이용해서 변경하면 될 듯 하다
Posted by 구차니
프로그램 사용/gcc2009. 5. 28. 23:06
오늘 희한한 switch - case문을 들었다

case 1 ... 10:

이런식으로 기존에는
case 1:
case 2:
...
case 9:
case 10:
이라고 쓰던것을 줄여 쓸수 있다고 한다.

검색을 해보니 c#과 gcc에서 지원하고 C99 등에는 검색이 걸려 나오지 않는다.
정체가 머냐?


[링크 : http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic62939.aspx]
[링크 : http://www.devhood.com/messages/message_view-2.aspx?thread_id=13708]
Posted by 구차니
프로그램 사용/gcc2009. 2. 18. 17:13
char str[] = "Hello world!";

만약에 키보드로는 입력 불가능한 control chacter(제어문자)를 문자열 상에 넣고 싶으면 어떻게 해야 할까?
일단 가장 흔히 쓰는 제어문자로는

\t
\n

인데, 자신이 직접 헥사로 넣고 싶다면

\x20

이런식으로 입력을 하면된다.


덧 : 개인적으로는 ISO8859 용 스트링의 첫 바이트에 들어 가는 제어문자를 넣는 방법으로 활용하고 있다.
덧2: 솔찍히 이실직고 하자면, 직접해보니 오작동을 하는 경향이 보인다.
      비쥬얼 스튜디오나 일반 gcc 에서도 테스트를 해봐야겠다.
Posted by 구차니