GCC installation on Android

作者详细介绍了如何在没有root权限的Android设备上安装GCC,通过使用KBox环境和一系列配置步骤实现了在ARMv7 CPU上的C/C++语言编译。文章深入探讨了Android的安全模型、KBox环境的引入以及如何解决传统Linux应用程序无法在Android中安装的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Decheng (Robbie) Fan
2014-08-26
I wanted to install GCC (GNU Compiler Collection) on my Android phone.
Yes, you read it correctly, my Android phone! Not a Linux PC or Windows
PC. Not a Windows 8 tablet.
The reason that I want to do it is to exploit more power out of my
Android phone. I understand that Android is not Linux, so to use
Android without rooting, I must perform all the installation "the
Android way".
Android controls security based on application level. Each application
is run in its own user account, with limited access to system resources
and to other applications. An application can access system resources
according to the security requirements of it, which are confirmed by
the user during installation. It cannot break the barrier the system
sets on it. By default, it cannot access other applications through the
file system or through process manipulation. It can only call another
application's "Activity", or "Share" contents with another other
application. "Activity" and "Share" are Android UI concepts for
connecting applications together.
This strict security model means that, a non-rooted Android device
cannot install Linux applications in the traditional way--because
traditional Linux applications require access to some common
directories such as /usr/lib, which is forbidden in Android. In
addition, the default directory locations are not usually available on
Android.
So I went on exploring a way to get GCC installed on my KBox
environment. What is KBox, you might ask? It is a minimalist
command-line environment introduced by Kevin Boone. Visit his website
at http://kevinboone.net/index.html to get documentation on KBox and
how to install it. The current version is KBox2, by the way.
Although there is a package for GCC on KBox2, my environment is the
first generation KBox. I don't have an alternate Android device so I
could only do with 1st-gen KBox. I downloaded the KBox2 manual
installation package and installed it into a temporary directory
(within my real KBox environment). The installation is not
global--manual configuration is required to use it as the default shell
environment. However, because I already have a first-gen KBox, what I
need is the `dpkg*' utility only. So I examined the `dpkg*' commands
available, and found two symbolic links--dpkg and dpkg-deb, pointing to
the busybox executable of KBox2. I copied the busybox of KBox2 and
renamed it to kbox2_busybox, and then manually created the dpkg and
dpkg-deb symbolic links.
Then I used the dpkg command to extract the gcc 4.7 package downloaded
from Kevin Boone's website. It successfully installs gcc to my KBox
installation: /data/data/jackpal.androidterm/app_HOME/kbox/usr/lib/gcc.
By the way, my $KBOX variable points to
/data/data/jackpal.androidterm/app_HOME/kbox.
After installation, there is already an executable shell script called
gcc under the $KBOX/usr/bin directory. I tried to adapt it and copy it
into my actual bin directory--$KBOX/bin--to release it to
manufactoring, but it doesn't work out of the box.
The original script has one inconvenience: it puts all environment
variables on one line and then call the gcc executable file. It looks
like (below is one line): 
TMPDIR=$KBOX/tmp PATH=$PATH:$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7
/bin $KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/bin/gcc "$@"
For convenience, I changed it to export the environment variables, and
then call the gcc executable, like:
export TMPDIR=$KBOX/tmp
export PATH=$PATH:$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/bin
$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/bin/gcc "$@"
Another benefit of using `export' is that in some (older) shells,
environment variables specified on the command line without exporting
won't be propagated to child processes, which would cause problems.
But it didn't work. To fix it, I started investigating. Later I also
found out how to print debugging information and how to display verbose
information of the compiler. The discovery was later than I tried
several ways, but it is helpful, so I put the tips here:
- Use "gcc --print-search-dir" to show its search directories,
  including compiler program paths, include paths and library paths.
- Use "gcc -v" to print all sub-commands that have been run during a
  compilation process.
- gcc option "-Wl,-option" will pass an option to the linker, such as
  "-Wl,--debug".
With the help of the debugging commands above, I did the things below
to make the configuration correct, for compiling a program written in
the C programming language (C++ compilation--g++--is not covered here).
First of all, the include directories are not specified yet. I found
that two include paths are necessary: $KBOX/usr/lib/gcc/arm-linux-
androideabi/4.7/arm-linux-androideabi/include contains stdio.h and the
`sys' directory; $KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/lib/gcc/
arm-linux-androideabi/4.7/include contains stdarg.h. A third directory,
$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/lib/gcc/arm-linux-
androideabi/4.7/include-fixed, contains stdio.h, but is optional.
GCC_EXEC_PREFIX=$KBOX/usr/lib/gcc/ is necessary. It must end with a
slash (the path separator). It will be used to append pre-configured
directories after it. However most pre-configured directories don't
match the KBox2 package installation, so it's just for reference.
liblto_plugin.so is used for link time optimization. Note that it
locates under $KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/libexec/gcc/
arm-linux-androideabi/4.7. It is a shared library (`.so' means "shared
object") for the linker. Together with the directory containing the
compiler executables, two directories need to be included in both PATH
and COMPILER_PATH:
- $KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/bin
- $KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/libexec/gcc/arm-linux-
  androideabi/4.7
Then I found that, gcc still doesn't work. By using "gcc -v test.c", I
got much more debug information. It contains the command lines it uses
to call sub-programs. Firstly it calls `cc1' to compile the C program
into assembly (a `.s' file). Then it calls `as' to assemble the
assembly code into machine code (a `.o' file, meaning "object"). Later,
it calls `collect2' to link the object file with standard stubs (two .o
files, crtbegin_dynamic.o and crtend_android.o) and standard libraries
(lib*.a files, here libgcc.a, libc.a and libdl.a).
I can run the individual commands to see the output of each step. What
I observed is that the first two commands ran successfully--`cc1' and
`as' do generate expected outputs. The third command `collect2',
however, doesn't generate any output. No error messages are issued
either. I checked online what the command is for, and got the
information that it is a wrapper (frontend) for the `ld' command. In
addition to `ld', `collect2' supports C++ global object
constructor/destructor calling code generation. So it is a necessary
tool, but why doesn't it generate any output?
During my testing I accidentally found that the individual command of
`collect2' reaches the length limit of a shell command on the command
line. But later I found that this is not the reason, because the length
limit only has effect on the terminal command line. It doesn't apply
when running a shell script, as I tried adding a lot of dummy non-space
characters to the command line, whether it works or not doesn't depend
on this.
I found another interesting thing: when I call `collect2' with its
full path, /data/data/jackpal.androidterm/app_HOME/kbox/usr/lib/gcc/
arm-linux-androideabi/4.7/libexec/gcc/arm-linux-androideabi/4.7/
collect2, it doesn't work. But if I set up all necessary environment
variables and call it by its name alone, `collect2', it works fine!
I downloaded gcc 4.7.4 source code and read through the main() function
of collect2. I found that in some step it gets its executable file name
by examining the last path component of argv[0]. I'm not sure whether
there is any problem regarding this mechanism in the version of gcc
contained in KBox2, but for safety I renamed collect2 to real_collect2,
and wrote a shell script `collect2' to replace it. In the shell script,
I just put the lines below:
#!/system/bin/sh
real_collect2 "$@"
By using this shell script, the linker, `ld', seems to get invoked
correctly. The only problem left here is that it mentions:
ld: cannot find -lgcc
Then I looked up the `ld' documentation and found that the `-l' switch
is used to specify the library name. So `-lgcc' means libgcc.a or
libgcc.so. I searched through the gcc installation directory tree and
found libgcc.a located under two places. I chose one place, plus the
location for standard C library (libc.a), I added two paths to
LIBRARY_PATH: $KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/arm-linux-
androideabi/lib:$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/lib/gcc/
arm-linux-androideabi/4.7.
Then, my gcc installation can compile C programs! How exciting! So it's
the end of this story. Later I will of course investigate how to make
g++ work. But for now I can already use a huge base of C programs.
The final `gccrun' shell script contains the lines below (backslash at
the end of lines are used to connect two lines due to line length
limit of SJTU BBS):
#!/system/bin/sh
export PATH=$PATH:$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/bin:\
$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/libexec/gcc/arm-linux-\
androideabi/4.7
export GCC_EXEC_PREFIX=$KBOX/usr/lib/gcc/
export COMPILER_PATH=$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/bin\
:$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/libexec/gcc/arm-linux-
androideabi/4.7
export LIBRARY_PATH=$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/arm-\
linux-androideabi/lib:$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/lib\
/gcc/arm-linux-androideabi/4.7
export C_INCLUDE_PATH=$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7/arm-\
linux-androideabi/include:$KBOX/usr/lib/gcc/arm-linux-androideabi/4.7\
/lib/gcc/arm-linux-androideabi/4.7/include
"$@"
To compile a C program, I just type "gccrun gcc program.c" and I will
get an "a.out". I will also make programs using "gccrun make" as long
as there is a Makefile available.
Terminologies:
busybox - a multi-call binary program that supports many useful
    commands. It also provides the default shell for 1st-gen KBox (run
    "busybox sh"). 1st-gen KBox busybox doesn't have dpkg support but
    KBox2 busybox does.
chmod - changes access rights--read, write and execute--to a file: for
    the file owner, for a specified group, and for all others.
dpkg - within the context of KBox2, it is a command used to extract
    `.deb' packages, such as those on Kevin Boone's website, including
    GCC. This command is a symbolic link to the KBox2 busybox
    executable.
GCC - GNU Compiler Collection. Here the GCC is built for Android and
    runs on the ARMv7 CPU. It supports C and C++ languages, standard
    libraries and Android-specific libraries.
KBox/KBox2 - a busybox command line environment created by Kevin Boone.
    These environments don't require rooting the Android device, and
    works with Jack Palevich's Android Terminal.
ld - the static linker contained in gcc. The linker links object files
    together to make an executable file.
.so files - shared object files. Like DLLs on Windows, they are
    dynamically-linked libraries loaded for an executable file at
    runtime.
shell script - a script program file that is interpreted by a Linux or
    Unix shell, such as /system/bin/sh or "busybox sh". It can be set
    to be executable by using the `chmod' command.
symbolic link - a mechanism supported by most Linux file systems,
    including Android's internal flash memory file system. Use command
    `ln' with `-s' switch to create symbolic links.
/system/bin/linker - the dynamic linker, which is used to load and link
    to `.so' files. When used during the static link stage, it can help
    the linker generate function calls to the shared object file. It's
    somewhat like the feature of import libraries in Win32. When used
    during runtime, it helps the executable file to load the shared
    object file into virtual memory and gets the address of the
    function in the shared object. dlopen/dlsym/dlclose/dlerror
    functions are used for dynamic loading, just like Win32 API
    LoadLibrary/GetProcAddress/FreeLibrary functions.

1 #!/bin/bash 2 3 # variables, parent script must set it: 4 # SRS_JOBS: the build jobs. 5 # SrsArmMakeOptions: the arm make options for ubuntu12(armhf, v7cpu) 6 7 ##################################################################################### 8 ##################################################################################### 9 # prepare the depends tools and libraries 10 # DEPENDS: options.sh, only when user options parsed, the depends tools are known. 11 ##################################################################################### 12 ##################################################################################### 13 14 ##################################################################################### 15 # Check OS and CPU architectures. 16 ##################################################################################### 17 if [[ $OS_IS_UBUNTU != YES && $OS_IS_CENTOS != YES && $OS_IS_OSX != YES && $SRS_CYGWIN64 != YES ]]; then 18 if [[ $SRS_CROSS_BUILD != YES && $SRS_GENERIC_LINUX != YES ]]; then 19 echo "Your OS `uname -s` is not supported." 20 if [[ $(uname -s) == "Linux" ]]; then 21 echo "Please try --generic-linux=on for other Linux systems." 22 fi 23 exit 1 24 fi 25 fi 26 27 # The absolute path of SRS_OBJS, for prefix and PKG_CONFIG_PATH 28 SRS_DEPENDS_LIBS=$(mkdir -p $SRS_OBJS && cd $SRS_OBJS && pwd) 29 echo -n "SRS_JOBS: $SRS_JOBS, SRS_DEPENDS_LIBS: ${SRS_DEPENDS_LIBS}" 30 if [[ ! -z $OS_IS_LINUX ]]; then echo -n ", OS_IS_LINUX: $OS_IS_LINUX"; fi 31 if [[ ! -z $OS_IS_OSX ]]; then echo -n ", OS_IS_OSX: $OS_IS_OSX"; fi 32 if [[ ! -z $OS_IS_CYGWIN ]]; then echo -n ", OS_IS_CYGWIN: $OS_IS_CYGWIN"; fi 33 if [[ ! -z $OS_IS_UBUNTU ]]; then echo -n ", OS_IS_UBUNTU: $OS_IS_UBUNTU"; fi 34 if [[ ! -z $OS_IS_CENTOS ]]; then echo -n ", OS_IS_CENTOS: $OS_IS_CENTOS"; fi 35 if [[ ! -z $SRS_CROSS_BUILD ]]; then echo -n ", SRS_CROSS_BUILD: $SRS_CROSS_BUILD"; fi 36 if [[ ! -z $OS_IS_LOONGARCH64 ]]; then echo -n ", OS_IS_LOONGARCH64: $OS_IS_LOONGARCH64"; fi 37 if [[ ! -z $OS_IS_MIPS64 ]]; then echo -n ", OS_IS_MIPS64: $OS_IS_MIPS64"; fi 38 if [[ ! -z $OS_IS_LOONGSON ]]; then echo -n ", OS_IS_LOONGSON: $OS_IS_LOONGSON"; fi 39 if [[ ! -z $OS_IS_X86_64 ]]; then echo -n ", OS_IS_X86_64: $OS_IS_X86_64"; fi 40 if [[ ! -z $OS_IS_RISCV ]]; then echo -n ", OS_IS_RISCV: $OS_IS_RISCV"; fi 41 echo "" 42 43 ##################################################################################### 44 # Check dependency tools. 45 ##################################################################################### 46 if [[ $SRS_OSX == YES ]]; then 47 brew --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 48 echo "Please install brew at https://brew.sh/"; exit $ret; 49 fi 50 fi 51 # Check perl, which is depended by automake for building libopus etc. 52 perl --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 53 if [[ $OS_IS_CENTOS == YES ]]; then 54 echo "Please install perl by:" 55 echo " yum install -y perl" 56 elif [[ $OS_IS_UBUNTU == YES ]]; then 57 echo "Please install perl by:" 58 echo " apt install -y perl" 59 else 60 echo "Please install perl" 61 fi 62 exit $ret; 63 fi 64 gcc --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 65 if [[ $OS_IS_CENTOS == YES ]]; then 66 echo "Please install gcc by:" 67 echo " yum install -y gcc" 68 elif [[ $OS_IS_UBUNTU == YES ]]; then 69 echo "Please install gcc by:" 70 echo " apt install -y gcc" 71 else 72 echo "Please install gcc" 73 fi 74 exit $ret; 75 fi 76 g++ --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 77 if [[ $OS_IS_CENTOS == YES ]]; then 78 echo "Please install g++ by:" 79 echo " yum install -y gcc-c++" 80 elif [[ $OS_IS_UBUNTU == YES ]]; then 81 echo "Please install g++ by:" 82 echo " apt install -y g++" 83 else 84 echo "Please install gcc-c++" 85 fi 86 exit $ret; 87 fi 88 make --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 89 if [[ $OS_IS_CENTOS == YES ]]; then 90 echo "Please install make by:" 91 echo " yum install -y make" 92 elif [[ $OS_IS_UBUNTU == YES ]]; then 93 echo "Please install make by:" 94 echo " apt install -y make" 95 else 96 echo "Please install make" 97 fi 98 exit $ret; 99 fi 100 patch --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 101 if [[ $OS_IS_CENTOS == YES ]]; then 102 echo "Please install patch by:" 103 echo " yum install -y patch" 104 elif [[ $OS_IS_UBUNTU == YES ]]; then 105 echo "Please install patch by:" 106 echo " apt install -y patch" 107 else 108 echo "Please install patch" 109 fi 110 exit $ret; 111 fi 112 unzip -v >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 113 if [[ $OS_IS_CENTOS == YES ]]; then 114 echo "Please install unzip by:" 115 echo " yum install -y unzip" 116 elif [[ $OS_IS_UBUNTU == YES ]]; then 117 echo "Please install unzip by:" 118 echo " apt install -y unzip" 119 else 120 echo "Please install unzip" 121 fi 122 exit $ret; 123 fi 124 automake --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 125 if [[ $OS_IS_CENTOS == YES ]]; then 126 echo "Please install automake by:" 127 echo " yum install -y automake" 128 elif [[ $OS_IS_UBUNTU == YES ]]; then 129 echo "Please install automake by:" 130 echo " apt install -y automake" 131 else 132 echo "Please install automake" 133 fi 134 exit $ret; 135 fi 136 if [[ $SRS_VALGRIND == YES ]]; then 137 valgrind --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 138 echo "Please install valgrind"; exit $ret; 139 fi 140 if [[ ! -f /usr/include/valgrind/valgrind.h ]]; then 141 echo "Please install valgrind-dev"; exit $ret; 142 fi 143 fi 144 # Check tclsh, which is depended by SRT. 145 if [[ $SRS_SRT == YES ]]; then 146 tclsh <<< "exit" >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then 147 if [[ $OS_IS_CENTOS == YES ]]; then 148 echo "Please install tclsh by:" 149 echo " yum install -y tcl" 150 elif [[ $OS_IS_UBUNTU == YES ]]; then 151 echo "Please install tclsh by:" 152 echo " apt install -y tclsh" 153 else 154 echo "Please install tclsh" 155 fi 156 exit $ret; 157 fi 158 cmake --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 159 if [[ $OS_IS_CENTOS == YES ]]; then 160 echo "Please install cmake by:" 161 echo " yum install -y cmake" 162 elif [[ $OS_IS_UBUNTU == YES ]]; then 163 echo "Please install cmake by:" 164 echo " apt install -y cmake" 165 else 166 echo "Please install cmake" 167 fi 168 exit $ret; 169 fi 170 fi 171 pkg-config --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 172 echo "Please install pkg-config"; exit $ret; 173 fi 174 which ls >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then 175 if [[ $OS_IS_CENTOS == YES ]]; then 176 echo "Please install which by:" 177 echo " yum install -y which" 178 elif [[ $OS_IS_UBUNTU == YES ]]; then 179 echo "Please install which by:" 180 echo " apt install -y which" 181 else 182 echo "Please install which" 183 fi 184 exit $ret; 185 fi 186 187 ##################################################################################### 188 # Try to load cache if exists /usr/local/srs-cache 189 ##################################################################################### 190 # Use srs-cache from base image. See https://github.com/ossrs/dev-docker/blob/ubuntu20-cache/Dockerfile 191 # Note that the cache for cygwin is not under /usr/local, but copy to objs instead. 192 if [[ -d /usr/local/srs-cache/srs/trunk/objs && $(pwd) != "/usr/local/srs-cache/srs/trunk" && $SRS_BUILD_CACHE == YES ]]; then 193 SOURCE_DIR=$(ls -d /usr/local/srs-cache/srs/trunk/objs/Platform-SRS${SRS_MAJOR}-* 2>/dev/null|head -n 1) 194 if [[ -d $SOURCE_DIR ]]; then 195 TARGET_DIR=${SRS_OBJS}/${SRS_PLATFORM} && 196 echo "Build from cache, source=$SOURCE_DIR, target=$TARGET_DIR" && 197 rm -rf $TARGET_DIR && mkdir -p ${SRS_OBJS} && cp -R $SOURCE_DIR $TARGET_DIR && 198 du -sh /usr/local/srs-cache/srs/trunk/objs/Platform-* && 199 du -sh /usr/local/srs-cache/srs/trunk/objs/Platform-*/* && 200 du -sh objs/Platform-* && 201 ls -lh objs 202 fi 203 fi 204 205 ##################################################################################### 206 # Check for address sanitizer, see https://github.com/google/sanitizers 207 ##################################################################################### 208 if [[ $SRS_SANITIZER == YES && $OS_IS_X86_64 == YES ]]; then 209 echo 'int main() { return 0; }' > ${SRS_OBJS}/test_sanitizer.c && 210 gcc -fsanitize=address -fno-omit-frame-pointer -g -O0 ${SRS_OBJS}/test_sanitizer.c \ 211 -o ${SRS_OBJS}/test_sanitizer 1>/dev/null 2>&1; 212 ret=$?; rm -rf ${SRS_OBJS}/test_sanitizer* 213 if [[ $ret -ne 0 ]]; then 214 echo "Please install libasan, see https://github.com/google/sanitizers"; 215 if [[ $OS_IS_CENTOS == YES ]]; then echo " sudo yum install -y libasan"; fi 216 exit $ret; 217 fi 218 fi 219 220 if [[ $SRS_SANITIZER == YES && $OS_IS_X86_64 == YES && $SRS_SANITIZER_STATIC == NO ]]; then 221 echo 'int main() { return 0; }' > ${SRS_OBJS}/test_sanitizer.c && 222 gcc -fsanitize=address -fno-omit-frame-pointer -static-libasan -g -O0 ${SRS_OBJS}/test_sanitizer.c \ 223 -o ${SRS_OBJS}/test_sanitizer 1>/dev/null 2>&1; 224 ret=$?; rm -rf ${SRS_OBJS}/test_sanitizer* 225 if [[ $ret -eq 0 ]]; then 226 echo "link static-libasan" 227 SRS_SANITIZER_STATIC=YES 228 fi 229 fi 230 231 if [[ $SRS_SANITIZER == YES && $OS_IS_X86_64 == YES && $SRS_SANITIZER_LOG == NO ]]; then 232 echo "#include <sanitizer/asan_interface.h>" > ${SRS_OBJS}/test_sanitizer.c && 233 echo "int main() { return 0; }" >> ${SRS_OBJS}/test_sanitizer.c && 234 gcc -fsanitize=address -fno-omit-frame-pointer -g -O0 ${SRS_OBJS}/test_sanitizer.c \ 235 -o ${SRS_OBJS}/test_sanitizer 1>/dev/null 2>&1; 236 ret=$?; rm -rf ${SRS_OBJS}/test_sanitizer* 237 if [[ $ret -eq 0 ]]; then 238 echo "libasan api found ok!"; 239 SRS_SANITIZER_LOG=YES 240 fi 241 fi 242 243 ##################################################################################### 244 # state-threads 245 ##################################################################################### 246 # check the cross build flag file, if flag changed, need to rebuild the st. 247 _ST_MAKE=linux-debug && _ST_OBJ="LINUX_`uname -r`_DBG" 248 # Always alloc on heap, @see https://github.com/ossrs/srs/issues/509#issuecomment-719931676 249 _ST_EXTRA_CFLAGS="-DMALLOC_STACK" 250 # For valgrind to detect memory issues. 251 if [[ $SRS_VALGRIND == YES ]]; then 252 _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DMD_VALGRIND" 253 fi 254 # for osx, use darwin for st, donot use epoll. 255 if [[ $SRS_OSX == YES ]]; then 256 _ST_MAKE=darwin-debug && _ST_OBJ="DARWIN_`uname -r`_DBG" 257 fi 258 # for windows/cygwin 259 if [[ $SRS_CYGWIN64 = YES ]]; then 260 _ST_MAKE=cygwin64-debug && _ST_OBJ="CYGWIN64_`uname -s`_DBG" 261 fi 262 # For Ubuntu, the epoll detection might be fail. 263 if [[ $OS_IS_UBUNTU == YES ]]; then 264 _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DMD_HAVE_EPOLL" 265 fi 266 # Whether enable debug stats. 267 if [[ $SRS_DEBUG_STATS == YES ]]; then 268 _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DDEBUG_STATS" 269 fi 270 # Pass the global extra flags. 271 if [[ $SRS_EXTRA_FLAGS != '' ]]; then 272 _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS $SRS_EXTRA_FLAGS" 273 fi 274 # Whether link as .so 275 if [[ $SRS_SHARED_ST == YES ]]; then 276 _ST_STATIC_ONLY=no; 277 else 278 _ST_STATIC_ONLY=yes; 279 fi 280 # The final args to make st. 281 _ST_MAKE_ARGS="${_ST_MAKE} STATIC_ONLY=${_ST_STATIC_ONLY}" 282 _ST_MAKE_ARGS="${_ST_MAKE_ARGS} CC=${SRS_TOOL_CC} AR=${SRS_TOOL_AR} LD=${SRS_TOOL_LD} RANDLIB=${SRS_TOOL_RANDLIB}" 283 # Patched ST from https://github.com/ossrs/state-threads/tree/srs 284 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/st/libst.a ]]; then 285 rm -rf ${SRS_OBJS}/st && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/st ${SRS_OBJS}/ && 286 echo "The state-threads is ok." 287 else 288 echo "Building state-threads." && 289 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/st-srs ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/st ${SRS_OBJS}/st && 290 cp -rf ${SRS_WORKDIR}/3rdparty/st-srs ${SRS_OBJS}/${SRS_PLATFORM}/ && 291 env EXTRA_CFLAGS="${_ST_EXTRA_CFLAGS}" make -C ${SRS_OBJS}/${SRS_PLATFORM}/st-srs ${_ST_MAKE_ARGS} && 292 mkdir -p ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/st && 293 cp -f ${SRS_OBJS}/${SRS_PLATFORM}/st-srs/${_ST_OBJ}/st.h ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/st/ && 294 cp -f ${SRS_OBJS}/${SRS_PLATFORM}/st-srs/${_ST_OBJ}/libst.a ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/st/ && 295 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/st ${SRS_OBJS}/ && 296 echo "The state-threads is ok." 297 fi 298 # check status 299 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build state-threads failed, ret=$ret"; exit $ret; fi 300 301 ##################################################################################### 302 # nginx for HLS, nginx-1.5.0 303 ##################################################################################### 304 function write_nginx_html5() 305 { 306 cat<<END > ${html_file} 307 <video width="100%" autoplay controls autobuffer type="application/vnd.apple.mpegurl" 308 src="${hls_stream}"> 309 </video> 310 END 311 } 312 # create the nginx dir, for http-server if not build nginx 313 mkdir -p ${SRS_OBJS}/nginx 314 315 # the demo dir. 316 # create forward dir 317 mkdir -p ${SRS_OBJS}/nginx/html/live && 318 html_file=${SRS_OBJS}/nginx/html/live/livestream.html && hls_stream=livestream.m3u8 && write_nginx_html5 && 319 320 # copy players to nginx html dir. 321 rm -rf ${SRS_OBJS}/nginx/html/players && 322 cp -rf $SRS_WORKDIR/research/players ${SRS_OBJS}/nginx/html/ && 323 324 # for favicon.ico 325 rm -rf ${SRS_OBJS}/nginx/html/favicon.ico && 326 cp -f $SRS_WORKDIR/research/api-server/static-dir/favicon.ico ${SRS_OBJS}/nginx/html/favicon.ico && 327 328 # For srs-console. 329 rm -rf ${SRS_OBJS}/nginx/html/console && 330 cp -rf $SRS_WORKDIR/research/console ${SRS_OBJS}/nginx/html/ && 331 332 # For SRS signaling. 333 rm -rf ${SRS_OBJS}/nginx/html/demos && 334 cp -rf $SRS_WORKDIR/3rdparty/signaling/www/demos ${SRS_OBJS}/nginx/html/ && 335 336 # For home page index.html 337 rm -rf ${SRS_OBJS}/nginx/html/index.html && 338 cp -f $SRS_WORKDIR/research/api-server/static-dir/index.html ${SRS_OBJS}/nginx/html/index.html && 339 340 # nginx.html to detect whether nginx is alive 341 echo "Nginx is ok." > ${SRS_OBJS}/nginx/html/nginx.html 342 343 # check status 344 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build web pages failed, ret=$ret"; exit $ret; fi 345 346 ##################################################################################### 347 # Generate default self-sign certificate for HTTPS server, test only. 348 ##################################################################################### 349 if [[ ! -f $SRS_WORKDIR/conf/server.key || ! -f $SRS_WORKDIR/conf/server.crt ]]; then 350 openssl genrsa -out $SRS_WORKDIR/conf/server.key 2048 && 351 openssl req -new -x509 -key $SRS_WORKDIR/conf/server.key -out $SRS_WORKDIR/conf/server.crt -days 3650 \ 352 -subj "/C=CN/ST=Beijing/L=Beijing/O=Me/OU=Me/CN=ossrs.net" && 353 echo "Generate test-only self-sign certificate files" 354 fi 355 356 ##################################################################################### 357 # openssl, for rtmp complex handshake and HLS encryption. 358 ##################################################################################### 359 if [[ $SRS_SSL == YES && $SRS_USE_SYS_SSL == YES ]]; then 360 echo "Warning: Use system libssl, without compiling openssl." 361 fi 362 # @see http://www.openssl.org/news/secadv/20140407.txt 363 # Affected users should upgrade to OpenSSL 1.1.0e. Users unable to immediately 364 # upgrade can alternatively recompile OpenSSL with -DOPENSSL_NO_HEARTBEATS. 365 if [[ $SRS_SSL == YES && $SRS_USE_SYS_SSL != YES ]]; then 366 OPENSSL_OPTIONS="-no-shared -no-threads -DOPENSSL_NO_HEARTBEATS" 367 OPENSSL_CONFIG="./config" 368 # https://stackoverflow.com/questions/15539062/cross-compiling-of-openssl-for-linux-arm-v5te-linux-gnueabi-toolchain 369 if [[ $SRS_CROSS_BUILD == YES ]]; then 370 OPENSSL_CONFIG="./Configure linux-generic32" 371 if [[ $SRS_CROSS_BUILD_ARCH == "arm" ]]; then OPENSSL_CONFIG="./Configure linux-armv4"; fi 372 if [[ $SRS_CROSS_BUILD_ARCH == "aarch64" ]]; then OPENSSL_CONFIG="./Configure linux-aarch64"; fi 373 if [[ $SRS_CROSS_BUILD_ARCH == "mipsel" ]]; then OPENSSL_CONFIG="./Configure linux-mips32"; fi 374 elif [[ ! -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl/lib/libssl.a ]]; then 375 # Try to use exists libraries. 376 if [[ -f /usr/local/ssl/lib/libssl.a && $SRS_SSL_LOCAL == NO ]]; then 377 (mkdir -p ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl/lib && cd ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl/lib && 378 cp /usr/local/ssl/lib/libssl.a . && cp /usr/local/ssl/lib/libcrypto.a . && 379 mkdir -p /usr/local/ssl/lib/pkgconfig && cp -rf /usr/local/ssl/lib/pkgconfig .) 380 (mkdir -p ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl/include && cd ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl/include && 381 cp -rf /usr/local/ssl/include/openssl .) 382 fi 383 # Warning if not use the system ssl. 384 if [[ -f /usr/local/ssl/lib/libssl.a && $SRS_SSL_LOCAL == YES ]]; then 385 echo "Warning: Local openssl is on, ignore system openssl" 386 fi 387 fi 388 # Patch for loongarch mips64, disable ASM for build failed message as bellow: 389 # Error: opcode not supported on this processor: mips3 (mips3) 390 if [[ $OS_IS_MIPS64 == YES ]]; then OPENSSL_CONFIG="./Configure linux64-mips64"; fi 391 if [[ $OS_IS_LOONGSON == YES ]]; then OPENSSL_OPTIONS="$OPENSSL_OPTIONS -no-asm"; fi 392 # For RTC, we should use ASM to improve performance, not a little improving. 393 if [[ $SRS_RTC == NO || $SRS_NASM == NO ]]; then 394 OPENSSL_OPTIONS="$OPENSSL_OPTIONS -no-asm" 395 echo "Warning: NASM is off, performance is hurt" 396 fi 397 # Mac OS X can have issues (its often a neglected platform). 398 # @see https://wiki.openssl.org/index.php/Compilation_and_Installation 399 if [[ $SRS_OSX == YES ]]; then 400 export KERNEL_BITS=64; 401 fi 402 # Use 1.0 if required. 403 if [[ $SRS_SSL_1_0 == YES ]]; then 404 OPENSSL_AR="$SRS_TOOL_AR -r" # For openssl 1.0, MUST specifies the args for ar or build faild. 405 OPENSSL_CANDIDATE="openssl-OpenSSL_1_0_2u" && 406 OPENSSL_UNZIP="tar xf ${SRS_WORKDIR}/3rdparty/$OPENSSL_CANDIDATE.tar.gz -C ${SRS_OBJS}/${SRS_PLATFORM}" 407 else 408 OPENSSL_AR="$SRS_TOOL_AR" 409 OPENSSL_CANDIDATE="openssl-1.1-fit" && 410 OPENSSL_UNZIP="cp -R ${SRS_WORKDIR}/3rdparty/$OPENSSL_CANDIDATE ${SRS_OBJS}/${SRS_PLATFORM}/" 411 fi 412 # 413 # https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options 414 # Already defined: -no-shared -no-threads -no-asm 415 # Should enable: -no-dtls -no-dtls1 -no-ssl3 416 # Might able to disable: -no-ssl2 -no-comp -no-idea -no-hw -no-engine -no-dso -no-err -no-nextprotoneg -no-psk -no-srp -no-ec2m -no-weak-ssl-ciphers 417 # Note that we do not disable more features, because no file could be removed. 418 #OPENSSL_OPTIONS="$OPENSSL_OPTIONS -no-ssl2 -no-comp -no-idea -no-hw -no-engine -no-dso -no-err -no-nextprotoneg -no-psk -no-srp -no-ec2m -no-weak-ssl-ciphers" 419 # 420 # cross build not specified, if exists flag, need to rebuild for no-arm platform. 421 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl/lib/libssl.a ]]; then 422 rm -rf ${SRS_OBJS}/openssl && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl ${SRS_OBJS}/ && 423 echo "The $OPENSSL_CANDIDATE is ok." 424 else 425 echo "Building $OPENSSL_CANDIDATE." && 426 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/${OPENSSL_CANDIDATE} ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl \ 427 ${SRS_OBJS}/openssl && 428 ${OPENSSL_UNZIP} && 429 ( 430 cd ${SRS_OBJS}/${SRS_PLATFORM}/${OPENSSL_CANDIDATE} && 431 chmod +x ./config ./Configure && 432 ${OPENSSL_CONFIG} --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdparty/openssl $OPENSSL_OPTIONS 433 ) && 434 make -C ${SRS_OBJS}/${SRS_PLATFORM}/${OPENSSL_CANDIDATE} CC=${SRS_TOOL_CC} AR="${OPENSSL_AR}" \ 435 LD=${SRS_TOOL_LD} RANDLIB=${SRS_TOOL_RANDLIB} ${SRS_JOBS} && 436 make -C ${SRS_OBJS}/${SRS_PLATFORM}/${OPENSSL_CANDIDATE} install_sw && 437 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/openssl ${SRS_OBJS}/ && 438 echo "The $OPENSSL_CANDIDATE is ok." 439 fi 440 # check status 441 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build $OPENSSL_CANDIDATE failed, ret=$ret"; exit $ret; fi 442 fi 443 444 ##################################################################################### 445 # srtp 446 ##################################################################################### 447 if [[ $SRS_RTC == YES && $SRS_USE_SYS_SRTP == YES ]]; then 448 echo "Warning: Use system libsrtp, without compiling srtp." 449 fi 450 if [[ $SRS_RTC == YES && $SRS_USE_SYS_SRTP == NO ]]; then 451 SRTP_OPTIONS="" 452 # To eliminate warnings, see https://stackoverflow.com/a/34208904/17679565 453 # was built for newer macOS version (11.6) than being linked (11.0) 454 if [[ $SRS_OSX == YES ]]; then 455 export MACOSX_DEPLOYMENT_TARGET=11.0 456 echo "Set MACOSX_DEPLOYMENT_TARGET to avoid warnings" 457 fi 458 # If use ASM for SRTP, we enable openssl(with ASM). 459 if [[ $SRS_SRTP_ASM == YES ]]; then 460 SRTP_OPTIONS="--enable-openssl" 461 SRTP_CONFIGURE="env PKG_CONFIG_PATH=${SRS_DEPENDS_LIBS}/openssl/lib/pkgconfig ./configure" 462 else 463 SRTP_OPTIONS="--disable-openssl" 464 SRTP_CONFIGURE="./configure" 465 fi 466 if [[ $SRS_CROSS_BUILD == YES ]]; then 467 SRTP_OPTIONS="$SRTP_OPTIONS --host=$SRS_CROSS_BUILD_HOST" 468 fi 469 if [[ $OS_IS_LOONGARCH64 == YES ]]; then 470 SRTP_OPTIONS="$SRTP_OPTIONS --build=loongarch64-unknown-linux-gnu" 471 fi 472 # Copy and patch source files, then build and install libsrtp. 473 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srtp2/lib/libsrtp2.a ]]; then 474 rm -rf ${SRS_OBJS}/srtp2 && 475 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srtp2 ${SRS_OBJS} && 476 echo "The libsrtp-2-fit is ok." 477 else 478 echo "Building libsrtp-2-fit." 479 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srtp2 \ 480 ${SRS_OBJS}/srtp2 && 481 cp -rf ${SRS_WORKDIR}/3rdparty/libsrtp-2-fit ${SRS_OBJS}/${SRS_PLATFORM}/ && 482 # For cygwin64, the patch is not available, so use sed instead. 483 if [[ $SRS_CYGWIN64 == YES ]]; then 484 sed -i 's/char bit_string/static char bit_string/g' ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit/crypto/math/datatypes.c 485 else 486 patch -p0 ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit/crypto/math/datatypes.c ${SRS_WORKDIR}/3rdparty/patches/srtp/gcc10-01.patch 487 fi && 488 # Patch the cpu arch guessing for RISCV. 489 if [[ $OS_IS_RISCV == YES ]]; then 490 patch -p0 ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit/config.guess ${SRS_WORKDIR}/3rdparty/patches/srtp/config.guess-02.patch 491 fi && 492 ( 493 cd ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit && 494 $SRTP_CONFIGURE ${SRTP_OPTIONS} --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdparty/srtp2 495 ) && 496 # Sometimes it might fail because autoconf failed to generate crypto/include.config.h 497 if [[ $SRS_CYGWIN64 == YES ]]; then 498 SRS_PATCH_SOURCE=${SRS_WORKDIR}/3rdparty/patches/srtp/cygwin-crypto-include-config.h 499 if [[ $SRS_SRTP_ASM == YES ]]; then 500 SRS_PATCH_SOURCE=${SRS_WORKDIR}/3rdparty/patches/srtp/cygwin-gcm-crypto-include-config.h 501 fi 502 grep -q 'HAVE_UINT64_T 1' ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit/crypto/include/config.h || 503 cp -f $SRS_PATCH_SOURCE ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit/crypto/include/config.h 504 fi && 505 make -C ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit ${SRS_JOBS} && 506 make -C ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit install && 507 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srtp2 ${SRS_OBJS}/ && 508 echo "The libsrtp-2-fit is ok." 509 fi 510 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build libsrtp failed, ret=$ret"; exit $ret; fi 511 fi 512 513 ##################################################################################### 514 # libopus, for WebRTC to transcode AAC with Opus. 515 ##################################################################################### 516 # For cross build, we use opus of FFmpeg, so we don't build the libopus. 517 if [[ $SRS_RTC == YES && $SRS_USE_SYS_FFMPEG != YES && $SRS_FFMPEG_OPUS != YES ]]; then 518 # Only build static libraries if no shared FFmpeg. 519 if [[ $SRS_SHARED_FFMPEG != YES ]]; then 520 OPUS_OPTIONS="--disable-shared --disable-doc" 521 fi 522 if [[ $OS_IS_LOONGARCH64 == YES ]]; then 523 OPUS_OPTIONS="$OPUS_OPTIONS --build=loongarch64-unknown-linux-gnu" 524 fi 525 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/opus/lib/libopus.a ]]; then 526 rm -rf ${SRS_OBJS}/opus && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/opus ${SRS_OBJS}/ && 527 echo "The opus-1.3.1 is ok." 528 else 529 echo "Building opus-1.3.1." && 530 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/opus ${SRS_OBJS}/opus && 531 tar xf ${SRS_WORKDIR}/3rdparty/opus-1.3.1.tar.gz -C ${SRS_OBJS}/${SRS_PLATFORM} && 532 ( 533 # Opus requires automake 1.15, and fails for automake 1.16+, so we run autoreconf to fix it. 534 cd ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 && autoreconf && 535 ./configure --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdparty/opus --enable-static $OPUS_OPTIONS 536 ) && 537 make -C ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 ${SRS_JOBS} && 538 make -C ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 install && 539 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/opus ${SRS_OBJS}/ && 540 echo "The opus-1.3.1 is ok." 541 fi 542 if [ ! -f ${SRS_OBJS}/opus/lib/libopus.a ]; then echo "Build opus-1.3.1 failed."; exit -1; fi 543 fi 544 545 ##################################################################################### 546 # ffmpeg-fit, for WebRTC to transcode AAC with Opus. 547 ##################################################################################### 548 if [[ $SRS_FFMPEG_FIT == YES && $SRS_USE_SYS_FFMPEG == YES ]]; then 549 echo "Warning: Use system ffmpeg, without compiling ffmpeg." 550 fi 551 if [[ $SRS_FFMPEG_FIT == YES && $SRS_USE_SYS_FFMPEG == NO ]]; then 552 FFMPEG_CONFIGURE="env SRS_FFMPEG_FIT=on" 553 if [[ $SRS_FFMPEG_OPUS != YES ]]; then 554 FFMPEG_CONFIGURE="$FFMPEG_CONFIGURE PKG_CONFIG_PATH=${SRS_DEPENDS_LIBS}/opus/lib/pkgconfig" 555 fi 556 FFMPEG_CONFIGURE="$FFMPEG_CONFIGURE ./configure" 557 558 # Disable all features, note that there are still some options need to be disabled. 559 FFMPEG_OPTIONS="--disable-everything" 560 # Disable all asm for FFmpeg, to compatible with ARM CPU. 561 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-asm --disable-x86asm --disable-inline-asm" 562 # Only build static libraries if no shared FFmpeg. 563 if [[ $SRS_SHARED_FFMPEG == YES ]]; then 564 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-shared" 565 fi 566 # For loongson/mips64, disable mips64r6, or build failed. 567 if [[ $OS_IS_MIPS64 == YES && $OS_IS_LOONGSON == YES ]]; then FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-mips64r6"; fi 568 # For cross-build. 569 if [[ $SRS_CROSS_BUILD == YES ]]; then 570 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-cross-compile --target-os=linux --disable-pthreads" 571 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --arch=$SRS_CROSS_BUILD_ARCH"; 572 if [[ $SRS_CROSS_BUILD_CPU != "" ]]; then FFMPEG_OPTIONS="$FFMPEG_OPTIONS --cpu=$SRS_CROSS_BUILD_CPU"; fi 573 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --cross-prefix=$SRS_CROSS_BUILD_PREFIX" 574 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --cc=${SRS_TOOL_CC} --cxx=${SRS_TOOL_CXX} --ar=${SRS_TOOL_AR} --ld=${SRS_TOOL_LD}" 575 fi 576 # For audio codec opus, use FFmpeg native one, or external libopus. 577 if [[ $SRS_FFMPEG_OPUS == YES ]]; then 578 # TODO: FIXME: Note that the audio might be corrupted, see https://github.com/ossrs/srs/issues/3140 579 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-decoder=opus --enable-encoder=opus" 580 else 581 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-decoder=libopus --enable-encoder=libopus --enable-libopus" 582 fi 583 # Disable features of ffmpeg. 584 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-avdevice --disable-avformat --disable-swscale --disable-postproc --disable-avfilter --disable-network" 585 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-dwt --disable-error-resilience --disable-lsp --disable-lzo --disable-faan --disable-pixelutils" 586 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-hwaccels --disable-devices --disable-audiotoolbox --disable-videotoolbox --disable-cuvid" 587 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-d3d11va --disable-dxva2 --disable-ffnvcodec --disable-nvdec --disable-nvenc --disable-v4l2-m2m --disable-vaapi" 588 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-vdpau --disable-appkit --disable-coreimage --disable-avfoundation --disable-securetransport --disable-iconv" 589 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --disable-lzma --disable-sdl2" 590 # Enable FFmpeg native AAC encoder and decoder. 591 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm --enable-encoder=aac" 592 # Enable FFmpeg native MP3 decoder, which depends on dct. 593 FFMPEG_OPTIONS="$FFMPEG_OPTIONS --enable-decoder=mp3 --enable-dct" 594 595 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/ffmpeg/lib/libavcodec.a ]]; then 596 rm -rf ${SRS_OBJS}/ffmpeg && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/ffmpeg ${SRS_OBJS}/ && 597 echo "The ffmpeg-4-fit is ok." 598 else 599 echo "Building ffmpeg-4-fit." && 600 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/ffmpeg \ 601 ${SRS_OBJS}/ffmpeg && 602 cp -rf ${SRS_WORKDIR}/3rdparty/ffmpeg-4-fit ${SRS_OBJS}/${SRS_PLATFORM}/ && 603 ( 604 cd ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit && 605 $FFMPEG_CONFIGURE --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdparty/ffmpeg \ 606 --pkg-config=pkg-config --pkg-config-flags='--static' --extra-libs='-lpthread' --extra-libs='-lm' \ 607 ${FFMPEG_OPTIONS} 608 ) && 609 # See https://www.laoyuyu.me/2019/05/23/android/clang_compile_ffmpeg/ 610 if [[ $SRS_CROSS_BUILD == YES ]]; then 611 sed -i -e 's/#define getenv(x) NULL/\/\*#define getenv(x) NULL\*\//g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 612 sed -i -e 's/#define HAVE_GMTIME_R 0/#define HAVE_GMTIME_R 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 613 sed -i -e 's/#define HAVE_LOCALTIME_R 0/#define HAVE_LOCALTIME_R 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 614 # For MIPS, which fail with: 615 # ./libavutil/libm.h:54:32: error: static declaration of 'cbrt' follows non-static declaration 616 # /root/openwrt/staging_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/include/math.h:163:13: note: previous declaration of 'cbrt' was here 617 if [[ $SRS_CROSS_BUILD_ARCH == "mipsel" || $SRS_CROSS_BUILD_ARCH == "arm" || $SRS_CROSS_BUILD_ARCH == "aarch64" ]]; then 618 sed -i -e 's/#define HAVE_CBRT 0/#define HAVE_CBRT 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 619 sed -i -e 's/#define HAVE_CBRTF 0/#define HAVE_CBRTF 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 620 sed -i -e 's/#define HAVE_COPYSIGN 0/#define HAVE_COPYSIGN 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 621 sed -i -e 's/#define HAVE_ERF 0/#define HAVE_ERF 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 622 sed -i -e 's/#define HAVE_HYPOT 0/#define HAVE_HYPOT 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 623 sed -i -e 's/#define HAVE_RINT 0/#define HAVE_RINT 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 624 sed -i -e 's/#define HAVE_LRINT 0/#define HAVE_LRINT 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 625 sed -i -e 's/#define HAVE_LRINTF 0/#define HAVE_LRINTF 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 626 sed -i -e 's/#define HAVE_ROUND 0/#define HAVE_ROUND 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 627 sed -i -e 's/#define HAVE_ROUNDF 0/#define HAVE_ROUNDF 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 628 sed -i -e 's/#define HAVE_TRUNC 0/#define HAVE_TRUNC 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 629 sed -i -e 's/#define HAVE_TRUNCF 0/#define HAVE_TRUNCF 1/g' ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit/config.h && 630 echo "FFmpeg sed ok" 631 fi 632 fi && 633 make -C ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit ${SRS_JOBS} && 634 make -C ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg-4-fit install && 635 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/ffmpeg ${SRS_OBJS}/ && 636 echo "The ffmpeg-4-fit is ok." 637 fi 638 # check status 639 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build ffmpeg-4-fit failed, ret=$ret"; exit $ret; fi 640 fi 641 642 ##################################################################################### 643 # live transcoding, ffmpeg-4.1, x264-core157, lame-3.99.5, libaacplus-2.0.2. 644 ##################################################################################### 645 # Guess where is the ffmpeg. 646 SYSTEMP_FFMPEG_BIN=`which ffmpeg` 647 # Always link the ffmpeg tools if exists. 648 if [[ -f $SYSTEMP_FFMPEG_BIN && ! -f ${SRS_OBJS}/ffmpeg/bin/ffmpeg ]]; then 649 mkdir -p ${SRS_OBJS}/ffmpeg/bin && 650 cp -f $SYSTEMP_FFMPEG_BIN ${SRS_OBJS}/ffmpeg/bin/ 651 fi 652 if [[ $SRS_FFMPEG_TOOL == YES ]]; then 653 if [[ -f ${SRS_OBJS}/ffmpeg/bin/ffmpeg ]]; then 654 cp -f $SYSTEMP_FFMPEG_BIN ${SRS_OBJS}/ffmpeg/bin/ && 655 echo "ffmpeg-4.1 is ok."; 656 else 657 echo -e "${RED}Error: No FFmpeg found at /usr/local/bin/ffmpeg${BLACK}" 658 echo -e "${RED} Please copy it from srs-docker${BLACK}" 659 echo -e "${RED} or download from http://ffmpeg.org/download.html${BLACK}" 660 echo -e "${RED} or disable it by --without-ffmpeg${BLACK}" 661 exit -1; 662 fi 663 fi 664 665 ##################################################################################### 666 # SRT module, https://github.com/ossrs/srs/issues/1147#issuecomment-577469119 667 ##################################################################################### 668 if [[ $SRS_SRT == YES && $SRS_USE_SYS_SRT == YES ]]; then 669 echo "Warning: Use system libsrt, without compiling srt." 670 fi 671 if [[ $SRS_SRT == YES && $SRS_USE_SYS_SRT == NO ]]; then 672 # Always disable c++11 for libsrt, because only the srt-app requres it. 673 LIBSRT_OPTIONS="--enable-apps=0 --enable-static=1 --enable-c++11=0" 674 if [[ $SRS_SHARED_SRT == YES ]]; then 675 LIBSRT_OPTIONS="$LIBSRT_OPTIONS --enable-shared=1" 676 else 677 LIBSRT_OPTIONS="$LIBSRT_OPTIONS --enable-shared=0" 678 fi 679 # For windows build, over cygwin 680 if [[ $SRS_CYGWIN64 == YES ]]; then 681 LIBSRT_OPTIONS="$LIBSRT_OPTIONS --cygwin-use-posix" 682 fi 683 # For cross-build. 684 if [[ $SRS_CROSS_BUILD == YES ]]; then 685 TOOL_GCC_REALPATH=$(realpath $(which $SRS_TOOL_CC)) 686 SRT_COMPILER_PREFIX=$(echo $TOOL_GCC_REALPATH |sed 's/-gcc.*$/-/') 687 LIBSRT_OPTIONS="$LIBSRT_OPTIONS --with-compiler-prefix=$SRT_COMPILER_PREFIX" 688 fi 689 690 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srt/lib/libsrt.a ]]; then 691 rm -rf ${SRS_OBJS}/srt && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srt ${SRS_OBJS}/ && 692 echo "libsrt-1-fit is ok." 693 else 694 if [[ $SRS_USE_SYS_SSL != YES && ! -d ${SRS_OBJS}/openssl/lib/pkgconfig ]]; then 695 echo "OpenSSL pkgconfig no found, build srt-1-fit failed." 696 exit -1 697 fi 698 echo "Build srt-1-fit" && 699 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/srt-1-fit ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srt ${SRS_OBJS}/srt && 700 cp -rf ${SRS_WORKDIR}/3rdparty/srt-1-fit ${SRS_OBJS}/${SRS_PLATFORM}/ && 701 patch -p0 -R ${SRS_OBJS}/${SRS_PLATFORM}/srt-1-fit/srtcore/api.cpp ${SRS_WORKDIR}/3rdparty/patches/srt/api.cpp-01.patch && 702 ( 703 cd ${SRS_OBJS}/${SRS_PLATFORM}/srt-1-fit && 704 env PKG_CONFIG_PATH=${SRS_DEPENDS_LIBS}/openssl/lib/pkgconfig \ 705 ./configure --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdparty/srt $LIBSRT_OPTIONS 706 ) && 707 make -C ${SRS_OBJS}/${SRS_PLATFORM}/srt-1-fit ${SRS_JOBS} && 708 make -C ${SRS_OBJS}/${SRS_PLATFORM}/srt-1-fit install && 709 # If exists lib64 of libsrt, copy it to lib 710 if [[ -d ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srt/lib64 ]]; then 711 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srt/lib64 ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srt/lib 712 fi && 713 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/srt ${SRS_OBJS}/ && 714 echo "libsrt-1-fit is ok." 715 fi 716 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build srt-1-fit failed, ret=$ret"; exit $ret; fi 717 fi 718 719 ##################################################################################### 720 # build utest code 721 ##################################################################################### 722 if [[ $SRS_UTEST == YES ]]; then 723 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gtest/googletest/include/gtest/gtest.h ]]; then 724 rm -rf ${SRS_OBJS}/gtest && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gtest ${SRS_OBJS}/ && 725 echo "The gtest-fit is ok." 726 else 727 echo "Build gtest-fit" && 728 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}gtest-fit ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gtest ${SRS_OBJS}/gtest && 729 cp -rf ${SRS_WORKDIR}/3rdparty/gtest-fit ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gtest && 730 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gtest ${SRS_OBJS}/ && 731 echo "The gtest-fit is ok." 732 fi 733 # check status 734 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build gtest-1.6.0 failed, ret=$ret"; exit $ret; fi 735 fi 736 737 ##################################################################################### 738 # build gperf code 739 ##################################################################################### 740 if [[ $SRS_GPERF == YES ]]; then 741 if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gperf/bin/pprof ]]; then 742 rm -rf ${SRS_OBJS}/gperf && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gperf ${SRS_OBJS}/ && 743 cp -f ${SRS_OBJS}/gperf/bin/pprof ${SRS_OBJS}/ && 744 echo "The gperftools-2-fit is ok." 745 else 746 echo "Build gperftools-2-fit" && 747 rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/gperftools-2-fit ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gperf \ 748 ${SRS_OBJS}/gperf ${SRS_OBJS}/pprof && 749 cp -rf ${SRS_WORKDIR}/3rdparty/gperftools-2-fit ${SRS_OBJS}/${SRS_PLATFORM}/ && 750 ( 751 cd ${SRS_OBJS}/${SRS_PLATFORM}/gperftools-2-fit && 752 ./configure --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdparty/gperf --enable-frame-pointers 753 ) && 754 make -C ${SRS_OBJS}/${SRS_PLATFORM}/gperftools-2-fit ${SRS_JOBS} && 755 make -C ${SRS_OBJS}/${SRS_PLATFORM}/gperftools-2-fit install && 756 cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdparty/gperf ${SRS_OBJS}/ && 757 cp -f ${SRS_OBJS}/gperf/bin/pprof ${SRS_OBJS}/ && 758 echo "The gperftools-2-fit is ok." 759 fi 760 # check status 761 ret=$?; if [[ $ret -ne 0 ]]; then echo "Build gperftools-2-fit failed, ret=$ret"; exit $ret; fi 762 fi 分析一下这个脚本都是什么功能 如果我想新增一个能编译app/srs_app_jwt.cpp的功能怎么添加,请帮我添加
最新发布
07-23
<think>我们首先分析deps.sh脚本的功能,然后指导如何在Makefile中添加对app/srs_app_jwt.cpp的编译支持。 ### 1. 分析deps.sh脚本功能 SRS(Simple RTMP Server)的`deps.sh`脚本位于`trunk/auto`目录下,主要用于安装构建SRS所需的依赖库。该脚本通常执行以下任务: - 检查并安装系统依赖(如编译器、基础工具) - 下载并编译第三方库(如OpenSSL、FFmpeg等) - 为SRS构建准备环境 在`deps.sh`中添加jwt-cpp依赖库的步骤(根据之前的讨论): 1. 克隆jwt-cpp仓库到`third_party/jwt-cpp`目录 2. 可选:创建符号链接将头文件放入系统目录(但通常SRS的Makefile会直接指定第三方库的路径) ### 2. 修改deps.sh添加jwt-cpp 在`deps.sh`中,我们可以添加一个函数来安装jwt-cpp,并在主流程中调用它。例如: ```bash # 在deps.sh中添加以下函数 install_jwt_cpp() { if [ ! -d jwt-cpp ]; then echo "Installing jwt-cpp..." git clone https://github.com/Thalhammer/jwt-cpp.git \ --depth 1 third_party/jwt-cpp if [ $? -ne 0 ]; then echo "Failed to clone jwt-cpp" exit 1 fi else echo "jwt-cpp already exists" fi } # 然后在install_dependencies函数中调用 install_dependencies() { # ... 其他依赖安装 install_jwt_cpp } ``` ### 3. 在Makefile中添加对srs_app_jwt.cpp的编译支持 SRS的Makefile位于`trunk/src`目录。我们需要完成以下步骤: #### 步骤1: 将srs_app_jwt.cpp添加到OBJS中 在Makefile中,找到定义`OBJS`的地方(通常是一系列.o文件的列表),添加`srs_app_jwt.o`。例如: ```makefile # 修改前 OBJS = srs_app_server.o srs_app_source.o ... # 修改后 OBJS = srs_app_server.o srs_app_source.o ... srs_app_jwt.o ``` #### 步骤2: 添加头文件路径 由于jwt-cpp是第三方库,我们需要在编译时指定其头文件路径。在Makefile中找到`CFLAGS`(或`CXXFLAGS`)的定义,添加`-I`选项: ```makefile # 在已有的CFLAGS或CXXFLAGS后添加 CFLAGS += -I$(SRS_OBJS)/../../third_party/jwt-cpp/include ``` 注意:`$(SRS_OBJS)`是Makefile中定义的中间文件目录,通常为`objs`。但具体路径需要根据SRS的Makefile结构确定。更常见的做法是使用相对路径,例如: ```makefile CFLAGS += -I../../../third_party/jwt-cpp/include ``` #### 步骤3: 添加依赖关系(可选) 如果`srs_app_jwt.cpp`包含自己的头文件(例如`srs_app_jwt.hpp`),我们可以添加显式规则以确保头文件变更时重新编译: ```makefile srs_app_jwt.o: app/srs_app_jwt.cpp app/srs_app_jwt.hpp $(CXX) -c $(CXXFLAGS) $< -o $@ ``` 但通常Makefile已有通用规则,所以这一步可能不需要。 ### 4. 验证修改 - 运行`deps.sh`安装jwt-cpp: ```bash cd trunk/auto ./deps.sh ``` - 编译SRS: ```bash cd ../src make ``` 检查是否成功编译`srs_app_jwt.cpp`。 ### 5. 注意事项 - **路径问题**:确保Makefile中指定的jwt-cpp头文件路径与`deps.sh`下载的路径一致。 - **版本控制**:在`deps.sh`中指定jwt-cpp的版本(使用`git clone --branch`)以避免未来兼容性问题。 - **依赖关系**:如果jwt-cpp还依赖其他库(如OpenSSL),则需要在`deps.sh`中确保这些依赖已安装,并在Makefile中链接。 ### 相关问题 1. 如何解决编译时找不到jwt-cpp头文件的问题? 2. 如何在Makefile中添加动态链接库的支持? 3. SRS的Makefile结构是怎样的? 4. 如何为SRS添加新的模块文件? 5. 如何指定第三方库的版本以避免兼容性问题?</think>### 分析 SRS 的 deps.sh 脚本功能 SRS (Simple RTMP Server) 的 `deps.sh` 脚本主要功能是自动化安装项目依赖项,包含以下核心功能: 1. **依赖项检测与安装** - 检查系统是否安装必需工具(如 gcc/g++、make 等) - 自动安装缺失的基础开发工具[^1] ```bash check_tools() { if ! which gcc >/dev/null; then apt-get install -y build-essential fi } ``` 2. **第三方库管理** - 下载并编译第三方依赖库(如 OpenSSL、FFmpeg 等) - 支持源码编译和包管理器安装两种方式[^2] ```bash install_openssl() { if [ ! -d "openssl" ]; then git clone https://github.com/openssl/openssl cd openssl && ./config && make fi } ``` 3. **环境配置** - 设置编译环境变量 - 创建必要的目录结构 - 生成配置头文件 4. **跨平台支持** - 自动检测操作系统类型(Linux/macOS/Windows) - 适配不同平台的包管理器(apt/yum/brew) ### 添加 srs_app_jwt.cpp 的编译支持 #### 步骤 1:在 Makefile 中添加新文件 在 `trunk/objs/Makefile` 中修改以下部分: ```makefile # 修改前 SRC_OBJS = srs_app_server.o srs_app_source.o ... # 修改后:添加 srs_app_jwt.o SRC_OBJS = srs_app_server.o srs_app_source.o ... srs_app_jwt.o ``` #### 步骤 2:添加头文件路径 在 CFLAGS 中添加 JWT 库的包含路径: ```makefile # 在已有的 CFLAGS 后添加 CFLAGS += -I$(SRS_OBJS)/../../third_party/jwt-cpp/include ``` #### 步骤 3:添加编译规则 在 Makefile 中添加显式编译规则: ```makefile srs_app_jwt.o: $(SRS_OBJS)/app/srs_app_jwt.cpp $(GCC) -c $(CFLAGS) $< -o $@ ``` #### 步骤 4:添加清理规则 在 clean 目标中添加新文件的清理: ```makefile clean: rm -f ... srs_app_jwt.o ``` ### 完整修改示例 ```diff # trunk/objs/Makefile # 添加新目标文件 SRC_OBJS = ... \ + srs_app_jwt.o # 添加头文件路径 CFLAGS += ... \ + -I$(SRS_OBJS)/../../third_party/jwt-cpp/include # 添加显式编译规则 +srs_app_jwt.o: $(SRS_OBJS)/app/srs_app_jwt.cpp + $(GCC) -c $(CFLAGS) $< -o $@ # 添加清理规则 clean: - rm -f ... + rm -f ... srs_app_jwt.o ``` ### 验证步骤 1. **安装依赖**: ```bash cd trunk/auto && ./deps.sh ``` 2. **编译项目**: ```bash cd ../objs && make # 检查输出中是否包含: # [GCC] app/srs_app_jwt.cpp ``` 3. **验证目标文件**: ```bash ls -l srs_app_jwt.o ``` ### 关键注意事项 1. **路径一致性** Makefile 中的 `$(SRS_OBJS)` 变量指向中间文件目录,确保路径正确[^1] 2. **依赖关系** 如果 `srs_app_jwt.cpp` 依赖其他头文件,需在规则中声明: ```makefile srs_app_jwt.o: app/srs_app_jwt.cpp app/srs_app_jwt.h ``` 3. **跨平台支持** 在 `deps.sh` 中添加 Windows 支持: ```bash if [[ "$OSTYPE" == "msys" ]]; then pacman -S mingw-w64-x86_64-jwt-cpp fi ``` 4. **版本控制** 在 `deps.sh` 中指定 JWT 版本: ```bash git clone --branch v0.6.0 https://github.com/Thalhammer/jwt-cpp ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值